1Base object structs 2=================== 3 4The Vulkan runtime code provides a set of base object structs which must be 5used if you want your driver to take advantage of any of the runtime code. 6There are other base structs for various things which are not covered here 7but those are optional. The ones covered here are the bare minimum set 8which form the core of the Vulkan runtime code: 9 10.. contents:: 11 :local: 12 13As one might expect, :c:struct:`vk_instance` is the required base struct 14for implementing ``VkInstance``, :c:struct:`vk_physical_device` is 15required for ``VkPhysicalDevice``, and :c:struct:`vk_device` for 16``VkDevice``. Everything else must derive from 17:c:struct:`vk_object_base` or from some struct that derives from 18:c:struct:`vk_object_base`. 19 20 21vk_object_base 22-------------- 23 24The root base struct for all Vulkan objects is 25:c:struct:`vk_object_base`. Every object exposed to the client through 26the Vulkan API *must* inherit from :c:struct:`vk_object_base` by having a 27:c:struct:`vk_object_base` or some struct that inherits from 28:c:struct:`vk_object_base` as the driver struct's first member. Even 29though we have ``container_of()`` and use it liberally, the 30:c:struct:`vk_object_base` should be the first member as there are a few 31places, particularly in the logging framework, where we use void pointers 32to avoid casting and this only works if the address of the driver struct is 33the same as the address of the :c:struct:`vk_object_base`. 34 35The standard pattern for defining a Vulkan object inside a driver looks 36something like this: 37 38.. code-block:: c 39 40 struct drv_sampler { 41 struct vk_object_base base; 42 43 /* Driver fields */ 44 }; 45 46 VK_DEFINE_NONDISP_HANDLE_CASTS(drv_sampler, base, VkSampler, 47 VK_OBJECT_TYPE_SAMPLER); 48 49Then, to the object in a Vulkan entrypoint, 50 51.. code-block:: c 52 53 VKAPI_ATTR void VKAPI_CALL drv_DestroySampler( 54 VkDevice _device, 55 VkSampler _sampler, 56 const VkAllocationCallbacks* pAllocator) 57 { 58 VK_FROM_HANDLE(drv_device, device, _device); 59 VK_FROM_HANDLE(drv_sampler, sampler, _sampler); 60 61 if (!sampler) 62 return; 63 64 /* Tear down the sampler */ 65 66 vk_object_free(&device->vk, pAllocator, sampler); 67 } 68 69The :c:macro:`VK_DEFINE_NONDISP_HANDLE_CASTS()` macro defines a set of 70type-safe cast functions called ``drv_sampler_from_handle()`` and 71``drv_sampler_to_handle()`` which cast a :c:type:`VkSampler` to and from a 72``struct drv_sampler *``. Because compile-time type checking with Vulkan 73handle types doesn't always work in C, the ``_from_handle()`` helper uses the 74provided :c:type:`VkObjectType` to assert at runtime that the provided 75handle is the correct type of object. Both cast helpers properly handle 76``NULL`` and ``VK_NULL_HANDLE`` as inputs. The :c:macro:`VK_FROM_HANDLE()` 77macro provides a convenient way to declare a ``drv_foo`` pointer and 78initialize it from a ``VkFoo`` handle in one smooth motion. 79 80.. c:autostruct:: vk_object_base 81 :file: src/vulkan/runtime/vk_object.h 82 :members: 83 84.. c:autofunction:: vk_object_base_init 85 86.. c:autofunction:: vk_object_base_finish 87 88.. c:automacro:: VK_DEFINE_HANDLE_CASTS 89 90.. c:automacro:: VK_DEFINE_NONDISP_HANDLE_CASTS 91 92.. c:automacro:: VK_FROM_HANDLE 93 94 95vk_instance 96----------- 97 98.. c:autostruct:: vk_instance 99 :file: src/vulkan/runtime/vk_instance.h 100 :members: 101 102.. c:autofunction:: vk_instance_init 103 104.. c:autofunction:: vk_instance_finish 105 106Once a driver has a :c:struct:`vk_instance`, implementing all the various 107instance-level ``vkGet*ProcAddr()`` entrypoints is trivial: 108 109.. code-block:: c 110 111 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 112 drv_GetInstanceProcAddr(VkInstance _instance, 113 const char *pName) 114 { 115 VK_FROM_HANDLE(vk_instance, instance, _instance); 116 return vk_instance_get_proc_addr(instance, 117 &drv_instance_entrypoints, 118 pName); 119 } 120 121 PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 122 vk_icdGetInstanceProcAddr(VkInstance instance, 123 const char *pName) 124 { 125 return drv_GetInstanceProcAddr(instance, pName); 126 } 127 128.. c:autofunction:: vk_instance_get_proc_addr 129 130.. c:autofunction:: vk_instance_get_proc_addr_unchecked 131 132.. c:autofunction:: vk_instance_get_physical_device_proc_addr 133 134We also provide an implementation of 135``vkEnumerateInstanceExtensionProperties()`` which can be used similarly: 136 137.. code-block:: c 138 139 VKAPI_ATTR VkResult VKAPI_CALL 140 drv_EnumerateInstanceExtensionProperties(const char *pLayerName, 141 uint32_t *pPropertyCount, 142 VkExtensionProperties *pProperties) 143 { 144 if (pLayerName) 145 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 146 147 return vk_enumerate_instance_extension_properties( 148 &instance_extensions, pPropertyCount, pProperties); 149 } 150 151.. c:autofunction:: vk_enumerate_instance_extension_properties 152 153vk_physical_device 154------------------ 155 156.. c:autostruct:: vk_physical_device 157 :file: src/vulkan/runtime/vk_physical_device.h 158 :members: 159 160.. c:autofunction:: vk_physical_device_init 161 162.. c:autofunction:: vk_physical_device_finish 163 164vk_device 165------------------ 166 167.. c:autostruct:: vk_device 168 :file: src/vulkan/runtime/vk_device.h 169 :members: 170 171.. c:autofunction:: vk_device_init 172 173.. c:autofunction:: vk_device_finish 174