Move back buffer rendering to a separate "present" command buffer

This commit is contained in:
Henrik Rydgård 2022-09-17 01:11:41 +02:00
parent 242efba6f7
commit 415a795b11
4 changed files with 38 additions and 13 deletions

View file

@ -376,7 +376,7 @@ void VulkanQueueRunner::PreprocessSteps(std::vector<VKRStep *> &steps) {
} }
} }
void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &steps, QueueProfileContext *profile) { void VulkanQueueRunner::RunSteps(VkCommandBuffer mainCmd, VkCommandBuffer presentCmd, bool *hasPresentCommands, std::vector<VKRStep *> &steps, QueueProfileContext *profile) {
if (profile) if (profile)
profile->cpuStartTime = time_now_d(); profile->cpuStartTime = time_now_d();
@ -388,36 +388,47 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &st
if (emitLabels) { if (emitLabels) {
VkDebugUtilsLabelEXT labelInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; VkDebugUtilsLabelEXT labelInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT };
labelInfo.pLabelName = step.tag; labelInfo.pLabelName = step.tag;
vkCmdBeginDebugUtilsLabelEXT(cmd, &labelInfo); vkCmdBeginDebugUtilsLabelEXT(mainCmd, &labelInfo);
} }
switch (step.stepType) { switch (step.stepType) {
case VKRStepType::RENDER: case VKRStepType::RENDER:
PerformRenderPass(step, cmd); if (!step.render.framebuffer) {
_dbg_assert_(!*hasPresentCommands);
if (!*hasPresentCommands) {
*hasPresentCommands = true;
VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(presentCmd, &begin);
}
PerformRenderPass(step, presentCmd);
} else {
PerformRenderPass(step, mainCmd);
}
break; break;
case VKRStepType::COPY: case VKRStepType::COPY:
PerformCopy(step, cmd); PerformCopy(step, mainCmd);
break; break;
case VKRStepType::BLIT: case VKRStepType::BLIT:
PerformBlit(step, cmd); PerformBlit(step, mainCmd);
break; break;
case VKRStepType::READBACK: case VKRStepType::READBACK:
PerformReadback(step, cmd); PerformReadback(step, mainCmd);
break; break;
case VKRStepType::READBACK_IMAGE: case VKRStepType::READBACK_IMAGE:
PerformReadbackImage(step, cmd); PerformReadbackImage(step, mainCmd);
break; break;
case VKRStepType::RENDER_SKIP: case VKRStepType::RENDER_SKIP:
break; break;
} }
if (profile && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) { if (profile && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) {
vkCmdWriteTimestamp(cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, profile->queryPool, (uint32_t)profile->timestampDescriptions.size()); vkCmdWriteTimestamp(mainCmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, profile->queryPool, (uint32_t)profile->timestampDescriptions.size());
profile->timestampDescriptions.push_back(StepToString(step)); profile->timestampDescriptions.push_back(StepToString(step));
} }
if (emitLabels) { if (emitLabels) {
vkCmdEndDebugUtilsLabelEXT(cmd); vkCmdEndDebugUtilsLabelEXT(mainCmd);
} }
} }

View file

@ -257,7 +257,7 @@ public:
} }
void PreprocessSteps(std::vector<VKRStep *> &steps); void PreprocessSteps(std::vector<VKRStep *> &steps);
void RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &steps, QueueProfileContext *profile); void RunSteps(VkCommandBuffer cmd, VkCommandBuffer presentCmd, bool *hasPresentCommands, std::vector<VKRStep *> &steps, QueueProfileContext *profile);
void LogSteps(const std::vector<VKRStep *> &steps, bool verbose); void LogSteps(const std::vector<VKRStep *> &steps, bool verbose);
std::string StepToString(const VKRStep &step) const; std::string StepToString(const VKRStep &step) const;

View file

@ -309,11 +309,11 @@ VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan
cmd_alloc.commandPool = frameData_[i].cmdPoolInit; cmd_alloc.commandPool = frameData_[i].cmdPoolInit;
cmd_alloc.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cmd_alloc.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cmd_alloc.commandBufferCount = 1; cmd_alloc.commandBufferCount = 1;
res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].initCmd); res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].initCmd);
_dbg_assert_(res == VK_SUCCESS); _dbg_assert_(res == VK_SUCCESS);
cmd_alloc.commandPool = frameData_[i].cmdPoolMain; cmd_alloc.commandPool = frameData_[i].cmdPoolMain;
res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].mainCmd); res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].mainCmd);
res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].presentCmd);
_dbg_assert_(res == VK_SUCCESS); _dbg_assert_(res == VK_SUCCESS);
// Creating the frame fence with true so they can be instantly waited on the first frame // Creating the frame fence with true so they can be instantly waited on the first frame
@ -1481,14 +1481,22 @@ void VulkanRenderManager::Submit(int frame, bool triggerFrameFence) {
VkResult res = vkEndCommandBuffer(frameData.mainCmd); VkResult res = vkEndCommandBuffer(frameData.mainCmd);
_assert_msg_(res == VK_SUCCESS, "vkEndCommandBuffer failed (main)! result=%s", VulkanResultToString(res)); _assert_msg_(res == VK_SUCCESS, "vkEndCommandBuffer failed (main)! result=%s", VulkanResultToString(res));
if (frameData.hasPresentCommands) {
VkResult res = vkEndCommandBuffer(frameData.presentCmd);
_assert_msg_(res == VK_SUCCESS, "vkEndCommandBuffer failed (present)! result=%s", VulkanResultToString(res));
}
SubmitInitCommands(frame); SubmitInitCommands(frame);
// Submit the main and final cmdbuf, ending by signalling the fence. // Submit the main and final cmdbuf, ending by signalling the fence.
VkCommandBuffer cmdBufs[1]; VkCommandBuffer cmdBufs[2];
int numCmdBufs = 0; int numCmdBufs = 0;
cmdBufs[numCmdBufs++] = frameData.mainCmd; cmdBufs[numCmdBufs++] = frameData.mainCmd;
if (frameData.hasPresentCommands) {
cmdBufs[numCmdBufs++] = frameData.presentCmd;
}
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
VkPipelineStageFlags waitStage[1]{ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags waitStage[1]{ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
@ -1519,6 +1527,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFrameFence) {
} }
frameData.hasInitCommands = false; frameData.hasInitCommands = false;
frameData.hasPresentCommands = false;
} }
void VulkanRenderManager::EndSubmitFrame(int frame) { void VulkanRenderManager::EndSubmitFrame(int frame) {
@ -1564,7 +1573,7 @@ void VulkanRenderManager::Run(int frame) {
VkCommandBuffer cmd = frameData.mainCmd; VkCommandBuffer cmd = frameData.mainCmd;
queueRunner_.PreprocessSteps(stepsOnThread); queueRunner_.PreprocessSteps(stepsOnThread);
//queueRunner_.LogSteps(stepsOnThread, false); //queueRunner_.LogSteps(stepsOnThread, false);
queueRunner_.RunSteps(cmd, stepsOnThread, frameData.profilingEnabled_ ? &frameData.profile : nullptr); queueRunner_.RunSteps(cmd, frameData.presentCmd, &frameData.hasPresentCommands, stepsOnThread, frameData.profilingEnabled_ ? &frameData.profile : nullptr);
stepsOnThread.clear(); stepsOnThread.clear();
switch (frameData.type) { switch (frameData.type) {
@ -1586,6 +1595,7 @@ void VulkanRenderManager::Run(int frame) {
void VulkanRenderManager::EndSyncFrame(int frame) { void VulkanRenderManager::EndSyncFrame(int frame) {
FrameData &frameData = frameData_[frame]; FrameData &frameData = frameData_[frame];
_dbg_assert_(!frameData.hasPresentCommands);
frameData.readbackFenceUsed = true; frameData.readbackFenceUsed = true;
// The submit will trigger the readbackFence. // The submit will trigger the readbackFence.

View file

@ -507,10 +507,14 @@ private:
// These are on different threads so need separate pools. // These are on different threads so need separate pools.
VkCommandPool cmdPoolInit; // Written to from main thread VkCommandPool cmdPoolInit; // Written to from main thread
VkCommandPool cmdPoolMain; // Written to from render thread, which also submits VkCommandPool cmdPoolMain; // Written to from render thread, which also submits
VkCommandBuffer initCmd; VkCommandBuffer initCmd;
VkCommandBuffer mainCmd; VkCommandBuffer mainCmd;
VkCommandBuffer presentCmd;
bool hasInitCommands = false; bool hasInitCommands = false;
bool hasPresentCommands = false;
std::vector<VKRStep *> steps; std::vector<VKRStep *> steps;
// Swapchain. // Swapchain.