@@ -34,17 +34,16 @@ class CommandBufferManager
// is submitted, after that you should call these functions again.
VkCommandBuffer GetCurrentInitCommandBuffer ()
{
m_frame_resources[m_current_frame].init_command_buffer_used = true ;
return m_frame_resources[m_current_frame].command_buffers [0 ];
CmdBufferResources& cmd_buffer_resources = GetCurrentCmdBufferResources ();
cmd_buffer_resources.init_command_buffer_used = true ;
return cmd_buffer_resources.command_buffers [0 ];
}
VkCommandBuffer GetCurrentCommandBuffer () const
{
return m_frame_resources[m_current_frame].command_buffers [1 ];
}
VkDescriptorPool GetCurrentDescriptorPool () const
{
return m_frame_resources[m_current_frame].descriptor_pool ;
const CmdBufferResources& cmd_buffer_resources = m_command_buffers[m_current_cmd_buffer];
return cmd_buffer_resources.command_buffers [1 ];
}
VkDescriptorPool GetCurrentDescriptorPool () const { return m_descriptor_pools[m_current_frame]; }
// Allocates a descriptors set from the pool reserved for the current frame.
VkDescriptorSet AllocateDescriptorSet (VkDescriptorSetLayout set_layout);
@@ -56,14 +55,19 @@ class CommandBufferManager
// Gets the fence that will be signaled when the currently executing command buffer is
// queued and executed. Do not wait for this fence before the buffer is executed.
u64 GetCurrentFenceCounter () const { return m_frame_resources[m_current_frame].fence_counter ; }
u64 GetCurrentFenceCounter () const
{
auto & resources = m_command_buffers[m_current_cmd_buffer];
return resources.fence_counter ;
}
// Returns the semaphore for the current command buffer, which can be used to ensure the
// swap chain image is ready before the command buffer executes.
VkSemaphore GetCurrentCommandBufferSemaphore ()
{
m_frame_resources[m_current_frame].semaphore_used = true ;
return m_frame_resources[m_current_frame].semaphore ;
auto & resources = m_command_buffers[m_current_cmd_buffer];
resources.semaphore_used = true ;
return resources.semaphore ;
}
// Ensure that the worker thread has submitted any previous command buffers and is idle.
@@ -101,30 +105,35 @@ class CommandBufferManager
u32 present_image_index);
void BeginCommandBuffer ();
struct FrameResources
struct CmdBufferResources
{
// [0] - Init (upload) command buffer, [1] - draw command buffer
VkCommandPool command_pool = VK_NULL_HANDLE;
std::array<VkCommandBuffer, 2 > command_buffers = {};
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
VkFence fence = VK_NULL_HANDLE;
VkSemaphore semaphore = VK_NULL_HANDLE;
u64 fence_counter = 0 ;
bool init_command_buffer_used = false ;
bool semaphore_used = false ;
u32 frame_index = 0 ;
std::vector<std::function<void ()>> cleanup_resources;
};
CmdBufferResources& GetCurrentCmdBufferResources ()
{
return m_command_buffers[m_current_cmd_buffer];
}
u64 m_next_fence_counter = 1 ;
u64 m_completed_fence_counter = 0 ;
std::array<FrameResources, NUM_COMMAND_BUFFERS> m_frame_resources;
std::array<VkDescriptorPool, NUM_FRAMES_IN_FLIGHT> m_descriptor_pools;
std::array<CmdBufferResources, NUM_COMMAND_BUFFERS> m_command_buffers;
u32 m_current_frame = 0 ;
u32 m_current_cmd_buffer = 0 ;
// Threaded command buffer execution
// Semaphore determines when a command buffer can be queued
Common::Semaphore m_submit_semaphore;
std::thread m_submit_thread;
std::unique_ptr<Common::BlockingLoop> m_submit_loop;
struct PendingCommandBufferSubmit
@@ -136,6 +145,8 @@ class CommandBufferManager
VkSemaphore m_present_semaphore = VK_NULL_HANDLE;
std::deque<PendingCommandBufferSubmit> m_pending_submits;
std::mutex m_pending_submit_lock;
std::condition_variable m_submit_worker_condvar;
bool m_submit_worker_idle = true ;
Common::Flag m_last_present_failed;
VkResult m_last_present_result = VK_SUCCESS;
bool m_use_threaded_submission = false ;