xref: /aosp_15_r20/external/mesa3d/docs/vulkan/base-objs.rst (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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