1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[dxvk] Implement discardImageView

Built on top of the deferred clear logic.
This commit is contained in:
Philip Rebohle 2021-02-21 01:36:46 +01:00
parent 0ba3e693c9
commit e46bf78f31
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 63 additions and 36 deletions

View File

@ -583,7 +583,7 @@ namespace dxvk {
} }
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) if (m_flags.test(DxvkContextFlag::GpRenderPassBound))
this->performClear(imageView, attachmentIndex, clearAspects, clearValue); this->performClear(imageView, attachmentIndex, 0, clearAspects, clearValue);
else else
this->deferClear(imageView, clearAspects, clearValue); this->deferClear(imageView, clearAspects, clearValue);
} }
@ -1224,22 +1224,18 @@ namespace dxvk {
} }
void DxvkContext::discardImage( void DxvkContext::discardImageView(
const Rc<DxvkImage>& image, const Rc<DxvkImageView>& imageView,
VkImageSubresourceRange subresources) { VkImageAspectFlags discardAspects) {
this->spillRenderPass(false); VkImageUsageFlags viewUsage = imageView->info().usage;
if (m_execBarriers.isImageDirty(image, subresources, DxvkAccess::Write)) // Ignore non-render target views since there's likely no good use case for
m_execBarriers.recordCommands(m_cmd); // discarding those. Also, force reinitialization even if the image is bound
// as a render target, which may have niche use cases for depth buffers.
m_execBarriers.accessImage(image, subresources, if (viewUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
VK_IMAGE_LAYOUT_UNDEFINED, this->spillRenderPass(true);
image->info().stages, 0, this->deferDiscard(imageView, discardAspects);
image->info().layout, }
image->info().stages,
image->info().access);
m_cmd->trackResource<DxvkAccess::Write>(image);
} }
@ -1728,6 +1724,7 @@ namespace dxvk {
void DxvkContext::performClear( void DxvkContext::performClear(
const Rc<DxvkImageView>& imageView, const Rc<DxvkImageView>& imageView,
int32_t attachmentIndex, int32_t attachmentIndex,
VkImageAspectFlags discardAspects,
VkImageAspectFlags clearAspects, VkImageAspectFlags clearAspects,
VkClearValue clearValue) { VkClearValue clearValue) {
DxvkColorAttachmentOps colorOp; DxvkColorAttachmentOps colorOp;
@ -1743,16 +1740,22 @@ namespace dxvk {
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
else if (discardAspects & VK_IMAGE_ASPECT_COLOR_BIT)
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT) if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_CLEAR; depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_CLEAR;
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT) if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR; depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR;
else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D; bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D;
if (clearAspects == imageView->info().aspect && !is3D) { if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) {
colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; depthOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
} }
@ -1815,32 +1818,33 @@ namespace dxvk {
clearRect.baseArrayLayer = 0; clearRect.baseArrayLayer = 0;
clearRect.layerCount = imageView->info().numLayers; clearRect.layerCount = imageView->info().numLayers;
if (clearAspects)
m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect); m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect);
} else { } else {
// Perform the clear when starting the render pass // Perform the operation when starting the next render pass
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_COLOR_BIT) {
uint32_t colorIndex = m_state.om.framebuffer->getColorAttachmentIndex(attachmentIndex); uint32_t colorIndex = m_state.om.framebuffer->getColorAttachmentIndex(attachmentIndex);
m_state.om.renderPassOps.colorOps[colorIndex].loadOp = colorOp.loadOp; m_state.om.renderPassOps.colorOps[colorIndex].loadOp = colorOp.loadOp;
if (m_state.om.renderPassOps.colorOps[colorIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR && !is3D) if (m_state.om.renderPassOps.colorOps[colorIndex].loadOp != VK_ATTACHMENT_LOAD_OP_LOAD && !is3D)
m_state.om.renderPassOps.colorOps[colorIndex].loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; m_state.om.renderPassOps.colorOps[colorIndex].loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
m_state.om.clearValues[attachmentIndex].color = clearValue.color; m_state.om.clearValues[attachmentIndex].color = clearValue.color;
} }
if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT) { if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_DEPTH_BIT) {
m_state.om.renderPassOps.depthOps.loadOpD = depthOp.loadOpD; m_state.om.renderPassOps.depthOps.loadOpD = depthOp.loadOpD;
m_state.om.clearValues[attachmentIndex].depthStencil.depth = clearValue.depthStencil.depth; m_state.om.clearValues[attachmentIndex].depthStencil.depth = clearValue.depthStencil.depth;
} }
if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT) { if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_STENCIL_BIT) {
m_state.om.renderPassOps.depthOps.loadOpS = depthOp.loadOpS; m_state.om.renderPassOps.depthOps.loadOpS = depthOp.loadOpS;
m_state.om.clearValues[attachmentIndex].depthStencil.stencil = clearValue.depthStencil.stencil; m_state.om.clearValues[attachmentIndex].depthStencil.stencil = clearValue.depthStencil.stencil;
} }
if (clearAspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { if ((clearAspects | discardAspects) & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if (m_state.om.renderPassOps.depthOps.loadOpD == VK_ATTACHMENT_LOAD_OP_CLEAR if (m_state.om.renderPassOps.depthOps.loadOpD != VK_ATTACHMENT_LOAD_OP_LOAD
&& m_state.om.renderPassOps.depthOps.loadOpS == VK_ATTACHMENT_LOAD_OP_CLEAR) && m_state.om.renderPassOps.depthOps.loadOpS != VK_ATTACHMENT_LOAD_OP_LOAD)
m_state.om.renderPassOps.depthOps.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; m_state.om.renderPassOps.depthOps.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
} }
} }
@ -1853,6 +1857,7 @@ namespace dxvk {
VkClearValue clearValue) { VkClearValue clearValue) {
for (auto& entry : m_deferredClears) { for (auto& entry : m_deferredClears) {
if (entry.imageView == imageView) { if (entry.imageView == imageView) {
entry.discardAspects &= ~clearAspects;
entry.clearAspects |= clearAspects; entry.clearAspects |= clearAspects;
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
@ -1866,7 +1871,22 @@ namespace dxvk {
} }
} }
m_deferredClears.push_back({ imageView, clearAspects, clearValue }); m_deferredClears.push_back({ imageView, 0, clearAspects, clearValue });
}
void DxvkContext::deferDiscard(
const Rc<DxvkImageView>& imageView,
VkImageAspectFlags discardAspects) {
for (auto& entry : m_deferredClears) {
if (entry.imageView == imageView) {
entry.discardAspects |= discardAspects;
entry.clearAspects &= ~discardAspects;
return;
}
}
m_deferredClears.push_back({ imageView, discardAspects });
} }
@ -1878,7 +1898,8 @@ namespace dxvk {
if (useRenderPass && m_state.om.framebuffer->isFullSize(clear.imageView)) if (useRenderPass && m_state.om.framebuffer->isFullSize(clear.imageView))
attachmentIndex = m_state.om.framebuffer->findAttachment(clear.imageView); attachmentIndex = m_state.om.framebuffer->findAttachment(clear.imageView);
this->performClear(clear.imageView, attachmentIndex, clear.clearAspects, clear.clearValue); this->performClear(clear.imageView, attachmentIndex,
clear.discardAspects, clear.clearAspects, clear.clearValue);
} }
m_deferredClears.clear(); m_deferredClears.clear();

View File

@ -474,17 +474,17 @@ namespace dxvk {
const Rc<DxvkBuffer>& buffer); const Rc<DxvkBuffer>& buffer);
/** /**
* \brief Discards image subresources * \brief Discards contents of an image view
* *
* Discards the current contents of the image * Discards the current contents of the image
* and performs a fast layout transition. This * and performs a fast layout transition. This
* may improve performance in some cases. * may improve performance in some cases.
* \param [in] image The image to discard * \param [in] imageView View to discard
* \param [in] subresources Image subresources * \param [in] discardAspects Image aspects to discard
*/ */
void discardImage( void discardImageView(
const Rc<DxvkImage>& image, const Rc<DxvkImageView>& imageView,
VkImageSubresourceRange subresources); VkImageAspectFlags discardAspects);
/** /**
* \brief Starts compute jobs * \brief Starts compute jobs
@ -1090,6 +1090,7 @@ namespace dxvk {
void performClear( void performClear(
const Rc<DxvkImageView>& imageView, const Rc<DxvkImageView>& imageView,
int32_t attachmentIndex, int32_t attachmentIndex,
VkImageAspectFlags discardAspects,
VkImageAspectFlags clearAspects, VkImageAspectFlags clearAspects,
VkClearValue clearValue); VkClearValue clearValue);
@ -1098,6 +1099,10 @@ namespace dxvk {
VkImageAspectFlags clearAspects, VkImageAspectFlags clearAspects,
VkClearValue clearValue); VkClearValue clearValue);
void deferDiscard(
const Rc<DxvkImageView>& imageView,
VkImageAspectFlags discardAspects);
void flushClears( void flushClears(
bool useRenderPass); bool useRenderPass);

View File

@ -145,6 +145,7 @@ namespace dxvk {
struct DxvkDeferredClear { struct DxvkDeferredClear {
Rc<DxvkImageView> imageView; Rc<DxvkImageView> imageView;
VkImageAspectFlags discardAspects;
VkImageAspectFlags clearAspects; VkImageAspectFlags clearAspects;
VkClearValue clearValue; VkClearValue clearValue;
}; };