• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, :cpp:struct:`vk_instance` is the required base struct
14for implementing ``VkInstance``, :cpp:struct:`vk_physical_device` is
15required for ``VkPhysicalDevice``, and :cpp:struct:`vk_device` for
16``VkDevice``.  Everything else must derive from
17:cpp:struct:`vk_vk_objet_base` or from some struct that derives from
18:cpp:struct:`vk_vk_objet_base`.
19
20
21vk_object_base
22--------------
23
24The root base struct for all Vulkan objects is
25:cpp:struct:`vk_object_base`.  Every object exposed to the client through
26the Vulkan API *must* inherit from :cpp:struct:`vk_object_base` by having a
27:cpp:struct:`vk_object_base` or some struct that inherits from
28:cpp:struct:`vk_object_base` as the driver struct's first member.  Even
29though we have `container_of()` and use it liberally, the
30:cpp: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 :cpp: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 :cpp:any:`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 :cpp: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 :cpp: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 :cpp:any:`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.. doxygenstruct:: vk_object_base
81   :members:
82
83.. doxygenfunction:: vk_object_base_init
84.. doxygenfunction:: vk_object_base_finish
85
86.. doxygendefine:: VK_DEFINE_HANDLE_CASTS
87
88.. doxygendefine:: VK_DEFINE_NONDISP_HANDLE_CASTS
89
90.. doxygendefine:: VK_FROM_HANDLE
91
92
93vk_instance
94-----------
95
96.. doxygenstruct:: vk_instance
97   :members:
98
99.. doxygenfunction:: vk_instance_init
100.. doxygenfunction:: vk_instance_finish
101
102Once a driver has a :cpp:struct:`vk_instance`, implementing all the various
103instance-level ``vkGet*ProcAddr()`` entrypoints is trivial:
104
105.. code-block:: c
106
107   VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
108   drv_GetInstanceProcAddr(VkInstance _instance,
109                           const char *pName)
110   {
111      VK_FROM_HANDLE(vk_instance, instance, _instance);
112      return vk_instance_get_proc_addr(instance,
113                                       &drv_instance_entrypoints,
114                                       pName);
115   }
116
117   PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
118   vk_icdGetInstanceProcAddr(VkInstance instance,
119                             const char *pName);
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   PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
129   vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
130                                   const char* pName);
131
132   PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
133   vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
134                                   const char* pName)
135   {
136      VK_FROM_HANDLE(vk_instance, instance, _instance);
137      return vk_instance_get_physical_device_proc_addr(instance, pName);
138   }
139
140The prototypes for the ``vk_icd*`` versions are needed because those are not
141actually defined in the Vulkan headers and you need the prototype somewhere
142to get the C compiler to not complain.  These are all implemented by
143wrapping one of the provided ``vk_instance_get*_proc_addr()`` functions.
144
145.. doxygenfunction:: vk_instance_get_proc_addr
146.. doxygenfunction:: vk_instance_get_proc_addr_unchecked
147.. doxygenfunction:: vk_instance_get_physical_device_proc_addr
148
149We also provide an implementation of
150``vkEnumerateInstanceExtensionProperties()`` which can be used similarly:
151
152.. code-block:: c
153
154   VKAPI_ATTR VkResult VKAPI_CALL
155   drv_EnumerateInstanceExtensionProperties(const char *pLayerName,
156                                            uint32_t *pPropertyCount,
157                                            VkExtensionProperties *pProperties)
158   {
159      if (pLayerName)
160         return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
161
162      return vk_enumerate_instance_extension_properties(
163         &instance_extensions, pPropertyCount, pProperties);
164   }
165
166.. doxygenfunction:: vk_enumerate_instance_extension_properties
167
168vk_physical_device
169------------------
170
171.. doxygenstruct:: vk_physical_device
172   :members:
173
174.. doxygenfunction:: vk_physical_device_init
175.. doxygenfunction:: vk_physical_device_finish
176
177vk_device
178------------------
179
180.. doxygenstruct:: vk_device
181   :members:
182
183.. doxygenfunction:: vk_device_init
184.. doxygenfunction:: vk_device_finish
185