From f2ab76c8db5369a86cbdddd2867ee7902100e758 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 19 Feb 2025 02:22:23 +0100 Subject: [PATCH] [d3d11] Lazy-bind shader resources --- src/d3d11/d3d11_context.cpp | 74 ++++++++++++++++++++++++++++--------- src/d3d11/d3d11_context.h | 12 +++++- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 163837689..58a110048 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3206,6 +3206,28 @@ namespace dxvk { } + template + void D3D11CommonContext::ApplyDirtyShaderResources( + DxbcProgramType Stage, + const DxbcBindingMask& BoundMask, + DxbcBindingMask& DirtyMask) { + const auto& state = m_state.srv[Stage]; + + for (uint32_t i = 0; i < state.maxCount; i += 64u) { + uint32_t maskIndex = i / 64u; + uint64_t bindMask = BoundMask.srvMask[maskIndex] & DirtyMask.srvMask[maskIndex]; + + if (!bindMask) + continue; + + DirtyMask.srvMask[maskIndex] -= bindMask; + + for (uint32_t slot : bit::BitMask(bindMask)) + BindShaderResource(Stage, slot + i, state.views[slot + i].ptr()); + } + } + + template void D3D11CommonContext::ApplyDirtyGraphicsBindings() { auto dirtyMask = m_state.lazy.shadersDirty & m_state.lazy.shadersUsed; @@ -3218,6 +3240,7 @@ namespace dxvk { auto& dirtyMask = m_state.lazy.bindingsDirty[stage]; ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask); + ApplyDirtyShaderResources(stage, boundMask, dirtyMask); m_state.lazy.shadersDirty.clr(stage); } @@ -3232,6 +3255,7 @@ namespace dxvk { auto& dirtyMask = m_state.lazy.bindingsDirty[stage]; ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask); + ApplyDirtyShaderResources(stage, boundMask, dirtyMask); m_state.lazy.shadersDirty.clr(stage); } @@ -3839,36 +3863,38 @@ namespace dxvk { template - template void D3D11CommonContext::BindShaderResource( + DxbcProgramType ShaderStage, UINT Slot, D3D11ShaderResourceView* pResource) { + uint32_t slotId = computeSrvBinding(ShaderStage, Slot); + if (pResource) { if (pResource->GetViewInfo().Dimension != D3D11_RESOURCE_DIMENSION_BUFFER) { EmitCs([ - cSlotId = Slot, + cSlotId = slotId, + cStage = GetShaderStage(ShaderStage), cView = pResource->GetImageView() ] (DxvkContext* ctx) mutable { - VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); - ctx->bindResourceImageView(stage, cSlotId, + ctx->bindResourceImageView(cStage, cSlotId, Forwarder::move(cView)); }); } else { EmitCs([ - cSlotId = Slot, + cSlotId = slotId, + cStage = GetShaderStage(ShaderStage), cView = pResource->GetBufferView() ] (DxvkContext* ctx) mutable { - VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); - ctx->bindResourceBufferView(stage, cSlotId, + ctx->bindResourceBufferView(cStage, cSlotId, Forwarder::move(cView)); }); } } else { EmitCs([ - cSlotId = Slot + cSlotId = slotId, + cStage = GetShaderStage(ShaderStage) ] (DxvkContext* ctx) { - VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); - ctx->bindResourceImageView(stage, cSlotId, nullptr); + ctx->bindResourceImageView(cStage, cSlotId, nullptr); }); } } @@ -4362,6 +4388,20 @@ namespace dxvk { } + template + bool D3D11CommonContext::DirtyShaderResource( + DxbcProgramType ShaderStage, + uint32_t Slot, + bool IsNull) { + uint32_t idx = Slot / 64u; + + return DirtyBindingGeneric(ShaderStage, + m_state.lazy.bindingsUsed[ShaderStage].srvMask[idx], + m_state.lazy.bindingsDirty[ShaderStage].srvMask[idx], + uint64_t(1u) << Slot, IsNull); + } + + template void D3D11CommonContext::DiscardBuffer( ID3D11Resource* pResource) { @@ -4694,8 +4734,6 @@ namespace dxvk { void D3D11CommonContext::ResolveSrvHazards( T* pView) { auto& bindings = m_state.srv[ShaderStage]; - - uint32_t slotId = computeSrvBinding(ShaderStage, 0); int32_t srvId = bindings.hazardous.findNext(0); while (srvId >= 0) { @@ -4708,7 +4746,8 @@ namespace dxvk { bindings.views[srvId] = nullptr; bindings.hazardous.clr(srvId); - BindShaderResource(slotId + srvId, nullptr); + if (!DirtyShaderResource(ShaderStage, srvId, true)) + BindShaderResource(ShaderStage, srvId, nullptr); } } else { // Avoid further redundant iterations @@ -4880,10 +4919,8 @@ namespace dxvk { template void D3D11CommonContext::RestoreShaderResources() { const auto& bindings = m_state.srv[Stage]; - uint32_t slotId = computeSrvBinding(Stage, 0); - for (uint32_t i = 0; i < bindings.maxCount; i++) - BindShaderResource(slotId + i, bindings.views[i].ptr()); + BindShaderResource(Stage, i, bindings.views[i].ptr()); } @@ -5015,7 +5052,6 @@ namespace dxvk { UINT NumResources, ID3D11ShaderResourceView* const* ppResources) { auto& bindings = m_state.srv[ShaderStage]; - uint32_t slotId = computeSrvBinding(ShaderStage, StartSlot); for (uint32_t i = 0; i < NumResources; i++) { auto resView = static_cast(ppResources[i]); @@ -5034,7 +5070,9 @@ namespace dxvk { } bindings.views[StartSlot + i] = resView; - BindShaderResource(slotId + i, resView); + + if (!DirtyShaderResource(ShaderStage, StartSlot + i, !resView)) + BindShaderResource(ShaderStage, StartSlot + i, resView); } } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 734cede69..6a0b9f7fb 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -804,6 +804,11 @@ namespace dxvk { const DxbcBindingMask& BoundMask, DxbcBindingMask& DirtyMask); + void ApplyDirtyShaderResources( + DxbcProgramType Stage, + const DxbcBindingMask& BoundMask, + DxbcBindingMask& DirtyMask); + void ApplyDirtyGraphicsBindings(); void ApplyDirtyComputeBindings(); @@ -881,8 +886,8 @@ namespace dxvk { UINT Slot, D3D11SamplerState* pSampler); - template void BindShaderResource( + DxbcProgramType ShaderStage, UINT Slot, D3D11ShaderResourceView* pResource); @@ -933,6 +938,11 @@ namespace dxvk { uint32_t Slot, bool IsNull); + bool DirtyShaderResource( + DxbcProgramType ShaderStage, + uint32_t Slot, + bool IsNull); + void DiscardBuffer( ID3D11Resource* pResource);