From d61619db47308ad29f936df646275352b08f0e46 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Aug 2022 14:03:24 -0700 Subject: [PATCH 1/2] GPU: Dirty params when converting viewport state. This flag will be false when we convert next time, so parameters won't get updated as expected. --- GPU/D3D11/DrawEngineD3D11.cpp | 7 +++++++ GPU/Directx9/DrawEngineDX9.cpp | 7 +++++++ GPU/GLES/DrawEngineGLES.cpp | 7 +++++++ GPU/Vulkan/DrawEngineVulkan.cpp | 7 +++++++ 4 files changed, 28 insertions(+) diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 91a4dda0d3..ec4240ce9a 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -617,6 +617,13 @@ rotateVBO: framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 889e08387c..c206e0188c 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -582,6 +582,13 @@ rotateVBO: framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 6610fcde6a..5ff37bf13a 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -364,6 +364,13 @@ void DrawEngineGLES::DoFlush() { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 7be943ed63..a29d9fc8ce 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -856,6 +856,13 @@ void DrawEngineVulkan::DoFlush() { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } int maxIndex = indexGen.MaxIndex(); From b5a4843c1fb06372bf14b5cb921d7c3e2b5b7607 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Aug 2022 14:16:55 -0700 Subject: [PATCH 2/2] GPU: Purify ConvertViewportAndScissor(). This makes it harder to misuse. See #15856. --- GPU/Common/GPUStateUtils.cpp | 62 +++++++++++++++++-------------- GPU/Common/GPUStateUtils.h | 10 ++++- GPU/D3D11/DrawEngineD3D11.cpp | 8 +--- GPU/D3D11/StateMappingD3D11.cpp | 8 +--- GPU/Directx9/DrawEngineDX9.cpp | 8 +--- GPU/Directx9/StateMappingDX9.cpp | 7 +--- GPU/GLES/DrawEngineGLES.cpp | 8 +--- GPU/GLES/StateMappingGLES.cpp | 8 +--- GPU/Vulkan/DrawEngineVulkan.cpp | 8 +--- GPU/Vulkan/StateMappingVulkan.cpp | 8 +--- 10 files changed, 50 insertions(+), 85 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 51f0e3f8eb..1272a0d7c0 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -557,9 +557,7 @@ DepthScaleFactors GetDepthScaleFactors() { } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { - bool throughmode = gstate.isModeThrough(); - out.dirtyProj = false; - out.dirtyDepth = false; + out.throughMode = gstate.isModeThrough(); float renderWidthFactor, renderHeightFactor; float renderX = 0.0f, renderY = 0.0f; @@ -610,7 +608,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo float offsetX = gstate.getOffsetX(); float offsetY = gstate.getOffsetY(); - if (throughmode) { + if (out.throughMode) { out.viewportX = renderX * renderWidthFactor + displayOffsetX; out.viewportY = renderY * renderHeightFactor + displayOffsetY; out.viewportW = curRTWidth * renderWidthFactor; @@ -647,10 +645,10 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo float right = left + vpWidth; float bottom = top + vpHeight; - float wScale = 1.0f; - float xOffset = 0.0f; - float hScale = 1.0f; - float yOffset = 0.0f; + out.widthScale = 1.0f; + out.xOffset = 0.0f; + out.heightScale = 1.0f; + out.yOffset = 0.0f; // If we're within the bounds, we want clipping the viewport way. So leave it be. { @@ -678,8 +676,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo right = left + 1.0f; } - wScale = vpWidth / (right - left); - xOffset = drift / (right - left); + out.widthScale = vpWidth / (right - left); + out.xOffset = drift / (right - left); } } @@ -707,8 +705,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo bottom = top + 1.0f; } - hScale = vpHeight / (bottom - top); - yOffset = drift / (bottom - top); + out.heightScale = vpHeight / (bottom - top); + out.yOffset = drift / (bottom - top); } } @@ -740,13 +738,13 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo } // Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz. float halfActualZRange = (maxz - minz) * (1.0f / 2.0f); - float zScale = halfActualZRange < std::numeric_limits::epsilon() ? 1.0f : vpZScale / halfActualZRange; + out.depthScale = halfActualZRange < std::numeric_limits::epsilon() ? 1.0f : vpZScale / halfActualZRange; // This adjusts the center from halfActualZRange to vpZCenter. - float zOffset = halfActualZRange < std::numeric_limits::epsilon() ? 0.0f : (vpZCenter - (minz + halfActualZRange)) / halfActualZRange; + out.zOffset = halfActualZRange < std::numeric_limits::epsilon() ? 0.0f : (vpZCenter - (minz + halfActualZRange)) / halfActualZRange; if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) { - zScale = 1.0f; - zOffset = 0.0f; + out.depthScale = 1.0f; + out.zOffset = 0.0f; out.depthRangeMin = ToScaledDepthFromIntegerScale(vpZCenter - vpZScale); out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale); } else { @@ -757,19 +755,27 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // OpenGL will clamp these for us anyway, and Direct3D will error if not clamped. out.depthRangeMin = std::max(out.depthRangeMin, 0.0f); out.depthRangeMax = std::min(out.depthRangeMax, 1.0f); + } +} - bool scaleChanged = gstate_c.vpWidthScale != wScale || gstate_c.vpHeightScale != hScale; - bool offsetChanged = gstate_c.vpXOffset != xOffset || gstate_c.vpYOffset != yOffset; - bool depthChanged = gstate_c.vpDepthScale != zScale || gstate_c.vpZOffset != zOffset; - if (scaleChanged || offsetChanged || depthChanged) { - gstate_c.vpWidthScale = wScale; - gstate_c.vpHeightScale = hScale; - gstate_c.vpDepthScale = zScale; - gstate_c.vpXOffset = xOffset; - gstate_c.vpYOffset = yOffset; - gstate_c.vpZOffset = zOffset; - out.dirtyProj = true; - out.dirtyDepth = depthChanged; +void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor) { + if (vpAndScissor.throughMode) + return; + + bool scaleChanged = gstate_c.vpWidthScale != vpAndScissor.widthScale || gstate_c.vpHeightScale != vpAndScissor.heightScale; + bool offsetChanged = gstate_c.vpXOffset != vpAndScissor.xOffset || gstate_c.vpYOffset != vpAndScissor.yOffset; + bool depthChanged = gstate_c.vpDepthScale != vpAndScissor.depthScale || gstate_c.vpZOffset != vpAndScissor.zOffset; + if (scaleChanged || offsetChanged || depthChanged) { + gstate_c.vpWidthScale = vpAndScissor.widthScale; + gstate_c.vpHeightScale = vpAndScissor.heightScale; + gstate_c.vpDepthScale = vpAndScissor.depthScale; + gstate_c.vpXOffset = vpAndScissor.xOffset; + gstate_c.vpYOffset = vpAndScissor.yOffset; + gstate_c.vpZOffset = vpAndScissor.zOffset; + + gstate_c.Dirty(DIRTY_PROJMATRIX); + if (depthChanged) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); } } } diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 956a71e7f6..41ee3adc73 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -75,10 +75,16 @@ struct ViewportAndScissor { float viewportH; float depthRangeMin; float depthRangeMax; - bool dirtyProj; - bool dirtyDepth; + float widthScale; + float heightScale; + float depthScale; + float xOffset; + float yOffset; + float zOffset; + bool throughMode; }; void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); +void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); float ToScaledDepthFromIntegerScale(float z); struct DepthScaleFactors { diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index ec4240ce9a..eea3004b30 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -617,13 +617,7 @@ rotateVBO: framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } + UpdateCachedViewportState(vpAndScissor); } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 0cbc600ebc..11db65c553 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -374,15 +374,13 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + UpdateCachedViewportState(vpAndScissor); float depthMin = vpAndScissor.depthRangeMin; float depthMax = vpAndScissor.depthRangeMax; if (depthMin < 0.0f) depthMin = 0.0f; if (depthMax > 1.0f) depthMax = 1.0f; - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } Draw::Viewport &vp = dynState_.viewport; vp.TopLeftX = vpAndScissor.viewportX; @@ -392,10 +390,6 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { vp.MinDepth = depthMin; vp.MaxDepth = depthMax; - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - D3D11_RECT &scissor = dynState_.scissor; scissor.left = vpAndScissor.scissorX; scissor.top = vpAndScissor.scissorY; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index c206e0188c..130ee36b8f 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -582,13 +582,7 @@ rotateVBO: framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } + UpdateCachedViewportState(vpAndScissor); } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index 828f9d4b4d..9fb92db6fe 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -260,6 +260,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + UpdateCachedViewportState(vpAndScissor); dxstate.scissorTest.enable(); dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH); @@ -268,12 +269,6 @@ void DrawEngineDX9::ApplyDrawState(int prim) { float depthMax = vpAndScissor.depthRangeMax; dxstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, depthMin, depthMax); - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } } gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 5ff37bf13a..96dc11ea22 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -364,13 +364,7 @@ void DrawEngineGLES::DoFlush() { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } + UpdateCachedViewportState(vpAndScissor); } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 35f9329629..4ebdd165d2 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -276,19 +276,13 @@ void DrawEngineGLES::ApplyDrawState(int prim) { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); + UpdateCachedViewportState(vpAndScissor); renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH }); renderManager->SetViewport({ vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax }); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } } } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index a29d9fc8ce..256c1adbac 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -856,13 +856,7 @@ void DrawEngineVulkan::DoFlush() { framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } + UpdateCachedViewportState(vpAndScissor); } int maxIndex = indexGen.MaxIndex(); diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index cb1f45aaca..566708480a 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -318,15 +318,13 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag fbManager.GetRenderWidth(), fbManager.GetRenderHeight(), fbManager.GetTargetBufferWidth(), fbManager.GetTargetBufferHeight(), vpAndScissor); + UpdateCachedViewportState(vpAndScissor); float depthMin = vpAndScissor.depthRangeMin; float depthMax = vpAndScissor.depthRangeMax; if (depthMin < 0.0f) depthMin = 0.0f; if (depthMax > 1.0f) depthMax = 1.0f; - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } VkViewport &vp = dynState.viewport; vp.x = vpAndScissor.viewportX; @@ -336,10 +334,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag vp.minDepth = vpAndScissor.depthRangeMin; vp.maxDepth = vpAndScissor.depthRangeMax; - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - ScissorRect &scissor = dynState.scissor; scissor.x = vpAndScissor.scissorX; scissor.y = vpAndScissor.scissorY;