From e76c71aad00475536f59994d62cb7bf3d8c64c4e Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 14 Feb 2025 21:49:51 +0100 Subject: [PATCH] [dxvk] Clean up shader resource hazard checking --- src/dxvk/dxvk_context.cpp | 91 +++++++++++---------------------------- src/dxvk/dxvk_context.h | 29 ++++++++----- 2 files changed, 43 insertions(+), 77 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 7a8deeb86..2d1ac6c54 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -6737,7 +6737,7 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { if (slot.bufferView) { if (!IsGraphics || slot.bufferView->buffer()->hasGfxStores()) - requiresBarrier |= checkBufferViewBarrier(slot.bufferView, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkBufferViewBarrier(slot.bufferView, binding.access); else if (binding.access & vk::AccessWriteMask) requiresBarrier |= !slot.bufferView->buffer()->trackGfxStores(); } @@ -6745,18 +6745,18 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { if (slot.bufferView && (!IsGraphics || slot.bufferView->buffer()->hasGfxStores())) - requiresBarrier |= checkBufferViewBarrier(slot.bufferView, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkBufferViewBarrier(slot.bufferView, binding.access); } break; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { if (slot.bufferSlice.length() && (!IsGraphics || slot.bufferSlice.buffer()->hasGfxStores())) - requiresBarrier |= checkBufferBarrier(slot.bufferSlice, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkBufferBarrier(slot.bufferSlice, binding.access); } break; case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: { if (slot.bufferSlice.length()) { if (!IsGraphics || slot.bufferSlice.buffer()->hasGfxStores()) - requiresBarrier |= checkBufferBarrier(slot.bufferSlice, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkBufferBarrier(slot.bufferSlice, binding.access); else if (binding.access & vk::AccessWriteMask) requiresBarrier |= !slot.bufferSlice.buffer()->trackGfxStores(); } @@ -6765,7 +6765,7 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { if (slot.imageView) { if (!IsGraphics || slot.imageView->image()->hasGfxStores()) - requiresBarrier |= checkImageViewBarrier(slot.imageView, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkImageViewBarrier(slot.imageView, binding.access); else if (binding.access & vk::AccessWriteMask) requiresBarrier |= !slot.imageView->image()->trackGfxStores(); } @@ -6774,7 +6774,7 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { if (slot.imageView && (!IsGraphics || slot.imageView->image()->hasGfxStores())) - requiresBarrier |= checkImageViewBarrier(slot.imageView, util::pipelineStages(binding.stage), binding.access); + requiresBarrier |= checkImageViewBarrier(slot.imageView, binding.access); } break; default: @@ -6829,14 +6829,12 @@ namespace dxvk { if (xfbBufferSlice.length()) { requiresBarrier |= !xfbBufferSlice.buffer()->trackGfxStores(); - requiresBarrier |= checkBufferBarrier(xfbBufferSlice, - VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, - VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT); + requiresBarrier |= checkBufferBarrier( + xfbBufferSlice, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT); if (xfbCounterSlice.length()) { requiresBarrier |= !xfbCounterSlice.buffer()->trackGfxStores(); - requiresBarrier |= checkBufferBarrier(xfbCounterSlice, - VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + requiresBarrier |= checkBufferBarrier(xfbCounterSlice, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT); } @@ -6858,7 +6856,7 @@ namespace dxvk { for (uint32_t i = 0; i < slices.size(); i++) { if (slices[i]->length() && slices[i]->buffer()->hasGfxStores()) { - if (checkBufferBarrier(*slices[i], VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT)) + if (checkBufferBarrier(*slices[i], VK_ACCESS_INDIRECT_COMMAND_READ_BIT)) return true; } } @@ -6870,7 +6868,7 @@ namespace dxvk { const auto& indexBufferSlice = m_state.vi.indexBuffer; if (indexBufferSlice.length() && indexBufferSlice.buffer()->hasGfxStores()) { - if (checkBufferBarrier(indexBufferSlice, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_INDEX_READ_BIT)) + if (checkBufferBarrier(indexBufferSlice, VK_ACCESS_INDEX_READ_BIT)) return true; } } @@ -6884,7 +6882,7 @@ namespace dxvk { const auto& vertexBufferSlice = m_state.vi.vertexBuffers[binding]; if (vertexBufferSlice.length() && vertexBufferSlice.buffer()->hasGfxStores()) { - if (checkBufferBarrier(vertexBufferSlice, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)) + if (checkBufferBarrier(vertexBufferSlice, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)) return true; } } @@ -6894,73 +6892,34 @@ namespace dxvk { } - template + template bool DxvkContext::checkBufferBarrier( const DxvkBufferSlice& bufferSlice, - VkPipelineStageFlags stages, VkAccessFlags access) { - if constexpr (DoEmit) { - accessBuffer(DxvkCmdBuffer::ExecBuffer, - *bufferSlice.buffer(), bufferSlice.offset(), - bufferSlice.length(), stages, access); - return false; - } else { - return checkResourceBarrier([this, &bufferSlice] (DxvkAccess access) { - return resourceHasAccess(*bufferSlice.buffer(), - bufferSlice.offset(), bufferSlice.length(), access); - }, stages, access); - } + return checkResourceBarrier([this, &bufferSlice] (DxvkAccess access) { + return resourceHasAccess(*bufferSlice.buffer(), + bufferSlice.offset(), bufferSlice.length(), access); + }, access); } - template + template bool DxvkContext::checkBufferViewBarrier( const Rc& bufferView, - VkPipelineStageFlags stages, VkAccessFlags access) { - if constexpr (DoEmit) { - accessBuffer(DxvkCmdBuffer::ExecBuffer, - *bufferView, stages, access); - return false; - } else { - return checkResourceBarrier([this, &bufferView] (DxvkAccess access) { - return resourceHasAccess(*bufferView, access); - }, stages, access); - } + return checkResourceBarrier([this, &bufferView] (DxvkAccess access) { + return resourceHasAccess(*bufferView, access); + }, access); } - template + template bool DxvkContext::checkImageViewBarrier( const Rc& imageView, - VkPipelineStageFlags stages, VkAccessFlags access) { - if constexpr (DoEmit) { - accessImage(DxvkCmdBuffer::ExecBuffer, - *imageView->image(), - imageView->imageSubresources(), - imageView->image()->info().layout, - stages, access); - return false; - } else { - return checkResourceBarrier([this, &imageView] (DxvkAccess access) { - return resourceHasAccess(*imageView, access); - }, stages, access); - } - } - - - bool DxvkContext::canIgnoreWawHazards(VkPipelineStageFlags stages) { - if (!m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) - return false; - - if (stages & VK_SHADER_STAGE_COMPUTE_BIT) { - VkPipelineStageFlags2 stageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT - | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT; - return !m_execBarriers.hasPendingStages(~stageMask); - } - - return true; + return checkResourceBarrier([this, &imageView] (DxvkAccess access) { + return resourceHasAccess(*imageView, access); + }, access); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index d1131032f..d0b72f0f6 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1767,26 +1767,34 @@ namespace dxvk { template bool checkGraphicsHazards(); - template + template bool checkBufferBarrier( const DxvkBufferSlice& bufferSlice, - VkPipelineStageFlags stages, VkAccessFlags access); - template + template bool checkBufferViewBarrier( const Rc& bufferView, - VkPipelineStageFlags stages, VkAccessFlags access); - template + template bool checkImageViewBarrier( const Rc& imageView, - VkPipelineStageFlags stages, VkAccessFlags access); - bool canIgnoreWawHazards( - VkPipelineStageFlags stages); + template + bool canIgnoreWawHazards() { + if (!m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) + return false; + + if (BindPoint == VK_PIPELINE_BIND_POINT_COMPUTE) { + VkPipelineStageFlags2 stageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT; + return !m_execBarriers.hasPendingStages(~stageMask); + } + + return true; + } void emitMemoryBarrier( VkPipelineStageFlags srcStages, @@ -2011,10 +2019,9 @@ namespace dxvk { const Rc& image, DxvkAccess access); - template + template bool checkResourceBarrier( const Pred& pred, - VkPipelineStageFlags stages, VkAccessFlags access) { // Check for read-after-write first, this is common bool hasPendingWrite = pred(DxvkAccess::Write); @@ -2024,7 +2031,7 @@ namespace dxvk { // Check for a write-after-write hazard, but // ignore it if there are no reads involved. - bool ignoreWaW = canIgnoreWawHazards(stages); + bool ignoreWaW = canIgnoreWawHazards(); if (hasPendingWrite && !ignoreWaW) return true;