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:
parent
be61341178
commit
41ec7b6a02
@ -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();
|
||||
|
@ -967,6 +967,8 @@ namespace dxvk {
|
||||
void ResolveOmUavHazards(
|
||||
D3D11RenderTargetView* pView);
|
||||
|
||||
void RestoreUsedBindings();
|
||||
|
||||
void RestoreCommandListState();
|
||||
|
||||
template<DxbcProgramType Stage>
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user