From 00872e9e4fdd87d92f2dd662791b8de6a7edf10c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 19 Apr 2024 01:44:14 +0200 Subject: [PATCH] [dxvk] Fix render target clears with format reinterpretation With LOAD_OP_CLEAR, we cannot rely on the clear actually being performed with the view format in mind. Use a vkCmdClearAttachment path instead. --- src/dxvk/dxvk_context.cpp | 46 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index d24d919b..e12553df 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2041,6 +2041,8 @@ namespace dxvk { } if (attachmentIndex < 0) { + bool hasViewFormatMismatch = imageView->info().format != imageView->imageInfo().format; + if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write)) m_execBarriers.recordCommands(m_cmd); @@ -2075,6 +2077,11 @@ namespace dxvk { attachmentInfo.loadOp = colorOp.loadOp; + // We can't use LOAD_OP_CLEAR if the view format does not match the + // underlying image format, so just discard here and use clear later. + if (hasViewFormatMismatch && attachmentInfo.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) + attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + renderingInfo.colorAttachmentCount = 1; renderingInfo.pColorAttachments = &attachmentInfo; @@ -2110,6 +2117,20 @@ namespace dxvk { } m_cmd->cmdBeginRendering(&renderingInfo); + + if (hasViewFormatMismatch) { + VkClearAttachment clearInfo = { }; + clearInfo.aspectMask = imageView->info().aspect; + clearInfo.clearValue = clearValue; + + VkClearRect clearRect = { }; + clearRect.rect.extent.width = extent.width; + clearRect.rect.extent.height = extent.height; + clearRect.layerCount = imageView->info().numLayers; + + m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect); + } + m_cmd->cmdEndRendering(); m_execBarriers.accessImage( @@ -4741,8 +4762,10 @@ namespace dxvk { this->renderPassEmitPostBarriers(framebufferInfo, ops); uint32_t colorInfoCount = 0; + uint32_t lateClearCount = 0; std::array colorInfos; + std::array lateClears; for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { const auto& colorTarget = framebufferInfo.getColorTarget(i); @@ -4754,9 +4777,21 @@ namespace dxvk { colorInfos[i].loadOp = ops.colorOps[i].loadOp; colorInfos[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) + if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { colorInfos[i].clearValue.color = ops.colorOps[i].clearValue; + // We can't use LOAD_OP_CLEAR if the view format does not match the + // underlying image format, so just discard here and use clear later. + if (colorTarget.view->info().format != colorTarget.view->imageInfo().format) { + colorInfos[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + auto& clear = lateClears[lateClearCount++]; + clear.colorAttachment = i; + clear.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + clear.clearValue.color = ops.colorOps[i].clearValue; + } + } + colorInfoCount = i + 1; } } @@ -4804,6 +4839,15 @@ namespace dxvk { m_cmd->cmdBeginRendering(&renderingInfo); + if (lateClearCount) { + VkClearRect clearRect = { }; + clearRect.rect.extent.width = fbSize.width; + clearRect.rect.extent.height = fbSize.height; + clearRect.layerCount = fbSize.layers; + + m_cmd->cmdClearAttachments(lateClearCount, lateClears.data(), 1, &clearRect); + } + for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) { m_cmd->trackResource (framebufferInfo.getAttachment(i).view); m_cmd->trackResource(framebufferInfo.getAttachment(i).view->image());