Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions lib/Support/Check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@
#include "llvm/Support/raw_ostream.h"
#include <cmath>

constexpr uint16_t Float16BitSign = 0x8000;
constexpr uint16_t Float16BitExp = 0x7c00;
constexpr uint16_t Float16BitMantissa = 0x03ff;

// limited to float, double, and long double
template <typename T> static bool isDenorm(T F) {
return std::fpclassify(F) == FP_SUBNORMAL;
}

static bool isFloat16NAN(uint16_t Val) {
return (Val & 0x7c00) == 0x7c00 && (Val & 0x03ff) != 0;
return (Val & Float16BitExp) == Float16BitExp &&
(Val & Float16BitMantissa) != 0;
}

static bool compareDoubleULP(const double &FSrc, const double &FRef,
Expand Down Expand Up @@ -64,12 +69,23 @@ 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 & ~Float16BitSign) == 0 && (FRef & ~Float16BitSign) == 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 & Float16BitSign) ? (~H & 0xFFFF) : (H | Float16BitSign);
};

// 16-bit floating point numbers must preserve denorms
const int Diff = FSrc - FRef;
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;
}
Expand Down
22 changes: 22 additions & 0 deletions test/Tools/Offloader/BufferFuzzy-16bit.test
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ RWStructuredBuffer<half> Out1 : register(u0);
RWStructuredBuffer<half> Out2 : register(u1);
RWStructuredBuffer<half> Out3 : register(u2);
RWStructuredBuffer<half> Out4 : register(u3);
RWStructuredBuffer<half> Out5 : register(u4);

[numthreads(1,1,1)]
void main() {
Out1[0] = (half)3.14159265;
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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -104,6 +119,13 @@ DescriptorSets:
Space: 0
VulkanBinding:
Binding: 3
- Name: Out5
Kind: RWStructuredBuffer
DirectXBinding:
Register: 4
Space: 0
VulkanBinding:
Binding: 4
...
#--- end

Expand Down