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.
doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygendefine: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
vk_instance¶
doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
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.
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
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);
}
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
vk_physical_device¶
doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
vk_device¶
doxygenstruct: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml
doxygenfunction: Cannot find file: /home/user/documentation/docs/mesa/repository/docs/doxygen_xml/index.xml