diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index ba6170581..4d71fec1c 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -549,12 +549,22 @@ namespace dxvk { if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { attachments.color[0].view = imageView; attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + ops.barrier.srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; ops.colorOps[0] = colorOp; } else { attachments.depth.view = imageView; attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + ops.barrier.srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + ops.barrier.srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; ops.depthOps = depthOp; } + + ops.barrier.dstStages = imageView->imageInfo().stages; + ops.barrier.dstAccess = imageView->imageInfo().access; this->renderPassBindFramebuffer( m_device->createFramebuffer(attachments), @@ -1762,6 +1772,10 @@ namespace dxvk { attachments.color[0].view = imageView; attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + ops.barrier.srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + ops.colorOps[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; ops.colorOps[0].loadLayout = imageView->imageInfo().layout; ops.colorOps[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -1770,6 +1784,11 @@ namespace dxvk { attachments.depth.view = imageView; attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + ops.barrier.srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + ops.depthOps.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD; ops.depthOps.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD; ops.depthOps.loadLayout = imageView->imageInfo().layout; @@ -1778,6 +1797,9 @@ namespace dxvk { ops.depthOps.storeLayout = imageView->imageInfo().layout; } + ops.barrier.dstStages = imageView->imageInfo().stages; + ops.barrier.dstAccess = imageView->imageInfo().access; + // We cannot leverage render pass clears // because we clear only part of the view this->renderPassBindFramebuffer( @@ -2435,6 +2457,25 @@ namespace dxvk { void DxvkContext::resetRenderPassOps( const DxvkRenderTargets& renderTargets, DxvkRenderPassOps& renderPassOps) { + renderPassOps.barrier.srcStages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + renderPassOps.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT + | VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + | VK_ACCESS_INDEX_READ_BIT + | VK_ACCESS_UNIFORM_READ_BIT + | VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + renderPassOps.barrier.dstStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + renderPassOps.barrier.dstAccess = renderPassOps.barrier.srcAccess + | VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + renderPassOps.depthOps = renderTargets.depth.view != nullptr ? DxvkDepthAttachmentOps { VK_ATTACHMENT_LOAD_OP_LOAD, diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 075b761d3..bdab8bbed 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -121,44 +121,39 @@ namespace dxvk { if (m_format.depth.format == VK_FORMAT_UNDEFINED) subpass.pDepthStencilAttachment = nullptr; - const std::array subpassDeps = {{ - { VK_SUBPASS_EXTERNAL, 0, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - 0, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 0 }, - { 0, 0, + std::array subpassDeps; + uint32_t subpassDepCount = 0; + + if (ops.barrier.srcStages & ( + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT | + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { + subpassDeps[subpassDepCount++] = { 0, 0, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */ VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }, - { 0, 0, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }; + } + + if (ops.barrier.srcStages & ( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { + subpassDeps[subpassDepCount++] = { 0, 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, 0 }, - { 0, VK_SUBPASS_EXTERNAL, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | - VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT | - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT | - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_HOST_READ_BIT | - VK_ACCESS_INDEX_READ_BIT | - VK_ACCESS_INDIRECT_COMMAND_READ_BIT | - VK_ACCESS_SHADER_READ_BIT | - VK_ACCESS_TRANSFER_READ_BIT | - VK_ACCESS_UNIFORM_READ_BIT | - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }, - }}; + VK_ACCESS_SHADER_READ_BIT, 0 }; + } + + if (ops.barrier.srcStages && ops.barrier.dstStages) { + subpassDeps[subpassDepCount++] = { + 0, VK_SUBPASS_EXTERNAL, + ops.barrier.srcStages, + ops.barrier.dstStages, + ops.barrier.srcAccess, + ops.barrier.dstAccess, 0 }; + } VkRenderPassCreateInfo info; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; @@ -168,8 +163,8 @@ namespace dxvk { info.pAttachments = attachments.data(); info.subpassCount = 1; info.pSubpasses = &subpass; - info.dependencyCount = subpassDeps.size(); - info.pDependencies = subpassDeps.data(); + info.dependencyCount = subpassDepCount; + info.pDependencies = subpassDepCount ? subpassDeps.data() : nullptr; VkRenderPass renderPass = VK_NULL_HANDLE; @@ -185,12 +180,19 @@ namespace dxvk { bool DxvkRenderPass::compareOps( const DxvkRenderPassOps& a, const DxvkRenderPassOps& b) { - bool eq = a.depthOps.loadOpD == b.depthOps.loadOpD - && a.depthOps.loadOpS == b.depthOps.loadOpS - && a.depthOps.loadLayout == b.depthOps.loadLayout - && a.depthOps.storeOpD == b.depthOps.storeOpD - && a.depthOps.storeOpS == b.depthOps.storeOpS - && a.depthOps.storeLayout == b.depthOps.storeLayout; + bool eq = a.barrier.srcStages == b.barrier.srcStages + && a.barrier.srcAccess == b.barrier.srcAccess + && a.barrier.dstStages == b.barrier.dstStages + && a.barrier.dstAccess == b.barrier.dstAccess; + + if (eq) { + eq &= a.depthOps.loadOpD == b.depthOps.loadOpD + && a.depthOps.loadOpS == b.depthOps.loadOpS + && a.depthOps.loadLayout == b.depthOps.loadLayout + && a.depthOps.storeOpD == b.depthOps.storeOpD + && a.depthOps.storeOpS == b.depthOps.storeOpS + && a.depthOps.storeLayout == b.depthOps.storeLayout; + } for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index 64b91f5b9..8c154098a 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -66,6 +66,20 @@ namespace dxvk { }; + /** + * \brief Render pass barrier + * + * External subpass dependency that is to be + * executed after a render pass has completed. + */ + struct DxvkRenderPassBarrier { + VkPipelineStageFlags srcStages = 0; + VkAccessFlags srcAccess = 0; + VkPipelineStageFlags dstStages = 0; + VkAccessFlags dstAccess = 0; + }; + + /** * \brief Render pass transitions * @@ -74,6 +88,7 @@ namespace dxvk { * from a group of render passes with the same format. */ struct DxvkRenderPassOps { + DxvkRenderPassBarrier barrier; DxvkDepthAttachmentOps depthOps; DxvkColorAttachmentOps colorOps[MaxNumRenderTargets]; };