Move back buffer rendering to a separate "present" command buffer
This commit is contained in:
parent
242efba6f7
commit
415a795b11
4 changed files with 38 additions and 13 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue