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

[d3d11] Lazy-bind shader resources

This commit is contained in:
Philip Rebohle 2025-02-19 02:22:23 +01:00 committed by Philip Rebohle
parent 4fdbfffdcc
commit f2ab76c8db
2 changed files with 67 additions and 19 deletions

View File

@ -3206,6 +3206,28 @@ namespace dxvk {
} }
template<typename ContextType>
void D3D11CommonContext<ContextType>::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<typename ContextType> template<typename ContextType>
void D3D11CommonContext<ContextType>::ApplyDirtyGraphicsBindings() { void D3D11CommonContext<ContextType>::ApplyDirtyGraphicsBindings() {
auto dirtyMask = m_state.lazy.shadersDirty & m_state.lazy.shadersUsed; auto dirtyMask = m_state.lazy.shadersDirty & m_state.lazy.shadersUsed;
@ -3218,6 +3240,7 @@ namespace dxvk {
auto& dirtyMask = m_state.lazy.bindingsDirty[stage]; auto& dirtyMask = m_state.lazy.bindingsDirty[stage];
ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask); ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask);
ApplyDirtyShaderResources(stage, boundMask, dirtyMask);
m_state.lazy.shadersDirty.clr(stage); m_state.lazy.shadersDirty.clr(stage);
} }
@ -3232,6 +3255,7 @@ namespace dxvk {
auto& dirtyMask = m_state.lazy.bindingsDirty[stage]; auto& dirtyMask = m_state.lazy.bindingsDirty[stage];
ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask); ApplyDirtyConstantBuffers(stage, boundMask, dirtyMask);
ApplyDirtyShaderResources(stage, boundMask, dirtyMask);
m_state.lazy.shadersDirty.clr(stage); m_state.lazy.shadersDirty.clr(stage);
} }
@ -3839,36 +3863,38 @@ namespace dxvk {
template<typename ContextType> template<typename ContextType>
template<DxbcProgramType ShaderStage>
void D3D11CommonContext<ContextType>::BindShaderResource( void D3D11CommonContext<ContextType>::BindShaderResource(
DxbcProgramType ShaderStage,
UINT Slot, UINT Slot,
D3D11ShaderResourceView* pResource) { D3D11ShaderResourceView* pResource) {
uint32_t slotId = computeSrvBinding(ShaderStage, Slot);
if (pResource) { if (pResource) {
if (pResource->GetViewInfo().Dimension != D3D11_RESOURCE_DIMENSION_BUFFER) { if (pResource->GetViewInfo().Dimension != D3D11_RESOURCE_DIMENSION_BUFFER) {
EmitCs([ EmitCs([
cSlotId = Slot, cSlotId = slotId,
cStage = GetShaderStage(ShaderStage),
cView = pResource->GetImageView() cView = pResource->GetImageView()
] (DxvkContext* ctx) mutable { ] (DxvkContext* ctx) mutable {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); ctx->bindResourceImageView(cStage, cSlotId,
ctx->bindResourceImageView(stage, cSlotId,
Forwarder::move(cView)); Forwarder::move(cView));
}); });
} else { } else {
EmitCs([ EmitCs([
cSlotId = Slot, cSlotId = slotId,
cStage = GetShaderStage(ShaderStage),
cView = pResource->GetBufferView() cView = pResource->GetBufferView()
] (DxvkContext* ctx) mutable { ] (DxvkContext* ctx) mutable {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); ctx->bindResourceBufferView(cStage, cSlotId,
ctx->bindResourceBufferView(stage, cSlotId,
Forwarder::move(cView)); Forwarder::move(cView));
}); });
} }
} else { } else {
EmitCs([ EmitCs([
cSlotId = Slot cSlotId = slotId,
cStage = GetShaderStage(ShaderStage)
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); ctx->bindResourceImageView(cStage, cSlotId, nullptr);
ctx->bindResourceImageView(stage, cSlotId, nullptr);
}); });
} }
} }
@ -4362,6 +4388,20 @@ namespace dxvk {
} }
template<typename ContextType>
bool D3D11CommonContext<ContextType>::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<typename ContextType> template<typename ContextType>
void D3D11CommonContext<ContextType>::DiscardBuffer( void D3D11CommonContext<ContextType>::DiscardBuffer(
ID3D11Resource* pResource) { ID3D11Resource* pResource) {
@ -4694,8 +4734,6 @@ namespace dxvk {
void D3D11CommonContext<ContextType>::ResolveSrvHazards( void D3D11CommonContext<ContextType>::ResolveSrvHazards(
T* pView) { T* pView) {
auto& bindings = m_state.srv[ShaderStage]; auto& bindings = m_state.srv[ShaderStage];
uint32_t slotId = computeSrvBinding(ShaderStage, 0);
int32_t srvId = bindings.hazardous.findNext(0); int32_t srvId = bindings.hazardous.findNext(0);
while (srvId >= 0) { while (srvId >= 0) {
@ -4708,7 +4746,8 @@ namespace dxvk {
bindings.views[srvId] = nullptr; bindings.views[srvId] = nullptr;
bindings.hazardous.clr(srvId); bindings.hazardous.clr(srvId);
BindShaderResource<ShaderStage>(slotId + srvId, nullptr); if (!DirtyShaderResource(ShaderStage, srvId, true))
BindShaderResource(ShaderStage, srvId, nullptr);
} }
} else { } else {
// Avoid further redundant iterations // Avoid further redundant iterations
@ -4880,10 +4919,8 @@ namespace dxvk {
template<DxbcProgramType Stage> template<DxbcProgramType Stage>
void D3D11CommonContext<ContextType>::RestoreShaderResources() { void D3D11CommonContext<ContextType>::RestoreShaderResources() {
const auto& bindings = m_state.srv[Stage]; const auto& bindings = m_state.srv[Stage];
uint32_t slotId = computeSrvBinding(Stage, 0);
for (uint32_t i = 0; i < bindings.maxCount; i++) for (uint32_t i = 0; i < bindings.maxCount; i++)
BindShaderResource<Stage>(slotId + i, bindings.views[i].ptr()); BindShaderResource(Stage, i, bindings.views[i].ptr());
} }
@ -5015,7 +5052,6 @@ namespace dxvk {
UINT NumResources, UINT NumResources,
ID3D11ShaderResourceView* const* ppResources) { ID3D11ShaderResourceView* const* ppResources) {
auto& bindings = m_state.srv[ShaderStage]; auto& bindings = m_state.srv[ShaderStage];
uint32_t slotId = computeSrvBinding(ShaderStage, StartSlot);
for (uint32_t i = 0; i < NumResources; i++) { for (uint32_t i = 0; i < NumResources; i++) {
auto resView = static_cast<D3D11ShaderResourceView*>(ppResources[i]); auto resView = static_cast<D3D11ShaderResourceView*>(ppResources[i]);
@ -5034,7 +5070,9 @@ namespace dxvk {
} }
bindings.views[StartSlot + i] = resView; bindings.views[StartSlot + i] = resView;
BindShaderResource<ShaderStage>(slotId + i, resView);
if (!DirtyShaderResource(ShaderStage, StartSlot + i, !resView))
BindShaderResource(ShaderStage, StartSlot + i, resView);
} }
} }

View File

@ -804,6 +804,11 @@ namespace dxvk {
const DxbcBindingMask& BoundMask, const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask); DxbcBindingMask& DirtyMask);
void ApplyDirtyShaderResources(
DxbcProgramType Stage,
const DxbcBindingMask& BoundMask,
DxbcBindingMask& DirtyMask);
void ApplyDirtyGraphicsBindings(); void ApplyDirtyGraphicsBindings();
void ApplyDirtyComputeBindings(); void ApplyDirtyComputeBindings();
@ -881,8 +886,8 @@ namespace dxvk {
UINT Slot, UINT Slot,
D3D11SamplerState* pSampler); D3D11SamplerState* pSampler);
template<DxbcProgramType ShaderStage>
void BindShaderResource( void BindShaderResource(
DxbcProgramType ShaderStage,
UINT Slot, UINT Slot,
D3D11ShaderResourceView* pResource); D3D11ShaderResourceView* pResource);
@ -933,6 +938,11 @@ namespace dxvk {
uint32_t Slot, uint32_t Slot,
bool IsNull); bool IsNull);
bool DirtyShaderResource(
DxbcProgramType ShaderStage,
uint32_t Slot,
bool IsNull);
void DiscardBuffer( void DiscardBuffer(
ID3D11Resource* pResource); ID3D11Resource* pResource);