From 8b274aeb33689b5967d82873a98b92a5ffff3c36 Mon Sep 17 00:00:00 2001 From: Kevin Wheatley Date: Wed, 24 Dec 2025 13:04:48 +0000 Subject: [PATCH 1/3] Add test to reproduce bug 2220 Code incorrectly deals with edge cases where atan2() returns end of range [-pi, pi] Signed-off-by: Kevin Wheatley --- .../FixedFunctionOpCPU_tests.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp b/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp index 9593c9cd8..f1a27c5ae 100644 --- a/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp +++ b/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp @@ -586,6 +586,33 @@ OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_rec709_100n_rt) __LINE__); } +OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_edge_cases) +{ + constexpr int test_cases = 2; + constexpr int num_channels = 4; + std::array input_32f = { + 0.0f, 0.0f, 0.0f, 1.0f, + 0.742242277f, 0.0931933373f, 0.321542144f, 1.0f // Bug 2220: related to hue angle calculation not wrapping + }; + constexpr std::array expected_32f = { + 0.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + + OCIO::FixedFunctionOpData::Params params = { + // Peak luminance + 100.f, + // Rec709 gamut + 0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600, 0.3127, 0.3290 + }; + + OCIO::ConstFixedFunctionOpDataRcPtr funcData + = std::make_shared(OCIO::FixedFunctionOpData::ACES_OUTPUT_TRANSFORM_20_FWD, + params); + + ApplyFixedFunction(input_32f.data(), expected_32f.data(), test_cases, funcData, 1e-6f, __LINE__); +} + OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_p3d65_100n_rt) { const int lut_size = 8; From f774cbeee79d4eba110acf960d74bb617bff0213 Mon Sep 17 00:00:00 2001 From: Kevin Wheatley Date: Wed, 24 Dec 2025 14:08:14 +0000 Subject: [PATCH 2/3] Extend tables to have an additonal entry to allow for boundary condition to not over flow table bounds during lookup All tables are now 1 entry larger and should have valid data wrapped into the extra entries Signed-off-by: Kevin Wheatley --- .../ops/fixedfunction/ACES2/Common.h | 7 +++-- .../ops/fixedfunction/ACES2/Transform.cpp | 30 +++++++++++-------- .../FixedFunctionOpCPU_tests.cpp | 7 +++-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/OpenColorIO/ops/fixedfunction/ACES2/Common.h b/src/OpenColorIO/ops/fixedfunction/ACES2/Common.h index 18f012363..2bfa79c90 100644 --- a/src/OpenColorIO/ops/fixedfunction/ACES2/Common.h +++ b/src/OpenColorIO/ops/fixedfunction/ACES2/Common.h @@ -47,10 +47,11 @@ inline float from_radians(const float v) { return wrap_to_hue_limit(v); }; struct TableBase { - static constexpr unsigned int _TABLE_ADDITION_ENTRIES = 2; - static constexpr unsigned int base_index = 1; + static constexpr unsigned int _TABLE_ADDITION_LOWER_ENTRIES = 1; + static constexpr unsigned int _TABLE_ADDITION_UPPER_ENTRIES = 2; + static constexpr unsigned int base_index = _TABLE_ADDITION_LOWER_ENTRIES; static constexpr unsigned int nominal_size = 360; - static constexpr unsigned int total_size = nominal_size + _TABLE_ADDITION_ENTRIES; + static constexpr unsigned int total_size = nominal_size + _TABLE_ADDITION_LOWER_ENTRIES + _TABLE_ADDITION_UPPER_ENTRIES; static constexpr unsigned int lower_wrap_index = 0; static constexpr unsigned int upper_wrap_index = base_index + nominal_size; diff --git a/src/OpenColorIO/ops/fixedfunction/ACES2/Transform.cpp b/src/OpenColorIO/ops/fixedfunction/ACES2/Transform.cpp index d3bd1771e..889c2a90b 100644 --- a/src/OpenColorIO/ops/fixedfunction/ACES2/Transform.cpp +++ b/src/OpenColorIO/ops/fixedfunction/ACES2/Transform.cpp @@ -730,8 +730,9 @@ void build_hue_table(Table1D &hue_table, const std::array find_display_cusp_for_hue(float hue, const std::array& RGB_corners, const std::array& JMh_corners, @@ -820,12 +821,15 @@ Table3D build_cusp_table(const Table1D& hue_table, const std::array input_32f = { 0.0f, 0.0f, 0.0f, 1.0f, - 0.742242277f, 0.0931933373f, 0.321542144f, 1.0f // Bug 2220: related to hue angle calculation not wrapping + 0.742242277f, 0.0931933373f, 0.321542144f, 1.0f // Bug #2220: related to hue angle calculation not wrapping }; constexpr std::array expected_32f = { 0.0f, 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 1.0f, + 0.74736571311951f, -0.0019352473318577f, 0.19451357424259f, 1.0f, // Note: exact output value is not significant to + // the test as the bug is in the internal logic }; OCIO::FixedFunctionOpData::Params params = { @@ -610,7 +611,7 @@ OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_edge_cases) = std::make_shared(OCIO::FixedFunctionOpData::ACES_OUTPUT_TRANSFORM_20_FWD, params); - ApplyFixedFunction(input_32f.data(), expected_32f.data(), test_cases, funcData, 1e-6f, __LINE__); + ApplyFixedFunction(input_32f.data(), expected_32f.data(), test_cases, funcData, 1e-4f, __LINE__); } OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_p3d65_100n_rt) From 2941cc5fa8e1322c13029a97383fc2583a2e539f Mon Sep 17 00:00:00 2001 From: Kevin Wheatley Date: Wed, 24 Dec 2025 15:14:09 +0000 Subject: [PATCH 3/3] Clarify ACES OT 2.0 edge-case test comments around hue-angle table access bug Signed-off-by: Kevin Wheatley --- tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp b/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp index 94000a675..7af081d04 100644 --- a/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp +++ b/tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp @@ -592,12 +592,15 @@ OCIO_ADD_TEST(FixedFunctionOpCPU, aces_ot_20_edge_cases) constexpr int num_channels = 4; std::array input_32f = { 0.0f, 0.0f, 0.0f, 1.0f, - 0.742242277f, 0.0931933373f, 0.321542144f, 1.0f // Bug #2220: related to hue angle calculation not wrapping + 0.742242277f, 0.0931933373f, 0.321542144f, 1.0f // Bug #2220: related to hue angle calculation + // triggering an out of bounds access in the tables + // at exactly 360 degrees }; constexpr std::array expected_32f = { 0.0f, 0.0f, 0.0f, 1.0f, - 0.74736571311951f, -0.0019352473318577f, 0.19451357424259f, 1.0f, // Note: exact output value is not significant to - // the test as the bug is in the internal logic + 0.74736571311951f, -0.0019352473318577f, 0.19451357424259f, 1.0f, // Note: exact output value is not + // significant to the test as the bug + // was in the internal table access logic }; OCIO::FixedFunctionOpData::Params params = {