Skip to content

Commit 6d23f0c

Browse files
authored
Update ULP comparison support for Float16 to reflect changes in DXC (#207)
* adopt changes from dxc for comparing float16s * respond to pr comments * clang format * fix warnings as errors
1 parent 87891f3 commit 6d23f0c

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

lib/Support/Check.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414
#include "llvm/Support/raw_ostream.h"
1515
#include <cmath>
1616

17+
constexpr uint16_t Float16BitSign = 0x8000;
18+
constexpr uint16_t Float16BitExp = 0x7c00;
19+
constexpr uint16_t Float16BitMantissa = 0x03ff;
20+
1721
// limited to float, double, and long double
1822
template <typename T> static bool isDenorm(T F) {
1923
return std::fpclassify(F) == FP_SUBNORMAL;
2024
}
2125

2226
static bool isFloat16NAN(uint16_t Val) {
23-
return (Val & 0x7c00) == 0x7c00 && (Val & 0x03ff) != 0;
27+
return (Val & Float16BitExp) == Float16BitExp &&
28+
(Val & Float16BitMantissa) != 0;
2429
}
2530

2631
static bool compareDoubleULP(const double &FSrc, const double &FRef,
@@ -64,12 +69,23 @@ static bool compareFloatULP(const float &FSrc, const float &FRef,
6469

6570
static bool compareFloat16ULP(const uint16_t &FSrc, const uint16_t &FRef,
6671
unsigned ULPTolerance) {
72+
// Treat +0 and -0 as equal
73+
if ((FSrc & ~Float16BitSign) == 0 && (FRef & ~Float16BitSign) == 0)
74+
return true;
6775
if (FSrc == FRef)
6876
return true;
6977
if (isFloat16NAN(FSrc) || isFloat16NAN(FRef))
7078
return isFloat16NAN(FRef) && isFloat16NAN(FSrc);
79+
80+
// Map to monotonic ordering for correct ULP diff
81+
auto ToOrdered = [](uint16_t H) -> int {
82+
return (H & Float16BitSign) ? (~H & 0xFFFF) : (H | Float16BitSign);
83+
};
84+
7185
// 16-bit floating point numbers must preserve denorms
72-
const int Diff = FSrc - FRef;
86+
const int IntFSrc = ToOrdered(FSrc);
87+
const int IntFRef = ToOrdered(FRef);
88+
const int Diff = IntFSrc - IntFRef;
7389
const unsigned int AbsDiff = Diff < 0 ? -Diff : Diff;
7490
return AbsDiff <= ULPTolerance;
7591
}

test/Tools/Offloader/BufferFuzzy-16bit.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ RWStructuredBuffer<half> Out1 : register(u0);
44
RWStructuredBuffer<half> Out2 : register(u1);
55
RWStructuredBuffer<half> Out3 : register(u2);
66
RWStructuredBuffer<half> Out4 : register(u3);
7+
RWStructuredBuffer<half> Out5 : register(u4);
78

89
[numthreads(1,1,1)]
910
void main() {
1011
Out1[0] = (half)3.14159265;
1112
Out2[0] = (half)(0.0 / 0.0); // Should be NaN
1213
Out3[0] = (half)5.40234375;
1314
Out4[0] = (half)6.40234375;
15+
Out5[0] = (half)-0.0;
1416
}
1517

1618
//--- pipeline.yaml
@@ -53,6 +55,14 @@ Buffers:
5355
Format: Float16
5456
Stride: 2
5557
Data: [ 0x4665, 0 ] # Should be 2 ulp away
58+
- Name: Out5
59+
Format: Float16
60+
Stride: 2
61+
ZeroInitSize: 4
62+
- Name: Expected5
63+
Format: Float16
64+
Stride: 2
65+
Data: [ 0, 0 ] # compare negative and positive zero
5666
Results:
5767
- Result: Test1 # Test two values are exactly the same
5868
Rule: BufferFuzzy
@@ -74,6 +84,11 @@ Results:
7484
ULPT: 2
7585
Actual: Out4
7686
Expected: Expected4
87+
- Result: Test5 # +0 and -0 should be equal
88+
Rule: BufferFuzzy
89+
ULPT: 0
90+
Actual: Out5
91+
Expected: Expected5
7792
DescriptorSets:
7893
- Resources:
7994
- Name: Out1
@@ -104,6 +119,13 @@ DescriptorSets:
104119
Space: 0
105120
VulkanBinding:
106121
Binding: 3
122+
- Name: Out5
123+
Kind: RWStructuredBuffer
124+
DirectXBinding:
125+
Register: 4
126+
Space: 0
127+
VulkanBinding:
128+
Binding: 4
107129
...
108130
#--- end
109131

0 commit comments

Comments
 (0)