From eae85836c9eedb0d8cf5e910af5b98d3bff0ca57 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 12 Nov 2022 20:01:46 -0800 Subject: [PATCH] GPU: Add a small error-compensation to depth clip. This was causing a depth that should've calculated as zero to be clipped, because the multiply and division resulted in a value that was off by about 2 / pow(2, 24) in the negative direction. --- GPU/Common/GeometryShaderGenerator.cpp | 6 ++++-- GPU/Common/VertexShaderGenerator.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/GPU/Common/GeometryShaderGenerator.cpp b/GPU/Common/GeometryShaderGenerator.cpp index 12bf25a550bd..8c24fa97313b 100644 --- a/GPU/Common/GeometryShaderGenerator.cpp +++ b/GPU/Common/GeometryShaderGenerator.cpp @@ -123,7 +123,8 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu if (!gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { // This is basically the same value as gl_ClipDistance would take, z + w. if (vertexRangeCulling) { - p.C(" clip0[i] = projZ * outPos.w + outPos.w;\n"); + // We add a small amount to prevent error as in #15816 (PSP Z is only 16-bit fixed point, anyway.) + p.F(" clip0[i] = projZ * outPos.w + outPos.w + %f;\n", 0.0625 / 65536.0); } else { // Let's not complicate the code overly for this case. We'll clipClampedDepth. p.C(" clip0[i] = 0.0;\n"); @@ -290,7 +291,8 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLangu p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", clipSuffix1); } else { // We shouldn't need to worry about rectangles-as-triangles here, since we don't use geometry shaders for that. - p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", clipSuffix0); + // We add a small amount to prevent error as in #15816 (PSP Z is only 16-bit fixed point, anyway.) + p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w + %f;\n", clipSuffix0, 0.0625 / 65536.0); } p.C(" gl_Position = outPos;\n"); if (gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 70fc803dd1c2..57e5e9675fa1 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -1328,7 +1328,8 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag const char *cull1 = compat.shaderLanguage == HLSL_D3D11 ? ".y" : "[1]"; if (gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { // TODO: Ignore triangles from GE_PRIM_RECTANGLES in transform mode, which should not clip to neg z. - WRITE(p, " %sgl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", compat.vsOutPrefix, vertexRangeClipSuffix); + // We add a small amount to prevent error as in #15816 (PSP Z is only 16-bit fixed point, anyway.) + WRITE(p, " %sgl_ClipDistance%s = projZ * outPos.w + outPos.w + %f;\n", compat.vsOutPrefix, vertexRangeClipSuffix, 0.0625 / 65536.0); } if (gstate_c.Use(GPU_USE_CULL_DISTANCE)) { // Cull any triangle fully outside in the same direction when depth clamp enabled.