diff --git a/filament/backend/src/vulkan/VulkanCommands.cpp b/filament/backend/src/vulkan/VulkanCommands.cpp index 9328602c22..bb10985a8e 100644 --- a/filament/backend/src/vulkan/VulkanCommands.cpp +++ b/filament/backend/src/vulkan/VulkanCommands.cpp @@ -51,23 +51,31 @@ VulkanCmdFence::~VulkanCmdFence() { CommandBufferObserver::~CommandBufferObserver() {} -VulkanCommands::VulkanCommands(VkDevice device, uint32_t queueFamilyIndex) : mDevice(device) { - VkCommandPoolCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - createInfo.flags = - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - createInfo.queueFamilyIndex = queueFamilyIndex; - vkCreateCommandPool(device, &createInfo, VKALLOC, &mPool); - vkGetDeviceQueue(device, queueFamilyIndex, 0, &mQueue); +static VkQueue getQueue(VkDevice device, uint32_t queueFamilyIndex) { + VkQueue queue; + vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue); + return queue; +} +static VkCommandPool createPool(VkDevice device, uint32_t queueFamilyIndex) { + VkCommandPoolCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = queueFamilyIndex, + }; + VkCommandPool pool; + vkCreateCommandPool(device, &createInfo, VKALLOC, &pool); + return pool; + +} + +VulkanCommands::VulkanCommands(VkDevice device, uint32_t queueFamilyIndex) : mDevice(device), + mQueue(getQueue(device, queueFamilyIndex)), mPool(createPool(mDevice, queueFamilyIndex)) { VkSemaphoreCreateInfo sci { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; for (auto& semaphore : mSubmissionSignals) { vkCreateSemaphore(mDevice, &sci, nullptr, &semaphore); } - - for (uint32_t index = 0; index < VK_MAX_COMMAND_BUFFERS; ++index) { - mStorage[index].index = index; - } } VulkanCommands::~VulkanCommands() { diff --git a/filament/backend/src/vulkan/VulkanCommands.h b/filament/backend/src/vulkan/VulkanCommands.h index d55a6bbced..0e360eb64c 100644 --- a/filament/backend/src/vulkan/VulkanCommands.h +++ b/filament/backend/src/vulkan/VulkanCommands.h @@ -46,7 +46,6 @@ struct VulkanCommandBuffer { VulkanCommandBuffer& operator=(VulkanCommandBuffer const&) = delete; VkCommandBuffer cmdbuffer = VK_NULL_HANDLE; std::shared_ptr fence; - uint32_t index = 0; }; // Allows classes to be notified after a new command buffer has been activated. @@ -56,8 +55,32 @@ public: virtual ~CommandBufferObserver(); }; -// Lazily creates command buffers and manages a set of submitted command buffers. -// Submitted command buffers form a dependency chain using VkSemaphore. +// Manages a set of command buffers and semaphores, exposing an API that is significantly simpler +// than the raw Vulkan API. +// +// The manager's API primarily consists of get() and flush(). The "get" method acquires a fresh +// command buffer in the recording state, while the "flush" method releases a command buffer and +// changes its state from recording to executing. Some of the operational details are listed below. +// +// - Manages a dependency chain of submitted command buffers using VkSemaphore. +// - This creates a guarantee of in-order execution. +// - Semaphores are recycled to prevent create / destroy churn. +// +// - Notifies listeners when recording begins in a new VkCommandBuffer. +// - Used by PipelineCache so that it knows when to clear out its shadow state. +// +// - Allows 1 user to inject a "dependency" semaphore that stalls the next flush. +// - This is used for asynchronous acquisition of a swap chain image, since the GPU +// might require a valid swap chain image when it starts executing the command buffer. +// +// - Allows 1 user to listen to the most recent flush event using a "finished" VkSemaphore. +// - This is used to trigger presentation of the swap chain image. +// +// - Allows off-thread queries of command buffer status. +// - Exposes an "updateFences" method that transfers current fence status into atomics. +// - Users can examine these atomic variables (see VulkanCmdFence) to determine status. +// - We do this because vkGetFenceStatus must be called from the rendering thread. +// class VulkanCommands { public: VulkanCommands(VkDevice device, uint32_t queueFamilyIndex); @@ -95,8 +118,8 @@ class VulkanCommands { private: static constexpr int CAPACITY = VK_MAX_COMMAND_BUFFERS; const VkDevice mDevice; - VkQueue mQueue; - VkCommandPool mPool; + const VkQueue mQueue; + const VkCommandPool mPool; VulkanCommandBuffer* mCurrent = nullptr; VkSemaphore mSubmissionSignal = {}; VkSemaphore mInjectedSignal = {};