-
Notifications
You must be signed in to change notification settings - Fork 882
Execution Tests: Long Vectors - Finish the basic WaveOp tests #7913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
40d147a
a0fb36d
344cafd
46011c3
0d866c8
b1bbfb9
9d06bdd
93f43c1
1148fdd
0e19c03
8779d3f
c32ba7d
70d00d8
3ee0d08
916f878
470e9af
842e639
eefa04e
0b1a8d7
1939982
4e6f6eb
6e22df5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't find where this is used?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The specializations for WaveActiveAllEqual, WaveReadLaneAt, and WaveReadLaneFirst need it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
|
@@ -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; } \ | ||
| }; | ||
|
|
@@ -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; | ||
|
|
@@ -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; | ||
|
|
@@ -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 | ||
|
|
@@ -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 | ||
|
|
@@ -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 | ||
|
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; | ||
|
|
||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.