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);