Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAras Pranckevicius <aras@nesnausk.org>2022-06-15 20:51:12 +0300
committerAras Pranckevicius <aras@nesnausk.org>2022-06-15 20:51:25 +0300
commit004d858138fced20d45cf3cc0149fcef1922c8a0 (patch)
tree456ba308c9119d6796c85b93467485174b64dcc8 /source/blender/blenlib/tests/BLI_math_color_test.cc
parent7e89bbb2ff3e060807beaef200d9173befeba528 (diff)
math: improve accuracy of Linear->sRGB conversion SIMD path
srgb_to_linearrgb_v3_v3 is using an approximation of powf that is SIMD. However, while the accuracy of it is ok, a larger issue is that it produces different results on Intel compared to ARM architectures. On ARM (e.g. AppleSilicon), the result of the SIMD code path is much closer to the reference implementation. This seems to be because of _mm_rsqrt_ps usage in _bli_math_fastpow512. The ARM/NEON code path emulates inverse square root with a combination of vrsqrteq_f32 followed by two Newton-Raphson iterations, because blender uses the SSE2NEON_PRECISE_SQRT define. This commit adds similar NR iterations to the "actual SSE" code path as well. Max error of srgb->linear->srgb conversion roundtrip goes from 0.000211 down to about 0.000062. Reviewed By: Sergey Sharybin Differential Revision: https://developer.blender.org/D15193
Diffstat (limited to 'source/blender/blenlib/tests/BLI_math_color_test.cc')
-rw-r--r--source/blender/blenlib/tests/BLI_math_color_test.cc68
1 files changed, 68 insertions, 0 deletions
diff --git a/source/blender/blenlib/tests/BLI_math_color_test.cc b/source/blender/blenlib/tests/BLI_math_color_test.cc
index 7f2c0a3f1ca..4d928477870 100644
--- a/source/blender/blenlib/tests/BLI_math_color_test.cc
+++ b/source/blender/blenlib/tests/BLI_math_color_test.cc
@@ -74,3 +74,71 @@ TEST(math_color, LinearRGBTosRGBRoundtrip)
EXPECT_NEAR(orig_linear_color, linear_color, 1e-5);
}
}
+
+TEST(math_color, linearrgb_to_srgb_v3_v3)
+{
+ float srgb_color[3];
+ {
+ const float kTolerance = 1.0e-8f;
+ const float linear_color[3] = {0.0023f, 0.0024f, 0.0025f};
+ linearrgb_to_srgb_v3_v3(srgb_color, linear_color);
+ EXPECT_NEAR(0.029716f, srgb_color[0], kTolerance);
+ EXPECT_NEAR(0.031008f, srgb_color[1], kTolerance);
+ EXPECT_NEAR(0.032300f, srgb_color[2], kTolerance);
+ }
+
+ {
+ /* SIMD implementation of linear->srgb for larger inputs
+ * is less accurate; use larger tolerance. */
+ const float kTolerance = 3.6e-5f;
+ const float linear_color[3] = {0.71f, 0.75f, 0.78f};
+ linearrgb_to_srgb_v3_v3(srgb_color, linear_color);
+ EXPECT_NEAR(0.859696f, srgb_color[0], kTolerance);
+ EXPECT_NEAR(0.880825f, srgb_color[1], kTolerance);
+ EXPECT_NEAR(0.896244f, srgb_color[2], kTolerance);
+ }
+
+ {
+ /* Not a common, but possible case: values beyond 1.0 range. */
+ const float kTolerance = 2.3e-4f;
+ const float linear_color[3] = {1.5f, 2.8f, 5.6f};
+ linearrgb_to_srgb_v3_v3(srgb_color, linear_color);
+ EXPECT_NEAR(1.19418f, srgb_color[0], kTolerance);
+ EXPECT_NEAR(1.56520f, srgb_color[1], kTolerance);
+ EXPECT_NEAR(2.10771f, srgb_color[2], kTolerance);
+ }
+}
+
+TEST(math_color, srgb_to_linearrgb_v3_v3)
+{
+ float linear_color[3];
+ {
+ const float kTolerance = 1.0e-8f;
+ const float srgb_color[3] = {0.0023f, 0.0024f, 0.0025f};
+ srgb_to_linearrgb_v3_v3(linear_color, srgb_color);
+ EXPECT_NEAR(0.000178019f, linear_color[0], kTolerance);
+ EXPECT_NEAR(0.000185759f, linear_color[1], kTolerance);
+ EXPECT_NEAR(0.000193498f, linear_color[2], kTolerance);
+ }
+
+ {
+ /* SIMD implementation of linear->srgb for larger inputs
+ * is less accurate; use larger tolerance. */
+ const float kTolerance = 1.5e-7f;
+ const float srgb_color[3] = {0.71f, 0.72f, 0.73f};
+ srgb_to_linearrgb_v3_v3(linear_color, srgb_color);
+ EXPECT_NEAR(0.4623615f, linear_color[0], kTolerance);
+ EXPECT_NEAR(0.4770000f, linear_color[1], kTolerance);
+ EXPECT_NEAR(0.4919052f, linear_color[2], kTolerance);
+ }
+
+ {
+ /* Not a common, but possible case: values beyond 1.0 range. */
+ const float kTolerance = 7.7e-6f;
+ const float srgb_color[3] = {1.1f, 2.5f, 5.6f};
+ srgb_to_linearrgb_v3_v3(linear_color, srgb_color);
+ EXPECT_NEAR(1.24277f, linear_color[0], kTolerance);
+ EXPECT_NEAR(8.35473f, linear_color[1], kTolerance);
+ EXPECT_NEAR(56.23833f, linear_color[2], kTolerance);
+ }
+}