1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-23 01:54:22 +01:00

[dxvk] Add store op optimization for image discards in tiler mode

This commit is contained in:
Philip Rebohle 2025-02-07 22:42:47 +01:00
parent 821386aeff
commit fcabffc1e5
2 changed files with 82 additions and 7 deletions

View File

@ -858,13 +858,39 @@ namespace dxvk {
VkImageAspectFlags discardAspects) {
VkImageUsageFlags viewUsage = imageView->info().usage;
// Ignore non-render target views since there's likely no good use case for
// discarding those. Also, force reinitialization even if the image is bound
// as a render target, which may have niche use cases for depth buffers.
if (viewUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
this->spillRenderPass(true);
this->deferDiscard(imageView, discardAspects);
if (!(viewUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
return;
// Perform store op optimization on bound render targets
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
VkImageSubresourceRange subresource = imageView->imageSubresources();
subresource.aspectMask &= discardAspects;
discardRenderTarget(*imageView->image(), subresource);
}
// Perform load op optimization on subsequent render passes
deferDiscard(imageView, discardAspects);
}
void DxvkContext::discardImage(
const Rc<DxvkImage>& image) {
VkImageUsageFlags imageUsage = image->info().usage;
if (!(imageUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
return;
// Perform store op optimization on bound render targets
VkImageSubresourceRange subresource = { };
subresource.aspectMask = image->formatInfo()->aspectMask;
subresource.layerCount = image->info().numLayers;
subresource.levelCount = image->info().mipLevels;
discardRenderTarget(*image, subresource);
// We don't really have a good way to queue up discards for
// subsequent render passes here without a view, so don't.
}
@ -7266,6 +7292,43 @@ namespace dxvk {
}
void DxvkContext::discardRenderTarget(
const DxvkImage& image,
const VkImageSubresourceRange& subresources) {
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
|| !m_device->perfHints().preferRenderPassOps)
return;
for (uint32_t i = 0; i < m_state.om.framebufferInfo.numAttachments(); i++) {
auto& view = m_state.om.framebufferInfo.getAttachment(i).view;
if (view->image() != &image)
continue;
// If the given subresource range fully contains any bound render target,
// retroactively change the corresponding store op to DONT_CARE.
auto viewSubresources = view->imageSubresources();
if (vk::checkSubresourceRangeSuperset(subresources, viewSubresources)) {
if (subresources.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if ((subresources.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && m_state.om.renderingInfo.depth.imageView)
m_state.om.renderingInfo.depth.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
if ((subresources.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && m_state.om.renderingInfo.stencil.imageView)
m_state.om.renderingInfo.stencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} else {
uint32_t index = m_state.om.framebufferInfo.getColorAttachmentIndex(i);
if (index < m_state.om.renderingInfo.rendering.colorAttachmentCount)
m_state.om.renderingInfo.color[i].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
m_flags.set(DxvkContextFlag::GpDirtyFramebuffer);
}
}
}
void DxvkContext::flushImageLayoutTransitions(
DxvkCmdBuffer cmdBuffer) {
if (m_imageLayoutTransitions.empty())

View File

@ -700,7 +700,7 @@ namespace dxvk {
/**
* \brief Discards contents of an image view
*
*
* Discards the current contents of the image
* and performs a fast layout transition. This
* may improve performance in some cases.
@ -711,6 +711,14 @@ namespace dxvk {
const Rc<DxvkImageView>& imageView,
VkImageAspectFlags discardAspects);
/**
* \brief Discards contents of an image
*
* \param [in] image Image to discard
*/
void discardImage(
const Rc<DxvkImage>& image);
/**
* \brief Starts compute jobs
*
@ -1808,6 +1816,10 @@ namespace dxvk {
void splitCommands();
void discardRenderTarget(
const DxvkImage& image,
const VkImageSubresourceRange& subresources);
void flushImageLayoutTransitions(
DxvkCmdBuffer cmdBuffer);