Merge framebuffer layout pre-transitions into render pass subpass dependencies.

With this, drivers should be able to completely get rid of layout
transitions into render passes that use CLEAR, at least.
This commit is contained in:
Henrik Rydgård committed 2018-03-18 09:55:36 +01:00
1 parent 33a1e6a080
commit f43935b030
3 files changed
+70 -67

No files matched your search

+62 -64
View File
@@ -150,8 +150,8 @@ void VulkanQueueRunner::InitBackbufferRenderPass() {
assert(res == VK_SUCCESS);
}
VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) {
RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction };
VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout) {
RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction, prevColorLayout, prevDepthLayout };
auto pass = renderPasses_.Get(key);
if (pass) {
return pass;
@@ -179,7 +179,7 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio
attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate.
#else
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[0].initialLayout = prevColorLayout;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: Look into auto-transitioning to SAMPLED when appropriate.
#endif
attachments[0].flags = 0;
@@ -214,7 +214,7 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio
attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
#else
attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[1].initialLayout = prevDepthLayout;
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
#endif
attachments[1].flags = 0;
@@ -239,12 +239,65 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
VkSubpassDependency dep{};
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
dep.dstSubpass = 0;
dep.dependencyFlags = 0;
switch (prevColorLayout) {
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
// Already the right color layout. Unclear that we need to do a lot here..
break;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
default:
_dbg_assert_msg_(G3D, false, "GetRenderPass: Unexpected color layout %d", (int)prevColorLayout);
break;
}
switch (prevDepthLayout) {
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
// Already the right depth layout. Unclear that we need to do a lot here..
break;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
dep.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT;
dep.srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
default:
_dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)prevDepthLayout);
break;
}
dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo rp{ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
rp.attachmentCount = 2;
rp.pAttachments = attachments;
rp.subpassCount = 1;
rp.pSubpasses = &subpass;
rp.dependencyCount = 0;
if (dep.srcAccessMask) {
rp.dependencyCount = 1;
rp.pDependencies = &dep;
}
VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp, nullptr, &pass);
_assert_(res == VK_SUCCESS);
@@ -605,67 +658,12 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
framebuf = fb->framebuf;
w = fb->width;
h = fb->height;
// Now, if the image needs transitioning, let's transition.
// The backbuffer does not, that's handled by VulkanContext.
if (step.render.framebuffer->color.layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
VkAccessFlags srcAccessMask = 0;
VkPipelineStageFlags srcStage = 0;
switch (fb->color.layout) {
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
default:
_dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected color layout %d", (int)fb->color.layout);
break;
}
// Due to a known bug in the Mali driver, pass the level count explicitly.
TransitionImageLayout2(cmd, fb->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
fb->color.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
srcStage, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
if (fb->depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
VkAccessFlags srcAccessMask = 0;
VkPipelineStageFlags srcStage = 0;
renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil, fb->color.layout, fb->depth.layout);
// We now do any layout pretransitions as part of the render pass.
fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
switch (fb->depth.layout) {
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
default:
_dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)fb->color.layout);
break;
}
// Due to a known bug in the Mali driver, pass the level count explicitly (last param).
TransitionImageLayout2(cmd, fb->depth.image, 0, 1, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
fb->depth.layout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
srcStage, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
srcAccessMask, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil);
if (step.render.color == VKRRenderPassAction::CLEAR) {
Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor);
numClearVals = 1;
+4 -1
View File
@@ -161,7 +161,8 @@ public:
VkRenderPass GetBackbufferRenderPass() const {
return backbufferRenderPass_;
}
VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction);
VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction,
VkImageLayout prevColorLayout, VkImageLayout prevDepthLayout);
inline int RPIndex(VKRRenderPassAction color, VKRRenderPassAction depth) {
return (int)depth * 3 + (int)color;
@@ -202,6 +203,8 @@ private:
VKRRenderPassAction colorAction;
VKRRenderPassAction depthAction;
VKRRenderPassAction stencilAction;
VkImageLayout prevColorLayout;
VkImageLayout prevDepthLayout;
};
// Renderpasses, all combinations of preserving or clearing or dont-care-ing fb contents.
+4 -2
View File
@@ -205,14 +205,16 @@ public:
VkCommandBuffer GetInitCmd();
VkRenderPass GetRenderPass(VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) {
return queueRunner_.GetRenderPass(colorLoadAction, depthLoadAction, stencilLoadAction);
return queueRunner_.GetRenderPass(colorLoadAction, depthLoadAction, stencilLoadAction,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
VkRenderPass GetBackbufferRenderPass() {
return queueRunner_.GetBackbufferRenderPass();
}
VkRenderPass GetCompatibleRenderPass() {
if (curRenderStep_ && curRenderStep_->render.framebuffer != nullptr) {
return queueRunner_.GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR);
return queueRunner_.GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} else {
return queueRunner_.GetBackbufferRenderPass();
}