Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 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
13 changes: 10 additions & 3 deletions tools/clang/unittests/HLSLExec/LongVectorOps.def
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ INPUT_SET(Positive)
INPUT_SET(Bitwise)
INPUT_SET(SelectCond)
INPUT_SET(FloatSpecial)
INPUT_SET(AllOnes)
INPUT_SET(AllScalarOnes)

#undef INPUT_SET

Expand Down Expand Up @@ -198,7 +198,14 @@ OP_LOAD_AND_STORE_SB(LoadAndStore_RD_SB_SRV, "RootDescriptor_SRV")
OP_DEFAULT(Wave, WaveActiveSum, 1, "WaveActiveSum", "")
OP_DEFAULT_DEFINES(Wave, WaveActiveMin, 1, "TestWaveActiveMin", "", " -DFUNC_WAVE_ACTIVE_MIN=1")
OP_DEFAULT_DEFINES(Wave, WaveActiveMax, 1, "TestWaveActiveMax", "", " -DFUNC_WAVE_ACTIVE_MAX=1")
OP(Wave, WaveActiveProduct, 1, "TestWaveActiveProduct", "", " -DFUNC_WAVE_ACTIVE_PRODUCT=1", "LongVectorOp",
AllOnes, Default2, Default3)
OP(Wave, WaveActiveProduct, 1, "TestWaveActiveProduct", "", " -DFUNC_WAVE_ACTIVE_PRODUCT=1", "LongVectorOp", AllScalarOnes, Default2, Default3)
OP_DEFAULT_DEFINES(Wave, WaveActiveBitAnd, 1, "TestWaveActiveBitAnd", "", " -DFUNC_WAVE_ACTIVE_BIT_AND=1")
OP_DEFAULT_DEFINES(Wave, WaveActiveBitOr, 1, "TestWaveActiveBitOr", "", " -DFUNC_WAVE_ACTIVE_BIT_OR=1")
OP_DEFAULT_DEFINES(Wave, WaveActiveBitXor, 1, "TestWaveActiveBitXor", "", " -DFUNC_WAVE_ACTIVE_BIT_XOR=1")
OP_DEFAULT_DEFINES(Wave, WaveActiveAllEqual, 1, "TestWaveActiveAllEqual", "", " -DFUNC_WAVE_ACTIVE_ALL_EQUAL=1")
OP_DEFAULT_DEFINES(Wave, WaveReadLaneAt, 1, "TestWaveReadLaneAt", "", " -DFUNC_WAVE_READ_LANE_AT=1")
OP_DEFAULT_DEFINES(Wave, WaveReadLaneFirst, 1, "TestWaveReadLaneFirst", "", " -DFUNC_WAVE_READ_LANE_FIRST=1")
OP_DEFAULT_DEFINES(Wave, WavePrefixSum, 1, "TestWavePrefixSum", "", " -DFUNC_WAVE_PREFIX_SUM=1 -DIS_WAVE_PREFIX_OP=1")
OP_DEFAULT_DEFINES(Wave, WavePrefixProduct, 1, "TestWavePrefixProduct", "", " -DFUNC_WAVE_PREFIX_PRODUCT=1 -DIS_WAVE_PREFIX_OP=1")

#undef OP
18 changes: 9 additions & 9 deletions tools/clang/unittests/HLSLExec/LongVectorTestData.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ INPUT_SET(InputSet::Bitwise, std::numeric_limits<int16_t>::min(), -1, 0, 1, 3,
6, 9, 0x5555, static_cast<int16_t>(0xAAAA),
std::numeric_limits<int16_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the "scalar" part implicit in all of these input sets? What's special about this one that means we need to call them out?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll revert this. For context I changed this name when I was also adding an input set that had all bits set to 1. I was trying to differentiate between them.

END_INPUT_SETS()

BEGIN_INPUT_SETS(int32_t)
Expand All @@ -303,7 +303,7 @@ INPUT_SET(InputSet::Bitwise, std::numeric_limits<int32_t>::min(), -1, 0, 1, 3,
6, 9, 0x55555555, static_cast<int32_t>(0xAAAAAAAA),
std::numeric_limits<int32_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);
END_INPUT_SETS()

BEGIN_INPUT_SETS(int64_t)
Expand All @@ -317,7 +317,7 @@ INPUT_SET(InputSet::Bitwise, std::numeric_limits<int64_t>::min(), -1, 0, 1, 3,
6, 9, 0x5555555555555555LL, 0xAAAAAAAAAAAAAAAALL,
std::numeric_limits<int64_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);
END_INPUT_SETS()

BEGIN_INPUT_SETS(uint16_t)
Expand All @@ -328,7 +328,7 @@ INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 12, 13, 14, 15);
INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x5555, 0xAAAA, 0x8000, 127,
std::numeric_limits<uint16_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);
END_INPUT_SETS()

BEGIN_INPUT_SETS(uint32_t)
Expand All @@ -339,7 +339,7 @@ INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 30, 31, 32);
INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x55555555, 0xAAAAAAAA, 0x80000000,
127, std::numeric_limits<uint32_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);
END_INPUT_SETS()

BEGIN_INPUT_SETS(uint64_t)
Expand All @@ -351,7 +351,7 @@ INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x5555555555555555,
0xAAAAAAAAAAAAAAAA, 0x8000000000000000, 127,
std::numeric_limits<uint64_t>::max());
INPUT_SET(InputSet::SelectCond, 0, 1);
INPUT_SET(InputSet::AllOnes, 1);
INPUT_SET(InputSet::AllScalarOnes, 1);
END_INPUT_SETS()

BEGIN_INPUT_SETS(HLSLHalf_t)
Expand Down Expand Up @@ -382,7 +382,7 @@ INPUT_SET(InputSet::FloatSpecial, std::numeric_limits<float>::infinity(),
-std::numeric_limits<float>::max(),
std::numeric_limits<float>::denorm_min(),
std::numeric_limits<float>::denorm_min() * 10.0, 1.0 / 3.0);
INPUT_SET(InputSet::AllOnes, 1.0);
INPUT_SET(InputSet::AllScalarOnes, 1.0);
END_INPUT_SETS()

BEGIN_INPUT_SETS(float)
Expand Down Expand Up @@ -410,7 +410,7 @@ INPUT_SET(InputSet::FloatSpecial, std::numeric_limits<float>::infinity(),
-std::numeric_limits<float>::max(),
std::numeric_limits<float>::denorm_min(),
std::numeric_limits<float>::denorm_min() * 10.0f, 1.0f / 3.0f);
INPUT_SET(InputSet::AllOnes, 1.0f);
INPUT_SET(InputSet::AllScalarOnes, 1.0f);
END_INPUT_SETS()

BEGIN_INPUT_SETS(double)
Expand All @@ -429,7 +429,7 @@ INPUT_SET(InputSet::SplitDouble, 0.0, -1.0, 1.0, -1.0, 12345678.87654321, -1.0,
INPUT_SET(InputSet::Positive, 1.0, 1.0, 65535.0, 0.01, 5531.0, 0.01, 1.0, 0.01,
331.2330, 3250.01);
INPUT_SET(InputSet::SelectCond, 0.0, 1.0);
INPUT_SET(InputSet::AllOnes, 1.0);
INPUT_SET(InputSet::AllScalarOnes, 1.0);
END_INPUT_SETS()

#undef BEGIN_INPUT_SETS
Expand Down
162 changes: 156 additions & 6 deletions tools/clang/unittests/HLSLExec/LongVectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ template <OpType OP, typename T, size_t Arity> struct Op;
// ExpectedBuilder - specializations are expected to have buildExpectedData
// member functions.
template <OpType OP, typename T> struct ExpectedBuilder;
template <OpType OP, typename T> struct WaveOpExpectedBuilder;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find where this is used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The specializations for WaveActiveAllEqual, WaveReadLaneAt, and WaveReadLaneFirst need it.
Although, they aren't making use of WaveSize argument to the WaveOpExpectedBuilder::buildExpected call. So, they could use the base one (ExpectedBuilder). But then I'd need to do something to call the right buildExpected in dispatchWaveTest.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it looks like WaveOpExpectedBuilder was added in an earlier change, so the call to it doesn't appear in the diffs for this one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it just didn't need the forward declaration when it was added.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed this in the previous change - I don't quite get why we need ExpectedBuilder as well as WaveOpExpectedBuilder?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were a few reasons initially. Now the only thing it's getting is the WaveCount argument for buildExpected.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The specializations don't need to match the argument structure of any of the other specializations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the other things I was going for there was to have the name be clear that it was for use with wave ops. But I guess that doesn't really matter. There's no reason another test couldn't use a wave size if it wanted to.

I've moved it back into the ExpectedBuilder.

Still debating if putting 'waveOp' in the name would make sense. It is heavily implied without it...


// Default Validation configuration - ULP for floating point types, exact
// matches for everything else.
Expand Down Expand Up @@ -1300,7 +1301,7 @@ template <typename T> struct ExpectedBuilder<OpType::ModF, T> {
// Wave Ops
//

#define WAVE_ACTIVE_OP(OP, IMPL) \
#define WAVE_OP(OP, IMPL) \
template <typename T> struct Op<OP, T, 1> : DefaultValidation<T> { \
T operator()(T A, UINT WaveSize) { return IMPL; } \
};
Expand All @@ -1310,7 +1311,7 @@ template <typename T> T waveActiveSum(T A, UINT WaveSize) {
return A * WaveSizeT;
}

WAVE_ACTIVE_OP(OpType::WaveActiveSum, (waveActiveSum(A, WaveSize)));
WAVE_OP(OpType::WaveActiveSum, (waveActiveSum(A, WaveSize)));

template <typename T> T waveActiveMin(T A, UINT WaveSize) {
std::vector<T> Values;
Expand All @@ -1320,7 +1321,7 @@ template <typename T> T waveActiveMin(T A, UINT WaveSize) {
return *std::min_element(Values.begin(), Values.end());
}

WAVE_ACTIVE_OP(OpType::WaveActiveMin, (waveActiveMin(A, WaveSize)));
WAVE_OP(OpType::WaveActiveMin, (waveActiveMin(A, WaveSize)));

template <typename T> T waveActiveMax(T A, UINT WaveSize) {
std::vector<T> Values;
Expand All @@ -1330,7 +1331,7 @@ template <typename T> T waveActiveMax(T A, UINT WaveSize) {
return *std::max_element(Values.begin(), Values.end());
}

WAVE_ACTIVE_OP(OpType::WaveActiveMax, (waveActiveMax(A, WaveSize)));
WAVE_OP(OpType::WaveActiveMax, (waveActiveMax(A, WaveSize)));

template <typename T> T waveActiveProduct(T A, UINT WaveSize) {
// We want to avoid overflow of a large product. So, the WaveActiveProdFn has
Expand All @@ -1339,9 +1340,102 @@ template <typename T> T waveActiveProduct(T A, UINT WaveSize) {
return A * static_cast<T>(WaveSize - 1);
}

WAVE_ACTIVE_OP(OpType::WaveActiveProduct, (waveActiveProduct(A, WaveSize)));
WAVE_OP(OpType::WaveActiveProduct, (waveActiveProduct(A, WaveSize)));

#undef WAVE_ACTIVE_OP
template <typename T> T waveActiveBitAnd(T A, UINT) {
// We set the LSB to 0 in one of the lanes.
return static_cast<T>(A & ~static_cast<T>(1));
}

WAVE_OP(OpType::WaveActiveBitAnd, (waveActiveBitAnd(A, WaveSize)));

template <typename T> T waveActiveBitOr(T A, UINT) {
// We set the LSB to 0 in one of the lanes.
return static_cast<T>(A | static_cast<T>(1));
}

WAVE_OP(OpType::WaveActiveBitOr, (waveActiveBitOr(A, WaveSize)));

template <typename T> T waveActiveBitXor(T A, UINT) {
// We clear the LSB in every lane except the last lane which sets it to 1.
return static_cast<T>(A | static_cast<T>(1));
}

WAVE_OP(OpType::WaveActiveBitXor, (waveActiveBitXor(A, WaveSize)));

template <typename T>
struct Op<OpType::WaveActiveAllEqual, T, 1> : StrictValidation {};

template <typename T>
struct WaveOpExpectedBuilder<OpType::WaveActiveAllEqual, T> {
static std::vector<HLSLBool_t>
buildExpected(Op<OpType::WaveActiveAllEqual, T, 1> &,
const InputSets<T> &Inputs, UINT) {
DXASSERT_NOMSG(Inputs.size() == 1);

std::vector<HLSLBool_t> Expected;
const size_t VectorSize = Inputs[0].size();
Expected.assign(VectorSize - 1, static_cast<HLSLBool_t>(true));
// We set the last element to a different value on a single lane.
Expected[VectorSize - 1] = static_cast<HLSLBool_t>(false);

return Expected;
}
};

template <typename T>
struct Op<OpType::WaveReadLaneAt, T, 1> : StrictValidation {};

template <typename T> struct WaveOpExpectedBuilder<OpType::WaveReadLaneAt, T> {
static std::vector<T> buildExpected(Op<OpType::WaveReadLaneAt, T, 1> &,
const InputSets<T> &Inputs, UINT) {
DXASSERT_NOMSG(Inputs.size() == 1);

std::vector<T> Expected;
const size_t VectorSize = Inputs[0].size();
// Simple test, on the lane that we read we also fill the vector with the
// value of the first element.
Expected.assign(VectorSize, Inputs[0][0]);

return Expected;
}
};

template <typename T>
struct Op<OpType::WaveReadLaneFirst, T, 1> : StrictValidation {};

template <typename T>
struct WaveOpExpectedBuilder<OpType::WaveReadLaneFirst, T> {
static std::vector<T> buildExpected(Op<OpType::WaveReadLaneFirst, T, 1> &,
const InputSets<T> &Inputs, UINT) {
DXASSERT_NOMSG(Inputs.size() == 1);

std::vector<T> Expected;
const size_t VectorSize = Inputs[0].size();
// Simple test, on the lane that we read we also fill the vector with the
// value of the first element.
Expected.assign(VectorSize, Inputs[0][0]);

return Expected;
}
};

WAVE_OP(OpType::WavePrefixSum, (wavePrefixSum(A, WaveSize)));

template <typename T> T wavePrefixSum(T A, UINT WaveSize) {
// We test the prefix sume in the 'middle' lane. This choice is arbitrary.
return static_cast<T>(A * static_cast<T>(WaveSize / 2));
}

WAVE_OP(OpType::WavePrefixProduct, (wavePrefixProduct(A, WaveSize)));

template <typename T> T wavePrefixProduct(T A, UINT) {
// We test the the prefix product in the 3rd lane to avoid overflow issues.
// So the result is A * A.
return static_cast<T>(A * A);
}

#undef WAVE_OP

//
// dispatchTest
Expand Down Expand Up @@ -2243,44 +2337,100 @@ class DxilConf_SM69_Vectorized {
HLK_TEST(LoadAndStore_RD_SB_SRV, double);
HLK_TEST(LoadAndStore_RD_SB_UAV, double);

HLK_WAVEOP_TEST(WaveActiveAllEqual, HLSLBool_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, HLSLBool_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, HLSLBool_t);

HLK_WAVEOP_TEST(WaveActiveSum, int16_t);
HLK_WAVEOP_TEST(WaveActiveMin, int16_t);
HLK_WAVEOP_TEST(WaveActiveMax, int16_t);
HLK_WAVEOP_TEST(WaveActiveProduct, int16_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, int16_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, int16_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, int16_t);
HLK_WAVEOP_TEST(WavePrefixSum, int16_t);
HLK_WAVEOP_TEST(WavePrefixProduct, int16_t);
HLK_WAVEOP_TEST(WaveActiveSum, int32_t);
HLK_WAVEOP_TEST(WaveActiveMin, int32_t);
HLK_WAVEOP_TEST(WaveActiveMax, int32_t);
HLK_WAVEOP_TEST(WaveActiveProduct, int32_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, int32_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, int32_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, int32_t);
HLK_WAVEOP_TEST(WavePrefixSum, int32_t);
HLK_WAVEOP_TEST(WavePrefixProduct, int32_t);
HLK_WAVEOP_TEST(WaveActiveSum, int64_t);
HLK_WAVEOP_TEST(WaveActiveMin, int64_t);
HLK_WAVEOP_TEST(WaveActiveMax, int64_t);
HLK_WAVEOP_TEST(WaveActiveProduct, int64_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, int64_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, int64_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, int64_t);
HLK_WAVEOP_TEST(WavePrefixSum, int64_t);
HLK_WAVEOP_TEST(WavePrefixProduct, int64_t);

HLK_WAVEOP_TEST(WaveActiveSum, uint16_t);
HLK_WAVEOP_TEST(WaveActiveMin, uint16_t);
HLK_WAVEOP_TEST(WaveActiveMax, uint16_t);
HLK_WAVEOP_TEST(WaveActiveProduct, uint16_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, uint16_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, uint16_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, uint16_t);
HLK_WAVEOP_TEST(WavePrefixSum, uint16_t);
HLK_WAVEOP_TEST(WavePrefixProduct, uint16_t);
HLK_WAVEOP_TEST(WaveActiveSum, uint32_t);
HLK_WAVEOP_TEST(WaveActiveMin, uint32_t);
HLK_WAVEOP_TEST(WaveActiveMax, uint32_t);
HLK_WAVEOP_TEST(WaveActiveProduct, uint32_t);
// Note: WaveActiveBit* ops don't support uint16_t in HLSL
Comment thread
alsepkow marked this conversation as resolved.
HLK_WAVEOP_TEST(WaveActiveBitAnd, uint32_t);
HLK_WAVEOP_TEST(WaveActiveBitOr, uint32_t);
HLK_WAVEOP_TEST(WaveActiveBitXor, uint32_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, uint32_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, uint32_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, uint32_t);
HLK_WAVEOP_TEST(WavePrefixSum, uint32_t);
HLK_WAVEOP_TEST(WavePrefixProduct, uint32_t);
HLK_WAVEOP_TEST(WaveActiveSum, uint64_t);
HLK_WAVEOP_TEST(WaveActiveMin, uint64_t);
HLK_WAVEOP_TEST(WaveActiveMax, uint64_t);
HLK_WAVEOP_TEST(WaveActiveProduct, uint64_t);
HLK_WAVEOP_TEST(WaveActiveBitAnd, uint64_t);
HLK_WAVEOP_TEST(WaveActiveBitOr, uint64_t);
HLK_WAVEOP_TEST(WaveActiveBitXor, uint64_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, uint64_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, uint64_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, uint64_t);
HLK_WAVEOP_TEST(WavePrefixSum, uint64_t);
HLK_WAVEOP_TEST(WavePrefixProduct, uint64_t);

HLK_WAVEOP_TEST(WaveActiveSum, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveActiveMin, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveActiveMax, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveActiveProduct, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveActiveAllEqual, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveReadLaneAt, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveReadLaneFirst, HLSLHalf_t);
HLK_WAVEOP_TEST(WavePrefixSum, HLSLHalf_t);
HLK_WAVEOP_TEST(WavePrefixProduct, HLSLHalf_t);
HLK_WAVEOP_TEST(WaveActiveSum, float);
HLK_WAVEOP_TEST(WaveActiveMin, float);
HLK_WAVEOP_TEST(WaveActiveMax, float);
HLK_WAVEOP_TEST(WaveActiveProduct, float);
HLK_WAVEOP_TEST(WaveActiveAllEqual, float);
HLK_WAVEOP_TEST(WaveReadLaneAt, float);
HLK_WAVEOP_TEST(WaveReadLaneFirst, float);
HLK_WAVEOP_TEST(WavePrefixSum, float);
HLK_WAVEOP_TEST(WavePrefixProduct, float);
HLK_WAVEOP_TEST(WaveActiveSum, double);
HLK_WAVEOP_TEST(WaveActiveMin, double);
HLK_WAVEOP_TEST(WaveActiveMax, double);
HLK_WAVEOP_TEST(WaveActiveProduct, double);
HLK_WAVEOP_TEST(WaveActiveAllEqual, double);
HLK_WAVEOP_TEST(WaveReadLaneAt, double);
HLK_WAVEOP_TEST(WaveReadLaneFirst, double);
HLK_WAVEOP_TEST(WavePrefixSum, double);
HLK_WAVEOP_TEST(WavePrefixProduct, double);

private:
bool Initialized = false;
Expand Down
Loading