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

[d3d11] Track shader stages with dirty bindings as well as used bindings

This commit is contained in:
Philip Rebohle 2025-02-18 22:00:20 +01:00 committed by Philip Rebohle
parent be61341178
commit 41ec7b6a02
3 changed files with 82 additions and 1 deletions

View File

@ -3423,6 +3423,17 @@ namespace dxvk {
if (unlikely(shader->needsLibraryCompile()))
m_device->requestCompileShader(shader);
// If this shader activates any bindings that have not yet been applied,
// mark the shader stage as dirty so it gets applied on the next draw.
// Don't apply it right away since any dirty bindings are likely redundant.
m_state.lazy.shadersUsed.set(ShaderStage);
m_state.lazy.bindingsUsed[ShaderStage] = pShaderModule->GetBindingMask();
if (!m_state.lazy.shadersDirty.test(ShaderStage)) {
if (!(m_state.lazy.bindingsDirty[ShaderStage] & m_state.lazy.bindingsUsed[ShaderStage]).empty())
m_state.lazy.shadersDirty.set(ShaderStage);
}
EmitCs([
cBuffer = std::move(buffer),
cShader = std::move(shader)
@ -3438,6 +3449,15 @@ namespace dxvk {
Forwarder::move(cBuffer));
});
} else {
// Mark shader stage as inactive and clean since we'll have no active
// bindings. This works because if the app changes any binding at all
// for this stage, it will get flagged as dirty, and if another shader
// gets bound, it will check for any dirty bindings again.
m_state.lazy.shadersUsed.clr(ShaderStage);
m_state.lazy.shadersDirty.clr(ShaderStage);
m_state.lazy.bindingsUsed[ShaderStage].reset();
EmitCs([] (DxvkContext* ctx) {
constexpr VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
@ -4516,6 +4536,9 @@ namespace dxvk {
m_state.srv.reset();
m_state.uav.reset();
m_state.samplers.reset();
// Reset dirty tracking
m_state.lazy.reset();
}
@ -4623,6 +4646,36 @@ namespace dxvk {
}
template<typename ContextType>
void D3D11CommonContext<ContextType>::RestoreUsedBindings() {
// Mark all bindings used since the last reset as dirty so that subsequent draws
// and dispatches will reapply them as necessary. Marking null bindings here may
// lead to some redundant CS thread traffic, but is otherwise harmless.
auto maxBindings = GetMaxUsedBindings();
for (uint32_t i = 0; i < uint32_t(DxbcProgramType::Count); i++) {
auto stage = DxbcProgramType(i);
auto stageInfo = maxBindings.stages[i];
m_state.lazy.bindingsDirty[stage].cbvMask |= (1u << stageInfo.cbvCount) - 1u;
m_state.lazy.bindingsDirty[stage].samplerMask |= (1u << stageInfo.samplerCount) - 1u;
if (stageInfo.uavCount)
m_state.lazy.bindingsDirty[stage].uavMask |= uint64_t(-1) >> (64u - stageInfo.uavCount);
if (stageInfo.srvCount > 64u) {
m_state.lazy.bindingsDirty[stage].srvMask[0] |= uint64_t(-1);
m_state.lazy.bindingsDirty[stage].srvMask[1] |= uint64_t(-1) >> (128u - stageInfo.srvCount);
} else if (stageInfo.srvCount) {
m_state.lazy.bindingsDirty[stage].srvMask[0] |= uint64_t(-1) >> (64u - stageInfo.srvCount);
}
if (m_state.lazy.shadersUsed.test(stage) && !m_state.lazy.bindingsDirty[stage].empty())
m_state.lazy.shadersDirty.set(stage);
}
}
template<typename ContextType>
void D3D11CommonContext<ContextType>::RestoreCommandListState() {
BindFramebuffer();

View File

@ -967,6 +967,8 @@ namespace dxvk {
void ResolveOmUavHazards(
D3D11RenderTargetView* pView);
void RestoreUsedBindings();
void RestoreCommandListState();
template<DxbcProgramType Stage>

View File

@ -302,6 +302,30 @@ namespace dxvk {
predicateValue = false;
}
};
/**
* \brief Lazy binding state
*
* Keeps track of what state needs to be
* re-applied to the context.
*/
struct D3D11LazyBindings {
DxbcProgramTypeFlags shadersUsed = 0u;
DxbcProgramTypeFlags shadersDirty = 0u;
D3D11ShaderStageState<DxbcBindingMask> bindingsUsed;
D3D11ShaderStageState<DxbcBindingMask> bindingsDirty;
void reset() {
shadersUsed = 0u;
shadersDirty = 0u;
bindingsUsed.reset();
bindingsDirty.reset();
}
};
/**
* \brief Context state
@ -325,6 +349,8 @@ namespace dxvk {
D3D11SrvBindings srv;
D3D11UavBindings uav;
D3D11SamplerBindings samplers;
D3D11LazyBindings lazy;
};
/**
@ -342,7 +368,7 @@ namespace dxvk {
* \brief Maximum used binding numbers for all context state
*/
struct D3D11MaxUsedBindings {
std::array<D3D11MaxUsedStageBindings, 6> stages;
std::array<D3D11MaxUsedStageBindings, uint32_t(DxbcProgramType::Count)> stages;
uint32_t vbCount;
uint32_t soCount;
};