From 116b3ba8cc1d02dd8a15b371a669a1ceddbad8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:24:02 +0100 Subject: [PATCH 01/11] Increase precision of GetDepthScaleFactors to match ToScaledDepthFromIntegerScale --- GPU/Common/GPUStateUtils.cpp | 10 ++++++++-- unittest/UnitTest.cpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 8bbac0b9a2..c4e43bdd5c 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -573,8 +573,14 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { } const double depthSliceFactor = DepthSliceFactor(useFlags); - const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { + const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + const double scale = 16777215.0; + return DepthScaleFactors(offset, scale); + } else { + const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); + return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + } } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index e7fe46e52b..1236349da5 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -810,7 +810,7 @@ static bool TestDepthMath() { GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, // Here, GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT should take precedence over USE_DEPTH_CLAMP. }; - static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f, 65535.0f, 16776960.0f, }; + static const float expectedScale[] = { 65535.0f, 262140.0f, 16777215.0f, 65535.0f, 16777215.0f, }; static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f, 0.0f, 0.498047f, }; EXPECT_REL_EQ_FLOAT(100000.0f, 100001.0f, 0.00001f); @@ -822,7 +822,7 @@ static bool TestDepthMath() { EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); - EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f); + EXPECT_REL_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f, 0.0001f); for (int i = 0; i < ARRAY_SIZE(testValues); i++) { float testValue = testValues[i] * 65535.0f; From 9053d8ccc7c99ec3f87a71d7140aa32affabc12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:25:02 +0100 Subject: [PATCH 02/11] Flip a sign for consistency --- GPU/Common/DepthBufferCommon.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 5d118a4e10..6be46fb107 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -62,7 +62,7 @@ void GenerateDepthDownloadFs(ShaderWriter &writer) { writer.BeginFSMain(depthUniforms, varyings); writer.C(" float depth = ").SampleTexture2D("tex", "v_texcoord").C(".r; \n"); // At this point, clamped maps [0, 1] to [0, 65535]. - writer.C(" float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); + writer.C(" float clamped = clamp((depth - u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); writer.C(" vec4 enc = u_depthShift * clamped;\n"); writer.C(" enc = floor(mod(enc, 256.0)) * u_depthTo8;\n"); writer.C(" vec4 outColor = enc.yzww;\n"); // Let's ignore the bits outside 16 bit precision. @@ -228,9 +228,11 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x ub.u_depthFactor[1] = fudgeFactor; } else { const float factor = DepthSliceFactor(gstate_c.UseFlags()); - ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor); + ub.u_depthFactor[0] = 0.5f * (factor - 1.0f) * (1.0f / factor); ub.u_depthFactor[1] = factor * fudgeFactor; } + + // These are for packing a float in u8x4 colors. We should support more suitable readback formats on APIs that can do it. static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; memcpy(ub.u_depthShift, shifts, sizeof(shifts)); static constexpr float to8[] = { 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f }; From 805591e49335196f286248060c4036a9c8d8b409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:44:10 +0100 Subject: [PATCH 03/11] Replace all uses of ToScaledDepthFromIntegerScale. --- GPU/Common/GPUStateUtils.cpp | 15 +++++++++------ GPU/Common/SoftwareTransformCommon.cpp | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index c4e43bdd5c..0d77d5f2f5 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -575,6 +575,7 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { const double depthSliceFactor = DepthSliceFactor(useFlags); if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). const double scale = 16777215.0; return DepthScaleFactors(offset, scale); } else { @@ -638,6 +639,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo float offsetX = gstate.getOffsetX(); float offsetY = gstate.getOffsetY(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + if (out.throughMode) { // If renderX/renderY are offset to compensate for a split framebuffer, // applying the offset to the viewport isn't enough, since the viewport clips. @@ -646,8 +649,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo out.viewportY = renderY * renderHeightFactor + displayOffsetY; out.viewportW = curRTWidth * renderWidthFactor; out.viewportH = curRTHeight * renderHeightFactor; - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 0.0f); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 65536.0f); + out.depthRangeMin = depthScale.EncodeFromU16(0.0f); + out.depthRangeMax = depthScale.EncodeFromU16(65536.0f); } else { // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. float vpXScale = gstate.getViewportXScale(); @@ -784,11 +787,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { out.depthScale = 1.0f; out.zOffset = 0.0f; - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter - vpZScale); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter + vpZScale); + out.depthRangeMin = depthScale.EncodeFromU16(vpZCenter - vpZScale); + out.depthRangeMax = depthScale.EncodeFromU16(vpZCenter + vpZScale); } else { - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), minz); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), maxz); + out.depthRangeMin = depthScale.EncodeFromU16(minz); + out.depthRangeMax = depthScale.EncodeFromU16(maxz); } // OpenGL will clamp these for us anyway, and Direct3D will error if not clamped. diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index f05117160a..9aff2c301e 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -452,9 +452,10 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt bool matchingComponents = params_.allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil); bool stencilNotMasked = !gstate.isClearModeAlphaMask() || gstate.getStencilWriteMask() == 0x00; if (matchingComponents && stencilNotMasked) { + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); result->color = transformed[1].color0_32; // Need to rescale from a [0, 1] float. This is the final transformed value. - result->depth = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), (int)(transformed[1].z * 65535.0f)); + result->depth = depthScale.EncodeFromU16((float)(int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; gpuStats.numClears++; return; From d40aa17198240f6add2161a0963bb32bc9193606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:45:27 +0100 Subject: [PATCH 04/11] Remove ToScaledDepthFromIntegerScale --- GPU/Common/GPUStateUtils.cpp | 18 ------------------ GPU/Common/GPUStateUtils.h | 3 +-- unittest/UnitTest.cpp | 1 - 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 0d77d5f2f5..54daaf855c 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -548,24 +548,6 @@ float DepthSliceFactor(u32 useFlags) { return DEPTH_SLICE_FACTOR_HIGH; } -// This is used for float values which might not be integers, but are in the integer scale of 0-65535. -float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { - if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { - // Old style depth, shortcut. - return z * (1.0f / 65535.0f); - } - - const float depthSliceFactor = DepthSliceFactor(useFlags); - if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { - const double doffset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; - // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). - return (float)((double)z * (1.0 / 16777215.0) + doffset); - } else { - const float offset = 0.5f * (depthSliceFactor - 1.0f) / depthSliceFactor; - return z / depthSliceFactor * (1.0f / 65535.0f) + offset; - } -} - // See class DepthScaleFactors for how to apply. DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index f3a7338401..ae1abf3be8 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -119,8 +119,7 @@ private: DepthScaleFactors GetDepthScaleFactors(u32 useFlags); -// These two will be replaced with just DepthScaleFactors. -float ToScaledDepthFromIntegerScale(u32 useFlags, float z); +// This will be replaced with just DepthScaleFactors. float DepthSliceFactor(u32 useFlags); // These are common to all modern APIs and can be easily converted with a lookup table. diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 1236349da5..bfe752bb4a 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -830,7 +830,6 @@ static bool TestDepthMath() { float encoded = factors.EncodeFromU16(testValue); float decodedU16 = factors.DecodeToU16(encoded); EXPECT_REL_EQ_FLOAT(decodedU16, testValue, 0.0001f); - EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.000001f); } } From a2c9491a06c9c0329e36569f0e97e3ebb4d61c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 12:23:51 +0100 Subject: [PATCH 05/11] Remove a division by 0 that I hadn't noticed before. --- GPU/Common/ShaderUniforms.cpp | 5 +++-- GPU/Directx9/ShaderManagerDX9.cpp | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 02533b85aa..54d83874a5 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -251,11 +251,12 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float halfDepthPixel = (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float viewZCenter = minz + halfDepthPixel; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index ea341103a9..cb9c1e33b0 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -462,7 +462,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index c7d4d1a7f6..9df5b7f28d 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -588,7 +588,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange; float viewZCenter = minz + halfActualZRange; From 5bdbe6984c531aebb963d281b31a7d8192c1d94f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 13:34:08 +0100 Subject: [PATCH 06/11] Simplify GetDepthScaleFactors --- GPU/Common/GPUStateUtils.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 54daaf855c..e4c095d65a 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -554,15 +554,16 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { return DepthScaleFactors(0.0f, 65535.0f); } - const double depthSliceFactor = DepthSliceFactor(useFlags); if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { - const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + const double offset = 0.5 * (DEPTH_SLICE_FACTOR_16BIT - 1.0) / DEPTH_SLICE_FACTOR_16BIT; // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). const double scale = 16777215.0; return DepthScaleFactors(offset, scale); + } else if (useFlags & GPU_USE_DEPTH_CLAMP) { + return DepthScaleFactors(0.0f, 65535.0f); } else { - const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + const double offset = 0.5f * (DEPTH_SLICE_FACTOR_HIGH - 1.0f) * (1.0f / DEPTH_SLICE_FACTOR_HIGH); + return DepthScaleFactors(offset, (float)(DEPTH_SLICE_FACTOR_HIGH * 65535.0)); } } From 241f8e75bc14e446329851770d5fb11de76a939f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:37:48 +0100 Subject: [PATCH 07/11] Replace some uses of DepthSliceFactor --- GPU/Common/DepthBufferCommon.cpp | 13 +++---------- GPU/Common/GPUStateUtils.cpp | 5 +++-- GPU/Common/GPUStateUtils.h | 3 ++- unittest/UnitTest.cpp | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 6be46fb107..3c78362352 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -221,16 +221,9 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x // Setting this to 0.95f eliminates flickering lights with delayed readback in Syphon Filter. // That's pretty ugly though! But we'll need to do that if we're gonna enable delayed readback in those games. const float fudgeFactor = 1.0f; - - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { - // Don't scale anything, since we're not using factors outside accurate mode. - ub.u_depthFactor[0] = 0.0f; - ub.u_depthFactor[1] = fudgeFactor; - } else { - const float factor = DepthSliceFactor(gstate_c.UseFlags()); - ub.u_depthFactor[0] = 0.5f * (factor - 1.0f) * (1.0f / factor); - ub.u_depthFactor[1] = factor * fudgeFactor; - } + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + ub.u_depthFactor[0] = depthScale.Offset(); + ub.u_depthFactor[1] = depthScale.Scale(); // These are for packing a float in u8x4 colors. We should support more suitable readback formats on APIs that can do it. static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index e4c095d65a..d223283e3f 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -747,7 +747,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // Here, we should "clamp." But clamping per fragment would be slow. // So, instead, we just increase the available range and hope. // If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction. - float fullDepthRange = 65535.0f * (DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) * (1.0f / 2.0f); + float fullDepthRange = 65535.0f * (depthScale.Scale() - 1.0f) * (1.0f / 2.0f); if (minz == 0) { minz -= fullDepthRange; } @@ -758,9 +758,10 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // This means clamp isn't enabled, but we still want to allow values up to 65535.99. // If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1. // Since that would clamp, it would make Z=1234 not match between draws when maxz changes. - if (DepthSliceFactor(gstate_c.UseFlags()) > 1.0f) + if (depthScale.Scale() > 1.0f) maxz = 65535.99f; } + // Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz. float halfActualZRange = (maxz - minz) * (1.0f / 2.0f); out.depthScale = halfActualZRange < std::numeric_limits::epsilon() ? 1.0f : vpZScale / halfActualZRange; diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ae1abf3be8..ed021bbb83 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -108,8 +108,9 @@ public: } float Offset() const { return (float)offset_; } + float ScaleU16() const { return (float)scale_; } - // float Scale() const { return scale_ / 65535.0f; } + float Scale() const { return (float)(scale_ / 65535.0); } private: // Doubles hardly cost anything these days, and precision matters here. diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index bfe752bb4a..5e5f6e8d63 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -822,7 +822,7 @@ static bool TestDepthMath() { EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); - EXPECT_REL_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f, 0.0001f); + EXPECT_REL_EQ_FLOAT(factors.Scale(), DepthSliceFactor(useFlags), 0.0001f); for (int i = 0; i < ARRAY_SIZE(testValues); i++) { float testValue = testValues[i] * 65535.0f; From 99e6fd62f750c97c99db483feaa500dfca7bc428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:41:25 +0100 Subject: [PATCH 08/11] Remove a baffling depth offset I don't quite get --- GPU/Common/ShaderUniforms.cpp | 4 +--- GPU/Directx9/ShaderManagerDX9.cpp | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 54d83874a5..011d09a49b 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -254,9 +254,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; - // Account for the half pixel offset. - float halfDepthPixel = (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; - float viewZCenter = minz + halfDepthPixel; + float viewZCenter = minz; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index cb9c1e33b0..1571d517bd 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -465,8 +465,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; - // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float viewZCenter = minz; float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale); float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f; From 547ecec0741892a98949c52a6e02088b0a7ddabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:45:01 +0100 Subject: [PATCH 09/11] Replace the rest of the uses of DepthSliceFactor --- GPU/Common/FragmentShaderGenerator.cpp | 6 ++++-- GPU/Common/GPUStateUtils.h | 3 --- unittest/UnitTest.cpp | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index c6ee43f9ea..4cd163feab 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -1185,13 +1185,15 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { - const double scale = DepthSliceFactor(gstate_c.UseFlags()) * 65535.0; + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + + const double scale = depthScale.ScaleU16(); WRITE(p, " highp float z = gl_FragCoord.z;\n"); if (gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { // We center the depth with an offset, but only its fraction matters. // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. - if (((int)(DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) & 1) == 1) { + if (((int)(depthScale.Scale() - 1.0f) & 1) == 1) { WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); } else { WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ed021bbb83..a786190f60 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -120,9 +120,6 @@ private: DepthScaleFactors GetDepthScaleFactors(u32 useFlags); -// This will be replaced with just DepthScaleFactors. -float DepthSliceFactor(u32 useFlags); - // These are common to all modern APIs and can be easily converted with a lookup table. enum class BlendFactor : uint8_t { ZERO, diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 5e5f6e8d63..fcbe56f282 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -797,6 +797,8 @@ static bool TestSmallDataConvert() { return true; } +float DepthSliceFactor(u32 useFlags); + static bool TestDepthMath() { // These are in normalized space. static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, M_PI / 4.0f, 0.9f, 1.0f }; From a083a65f77727fbc1cde3c6004fce507826be3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 00:17:49 +0100 Subject: [PATCH 10/11] Depal: Get depth scale factors dynamically --- GPU/Common/DepalettizeShaderCommon.cpp | 5 +---- GPU/Common/Draw2D.cpp | 19 ++++++++++++++----- GPU/Common/Draw2D.h | 6 +++--- GPU/Common/FramebufferManagerCommon.cpp | 6 +++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index d1cd9149af..bca9e5c8dd 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -51,13 +51,10 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { writer.C(" vec2 texcoord = v_texcoord;\n"); // Implement the swizzle we need to simulate, if a game uses 8888 framebuffers and any other mode than "6" to access depth textures. - // This implements the "2" mode swizzle (it fixes up the Y direction but not X. See comments on issue #15898) + // This implements the "2" mode swizzle (it fixes up the Y direction but not X. See comments on issue #15898, Tantalus games) // NOTE: This swizzle can be made to work with any power-of-2 resolution scaleFactor by shifting // the bits around, but not sure how to handle 3x scaling. For now this is 1x-only (rough edges at higher resolutions). if (config.bufferFormat == GE_FORMAT_DEPTH16) { - DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); - writer.ConstFloat("z_scale", factors.ScaleU16()); - writer.ConstFloat("z_offset", factors.Offset()); if (config.depthUpperBits == 0x2) { writer.C(R"( int x = int((texcoord.x / scaleFactor) * texSize.x); diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 61911b2a81..0ffb2a0722 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -39,23 +39,28 @@ static const SamplerDef samplers[1] = { { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, }; -const UniformDef g_draw2Duniforms[2] = { +const UniformDef g_draw2Duniforms[4] = { { "vec2", "texSize", 0 }, { "float", "scaleFactor", 1}, + { "float", "z_scale", 2 }, + { "float", "z_offset", 3 }, }; struct Draw2DUB { float texSizeX; float texSizeY; float scaleFactor; + float zScale; + float zOffset; }; const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), { { "texSize", -1, 0, UniformType::FLOAT2, 0 }, { "scaleFactor", -1, 1, UniformType::FLOAT1, 8 }, + { "z_scale", -1, 1, UniformType::FLOAT1, 12 }, + { "z_offset", -1, 1, UniformType::FLOAT1, 16 }, } }; - Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) { writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings); @@ -95,8 +100,8 @@ Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(ShaderWriter &writer) { writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ - "draw2d_copy_depth", - RASTER_DEPTH, + "draw2d_copy_r16_to_depth", + RASTER_DEPTH, // Unused in this case, I think. RASTER_DEPTH, }; } @@ -319,6 +324,10 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, const Draw2DVertex *verts, int vert ub.texSizeY = tex ? tex->Height() : texH; ub.scaleFactor = (float)scaleFactor; + DepthScaleFactors zScaleFactors = GetDepthScaleFactors(gstate_c.UseFlags()); + ub.zScale = zScaleFactors.Scale(); + ub.zOffset = zScaleFactors.Offset(); + draw_->BindPipeline(pipeline->pipeline); draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub)); @@ -356,7 +365,7 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { pipeline = draw2DPipelineColorRect2Lin_; break; - case DRAW2D_COPY_DEPTH: + case DRAW2D_COPY_R16_TO_DEPTH: if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { // Can't do it return nullptr; diff --git a/GPU/Common/Draw2D.h b/GPU/Common/Draw2D.h index 4d7d728404..4302a3fa2e 100644 --- a/GPU/Common/Draw2D.h +++ b/GPU/Common/Draw2D.h @@ -13,7 +13,7 @@ struct Draw2DVertex { enum Draw2DShader { DRAW2D_COPY_COLOR, - DRAW2D_COPY_DEPTH, + DRAW2D_COPY_R16_TO_DEPTH, DRAW2D_565_TO_DEPTH, DRAW2D_565_TO_DEPTH_DESWIZZLE, DRAW2D_COPY_COLOR_RECT2LIN, @@ -21,7 +21,7 @@ enum Draw2DShader { inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) { switch (shader) { - case DRAW2D_COPY_DEPTH: + case DRAW2D_COPY_R16_TO_DEPTH: return RASTER_DEPTH; case DRAW2D_COPY_COLOR: case DRAW2D_565_TO_DEPTH: @@ -38,7 +38,7 @@ struct Draw2DPipelineInfo { Slice samplers; }; -extern const UniformDef g_draw2Duniforms[2]; +extern const UniformDef g_draw2Duniforms[4]; struct Draw2DPipeline { Draw::Pipeline *pipeline; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 24627f8c72..9768449970 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -974,7 +974,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir // Some GPUs can copy depth but only if stencil gets to come along for the ride. We only want to use this if there is no blit functionality. if (useRaster) { - BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster"); + BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_R16_TO_DEPTH), "BlitDepthRaster"); } else if (useCopy) { draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth"); RebindFramebuffer("After BlitFramebufferDepth"); @@ -3036,7 +3036,7 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa // Rearrange to strip form. std::swap(coord[2], coord[3]); - draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_DEPTH : DRAW2D_COPY_COLOR)); + draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); } @@ -3135,7 +3135,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag); } else { - Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH); + Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_R16_TO_DEPTH); Draw::Framebuffer *srcFBO = src->fbo; if (src == dst) { Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight); From 1938fa44d4de1eb3bc661bccdc1e1e29f9b958d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 09:41:18 +0100 Subject: [PATCH 11/11] Split the depth copy shader into depth copy and depth encode, dynamic depth scale in Draw2D --- GPU/Common/DepalettizeShaderCommon.cpp | 2 +- GPU/Common/Draw2D.cpp | 73 ++++++++++++++++++------- GPU/Common/Draw2D.h | 8 ++- GPU/Common/FramebufferManagerCommon.cpp | 11 ++-- GPU/Common/FramebufferManagerCommon.h | 5 +- 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index bca9e5c8dd..1d3630919c 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -114,7 +114,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { break; case GE_FORMAT_DEPTH16: // Decode depth buffer. - writer.C(" float depth = (color.x - z_offset) * z_scale;\n"); + writer.C(" float depth = (color.x - z_offset) * z_scale * 65535.0f;\n"); if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) { // Convert depth to 565, without going through a CLUT. diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 0ffb2a0722..4f19277956 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -39,11 +39,12 @@ static const SamplerDef samplers[1] = { { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, }; -const UniformDef g_draw2Duniforms[4] = { +const UniformDef g_draw2Duniforms[5] = { { "vec2", "texSize", 0 }, { "float", "scaleFactor", 1}, { "float", "z_scale", 2 }, - { "float", "z_offset", 3 }, + { "float", "z_scale_inv", 3 }, + { "float", "z_offset", 4 }, }; struct Draw2DUB { @@ -51,6 +52,7 @@ struct Draw2DUB { float texSizeY; float scaleFactor; float zScale; + float zScaleInv; float zOffset; }; @@ -58,7 +60,8 @@ const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), { { "texSize", -1, 0, UniformType::FLOAT2, 0 }, { "scaleFactor", -1, 1, UniformType::FLOAT1, 8 }, { "z_scale", -1, 1, UniformType::FLOAT1, 12 }, - { "z_offset", -1, 1, UniformType::FLOAT1, 16 }, + { "z_scale_inv", -1, 1, UniformType::FLOAT1, 16 }, + { "z_offset", -1, 1, UniformType::FLOAT1, 20 }, } }; Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) { @@ -100,23 +103,41 @@ Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(ShaderWriter &writer) { writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ - "draw2d_copy_r16_to_depth", + "draw2d_copy_depth", RASTER_DEPTH, // Unused in this case, I think. RASTER_DEPTH, }; } +Draw2DPipelineInfo GenerateDraw2DEncodeDepthFs(ShaderWriter &writer) { + writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); + writer.DeclareSamplers(samplers); + writer.BeginFSMain(g_draw2Duniforms, varyings); + writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); + writer.C(" float depthValue = ").SampleTexture2D("tex", "v_texcoord.xy").C(".x;\n"); + writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n"); + writer.EndFSMain("outColor"); + + return Draw2DPipelineInfo{ + "draw2d_copy_r16_to_depth", + RASTER_COLOR, + RASTER_DEPTH, + }; +} + Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); writer.DeclareSamplers(samplers); - writer.BeginFSMain(Slice::empty(), varyings); + writer.BeginFSMain(g_draw2Duniforms, varyings); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); // Unlike when just copying a depth buffer, here we're generating new depth values so we'll // have to apply the scaling. DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n"); - writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); + writer.F(" float depthValue = ((floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0)) / 65535.0; \n"); + writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n"); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ @@ -128,6 +149,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); writer.DeclareSamplers(samplers); writer.BeginFSMain(g_draw2Duniforms, varyings); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); @@ -140,11 +162,11 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.C(" float in_strip = mod(coord.y, strip);\n"); writer.C(" coord.y = coord.y - in_strip + strip - in_strip;\n"); writer.C(" coord /= tsize;\n"); - writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n"); - writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); + writer.C(" highp vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n"); + writer.F(" highp float depthValue = floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0; \n"); + writer.C(" gl_FragDepth = z_offset + ((depthValue / 65535.0) * z_scale_inv);\n"); writer.EndFSMain("outColor"); - + return Draw2DPipelineInfo{ "draw2d_565_to_depth_deswizzle", RASTER_COLOR, @@ -253,7 +275,7 @@ Draw2DPipeline *Draw2D::Create2DPipeline(std::functionCreateInputLayout(desc); - BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0 }); + BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0x0 }); DepthStencilStateDesc dsDesc{}; if (info.writeChannel == RASTER_DEPTH) { @@ -326,6 +348,7 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, const Draw2DVertex *verts, int vert DepthScaleFactors zScaleFactors = GetDepthScaleFactors(gstate_c.UseFlags()); ub.zScale = zScaleFactors.Scale(); + ub.zScaleInv = 1.0f / ub.zScale; ub.zOffset = zScaleFactors.Offset(); draw_->BindPipeline(pipeline->pipeline); @@ -352,10 +375,10 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { switch (shader) { case DRAW2D_COPY_COLOR: - if (!draw2DPipelineColor_) { - draw2DPipelineColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs); + if (!draw2DPipelineCopyColor_) { + draw2DPipelineCopyColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs); } - pipeline = draw2DPipelineColor_; + pipeline = draw2DPipelineCopyColor_; break; case DRAW2D_COPY_COLOR_RECT2LIN: @@ -364,16 +387,26 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { } pipeline = draw2DPipelineColorRect2Lin_; break; - - case DRAW2D_COPY_R16_TO_DEPTH: + case DRAW2D_COPY_DEPTH: if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { // Can't do it return nullptr; } - if (!draw2DPipelineDepth_) { - draw2DPipelineDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs); + if (!draw2DPipelineCopyDepth_) { + draw2DPipelineCopyDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs); } - pipeline = draw2DPipelineDepth_; + pipeline = draw2DPipelineCopyDepth_; + break; + + case DRAW2D_ENCODE_R16_TO_DEPTH: + if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + // Can't do it + return nullptr; + } + if (!draw2DPipelineEncodeDepth_) { + draw2DPipelineEncodeDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DEncodeDepthFs); + } + pipeline = draw2DPipelineEncodeDepth_; break; case DRAW2D_565_TO_DEPTH: diff --git a/GPU/Common/Draw2D.h b/GPU/Common/Draw2D.h index 4302a3fa2e..5df67f7493 100644 --- a/GPU/Common/Draw2D.h +++ b/GPU/Common/Draw2D.h @@ -13,7 +13,8 @@ struct Draw2DVertex { enum Draw2DShader { DRAW2D_COPY_COLOR, - DRAW2D_COPY_R16_TO_DEPTH, + DRAW2D_COPY_DEPTH, + DRAW2D_ENCODE_R16_TO_DEPTH, DRAW2D_565_TO_DEPTH, DRAW2D_565_TO_DEPTH_DESWIZZLE, DRAW2D_COPY_COLOR_RECT2LIN, @@ -21,9 +22,10 @@ enum Draw2DShader { inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) { switch (shader) { - case DRAW2D_COPY_R16_TO_DEPTH: + case DRAW2D_COPY_DEPTH: return RASTER_DEPTH; case DRAW2D_COPY_COLOR: + case DRAW2D_ENCODE_R16_TO_DEPTH: case DRAW2D_565_TO_DEPTH: case DRAW2D_565_TO_DEPTH_DESWIZZLE: default: @@ -38,7 +40,7 @@ struct Draw2DPipelineInfo { Slice samplers; }; -extern const UniformDef g_draw2Duniforms[4]; +extern const UniformDef g_draw2Duniforms[5]; struct Draw2DPipeline { Draw::Pipeline *pipeline; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9768449970..05289365e8 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -974,7 +974,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir // Some GPUs can copy depth but only if stencil gets to come along for the ride. We only want to use this if there is no blit functionality. if (useRaster) { - BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_R16_TO_DEPTH), "BlitDepthRaster"); + BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster"); } else if (useCopy) { draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth"); RebindFramebuffer("After BlitFramebufferDepth"); @@ -2964,9 +2964,10 @@ void FramebufferManagerCommon::ReleasePipelines() { DoRelease(stencilReadbackPipeline_); DoRelease(depthReadbackSampler_); DoRelease(depthReadbackPipeline_); - DoRelease(draw2DPipelineColor_); + DoRelease(draw2DPipelineCopyColor_); DoRelease(draw2DPipelineColorRect2Lin_); - DoRelease(draw2DPipelineDepth_); + DoRelease(draw2DPipelineCopyDepth_); + DoRelease(draw2DPipelineEncodeDepth_); DoRelease(draw2DPipeline565ToDepth_); DoRelease(draw2DPipeline565ToDepthDeswizzle_); } @@ -3036,7 +3037,7 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa // Rearrange to strip form. std::swap(coord[2], coord[3]); - draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); + draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_ENCODE_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); } @@ -3135,7 +3136,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag); } else { - Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_R16_TO_DEPTH); + Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH); Draw::Framebuffer *srcFBO = src->fbo; if (src == dst) { Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index df33d549b4..ea4565e6c0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -605,9 +605,10 @@ protected: Draw::SamplerState *depthReadbackSampler_ = nullptr; // Draw2D pipelines - Draw2DPipeline *draw2DPipelineColor_ = nullptr; + Draw2DPipeline *draw2DPipelineCopyColor_ = nullptr; Draw2DPipeline *draw2DPipelineColorRect2Lin_ = nullptr; - Draw2DPipeline *draw2DPipelineDepth_ = nullptr; + Draw2DPipeline *draw2DPipelineCopyDepth_ = nullptr; + Draw2DPipeline *draw2DPipelineEncodeDepth_ = nullptr; Draw2DPipeline *draw2DPipeline565ToDepth_ = nullptr; Draw2DPipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr;