From 0900dfd0e3b7dee0a422411de2d1fb2b2c3fbe3c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 22 Jan 2018 19:21:46 +0100 Subject: [PATCH] [dxvk] Removed explicit image barriers for render passes Instead, the color format and layout will now be set in the render pass description. This slows down render pass lookups but may improve efficiency and work around driver bugs. --- src/dxvk/dxvk_context.cpp | 99 ----------------------------------- src/dxvk/dxvk_context.h | 6 --- src/dxvk/dxvk_framebuffer.cpp | 10 +++- src/dxvk/dxvk_renderpass.cpp | 96 ++++++++++++++++++++++++++------- src/dxvk/dxvk_renderpass.h | 34 ++++++++---- src/dxvk/dxvk_swapchain.cpp | 6 ++- 6 files changed, 114 insertions(+), 137 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index d931b400..f9e7f5a8 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1108,9 +1108,6 @@ namespace dxvk { && (m_state.om.framebuffer != nullptr)) { m_flags.set(DxvkContextFlag::GpRenderPassBound); - this->transformLayoutsRenderPassBegin( - m_state.om.framebuffer->renderTargets()); - const DxvkFramebufferSize fbSize = m_state.om.framebuffer->size(); @@ -1139,9 +1136,6 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { m_flags.clr(DxvkContextFlag::GpRenderPassBound); m_cmd->cmdEndRenderPass(); - - this->transformLayoutsRenderPassEnd( - m_state.om.framebuffer->renderTargets()); } } @@ -1493,97 +1487,4 @@ namespace dxvk { m_barriers.recordCommands(m_cmd); } - - void DxvkContext::transformLayoutsRenderPassBegin( - const DxvkRenderTargets& renderTargets) { - // Ensure that all color attachments are in the optimal layout. - // Any image that is used as a present source requires special - // care as we cannot use it for reading. - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - const Rc target = renderTargets.getColorTarget(i); - - if ((target != nullptr) - && (target->imageInfo().layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)) { - VkImageLayout srcLayout = target->imageInfo().layout; - - if (srcLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) - srcLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - m_barriers.accessImage( - target->image(), - target->subresources(), - srcLayout, - target->imageInfo().stages, - target->imageInfo().access, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - } - } - - // Transform the depth-stencil view to the optimal layout - const Rc dsTarget = renderTargets.getDepthTarget(); - - if ((dsTarget != nullptr) - && (dsTarget->imageInfo().layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)) { - m_barriers.accessImage( - dsTarget->image(), - dsTarget->subresources(), - dsTarget->imageInfo().layout, - dsTarget->imageInfo().stages, - dsTarget->imageInfo().access, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); - } - - m_barriers.recordCommands(m_cmd); - } - - - void DxvkContext::transformLayoutsRenderPassEnd( - const DxvkRenderTargets& renderTargets) { - // Transform color attachments back to their original layouts and - // make sure that they can be used for subsequent draw or compute - // operations. Swap chain images are treated like any other image. - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - const Rc target = renderTargets.getColorTarget(i); - - if (target != nullptr) { - m_barriers.accessImage( - target->image(), - target->subresources(), - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - target->imageInfo().layout, - target->imageInfo().stages, - target->imageInfo().access); - } - } - - // Transform the depth-stencil attachment back to its original layout. - const Rc dsTarget = renderTargets.getDepthTarget(); - - if (dsTarget != nullptr) { - m_barriers.accessImage( - dsTarget->image(), - dsTarget->subresources(), - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - dsTarget->imageInfo().layout, - dsTarget->imageInfo().stages, - dsTarget->imageInfo().access); - } - - m_barriers.recordCommands(m_cmd); - } - } \ No newline at end of file diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 32fa541f..a63e3c3c 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -561,12 +561,6 @@ namespace dxvk { void commitComputeBarriers(); - void transformLayoutsRenderPassBegin( - const DxvkRenderTargets& renderTargets); - - void transformLayoutsRenderPassEnd( - const DxvkRenderTargets& renderTargets); - }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_framebuffer.cpp b/src/dxvk/dxvk_framebuffer.cpp index 73053082..eabae8a0 100644 --- a/src/dxvk/dxvk_framebuffer.cpp +++ b/src/dxvk/dxvk_framebuffer.cpp @@ -11,13 +11,19 @@ namespace dxvk { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { if (m_colorTargets.at(i) != nullptr) { - result.setColorFormat(i, m_colorTargets.at(i)->info().format); + result.setColorFormat(i, DxvkRenderTargetFormat { + m_colorTargets.at(i)->imageInfo().format, + m_colorTargets.at(i)->imageInfo().layout, + m_colorTargets.at(i)->imageInfo().layout }); result.setSampleCount(m_colorTargets.at(i)->image()->info().sampleCount); } } if (m_depthTarget != nullptr) { - result.setDepthFormat(m_depthTarget->info().format); + result.setDepthFormat(DxvkRenderTargetFormat { + m_depthTarget->imageInfo().format, + m_depthTarget->imageInfo().layout, + m_depthTarget->imageInfo().layout }); result.setSampleCount(m_depthTarget->image()->info().sampleCount); } diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index b8f7aa09..be2a4453 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -2,23 +2,38 @@ namespace dxvk { - DxvkRenderPassFormat::DxvkRenderPassFormat() { - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) - m_color[i] = VK_FORMAT_UNDEFINED; - m_depth = VK_FORMAT_UNDEFINED; - m_samples = VK_SAMPLE_COUNT_1_BIT; + bool DxvkRenderTargetFormat::operator == (const DxvkRenderTargetFormat& other) const { + return this->format == other.format + && this->initialLayout == other.initialLayout + && this->finalLayout == other.finalLayout; + } + + + bool DxvkRenderTargetFormat::operator != (const DxvkRenderTargetFormat& other) const { + return !this->operator == (other); + } + + + size_t DxvkRenderTargetFormat::hash() const { + std::hash fhash; + std::hash lhash; + + DxvkHashState result; + result.add(fhash(this->format)); + result.add(lhash(this->initialLayout)); + result.add(lhash(this->finalLayout)); + return result; } size_t DxvkRenderPassFormat::hash() const { - DxvkHashState result; - std::hash fhash; std::hash shash; + DxvkHashState result; for (uint32_t i = 0; i < MaxNumRenderTargets; i++) - result.add(fhash(m_color[i])); + result.add(m_color[i].hash()); - result.add(fhash(m_depth)); + result.add(m_depth.hash()); result.add(shash(m_samples)); return result; } @@ -49,17 +64,19 @@ namespace dxvk { // Render passes may not require the previous // contents of the attachments to be preserved. - if (fmt.getDepthFormat() != VK_FORMAT_UNDEFINED) { + const DxvkRenderTargetFormat depthFmt = fmt.getDepthFormat(); + + if (depthFmt.format != VK_FORMAT_UNDEFINED) { VkAttachmentDescription desc; desc.flags = 0; - desc.format = fmt.getDepthFormat(); + desc.format = depthFmt.format; desc.samples = fmt.getSampleCount(); desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + desc.initialLayout = depthFmt.initialLayout; + desc.finalLayout = depthFmt.finalLayout; depthRef.attachment = attachments.size(); depthRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -68,20 +85,22 @@ namespace dxvk { } for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const DxvkRenderTargetFormat colorFmt = fmt.getColorFormat(i); + colorRef[i].attachment = VK_ATTACHMENT_UNUSED; colorRef[i].layout = VK_IMAGE_LAYOUT_UNDEFINED; - if (fmt.getColorFormat(i) != VK_FORMAT_UNDEFINED) { + if (colorFmt.format != VK_FORMAT_UNDEFINED) { VkAttachmentDescription desc; desc.flags = 0; - desc.format = fmt.getColorFormat(i); + desc.format = colorFmt.format; desc.samples = fmt.getSampleCount(); desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + desc.initialLayout = colorFmt.initialLayout; + desc.finalLayout = colorFmt.finalLayout; colorRef[i].attachment = attachments.size(); colorRef[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -98,10 +117,47 @@ namespace dxvk { subpass.colorAttachmentCount = colorRef.size(); subpass.pColorAttachments = colorRef.data(); subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = fmt.getDepthFormat() != VK_FORMAT_UNDEFINED ? &depthRef : nullptr; + subpass.pDepthStencilAttachment = depthFmt.format != VK_FORMAT_UNDEFINED ? &depthRef : nullptr; subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; + std::array subpassDeps = {{ + { VK_SUBPASS_EXTERNAL, 0, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + 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_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT, + 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, VK_SUBPASS_EXTERNAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 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_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + 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_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT, 0 }, + }}; + VkRenderPassCreateInfo info; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; info.pNext = nullptr; @@ -110,8 +166,8 @@ namespace dxvk { info.pAttachments = attachments.data(); info.subpassCount = 1; info.pSubpasses = &subpass; - info.dependencyCount = 0; - info.pDependencies = nullptr; + info.dependencyCount = subpassDeps.size(); + info.pDependencies = subpassDeps.data(); if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &m_renderPass) != VK_SUCCESS) throw DxvkError("DxvkRenderPass::DxvkRenderPass: Failed to create render pass object"); diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index 80b76abd..1b3b2bcb 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -9,6 +9,24 @@ namespace dxvk { + /** + * \brief Format and layout info for a sigle render target + * + * Stores the format, initial layout and + * final layout of a render target. + */ + struct DxvkRenderTargetFormat { + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + bool operator == (const DxvkRenderTargetFormat& other) const; + bool operator != (const DxvkRenderTargetFormat& other) const; + + size_t hash() const; + }; + + /** * \brief Render pass format * @@ -19,8 +37,6 @@ namespace dxvk { public: - DxvkRenderPassFormat(); - /** * \brief Retrieves color target format * @@ -29,7 +45,7 @@ namespace dxvk { * \param [in] id Color target index * \returns Color target format */ - VkFormat getColorFormat(uint32_t id) const { + DxvkRenderTargetFormat getColorFormat(uint32_t id) const { return m_color.at(id); } @@ -39,7 +55,7 @@ namespace dxvk { * If the color target has not been defined, * this will return \c VK_FORMAT_UNDEFINED. */ - VkFormat getDepthFormat() const { + DxvkRenderTargetFormat getDepthFormat() const { return m_depth; } @@ -60,7 +76,7 @@ namespace dxvk { * \param [in] id Color target index * \param [in] fmt Color target format */ - void setColorFormat(uint32_t id, VkFormat fmt) { + void setColorFormat(uint32_t id, DxvkRenderTargetFormat fmt) { m_color.at(id) = fmt; } @@ -68,7 +84,7 @@ namespace dxvk { * \brief Sets depth-stencil format * \param [in] fmt Depth-stencil format */ - void setDepthFormat(VkFormat fmt) { + void setDepthFormat(DxvkRenderTargetFormat fmt) { m_depth = fmt; } @@ -91,9 +107,9 @@ namespace dxvk { private: - std::array m_color; - VkFormat m_depth; - VkSampleCountFlagBits m_samples; + std::array m_color; + DxvkRenderTargetFormat m_depth; + VkSampleCountFlagBits m_samples = VK_SAMPLE_COUNT_1_BIT; }; diff --git a/src/dxvk/dxvk_swapchain.cpp b/src/dxvk/dxvk_swapchain.cpp index ccacb6ec..05b5f249 100644 --- a/src/dxvk/dxvk_swapchain.cpp +++ b/src/dxvk/dxvk_swapchain.cpp @@ -132,7 +132,11 @@ namespace dxvk { // Create the render pass object DxvkRenderPassFormat renderTargetFormat; - renderTargetFormat.setColorFormat(0, fmt.format); + + renderTargetFormat.setColorFormat(0, + DxvkRenderTargetFormat { fmt.format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR }); m_renderPass = new DxvkRenderPass( m_vkd, renderTargetFormat);