From 849459ce9d80a58483c69174983af97b772947b8 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 27 May 2025 11:51:32 -0700 Subject: [PATCH 1/4] adopt changes from dxc for comparing float16s --- lib/Support/Check.cpp | 17 ++++++++++++++-- test/Tools/Offloader/BufferFuzzy-16bit.test | 22 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/Support/Check.cpp b/lib/Support/Check.cpp index 42bc8fae4..3baef0d60 100644 --- a/lib/Support/Check.cpp +++ b/lib/Support/Check.cpp @@ -14,6 +14,8 @@ #include "llvm/Support/raw_ostream.h" #include +#define FLOAT16_BIT_SIGN 0x8000 + // limited to float, double, and long double template static bool isDenorm(T F) { return std::fpclassify(F) == FP_SUBNORMAL; @@ -64,13 +66,24 @@ static bool compareFloatULP(const float &FSrc, const float &FRef, static bool compareFloat16ULP(const uint16_t &FSrc, const uint16_t &FRef, unsigned ULPTolerance) { + // Treat +0 and -0 as equal + if ((FSrc & ~FLOAT16_BIT_SIGN) == 0 && (FRef & ~FLOAT16_BIT_SIGN) == 0) + return true; if (FSrc == FRef) return true; if (isFloat16NAN(FSrc) || isFloat16NAN(FRef)) return isFloat16NAN(FRef) && isFloat16NAN(FSrc); + + // Map to monotonic ordering for correct ULP diff + auto toOrdered = [](uint16_t H) -> int { + return (H & FLOAT16_BIT_SIGN) ? (~H & 0xFFFF) : (H | 0x8000); + }; + // 16-bit floating point numbers must preserve denorms - const int Diff = FSrc - FRef; - const unsigned int AbsDiff = Diff < 0 ? -Diff : Diff; + int IntFSrc = toOrdered(FSrc); + int IntFRef = toOrdered(FRef); + int Diff = IntFSrc - IntFRef; + unsigned int AbsDiff = Diff < 0 ? -Diff : Diff; return AbsDiff <= ULPTolerance; } diff --git a/test/Tools/Offloader/BufferFuzzy-16bit.test b/test/Tools/Offloader/BufferFuzzy-16bit.test index e3e687e04..f392a7aef 100644 --- a/test/Tools/Offloader/BufferFuzzy-16bit.test +++ b/test/Tools/Offloader/BufferFuzzy-16bit.test @@ -4,6 +4,7 @@ RWStructuredBuffer Out1 : register(u0); RWStructuredBuffer Out2 : register(u1); RWStructuredBuffer Out3 : register(u2); RWStructuredBuffer Out4 : register(u3); +RWStructuredBuffer Out5 : register(u4); [numthreads(1,1,1)] void main() { @@ -11,6 +12,7 @@ void main() { Out2[0] = (half)(0.0 / 0.0); // Should be NaN Out3[0] = (half)5.40234375; Out4[0] = (half)6.40234375; + Out5[0] = (half)-0.0; } //--- pipeline.yaml @@ -53,6 +55,14 @@ Buffers: Format: Float16 Stride: 2 Data: [ 0x4665, 0 ] # Should be 2 ulp away + - Name: Out5 + Format: Float16 + Stride: 2 + ZeroInitSize: 4 + - Name: Expected5 + Format: Float16 + Stride: 2 + Data: [ 0, 0 ] # compare negative and positive zero Results: - Result: Test1 # Test two values are exactly the same Rule: BufferFuzzy @@ -74,6 +84,11 @@ Results: ULPT: 2 Actual: Out4 Expected: Expected4 + - Result: Test5 # +0 and -0 should be equal + Rule: BufferFuzzy + ULPT: 0 + Actual: Out5 + Expected: Expected5 DescriptorSets: - Resources: - Name: Out1 @@ -104,6 +119,13 @@ DescriptorSets: Space: 0 VulkanBinding: Binding: 3 + - Name: Out5 + Kind: RWStructuredBuffer + DirectXBinding: + Register: 4 + Space: 0 + VulkanBinding: + Binding: 4 ... #--- end From d23caee6965d94f4874f43750594b1bea2c03395 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 27 May 2025 16:42:54 -0700 Subject: [PATCH 2/4] respond to pr comments --- lib/Support/Check.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Support/Check.cpp b/lib/Support/Check.cpp index 3baef0d60..76539310a 100644 --- a/lib/Support/Check.cpp +++ b/lib/Support/Check.cpp @@ -14,7 +14,10 @@ #include "llvm/Support/raw_ostream.h" #include -#define FLOAT16_BIT_SIGN 0x8000 +constexpr uint16_t FLOAT16_BIT_SIGN = 0x8000; +constexpr uint16_t FLOAT16_BIT_EXP = 0x7c00; +constexpr uint16_t FLOAT16_BIT_MANTISSA = 0x03ff; + // limited to float, double, and long double template static bool isDenorm(T F) { @@ -22,7 +25,7 @@ template static bool isDenorm(T F) { } static bool isFloat16NAN(uint16_t Val) { - return (Val & 0x7c00) == 0x7c00 && (Val & 0x03ff) != 0; + return (Val & FLOAT16_BIT_EXP) == FLOAT16_BIT_EXP && (Val & FLOAT16_BIT_MANTISSA) != 0; } static bool compareDoubleULP(const double &FSrc, const double &FRef, From 220232af42da086c7429190e99ac4ea48f95fe90 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Tue, 27 May 2025 16:43:57 -0700 Subject: [PATCH 3/4] clang format --- lib/Support/Check.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Support/Check.cpp b/lib/Support/Check.cpp index 76539310a..7cfe8f5c4 100644 --- a/lib/Support/Check.cpp +++ b/lib/Support/Check.cpp @@ -18,14 +18,14 @@ constexpr uint16_t FLOAT16_BIT_SIGN = 0x8000; constexpr uint16_t FLOAT16_BIT_EXP = 0x7c00; constexpr uint16_t FLOAT16_BIT_MANTISSA = 0x03ff; - // limited to float, double, and long double template static bool isDenorm(T F) { return std::fpclassify(F) == FP_SUBNORMAL; } static bool isFloat16NAN(uint16_t Val) { - return (Val & FLOAT16_BIT_EXP) == FLOAT16_BIT_EXP && (Val & FLOAT16_BIT_MANTISSA) != 0; + return (Val & FLOAT16_BIT_EXP) == FLOAT16_BIT_EXP && + (Val & FLOAT16_BIT_MANTISSA) != 0; } static bool compareDoubleULP(const double &FSrc, const double &FRef, From 973184813f9fc64b9aa735594008db35787e8fb3 Mon Sep 17 00:00:00 2001 From: Sarah Spall Date: Wed, 28 May 2025 07:52:20 -0700 Subject: [PATCH 4/4] fix warnings as errors --- lib/Support/Check.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/Support/Check.cpp b/lib/Support/Check.cpp index 7cfe8f5c4..f0e0a1935 100644 --- a/lib/Support/Check.cpp +++ b/lib/Support/Check.cpp @@ -14,9 +14,9 @@ #include "llvm/Support/raw_ostream.h" #include -constexpr uint16_t FLOAT16_BIT_SIGN = 0x8000; -constexpr uint16_t FLOAT16_BIT_EXP = 0x7c00; -constexpr uint16_t FLOAT16_BIT_MANTISSA = 0x03ff; +constexpr uint16_t Float16BitSign = 0x8000; +constexpr uint16_t Float16BitExp = 0x7c00; +constexpr uint16_t Float16BitMantissa = 0x03ff; // limited to float, double, and long double template static bool isDenorm(T F) { @@ -24,8 +24,8 @@ template static bool isDenorm(T F) { } static bool isFloat16NAN(uint16_t Val) { - return (Val & FLOAT16_BIT_EXP) == FLOAT16_BIT_EXP && - (Val & FLOAT16_BIT_MANTISSA) != 0; + return (Val & Float16BitExp) == Float16BitExp && + (Val & Float16BitMantissa) != 0; } static bool compareDoubleULP(const double &FSrc, const double &FRef, @@ -70,7 +70,7 @@ static bool compareFloatULP(const float &FSrc, const float &FRef, static bool compareFloat16ULP(const uint16_t &FSrc, const uint16_t &FRef, unsigned ULPTolerance) { // Treat +0 and -0 as equal - if ((FSrc & ~FLOAT16_BIT_SIGN) == 0 && (FRef & ~FLOAT16_BIT_SIGN) == 0) + if ((FSrc & ~Float16BitSign) == 0 && (FRef & ~Float16BitSign) == 0) return true; if (FSrc == FRef) return true; @@ -78,15 +78,15 @@ static bool compareFloat16ULP(const uint16_t &FSrc, const uint16_t &FRef, return isFloat16NAN(FRef) && isFloat16NAN(FSrc); // Map to monotonic ordering for correct ULP diff - auto toOrdered = [](uint16_t H) -> int { - return (H & FLOAT16_BIT_SIGN) ? (~H & 0xFFFF) : (H | 0x8000); + auto ToOrdered = [](uint16_t H) -> int { + return (H & Float16BitSign) ? (~H & 0xFFFF) : (H | Float16BitSign); }; // 16-bit floating point numbers must preserve denorms - int IntFSrc = toOrdered(FSrc); - int IntFRef = toOrdered(FRef); - int Diff = IntFSrc - IntFRef; - unsigned int AbsDiff = Diff < 0 ? -Diff : Diff; + const int IntFSrc = ToOrdered(FSrc); + const int IntFRef = ToOrdered(FRef); + const int Diff = IntFSrc - IntFRef; + const unsigned int AbsDiff = Diff < 0 ? -Diff : Diff; return AbsDiff <= ULPTolerance; }