diff --git a/docs/vulkan/command-pools.rst b/docs/vulkan/command-pools.rst new file mode 100644 index 00000000000..da47059ece8 --- /dev/null +++ b/docs/vulkan/command-pools.rst @@ -0,0 +1,78 @@ +Command Pools +============= + +The Vulkan runtime code provides a common ``VkCommandPool`` implementation +which makes managing the lifetimes of command buffers and recycling their +internal state easier. To use the common command pool a driver needs to +fill out a :cpp:struct:`vk_command_buffer_ops` struct and set the +``command_buffer_ops`` field of :cpp:struct:`vk_device`. + +.. doxygenstruct:: vk_command_buffer_ops + :members: + +By reducing the entirety of command buffer lifetime management to these +three functions, much of the complexity of command pools can be implemented +in common code, providing better, more consistent behavior across Mesa. + + +Command Buffer Recycling +------------------------ + +The common command pool provides automatic command buffer recycling as long +as the driver uses the common ``vkAllocateCommandBuffers()`` and +``vkFreeCommandBuffers()`` implementations. The driver must also provide the +``reset`` function pointer in :cpp:struct:`vk_command_buffer_ops`. + +With the common command buffer pool, when the client calls +``vkFreeCommandBuffers()``, the command buffers are not immediately freed. +Instead, they are reset with +``VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT``, their base object is +recycled, and they are added to a free list inside the pool. When the +client then calls ``vkAllocateCommandBuffers()``, we check the free list +and return a recycled command buffer, if any are available. This provides +some basic command buffer pooling without the driver doing any additional +work. + + +Custom command pools +-------------------- + +If a driver wishes to recycle at a finer granularity than whole command +buffers, they can do so by providing their own command pool implementation +which wraps :cpp:struct:`vk_command_pool`. The common use-case here is if +the driver wants to pool command-buffer-internal objects at a finer +granularity than whole command buffers. The command pool provides a place +where things like GPU command buffers or upload buffers can be cached +without having to take a lock. + +When implementing a custom command pool, drivers need only implement three +entrypoints: + + - ``vkCreateCommandPool()`` + - ``vkDestroyCommandPool()`` + - ``vkTrimCommandPool()`` + +All of the other entrypoints will be handled by common code so long as the +driver's command pool derives from :cpp:struct:`vk_command_pool`. + +The driver implementation of the command buffer ``recycle()`` function +should respect ``VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT`` and, when +set, return any recyclable resources to the command pool. This may be set +by the client when it calls ``vkResetCommandBuffer()``, come from a +whole-pool reset via ``VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT``, or +come from the common command buffer code when a command buffer is recycled. + +The driver's implementation of ``vkTrimCommandPool()`` should free any +resources that have been cached within the command pool back to the device +or back to the OS. It **must** also call :cpp:func:`vk_command_pool_trim` +to allow the common code to free any recycled command buffers. + +Reference +--------- + +.. doxygenstruct:: vk_command_pool + :members: + +.. doxygenfunction:: vk_command_pool_init +.. doxygenfunction:: vk_command_pool_finish +.. doxygenfunction:: vk_command_pool_trim diff --git a/docs/vulkan/index.rst b/docs/vulkan/index.rst index 8562261135f..5aa24d67ee9 100644 --- a/docs/vulkan/index.rst +++ b/docs/vulkan/index.rst @@ -11,5 +11,6 @@ hardware-agnostic bits in common code. base-objs dispatch + command-pools graphics-state renderpass diff --git a/src/vulkan/runtime/vk_command_pool.h b/src/vulkan/runtime/vk_command_pool.h index a3ea03384e8..a4d66d768d2 100644 --- a/src/vulkan/runtime/vk_command_pool.h +++ b/src/vulkan/runtime/vk_command_pool.h @@ -31,6 +31,7 @@ extern "C" { #endif +/** Base object for implementin VkCommandPool */ struct vk_command_pool { struct vk_object_base base; @@ -57,17 +58,41 @@ struct vk_command_pool { }; VK_DEFINE_NONDISP_HANDLE_CASTS(vk_command_pool, base, VkCommandPool, - VK_OBJECT_TYPE_COMMAND_POOL) + VK_OBJECT_TYPE_COMMAND_POOL); +/** Initialize a vk_command_pool + * + * @param[in] device The Vulkan device + * @param[out] pool The command pool to initialize + * @param[in] pCreateInfo VkCommandPoolCreateInfo pointer passed to + * `vkCreateCommandPool()` + * @param[in] pAllocator Allocation callbacks passed to + * `vkCreateCommandPool()` + */ VkResult MUST_CHECK vk_command_pool_init(struct vk_device *device, struct vk_command_pool *pool, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator); +/** Tear down a vk_command_pool + * + * @param[inout] pool The command pool to tear down + */ void vk_command_pool_finish(struct vk_command_pool *pool); +/** Trim a vk_command_pool + * + * This discards any resources that may be cached by the common + * vk_command_pool code. For driver-implemented command pools, drivers should + * call this function inside their `vkTrimCommandPool()` implementation. This + * should be called before doing any driver-specific trimming in case it ends + * up returning driver-internal resources to the pool. + * + * @param[inout] pool The command pool to trim + * @param[in] flags Flags controling the trim operation + */ void vk_command_pool_trim(struct vk_command_pool *pool, VkCommandPoolTrimFlags flags);