GPU: Add a way to defer dirty rechecks.

These are situations where we have temporary state which will require
recalc again later.
This commit is contained in:
Unknown W. Brackets 2022-08-28 08:34:48 -07:00
parent 77c834ba5c
commit 18e1efece1
6 changed files with 35 additions and 16 deletions

View File

@ -189,6 +189,9 @@ protected:
bool fboTexNeedsBind_ = false;
bool fboTexBound_ = false;
// Sometimes, unusual situations mean we need to reset dirty flags after state calc finishes.
uint64_t dirtyRequiresRecheck_ = 0;
// Hardware tessellation
TessellationDataTransfer *tessDataTransfer;
};

View File

@ -174,12 +174,15 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState");
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
@ -193,6 +196,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
keys_.blend.destColor = d3d11BlendFactorLookup[(size_t)blendState.dstColor];
keys_.blend.destAlpha = d3d11BlendFactorLookup[(size_t)blendState.dstAlpha];
if (blendState.dirtyShaderBlendFixValues) {
dirtyRequiresRecheck_ |= DIRTY_SHADERBLEND;
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
dynState_.useBlendColor = blendState.useBlendColor;
@ -315,7 +319,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
keys_.depthStencil.stencilFailOp = D3D11_STENCIL_OP_ZERO;
keys_.depthStencil.stencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
// TODO: Need to set in a way that carries over to the next draw..
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
} else {
@ -464,8 +468,6 @@ void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRe
context_->OMSetDepthStencilState(depthStencilState_, applyStencilRef ? stencilRef : dynState_.stencilRef);
}
gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE);
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
if (fboTexBound_)
gstate_c.Dirty(DIRTY_BLEND_STATE);
gstate_c.Dirty(dirtyRequiresRecheck_);
dirtyRequiresRecheck_ = 0;
}

View File

@ -153,9 +153,11 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
device_->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
fboTexBound_ = true;
fboTexNeedsBind_ = false;
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
@ -169,6 +171,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
dxBlendFactorLookup[(size_t)blendState.srcColor], dxBlendFactorLookup[(size_t)blendState.dstColor],
dxBlendFactorLookup[(size_t)blendState.srcAlpha], dxBlendFactorLookup[(size_t)blendState.dstAlpha]);
if (blendState.dirtyShaderBlendFixValues) {
dirtyRequiresRecheck_ |= DIRTY_SHADERBLEND;
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
if (blendState.useBlendColor) {
@ -262,7 +265,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
// Invert
dxstate.stencilOp.set(D3DSTENCILOP_ZERO, D3DSTENCILOP_KEEP, D3DSTENCILOP_ZERO);
// TODO: Need to set in a way that carries over to the next draw..
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
} else {
@ -289,6 +292,8 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
}
gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE);
gstate_c.Dirty(dirtyRequiresRecheck_);
dirtyRequiresRecheck_ = 0;
}
void DrawEngineDX9::ApplyDrawStateLate() {

View File

@ -141,6 +141,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
// Start profiling here to skip SetTexture which is already accounted for
PROFILE_THIS_SCOPE("applydrawstate");
uint64_t dirtyRequiresRecheck_ = 0;
bool useBufferedRendering = framebufferManager_->UseBufferedRendering();
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
@ -177,17 +178,21 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState");
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
if (blendState.enabled) {
if (blendState.dirtyShaderBlendFixValues) {
// Not quite sure how necessary this is.
dirtyRequiresRecheck_ |= DIRTY_SHADERBLEND;
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
if (blendState.useBlendColor) {
@ -269,7 +274,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
renderManager->SetStencilFunc(true, GL_ALWAYS, 0xFF, 0xFF);
renderManager->SetStencilOp(0xFF, GL_ZERO, GL_KEEP, GL_ZERO);
// TODO: Need to set in a way that carries over to the next draw..
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
} else {
@ -293,6 +298,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
}
gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE);
gstate_c.Dirty(dirtyRequiresRecheck_);
dirtyRequiresRecheck_ = 0;
}
void DrawEngineGLES::ApplyDrawStateLate(bool setStencilValue, int stencilValue) {

View File

@ -796,11 +796,9 @@ void DrawEngineVulkan::DoFlush() {
}
ApplyDrawStateLate(renderManager, false, 0, pipeline->UsesBlendConstant());
gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
gstate_c.Dirty(dirtyRequiresRecheck_);
dirtyRequiresRecheck_ = 0;
lastPipeline_ = pipeline;
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
if (fboTexBound_)
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
lastPrim_ = prim;
@ -928,11 +926,9 @@ void DrawEngineVulkan::DoFlush() {
}
ApplyDrawStateLate(renderManager, result.setStencil, result.stencilValue, pipeline->UsesBlendConstant());
gstate_c.Clean(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
gstate_c.Dirty(dirtyRequiresRecheck_);
dirtyRequiresRecheck_ = 0;
lastPipeline_ = pipeline;
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
if (fboTexBound_)
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
lastPrim_ = prim;

View File

@ -173,9 +173,11 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
ApplyFramebufferRead(&fboTexNeedsBind_);
// The shader takes over the responsibility for blending, so recompute.
ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState);
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
dirtyRequiresRecheck_ |= DIRTY_FRAGMENTSHADER_STATE;
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
@ -188,6 +190,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
key.destColor = vkBlendFactorLookup[(size_t)blendState.dstColor];
key.destAlpha = vkBlendFactorLookup[(size_t)blendState.dstAlpha];
if (blendState.dirtyShaderBlendFixValues) {
dirtyRequiresRecheck_ |= DIRTY_SHADERBLEND;
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
dynState.useBlendColor = blendState.useBlendColor;
@ -322,7 +325,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
key.stencilFailOp = VK_STENCIL_OP_ZERO;
key.stencilDepthFailOp = VK_STENCIL_OP_KEEP;
// TODO: Need to set in a way that carries over to the next draw..
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
gstate_c.Dirty(DIRTY_BLEND_STATE);
}
} else {
@ -375,6 +378,9 @@ void DrawEngineVulkan::BindShaderBlendTex() {
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW);
fboTexBound_ = true;
fboTexNeedsBind_ = false;
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE;
}
}
}