Base object structs

The Vulkan runtime code provides a set of base object structs which must be used if you want your driver to take advantage of any of the runtime code. There are other base structs for various things which are not covered here but those are optional. The ones covered here are the bare minimum set which form the core of the Vulkan runtime code:

As one might expect, vk_instance is the required base struct for implementing VkInstance, vk_physical_device is required for VkPhysicalDevice, and vk_device for VkDevice. Everything else must derive from vk_object_base or from some struct that derives from vk_object_base.

vk_object_base

The root base struct for all Vulkan objects is vk_object_base. Every object exposed to the client through the Vulkan API must inherit from vk_object_base by having a vk_object_base or some struct that inherits from vk_object_base as the driver struct’s first member. Even though we have container_of() and use it liberally, the vk_object_base should be the first member as there are a few places, particularly in the logging framework, where we use void pointers to avoid casting and this only works if the address of the driver struct is the same as the address of the vk_object_base.

The standard pattern for defining a Vulkan object inside a driver looks something like this:

struct drv_sampler {
   struct vk_object_base base;

   /* Driver fields */
};

VK_DEFINE_NONDISP_HANDLE_CASTS(drv_sampler, base, VkSampler,
                               VK_OBJECT_TYPE_SAMPLER);

Then, to the object in a Vulkan entrypoint,

VKAPI_ATTR void VKAPI_CALL drv_DestroySampler(
    VkDevice                                    _device,
    VkSampler                                   _sampler,
    const VkAllocationCallbacks*                pAllocator)
{
   VK_FROM_HANDLE(drv_device, device, _device);
   VK_FROM_HANDLE(drv_sampler, sampler, _sampler);

   if (!sampler)
      return;

   /* Tear down the sampler */

   vk_object_free(&device->vk, pAllocator, sampler);
}

The VK_DEFINE_NONDISP_HANDLE_CASTS macro defines a set of type-safe cast functions called drv_sampler_from_handle() and drv_sampler_to_handle() which cast a VkSampler to and from a struct drv_sampler *. Because compile-time type checking with Vulkan handle types doesn’t always work in C, the _from_handle() helper uses the provided VkObjectType to assert at runtime that the provided handle is the correct type of object. Both cast helpers properly handle NULL and VK_NULL_HANDLE as inputs. The VK_FROM_HANDLE macro provides a convenient way to declare a drv_foo pointer and initialize it from a VkFoo handle in one smooth motion.

Warning

doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

vk_instance

Warning

doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Once a driver has a vk_instance, implementing all the various instance-level vkGet*ProcAddr() entrypoints is trivial:

VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
drv_GetInstanceProcAddr(VkInstance _instance,
                        const char *pName)
{
   VK_FROM_HANDLE(vk_instance, instance, _instance);
   return vk_instance_get_proc_addr(instance,
                                    &drv_instance_entrypoints,
                                    pName);
}

PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,
                          const char *pName);

PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,
                          const char *pName)
{
   return drv_GetInstanceProcAddr(instance, pName);
}

PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
                                const char* pName);

PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
                                const char* pName)
{
   VK_FROM_HANDLE(vk_instance, instance, _instance);
   return vk_instance_get_physical_device_proc_addr(instance, pName);
}

The prototypes for the vk_icd* versions are needed because those are not actually defined in the Vulkan headers and you need the prototype somewhere to get the C compiler to not complain. These are all implemented by wrapping one of the provided vk_instance_get*_proc_addr() functions.

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

We also provide an implementation of vkEnumerateInstanceExtensionProperties() which can be used similarly:

VKAPI_ATTR VkResult VKAPI_CALL
drv_EnumerateInstanceExtensionProperties(const char *pLayerName,
                                         uint32_t *pPropertyCount,
                                         VkExtensionProperties *pProperties)
{
   if (pLayerName)
      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);

   return vk_enumerate_instance_extension_properties(
      &instance_extensions, pPropertyCount, pProperties);
}
Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

vk_physical_device

Warning

doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

vk_device

Warning

doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml

Warning

doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml