mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +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.
|
// If not, we need to create a temporary framebuffer.
|
||||||
int32_t attachmentIndex = -1;
|
int32_t attachmentIndex = -1;
|
||||||
|
|
||||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
if (m_state.om.framebuffer != nullptr
|
||||||
&& m_state.om.framebuffer->isFullSize(imageView))
|
&& m_state.om.framebuffer->isFullSize(imageView))
|
||||||
attachmentIndex = m_state.om.framebuffer->findAttachment(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.
|
// If there is overlap, we need to explicitly transition affected attachments.
|
||||||
this->spillRenderPass(true);
|
this->spillRenderPass(true);
|
||||||
this->prepareImage(m_execBarriers, imageView->image(), imageView->subresources(), false);
|
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))
|
if (m_flags.test(DxvkContextFlag::GpRenderPassBound))
|
||||||
@ -1757,6 +1760,28 @@ namespace dxvk {
|
|||||||
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
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;
|
bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D;
|
||||||
|
|
||||||
if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) {
|
if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) {
|
||||||
@ -2718,6 +2743,9 @@ namespace dxvk {
|
|||||||
&& m_state.om.framebuffer->isFullSize(imageView))
|
&& m_state.om.framebuffer->isFullSize(imageView))
|
||||||
attachmentIndex = m_state.om.framebuffer->findAttachment(imageView);
|
attachmentIndex = m_state.om.framebuffer->findAttachment(imageView);
|
||||||
|
|
||||||
|
if (attachmentIndex >= 0 && !m_state.om.framebuffer->isWritable(attachmentIndex, aspect))
|
||||||
|
attachmentIndex = -1;
|
||||||
|
|
||||||
if (attachmentIndex < 0) {
|
if (attachmentIndex < 0) {
|
||||||
this->spillRenderPass(false);
|
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 DxvkFramebuffer::getRenderPassFormat(const DxvkRenderTargets& renderTargets) {
|
||||||
DxvkRenderPassFormat format;
|
DxvkRenderPassFormat format;
|
||||||
|
|
||||||
|
@ -207,6 +207,16 @@ namespace dxvk {
|
|||||||
* the framebuffer.
|
* the framebuffer.
|
||||||
*/
|
*/
|
||||||
bool isFullSize(const Rc<DxvkImageView>& view) const;
|
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
|
* \brief Generatess render pass format
|
||||||
|
@ -76,6 +76,27 @@ namespace dxvk::vk {
|
|||||||
&& a.baseArrayLayer + a.layerCount >= b.baseArrayLayer + b.layerCount;
|
&& 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