diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 65391be14f..fb1218224b 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -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; }; diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index b75edef5d5..9ed5385b4a 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -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; } diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index a82ccb4605..23a7645556 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -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() { diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index a06bac650c..7f98059a68 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -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) { diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 7cbaba3ca6..37243cac85 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -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; diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 9ca4a81b9d..b4e547a77b 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -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; } } }