From 66ddbe95137091caddb1b46438910f4e2f81e96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 1 May 2022 12:49:19 +0200 Subject: [PATCH] Remove the rather problematic limit on framebuffer copies --- GPU/Common/DrawEngineCommon.cpp | 22 +-------------------- GPU/Common/DrawEngineCommon.h | 2 +- GPU/D3D11/StateMappingD3D11.cpp | 11 +++-------- GPU/Directx9/StateMappingDX9.cpp | 11 +++-------- GPU/GLES/StateMappingGLES.cpp | 33 +++++++++++++------------------ GPU/Vulkan/StateMappingVulkan.cpp | 11 ++--------- 6 files changed, 24 insertions(+), 66 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 5b115df278..6af2348ae4 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -483,33 +483,13 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH)); } -bool DrawEngineCommon::ApplyFramebufferRead(bool *fboTexNeedsBind) { +void DrawEngineCommon::ApplyFramebufferRead(bool *fboTexNeedsBind) { if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) { *fboTexNeedsBind = false; - return true; } - - static const int MAX_REASONABLE_BLITS_PER_FRAME = 24; - - static int lastFrameBlit = -1; - static int blitsThisFrame = 0; - if (lastFrameBlit != gpuStats.numFlips) { - if (blitsThisFrame > MAX_REASONABLE_BLITS_PER_FRAME) { - WARN_LOG_REPORT_ONCE(blendingBlit, G3D, "Lots of blits needed for obscure blending: %d per frame, blend %d/%d/%d", blitsThisFrame, gstate.getBlendFuncA(), gstate.getBlendFuncB(), gstate.getBlendEq()); - } - blitsThisFrame = 0; - lastFrameBlit = gpuStats.numFlips; - } - ++blitsThisFrame; - if (blitsThisFrame > MAX_REASONABLE_BLITS_PER_FRAME * 4) { - WARN_LOG_ONCE(blendingBlit2, G3D, "Skipping additional blits needed for obscure blending: %d per frame, blend %d/%d/%d", blitsThisFrame, gstate.getBlendFuncA(), gstate.getBlendFuncB(), gstate.getBlendEq()); - return false; - } - *fboTexNeedsBind = true; gstate_c.Dirty(DIRTY_SHADERBLEND); - return true; } void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 0d56546854..b49a1df6fa 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -119,7 +119,7 @@ protected: // Vertex decoding void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts); - bool ApplyFramebufferRead(bool *fboTexNeedsBind); + void ApplyFramebufferRead(bool *fboTexNeedsBind); inline int IndexSize(u32 vtype) const { const u32 indexType = (vtype & GE_VTYPE_IDX_MASK); diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 0452d9f751..bf2370e89e 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -164,14 +164,9 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { ConvertBlendState(blendState, gstate_c.allowFramebufferRead, maskState.applyFramebufferRead); if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) { - if (ApplyFramebufferRead(&fboTexNeedsBind_)) { - // The shader takes over the responsibility for blending, so recompute. - ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); - } else { - // Until next time, force it off. - ResetFramebufferRead(); - gstate_c.SetAllowFramebufferRead(false); - } + ApplyFramebufferRead(&fboTexNeedsBind_); + // The shader takes over the responsibility for blending, so recompute. + ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } else if (blendState.resetFramebufferRead) { ResetFramebufferRead(); diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index 8db3338813..efbb0e0b46 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -133,14 +133,9 @@ void DrawEngineDX9::ApplyDrawState(int prim) { ConvertBlendState(blendState, gstate_c.allowFramebufferRead, maskState.applyFramebufferRead); if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) { - if (ApplyFramebufferRead(&fboTexNeedsBind_)) { - // The shader takes over the responsibility for blending, so recompute. - ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); - } else { - // Until next time, force it off. - ResetFramebufferRead(); - gstate_c.SetAllowFramebufferRead(false); - } + ApplyFramebufferRead(&fboTexNeedsBind_); + // The shader takes over the responsibility for blending, so recompute. + ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } else if (blendState.resetFramebufferRead) { ResetFramebufferRead(); diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index d6f0211cd1..91e77594aa 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -163,27 +163,22 @@ void DrawEngineGLES::ApplyDrawState(int prim) { ConvertBlendState(blendState, gstate_c.allowFramebufferRead, maskState.applyFramebufferRead); if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) { - if (ApplyFramebufferRead(&fboTexNeedsBind_)) { - // The shader takes over the responsibility for blending, so recompute. - ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); + ApplyFramebufferRead(&fboTexNeedsBind_); + // The shader takes over the responsibility for blending, so recompute. + ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); - // We copy the framebuffer here, as doing so will wipe any blend state if we do it later. - if (fboTexNeedsBind_) { - // Note that this is positions, not UVs, that we need the copy from. - framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); - // If we are rendering at a higher resolution, linear is probably best for the dest color. - renderManager->SetTextureSampler(1, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); - fboTexBound_ = true; - fboTexNeedsBind_ = false; + // We copy the framebuffer here, as doing so will wipe any blend state if we do it later. + if (fboTexNeedsBind_) { + // Note that this is positions, not UVs, that we need the copy from. + framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY); + // If we are rendering at a higher resolution, linear is probably best for the dest color. + renderManager->SetTextureSampler(1, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); + fboTexBound_ = true; + fboTexNeedsBind_ = false; - framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState"); - // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. - gstate_c.Dirty(DIRTY_BLEND_STATE); - } - } else { - // Until next time, force it off. - ResetFramebufferRead(); - gstate_c.SetAllowFramebufferRead(false); + framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState"); + // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. + gstate_c.Dirty(DIRTY_BLEND_STATE); } gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } else if (blendState.resetFramebufferRead) { diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index ef04d92dac..44b36ba645 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -169,15 +169,8 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag ConvertBlendState(blendState, gstate_c.allowFramebufferRead, maskState.applyFramebufferRead); if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) { - if (ApplyFramebufferRead(&fboTexNeedsBind_)) { - // The shader takes over the responsibility for blending, so recompute. - ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); - } else { - // Until next time, force it off. - ResetFramebufferRead(); - gstate_c.SetAllowFramebufferRead(false); - // Make sure we recompute the fragment shader ID to one that doesn't try to use shader blending. - } + // The shader takes over the responsibility for blending, so recompute. + ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState); gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } else if (blendState.resetFramebufferRead) { ResetFramebufferRead();