From e5b4b326ca77dbf962fa6d6bd831cdfd4c8f1b64 Mon Sep 17 00:00:00 2001 From: thuanquang Date: Sat, 17 Oct 2026 18:13:41 +0700 Subject: [PATCH] test(agc): accept any NaN where the f16 fma and fma_mix tests expect one agc_driver_f16_fma_denormal_modes and agc_driver_fma_mix_f16_denormal_modes compared NaN results (inf * 0) bit for bit with the RX 6700 XT's, but the NaN bits of f16 arithmetic and of v_fma_mix_f32 with f16 sources are left to the driver, so the tests fail on NVIDIA (0x7fff for 0xfe00). Rows whose expected value is a NaN now accept any NaN; every other row is still exact. Co-Authored-By: Claude Opus 5.5 --- .../tests/execution/F16FmaDenormalModes.cpp | 7 ++++++- .../tests/execution/FmaMixF16DenormalModes.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/F16FmaDenormalModes.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/F16FmaDenormalModes.cpp index 1152f71606..0bf9bf31c7 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/F16FmaDenormalModes.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/F16FmaDenormalModes.cpp @@ -205,13 +205,18 @@ void Run(AgcDriver::VulkanDevice& device, const Mode& mode) { device.WaitIdle(); } +bool Matches(std::uint32_t actual, std::uint32_t expected) { + const auto nan = [](std::uint32_t half) { return (half & 0x7fffu) > 0x7c00u; }; + return actual == expected || (nan(expected) && actual <= 0xffffu && nan(actual)); +} + void Check(const Mode& mode) { constexpr const char* Names[Results] = {"v_fma_f16", "v_fmac_f16"}; for (std::uint32_t tid = 0; tid < Threads; ++tid) { const std::uint32_t expected = Expected[tid][mode.column]; for (std::uint32_t form = 0; form < Results; ++form) { const std::uint32_t actual = Output[tid * Results + form]; - Require(actual == expected, std::string(Names[form]) + " " + mode.name + " of " + Hex(Rows[tid][0]) + ", " + Hex(Rows[tid][1]) + ", " + Hex(Rows[tid][2]) + " is " + Hex(actual) + ", expected " + Hex(expected)); + Require(Matches(actual, expected), std::string(Names[form]) + " " + mode.name + " of " + Hex(Rows[tid][0]) + ", " + Hex(Rows[tid][1]) + ", " + Hex(Rows[tid][2]) + " is " + Hex(actual) + ", expected " + Hex(expected)); } } } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/FmaMixF16DenormalModes.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/FmaMixF16DenormalModes.cpp index 537b0bb483..c772a521e1 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/FmaMixF16DenormalModes.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/FmaMixF16DenormalModes.cpp @@ -166,6 +166,11 @@ void Run(AgcDriver::VulkanDevice& device, const Mode& mode) { device.WaitIdle(); } +bool Matches(std::uint32_t actual, std::uint32_t expected) { + const auto nan = [](std::uint32_t single) { return (single & 0x7fffffffu) > 0x7f800000u; }; + return actual == expected || (nan(expected) && nan(actual)); +} + void Check(const Mode& mode) { constexpr const char* Names[Results] = {"v_fma_mix_f32 of three f16 sources", "v_fma_mix_f32 of an f16, an f32 and an f16 source"}; const std::uint32_t f32Kept = (mode.value.floatMode >> 4u) & 1u; @@ -174,7 +179,7 @@ void Check(const Mode& mode) { for (std::uint32_t form = 0; form < Results; ++form) { const std::uint32_t actual = Output[tid * Results + form]; const std::uint32_t expected = Expected[f32Kept][f16InputsKept][tid][form]; - Require(actual == expected, std::string(Names[form]) + " " + mode.name + " of " + Hex(Rows[tid][0]) + ", " + Hex(Rows[tid][1]) + ", " + Hex(Rows[tid][2]) + " is " + Hex(actual) + ", expected " + Hex(expected)); + Require(Matches(actual, expected), std::string(Names[form]) + " " + mode.name + " of " + Hex(Rows[tid][0]) + ", " + Hex(Rows[tid][1]) + ", " + Hex(Rows[tid][2]) + " is " + Hex(actual) + ", expected " + Hex(expected)); } } }