Mesa (main): vulkan,docs: Document vk_object_base

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 7 16:53:49 UTC 2022


Module: Mesa
Branch: main
Commit: f06fa8f7e0df525fc38135e3717f257d0ab39f68
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f06fa8f7e0df525fc38135e3717f257d0ab39f68

Author: Jason Ekstrand <jason.ekstrand at collabora.com>
Date:   Fri Mar 18 17:31:35 2022 -0500

vulkan,docs: Document vk_object_base

Acked-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15472>

---

 docs/vulkan/base-objs.rst      | 83 ++++++++++++++++++++++++++++++++++++++++++
 docs/vulkan/index.rst          |  1 +
 src/vulkan/runtime/vk_device.h | 17 +++++++++
 src/vulkan/runtime/vk_object.h | 75 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+)

diff --git a/docs/vulkan/base-objs.rst b/docs/vulkan/base-objs.rst
new file mode 100644
index 00000000000..fbad2b25282
--- /dev/null
+++ b/docs/vulkan/base-objs.rst
@@ -0,0 +1,83 @@
+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:
+
+.. contents::
+   :local:
+
+
+vk_object_base
+--------------
+
+The root base struct for all Vulkan objects is
+:cpp:struct:`vk_object_base`.  Every object exposed to the client through
+the Vulkan API *must* inherit from :cpp:struct:`vk_object_base` by having a
+:cpp:struct:`vk_object_base` or some struct that inherits from
+:cpp:struct:`vk_object_base` as the driver struct's first member.  Even
+though we have `container_of()` and use it liberally, the
+:cpp:struct:`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 :cpp:struct:`vk_object_base`.
+
+The standard pattern for defining a Vulkan object inside a driver looks
+something like this:
+
+.. code-block:: c
+
+   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,
+
+.. code-block:: c
+
+   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 :cpp:any:`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 :cpp:type:`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 :cpp:type:`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 :cpp:any:`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:: vk_object_base
+   :members:
+
+.. doxygenfunction:: vk_object_base_init
+.. doxygenfunction:: vk_object_base_finish
+
+.. doxygendefine:: VK_DEFINE_HANDLE_CASTS
+
+.. doxygendefine:: VK_DEFINE_NONDISP_HANDLE_CASTS
+
+.. doxygendefine:: VK_FROM_HANDLE
diff --git a/docs/vulkan/index.rst b/docs/vulkan/index.rst
index 58e387d6f97..b0993ffce5e 100644
--- a/docs/vulkan/index.rst
+++ b/docs/vulkan/index.rst
@@ -9,4 +9,5 @@ hardware-agnostic bits in common code.
 .. toctree::
    :maxdepth: 2
 
+   base-objs
    renderpass
diff --git a/src/vulkan/runtime/vk_device.h b/src/vulkan/runtime/vk_device.h
index 166cf1e9ce0..d1dc154ac8c 100644
--- a/src/vulkan/runtime/vk_device.h
+++ b/src/vulkan/runtime/vk_device.h
@@ -86,13 +86,24 @@ enum vk_queue_submit_mode {
    VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND,
 };
 
+/** Base struct for VkDevice */
 struct vk_device {
    struct vk_object_base base;
+
+   /** Allocator used to create this device
+    *
+    * This is used as a fall-back for when a NULL pAllocator is passed into a
+    * device-level create function such as vkCreateImage().
+    */
    VkAllocationCallbacks alloc;
+
+   /** Pointer to the physical device */
    struct vk_physical_device *physical;
 
+   /** Table of enabled extensions */
    struct vk_device_extension_table enabled_extensions;
 
+   /** Device-level dispatch table */
    struct vk_device_dispatch_table dispatch_table;
 
    /** Command dispatch table
@@ -228,6 +239,12 @@ struct vk_device {
       VK_DEVICE_TIMELINE_MODE_NATIVE,
    } timeline_mode;
 
+   /** Per-device submit mode
+    *
+    * This represents the device-wide submit strategy which may be different
+    * from the per-queue submit mode.  See vk_queue.submit.mode for more
+    * details.
+    */
    enum vk_queue_submit_mode submit_mode;
 
 #ifdef ANDROID
diff --git a/src/vulkan/runtime/vk_object.h b/src/vulkan/runtime/vk_object.h
index e8b3483976c..63d55f954f3 100644
--- a/src/vulkan/runtime/vk_object.h
+++ b/src/vulkan/runtime/vk_object.h
@@ -38,10 +38,23 @@ struct hash_table;
 
 struct vk_device;
 
+/** Base struct for all Vulkan objects */
 struct vk_object_base {
    VK_LOADER_DATA _loader_data;
+
+   /** Type of this object
+    *
+    * This is used for runtime type checking when casting to and from Vulkan
+    * handle types since compile-time type checking doesn't always work.
+    */
    VkObjectType type;
 
+   /** Pointer to the device in which this object exists, if any
+    *
+    * This is NULL for instances and physical devices but should point to a
+    * valid vk_device for almost everything else.  (There are a few WSI
+    * objects that don't inherit from a device.)
+    */
    struct vk_device *device;
 
    /* True if this object is fully constructed and visible to the client */
@@ -54,9 +67,20 @@ struct vk_object_base {
    char *object_name;
 };
 
+/** Initialize a vk_base_object
+ *
+ * @param[in]  device   The vk_device this object was created from or NULL
+ * @param[out] base     The vk_object_base to initialize
+ * @param[in]  obj_type The VkObjectType of the object being initialized
+ */
 void vk_object_base_init(struct vk_device *device,
                          struct vk_object_base *base,
                          VkObjectType obj_type);
+
+/** Tear down a vk_object_base
+ *
+ * @param[out] base     The vk_object_base being torn down
+ */
 void vk_object_base_finish(struct vk_object_base *base);
 
 static inline void
@@ -74,6 +98,26 @@ vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
    return base;
 }
 
+/** Define handle cast macros for the given dispatchable handle type
+ *
+ * For a given `driver_struct`, this defines `driver_struct_to_handle()` and
+ * `driver_struct_from_handle()` helpers which provide type-safe (as much as
+ * possible with Vulkan handle types) casts to and from the `driver_struct`
+ * type.  As an added layer of protection, these casts use the provided
+ * `VkObjectType` to assert that the object is of the correct type when
+ * running with a debug build.
+ *
+ * @param __driver_type The name of the driver struct; it is assumed this is
+ *                      the name of a struct type and `struct` will be
+ *                      prepended automatically
+ *
+ * @param __base        The name of the vk_base_object member
+ *
+ * @param __VkType      The Vulkan object type such as VkImage
+ *
+ * @param __VK_TYPE     The VkObjectType corresponding to __VkType, such as
+ *                      VK_OBJECT_TYPE_IMAGE
+ */
 #define VK_DEFINE_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
    static inline struct __driver_type *                                    \
    __driver_type ## _from_handle(__VkType _handle)                         \
@@ -93,6 +137,26 @@ vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
       return (__VkType) _obj;                                              \
    }
 
+/** Define handle cast macros for the given non-dispatchable handle type
+ *
+ * For a given `driver_struct`, this defines `driver_struct_to_handle()` and
+ * `driver_struct_from_handle()` helpers which provide type-safe (as much as
+ * possible with Vulkan handle types) casts to and from the `driver_struct`
+ * type.  As an added layer of protection, these casts use the provided
+ * `VkObjectType` to assert that the object is of the correct type when
+ * running with a debug build.
+ *
+ * @param __driver_type The name of the driver struct; it is assumed this is
+ *                      the name of a struct type and `struct` will be
+ *                      prepended automatically
+ *
+ * @param __base        The name of the vk_base_object member
+ *
+ * @param __VkType      The Vulkan object type such as VkImage
+ *
+ * @param __VK_TYPE     The VkObjectType corresponding to __VkType, such as
+ *                      VK_OBJECT_TYPE_IMAGE
+ */
 #define VK_DEFINE_NONDISP_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
    static inline struct __driver_type *                                    \
    __driver_type ## _from_handle(__VkType _handle)                         \
@@ -113,6 +177,17 @@ vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
       return (__VkType)(uintptr_t) _obj;                                   \
    }
 
+/** Declares a __driver_type pointer which represents __handle
+ *
+ * @param __driver_type The name of the driver struct; it is assumed this is
+ *                      the name of a struct type and `struct` will be
+ *                      prepended automatically
+ *
+ * @param __name        The name of the declared pointer
+ *
+ * @param __handle      The Vulkan object handle with which to initialize
+ *                      `__name`
+ */
 #define VK_FROM_HANDLE(__driver_type, __name, __handle) \
    struct __driver_type *__name = __driver_type ## _from_handle(__handle)
 



More information about the mesa-commit mailing list