Search by

serafim / vulkan

Serafim

PHP Vulkan Bindings

Package info

github.com/SerafimArts/Vulkan

pkg:composer/serafim/vulkan

Statistics

Installs: 17

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

dev-master / 1.0.x-dev 2026-10-30 22:48 UTC

This package is auto-updated.

Last update: 2026-10-30 22:48:09 UTC


README

Vulkan logo

PHP Vulkan Bindings

PHP bindings of the Vulkan API on top of ext-ffi for Linux (Xlib, XCB, Wayland), Windows and macOS (MoltenVK).

Requirements

  • PHP ^8.4
  • ext-ffi
  • GPU and drivers supporting Vulkan API

Installation

  • composer require serafim/vulkan

Usage

Creates an instance and prints the names of the GPUs.

use Serafim\Vulkan\Struct\VkApplicationInfo;
use Serafim\Vulkan\Struct\VkInstanceCreateInfo;
use Serafim\Vulkan\Vulkan;

$vk = Vulkan::load();

$instance = $vk->vkCreateInstance(new VkInstanceCreateInfo(
    applicationInfo: new VkApplicationInfo(
        applicationName: 'Example',
    ),
));

foreach ($vk->vkEnumeratePhysicalDevices($instance) as $device) {
    $properties = $vk->vkGetPhysicalDeviceProperties($device);

    echo $properties->deviceName . "\n";
}

Instance version and extensions

The highest API version and the instance extensions the installed Vulkan supports. Needs no instance. Lists of unknown length are lazy collections.

echo $vk->vkEnumerateInstanceVersion() . "\n";

foreach ($vk->vkEnumerateInstanceExtensionProperties() as $extension) {
    echo $extension->extensionName . "\n";
}

API version

The Vulkan version the application targets. All the macros of Vulkan (VK_MAKE_API_VERSION and others) are available as vk_* functions.

use function Serafim\Vulkan\vk_make_api_version;

$info = new VkApplicationInfo(
    applicationName: 'Example',
    apiVersion: vk_make_api_version(0, 1, 3, 0),
);

Queue families

Every queue belongs to a family with its own capabilities. Finds the families that support graphics, flags are checked with a bit mask.

use Serafim\Vulkan\Enum\VkQueueFlagBits;

foreach ($vk->vkGetPhysicalDeviceQueueFamilyProperties($device) as $index => $family) {
    if ($family->queueFlags & VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT) {
        echo "Graphics queue family: $index ($family->queueCount queues)\n";
    }
}

Chained structures

Properties are split across extension structures linked by pNext. List the classes you need and read each back by class.

use Serafim\Vulkan\Struct\VkPhysicalDeviceVulkan13Properties;

$properties = $vk->vkGetPhysicalDeviceProperties2($device, [
    VkPhysicalDeviceVulkan13Properties::class,
]);

$vulkan13 = $properties->chain[VkPhysicalDeviceVulkan13Properties::class];

echo $vulkan13->driverName . "\n";   // Vulkan 1.2
echo $vulkan13->deviceUUID . "\n";    // Vulkan 1.1
echo $vulkan13->maxSubgroupSize . "\n";

Logical device and queue

Opens a logical device on a GPU and gets its queue. There is no destroy: an object is destroyed with its PHP handle, children first.

use Serafim\Vulkan\Struct\VkDeviceCreateInfo;
use Serafim\Vulkan\Struct\VkDeviceQueueCreateInfo;

$logical = $vk->vkCreateDevice($device, new VkDeviceCreateInfo(
    queueCreateInfos: [
        new VkDeviceQueueCreateInfo(
            queueFamilyIndex: 0,
            queuePriorities: [1.0],
        ),
    ],
));

$queue = $vk->vkGetDeviceQueue($logical, 0, 0);
$vk->vkQueueWaitIdle($queue);

Enabling features

Structures that extend the one a command takes are given in its chain list. The structure of a Vulkan version holds the features of all the older ones.

use Serafim\Vulkan\Struct\VkPhysicalDeviceVulkan13Features;

$logical = $vk->vkCreateDevice($device, new VkDeviceCreateInfo(
    queueCreateInfos: [new VkDeviceQueueCreateInfo(
        queueFamilyIndex: 0, 
        queuePriorities: [1.0],
    )],
    chain: [new VkPhysicalDeviceVulkan13Features(
        dynamicRendering: true,
        bufferDeviceAddress: true, // Vulkan 1.2
        multiview: true,           // Vulkan 1.1
    )],
));

Errors

A failed command throws CommandFailedException, its code is the VkResult value.

use Serafim\Vulkan\Enum\VkResult;
use Serafim\Vulkan\Exception\CommandFailedException;

try {
    $vk->vkCreateInstance(new VkInstanceCreateInfo(
        enabledLayerNames: ['missing'],
    ));
} catch (CommandFailedException $e) {
    $result = VkResult::from($e->getCode());

    echo $result->name;
}

More in ./examples/*.php