diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index c15bd4075a..d1cd9149af 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -55,9 +55,9 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { // 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(); - writer.ConstFloat("z_scale", factors.scale); - writer.ConstFloat("z_offset", factors.offset); + 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); @@ -116,7 +116,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { writer.C(" int index = (a << 15) | (b << 10) | (g << 5) | (r);\n"); break; case GE_FORMAT_DEPTH16: - // Remap depth buffer. + // Decode depth buffer. writer.C(" float depth = (color.x - z_offset) * z_scale;\n"); if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) { @@ -161,9 +161,9 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config) { const int mask = config.mask; if (config.bufferFormat == GE_FORMAT_DEPTH16) { - DepthScaleFactors factors = GetDepthScaleFactors(); - writer.ConstFloat("z_scale", factors.scale); - writer.ConstFloat("z_offset", factors.offset); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); + writer.ConstFloat("z_scale", factors.ScaleU16()); + writer.ConstFloat("z_offset", factors.Offset()); } writer.C(" vec4 index = ").SampleTexture2D("tex", "v_texcoord").C(";\n"); diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 2e69260410..5d118a4e10 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -227,7 +227,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x ub.u_depthFactor[0] = 0.0f; ub.u_depthFactor[1] = fudgeFactor; } else { - const float factor = DepthSliceFactor(); + 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; } @@ -276,10 +276,10 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x // We downloaded float values directly in this case. uint16_t *dest = pixels; const float *packedf = (float *)convBuf_; - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); for (int yp = 0; yp < destH; ++yp) { for (int xp = 0; xp < destW; ++xp) { - float scaled = depthScale.Apply(packedf[xp]); + float scaled = depthScale.DecodeToU16(packedf[xp]); if (scaled <= 0.0f) { dest[xp] = 0; } else if (scaled >= 65535.0f) { diff --git a/GPU/Common/DepthBufferCommon.h b/GPU/Common/DepthBufferCommon.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/GPU/Common/DepthBufferCommon.h @@ -0,0 +1 @@ +#pragma once diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 6a37cb2c0d..61911b2a81 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -108,10 +108,10 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { 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(); + 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.scale, factors.offset); + writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ @@ -128,7 +128,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { 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(); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); writer.C(" vec2 tsize = texSize;\n"); writer.C(" vec2 coord = v_texcoord * tsize;\n"); writer.F(" float strip = 4.0 * scaleFactor;\n"); @@ -137,7 +137,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { 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.scale, factors.offset); + writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index d45f8391e7..c6ee43f9ea 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -1185,13 +1185,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { - const double scale = DepthSliceFactor() * 65535.0; + const double scale = DepthSliceFactor(gstate_c.UseFlags()) * 65535.0; 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() - 1.0f) & 1) == 1) { + if (((int)(DepthSliceFactor(gstate_c.UseFlags()) - 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/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index a5332d934c..24627f8c72 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1063,7 +1063,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe float clearDepth = 0.0f; if (vfb->usageFlags & FB_USAGE_INVALIDATE_DEPTH) { depthAction = Draw::RPAction::CLEAR; - clearDepth = GetDepthScaleFactors().offset; + clearDepth = GetDepthScaleFactors(gstate_c.UseFlags()).Offset(); vfb->usageFlags &= ~FB_USAGE_INVALIDATE_DEPTH; } draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, depthAction, Draw::RPAction::KEEP, 0, clearDepth}, "FBSwitch"); diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index ef6fdc9e25..23d156fae2 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -502,25 +502,28 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) { static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f; static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f; -float DepthSliceFactor() { - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { +float DepthSliceFactor(u32 useFlags) { + if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + return 1.0f; + } + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { return DEPTH_SLICE_FACTOR_16BIT; } - if (gstate_c.Use(GPU_USE_DEPTH_CLAMP)) { + if (useFlags & GPU_USE_DEPTH_CLAMP) { return 1.0f; } return DEPTH_SLICE_FACTOR_HIGH; } -// This is used for float values which might not be integers, but are in the integer scale of 65535. -float ToScaledDepthFromIntegerScale(float z) { - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { +// 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)) { return z * (1.0f / 65535.0f); } - const float depthSliceFactor = DepthSliceFactor(); - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { - const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor); + const float depthSliceFactor = DepthSliceFactor(useFlags); + const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor); + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). return (float)((double)z * (1.0 / 16777215.0) + doffset); } else { @@ -529,20 +532,15 @@ float ToScaledDepthFromIntegerScale(float z) { } } -// See struct DepthScaleFactors for how to apply. -DepthScaleFactors GetDepthScaleFactors() { - DepthScaleFactors factors; - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { - factors.offset = 0; - factors.scale = 65535.0f; - return factors; +// See class DepthScaleFactors for how to apply. +DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { + if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + return DepthScaleFactors(0.0f, 65535.0f); } - const float depthSliceFactor = DepthSliceFactor(); + const float depthSliceFactor = DepthSliceFactor(useFlags); const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - factors.scale = depthSliceFactor * 65535.0f; - factors.offset = offset; - return factors; + return DepthScaleFactors(offset, depthSliceFactor * 65535.0f); } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { @@ -608,8 +606,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo out.viewportY = renderY * renderHeightFactor + displayOffsetY; out.viewportW = curRTWidth * renderWidthFactor; out.viewportH = curRTHeight * renderHeightFactor; - out.depthRangeMin = ToScaledDepthFromIntegerScale(0); - out.depthRangeMax = ToScaledDepthFromIntegerScale(65536); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 0.0f); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 65536.0f); } else { // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. float vpXScale = gstate.getViewportXScale(); @@ -723,7 +721,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() - 1.0f) * (1.0f / 2.0f); + float fullDepthRange = 65535.0f * (DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) * (1.0f / 2.0f); if (minz == 0) { minz -= fullDepthRange; } @@ -734,7 +732,7 @@ 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() > 1.0f) + if (DepthSliceFactor(gstate_c.UseFlags()) > 1.0f) maxz = 65535.99f; } // Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz. @@ -746,11 +744,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(vpZCenter - vpZScale); - out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter - vpZScale); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter + vpZScale); } else { - out.depthRangeMin = ToScaledDepthFromIntegerScale(minz); - out.depthRangeMax = ToScaledDepthFromIntegerScale(maxz); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), minz); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), maxz); } // OpenGL will clamp these for us anyway, and Direct3D will error if not clamped. diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ab524f6c3f..8164967a0f 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -86,25 +86,38 @@ struct ViewportAndScissor { 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 { - float offset; - float scale; +class DepthScaleFactors { +public: + // This should only be used from GetDepthScaleFactors. + DepthScaleFactors(float offset, float scale) : offset_(offset), scale_(scale) {} - float Apply(float z) const { - return (z - offset) * scale; + // Decodes a value from a depth buffer to a value of range 0..65536 + float DecodeToU16(float z) const { + return (z - offset_) * scale_; } - float ApplyInverse(float z) const { - return (z / scale) + offset; + // Encodes a value from the range 0..65536 to a normalized depth value (0-1), in the + // range that we write to the depth buffer. + float EncodeFromU16(float z_u16) const { + return (z_u16 / scale_) + offset_; } + + float Offset() const { return offset_; } + float ScaleU16() const { return scale_; } + // float Scale() const { return scale_ / 65535.0f; } + +private: + float offset_; + float scale_; }; -DepthScaleFactors GetDepthScaleFactors(); -float DepthSliceFactor(); +DepthScaleFactors GetDepthScaleFactors(u32 useFlags); +float ToScaledDepthFromIntegerScale(u32 useFlags, float z); +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 { diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 8cfa0c3c55..02533b85aa 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -255,7 +255,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f; + float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 7270cd9b2a..f05117160a 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -454,7 +454,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt if (matchingComponents && stencilNotMasked) { result->color = transformed[1].color0_32; // Need to rescale from a [0, 1] float. This is the final transformed value. - result->depth = ToScaledDepthFromIntegerScale((int)(transformed[1].z * 65535.0f)); + result->depth = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), (int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; gpuStats.numClears++; return; diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 364bafbdf8..58d92756f0 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -74,13 +74,13 @@ bool FramebufferManagerDX9::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, i const u32 *packed = (const u32 *)locked.pBits; u16 *depth = (u16 *)pixels; - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); // TODO: Optimize. for (int yp = 0; yp < h; ++yp) { for (int xp = 0; xp < w; ++xp) { const int offset = (yp + y) * pixelsStride + x + xp; - float scaled = depthScale.Apply((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f)); + float scaled = depthScale.DecodeToU16((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f)); if (scaled <= 0.0f) { depth[offset] = 0; } else if (scaled >= 65535.0f) { diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index e6dc013922..ea341103a9 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -466,7 +466,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f; + float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale); float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 839f52f181..9f7e46432e 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -524,8 +524,10 @@ enum class SubmitType { }; struct GPUStateCache { - bool Use(u32 flags) { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true. - bool UseAll(u32 flags) { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true. + bool Use(u32 flags) const { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true. + bool UseAll(u32 flags) const { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true. + + u32 UseFlags() const { return useFlags_; } uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; } void Dirty(u64 what) { diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index f9496f13f9..ae35d85ab6 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -839,9 +839,9 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, case GPU_DBG_FORMAT_24BIT_8X: { - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); // These are only ever going to be depth values, so let's also show scaled to 16 bit. - snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.Apply((pix & 0x00FFFFFF) * (1.0f / 16777215.0f))); + snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f))); break; } @@ -860,8 +860,8 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, case GPU_DBG_FORMAT_FLOAT: { float pixf = *(float *)&pix; - DepthScaleFactors depthScale = GetDepthScaleFactors(); - snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.Apply(pixf)); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf)); break; } @@ -870,11 +870,11 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, double z = *(float *)&pix; int z24 = (int)(z * 16777215.0); - DepthScaleFactors factors = GetDepthScaleFactors(); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); // TODO: Use GetDepthScaleFactors here too, verify it's the same. int z16 = z24 - 0x800000 + 0x8000; - int z16_2 = factors.Apply(z); + int z16_2 = factors.DecodeToU16(z); snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0); } diff --git a/ext/armips b/ext/armips index 7bd1ec93d4..6719edebaa 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e +Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5 diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 05d2d35475..2212b5af65 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -61,6 +61,7 @@ #include "Core/MemMap.h" #include "Core/MIPS/MIPSVFPUUtils.h" #include "GPU/Common/TextureDecoder.h" +#include "GPU/Common/GPUStateUtils.h" #include "android/jni/AndroidContentURI.h" @@ -795,6 +796,44 @@ static bool TestSmallDataConvert() { return true; } +static bool TestDepthMath() { + // Flag combinations that can happen: + // 0 + // GPU_USE_ACCURATE_DEPTH + // GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT + // What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? + + // These are in normalized space. + static const float testValues[] = { 0.0f * 65535.0f, 0.1f * 65535.0f, 0.9f * 65535.0f, 1.0f * 65535.0f }; + + static const u32 useFlagsArray[] = { + 0, + GPU_USE_ACCURATE_DEPTH, + GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, + }; + static const float expectedScale[] = { 65535.0f, 262140.0f, -1.0f }; + static const float expectedOffset[] = { 0.0f, 0.375f, -2.0f }; + + for (int j = 0; j < ARRAY_SIZE(useFlagsArray); j++) { + u32 useFlags = useFlagsArray[j]; + printf("j: %d useflags: %d\n", j, useFlags); + DepthScaleFactors factors = GetDepthScaleFactors(useFlags); + + EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); + EXPECT_EQ_FLOAT(factors.Offset(), expectedOffset[j]); + EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f); + + for (int i = 0; i < ARRAY_SIZE(testValues); i++) { + float encoded = factors.EncodeFromU16(testValues[i]); + float decodedU16 = factors.DecodeToU16(encoded); + EXPECT_EQ_FLOAT(decodedU16, testValues[i]); + EXPECT_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValues[i])); + } + } + + return true; +} + typedef bool (*TestFunc)(); struct TestItem { const char *name; @@ -846,6 +885,7 @@ TestItem availableTests[] = { TEST_ITEM(WrapText), TEST_ITEM(TinySet), TEST_ITEM(SmallDataConvert), + TEST_ITEM(DepthMath), }; int main(int argc, const char *argv[]) {