1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-04-01 09:25:24 +02:00

[dxvk] Defer clears during render passes

This commit is contained in:
Philip Rebohle 2025-03-21 03:03:15 +01:00
parent 3417c559c8
commit 496091815e

View File

@ -384,17 +384,16 @@ namespace dxvk {
clearValue.color = util::swizzleClearColor(clearValue.color, clearValue.color = util::swizzleClearColor(clearValue.color,
util::invertComponentMapping(imageView->info().unpackSwizzle())); util::invertComponentMapping(imageView->info().unpackSwizzle()));
} }
// Check whether the render target view is an attachment // Check whether the render target view is an attachment
// of the current framebuffer and is included entirely. // of the current framebuffer and is included entirely.
// If not, we need to create a temporary framebuffer. // If not, we need to create a temporary framebuffer.
int32_t attachmentIndex = -1; int32_t attachmentIndex = -1;
if (m_state.om.framebufferInfo.isFullSize(imageView)) if (m_state.om.framebufferInfo.isFullSize(imageView))
attachmentIndex = m_state.om.framebufferInfo.findAttachment(imageView); attachmentIndex = m_state.om.framebufferInfo.findAttachment(imageView);
// Need to interrupt the render pass if there are pending resolves if (attachmentIndex < 0) {
if (attachmentIndex < 0 || m_flags.test(DxvkContextFlag::GpRenderPassNeedsFlush)) {
// Suspend works here because we'll end up with one of these scenarios: // Suspend works here because we'll end up with one of these scenarios:
// 1) The render pass gets ended for good, in which case we emit barriers // 1) The render pass gets ended for good, in which case we emit barriers
// 2) The clear gets folded into render pass ops, so the layout is correct // 2) The clear gets folded into render pass ops, so the layout is correct
@ -404,31 +403,20 @@ namespace dxvk {
this->spillRenderPass(true); this->spillRenderPass(true);
this->prepareImage(imageView->image(), imageView->subresources(), false); this->prepareImage(imageView->image(), imageView->subresources(), false);
} else if (!m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects)) { } else if (!m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects)) {
// We cannot inline clears if the clear aspects are not writable // We cannot inline clears if the clear aspects are not writable. End the
this->spillRenderPass(true); // render pass on the next draw to ensure that the image gets cleared.
if (m_flags.test(DxvkContextFlag::GpRenderPassBound))
m_flags.set(DxvkContextFlag::GpRenderPassNeedsFlush);
} }
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { // Unconditionally defer clears until either the next render pass, or the
uint32_t colorIndex = std::max(0, m_state.om.framebufferInfo.getColorAttachmentIndex(attachmentIndex)); // next draw if there is no reason to interrupt the render pass. This is
// useful to adjust store ops for tilers, and ensures that pending resolves
VkClearAttachment clearInfo; // are handled correctly.
clearInfo.aspectMask = clearAspects; if (clearAspects)
clearInfo.colorAttachment = colorIndex;
clearInfo.clearValue = clearValue;
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = imageView->mipLevelExtent(0).width;
clearRect.rect.extent.height = imageView->mipLevelExtent(0).height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = imageView->info().layerCount;
m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect);
} else {
this->deferClear(imageView, clearAspects, clearValue); this->deferClear(imageView, clearAspects, clearValue);
}
// Invalidate implicit resolves
if (imageView->isMultisampled()) { if (imageView->isMultisampled()) {
auto subresources = imageView->imageSubresources(); auto subresources = imageView->imageSubresources();
subresources.aspectMask = clearAspects; subresources.aspectMask = clearAspects;