mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 10:54:16 +01:00
[dxvk] Do not clear read-only aspects inside render pass
Instead, end the render pass as necessary and clear outside of it. May fix validation errors in some very rare scenarios where the game performs a clear and then uses a read-only depth-stencil view.
This commit is contained in:
parent
f48e3f596f
commit
b9360bacc2
@ -567,7 +567,7 @@ namespace dxvk {
|
||||
// If not, we need to create a temporary framebuffer.
|
||||
int32_t attachmentIndex = -1;
|
||||
|
||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
||||
if (m_state.om.framebuffer != nullptr
|
||||
&& m_state.om.framebuffer->isFullSize(imageView))
|
||||
attachmentIndex = m_state.om.framebuffer->findAttachment(imageView);
|
||||
|
||||
@ -580,6 +580,9 @@ namespace dxvk {
|
||||
// If there is overlap, we need to explicitly transition affected attachments.
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(m_execBarriers, imageView->image(), imageView->subresources(), false);
|
||||
} else if (!m_state.om.framebuffer->isWritable(attachmentIndex, clearAspects)) {
|
||||
// We cannot inline clears if the clear aspects are not writable
|
||||
this->spillRenderPass(true);
|
||||
}
|
||||
|
||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound))
|
||||
@ -1757,6 +1760,28 @@ namespace dxvk {
|
||||
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
|
||||
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound) && (attachmentIndex >= 0)) {
|
||||
// Do not fold the clear/discard into the render pass if any of the affected aspects
|
||||
// isn't writable. We can only hit this particular path when starting a render pass,
|
||||
// so we can safely manipulate load layouts here.
|
||||
if (!m_state.om.framebuffer->isWritable(attachmentIndex, clearAspects | discardAspects)) {
|
||||
int32_t colorIndex = m_state.om.framebuffer->getColorAttachmentIndex(attachmentIndex);
|
||||
VkImageLayout renderLayout = m_state.om.framebuffer->getAttachment(attachmentIndex).layout;
|
||||
|
||||
if (colorIndex < 0) {
|
||||
depthOp.loadLayout = m_state.om.renderPassOps.depthOps.loadLayout;
|
||||
depthOp.storeLayout = renderLayout;
|
||||
m_state.om.renderPassOps.depthOps.loadLayout = renderLayout;
|
||||
} else {
|
||||
colorOp.loadLayout = m_state.om.renderPassOps.colorOps[colorIndex].loadLayout;
|
||||
colorOp.storeLayout = renderLayout;
|
||||
m_state.om.renderPassOps.colorOps[colorIndex].loadLayout = renderLayout;
|
||||
}
|
||||
|
||||
attachmentIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D;
|
||||
|
||||
if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) {
|
||||
@ -2718,6 +2743,9 @@ namespace dxvk {
|
||||
&& m_state.om.framebuffer->isFullSize(imageView))
|
||||
attachmentIndex = m_state.om.framebuffer->findAttachment(imageView);
|
||||
|
||||
if (attachmentIndex >= 0 && !m_state.om.framebuffer->isWritable(attachmentIndex, aspect))
|
||||
attachmentIndex = -1;
|
||||
|
||||
if (attachmentIndex < 0) {
|
||||
this->spillRenderPass(false);
|
||||
|
||||
|
@ -78,6 +78,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
bool DxvkFramebuffer::isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const {
|
||||
VkImageAspectFlags writableAspects = vk::getWritableAspectsForLayout(getAttachment(attachmentIndex).layout);
|
||||
return (writableAspects & aspects) == aspects;
|
||||
}
|
||||
|
||||
|
||||
DxvkRenderPassFormat DxvkFramebuffer::getRenderPassFormat(const DxvkRenderTargets& renderTargets) {
|
||||
DxvkRenderPassFormat format;
|
||||
|
||||
|
@ -207,6 +207,16 @@ namespace dxvk {
|
||||
* the framebuffer.
|
||||
*/
|
||||
bool isFullSize(const Rc<DxvkImageView>& view) const;
|
||||
|
||||
/**
|
||||
* \brief Checks whether an attachment is writable
|
||||
*
|
||||
* Needed for certain clear optimizations.
|
||||
* \param [in] attachmentIndex Attachment to check
|
||||
* \param [in] aspects Aspect mask to check
|
||||
* \returns \c true if all aspects can be written for the given attachment
|
||||
*/
|
||||
bool isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const;
|
||||
|
||||
/**
|
||||
* \brief Generatess render pass format
|
||||
|
@ -76,6 +76,27 @@ namespace dxvk::vk {
|
||||
&& a.baseArrayLayer + a.layerCount >= b.baseArrayLayer + b.layerCount;
|
||||
}
|
||||
|
||||
inline VkImageAspectFlags getWritableAspectsForLayout(VkImageLayout layout) {
|
||||
switch (layout) {
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
return 0;
|
||||
default:
|
||||
Logger::err(str::format("Unhandled image layout ", layout));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user