From 8d40684833a3303ddfd4e86b3e95c0d0f4ff6b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 14:34:33 +0100 Subject: [PATCH] Make the test pass, add some commented-out failing ones --- GPU/Common/GPUStateUtils.cpp | 6 +++--- GPU/Common/GPUStateUtils.h | 10 +++++----- unittest/UnitTest.cpp | 24 ++++++++++++++++-------- unittest/UnitTest.h | 17 ++++++++++++++++- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 23d156fae2..b7c3bb65ae 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -522,13 +522,13 @@ float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { } 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) { + 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) * (1.0f / depthSliceFactor); - return z * (1.0f / depthSliceFactor) * (1.0f / 65535.0f) + offset; + const float offset = 0.5f * (depthSliceFactor - 1.0f) / depthSliceFactor; + return z / depthSliceFactor * (1.0f / 65535.0f) + offset; } } diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 8164967a0f..5d4406ac5a 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -93,7 +93,7 @@ void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); class DepthScaleFactors { public: // This should only be used from GetDepthScaleFactors. - DepthScaleFactors(float offset, float scale) : offset_(offset), scale_(scale) {} + DepthScaleFactors(double offset, double scale) : offset_(offset), scale_(scale) {} // Decodes a value from a depth buffer to a value of range 0..65536 float DecodeToU16(float z) const { @@ -106,13 +106,13 @@ public: return (z_u16 / scale_) + offset_; } - float Offset() const { return offset_; } - float ScaleU16() const { return scale_; } + float Offset() const { return (float)offset_; } + float ScaleU16() const { return (float)scale_; } // float Scale() const { return scale_ / 65535.0f; } private: - float offset_; - float scale_; + double offset_; + double scale_; }; DepthScaleFactors GetDepthScaleFactors(u32 useFlags); diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 2212b5af65..9d5027b1ec 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -29,6 +29,7 @@ #include "ppsspp_config.h" +#include #include #include #include @@ -801,18 +802,23 @@ static bool TestDepthMath() { // 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? + // + // TODO: 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 volatile float testValues[] = { 0.0f, 0.1f, 0.5f, 0.9f, 1.0f }; static const u32 useFlagsArray[] = { 0, GPU_USE_ACCURATE_DEPTH, GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, + // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, fails + // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, fails }; - static const float expectedScale[] = { 65535.0f, 262140.0f, -1.0f }; - static const float expectedOffset[] = { 0.0f, 0.375f, -2.0f }; + static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f }; + static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f }; + + EXPECT_REL_EQ_FLOAT(100000.0f, 100001.0f, 0.00001f); for (int j = 0; j < ARRAY_SIZE(useFlagsArray); j++) { u32 useFlags = useFlagsArray[j]; @@ -820,14 +826,16 @@ static bool TestDepthMath() { DepthScaleFactors factors = GetDepthScaleFactors(useFlags); EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); - EXPECT_EQ_FLOAT(factors.Offset(), expectedOffset[j]); + EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); 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 testValue = testValues[i] * 65535.0f; + + float encoded = factors.EncodeFromU16(testValue); float decodedU16 = factors.DecodeToU16(encoded); - EXPECT_EQ_FLOAT(decodedU16, testValues[i]); - EXPECT_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValues[i])); + EXPECT_REL_EQ_FLOAT(decodedU16, testValue, 0.0001f); + EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.00001f); } } diff --git a/unittest/UnitTest.h b/unittest/UnitTest.h index 2267a7a87f..37c02b091c 100644 --- a/unittest/UnitTest.h +++ b/unittest/UnitTest.h @@ -1,11 +1,26 @@ #pragma once +#include +#include + +inline bool rel_equal(float a, float b, float precision) { + float diff = fabsf(a - b); + if (diff == 0.0f) { + return true; + } + float range = std::max(fabsf(a), fabsf(b)); + float quot = diff / range; + return quot < precision; +} + + #define EXPECT_TRUE(a) if (!(a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; } #define EXPECT_FALSE(a) if ((a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; } #define EXPECT_EQ_INT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%d\nvs\n%d\n", __FUNCTION__, __LINE__, (int)(a), (int)(b)); return false; } #define EXPECT_EQ_HEX(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%x\nvs\n%x\n", __FUNCTION__, __LINE__, a, b); return false; } -#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); return false; } +#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); return false; } #define EXPECT_APPROX_EQ_FLOAT(a, b) if (fabsf((a)-(b))>0.00001f) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } +#define EXPECT_REL_EQ_FLOAT(a, b, precision) if (!rel_equal(a, b, precision)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } #define EXPECT_EQ_STR(a, b) if (a != b) { printf("%s: Test Fail\n%s\nvs\n%s\n", __FUNCTION__, a.c_str(), b.c_str()); return false; } #define RET(a) if (!(a)) { return false; }