Переглянути джерело

Update test for helperlane wave on VS. (#4367)

* Update test for helperlane wave on VS.
Xiang Li 3 роки тому
батько
коміт
6834925179

+ 2 - 2
tools/clang/test/HLSL/ShaderOpArith.xml

@@ -3250,7 +3250,7 @@
         
         PSInput VSMain(float3 pos : POSITION) {
             HelperLaneWaveTestResult60 tr60 = RunHelperLaneWaveTests60();
-            if (WaveGetLaneIndex() == 2) { // last lane writes results
+            if ( WaveGetLaneIndex() == WaveActiveMax(WaveGetLaneIndex())) { // last lane writes results
                 g_TestResults[VS_INDEX].sm60_wave = tr60;
             }
             PSInput r;
@@ -3261,7 +3261,7 @@
         PSInput VSMain65(float3 pos : POSITION) {
             HelperLaneWaveTestResult60 tr60 = RunHelperLaneWaveTests60();
             HelperLaneWaveTestResult65 tr65 = RunHelperLaneWaveTests65();
-            if (WaveGetLaneIndex() == 2) { // last lane writes results
+            if ( WaveGetLaneIndex() == WaveActiveMax(WaveGetLaneIndex())) { // last lane writes results
                 g_TestResults[VS_INDEX].sm60_wave = tr60;
                 g_TestResults[VS_INDEX].sm65_wave = tr65;
             }

+ 96 - 1
tools/clang/unittests/HLSL/ExecutionTest.cpp

@@ -28,6 +28,7 @@
 #include <atlcoll.h>
 #include <locale>
 #include <algorithm>
+#include <bitset>
 
 #undef _read
 #include "WexTestClass.h"
@@ -9754,6 +9755,100 @@ bool VerifyHelperLaneWaveResults(ExecutionTest::D3D_SHADER_MODEL sm, HelperLaneW
   }
   return passed;
 }
+// Contrary to compute or pixel shaders the layout of lanes in vertex shaders is
+// not specified. A conforming implementation could, in the extreme case, decide
+// to dispatch three waves that each process only a single vertex.
+// So instead of compare with fixed expected result, calculate the correct
+// result from ballot.
+bool VerifyHelperLaneWaveResultsForVS(ExecutionTest::D3D_SHADER_MODEL sm,
+                                      HelperLaneWaveTestResult &testResults) {
+  bool passed = true;
+  XMUINT4 mask = testResults.sm60.ballot;
+  unsigned countBits = 0;
+  std::bitset<32> x(mask.x);
+  std::bitset<32> y(mask.y);
+  std::bitset<32> z(mask.z);
+  std::bitset<32> w(mask.w);
+  countBits += (unsigned)x.count();
+  countBits += (unsigned)y.count();
+  countBits += (unsigned)z.count();
+  countBits += (unsigned)w.count();
+
+  {
+    // For VS, IsHelperLane always return false.
+    HelperLaneWaveTestResult60 &tr60 = testResults.sm60;
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveAnyTrue(IsHelperLane())",
+                                           0, tr60.anyTrue);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveActiveAllTrue(!IsHelperLane())", 1, tr60.allTrue);
+    bool ballotMatch = 1 <= countBits && countBits <= 3;
+
+    LogCommentFmt(L"%sWaveActiveBallot(true) expected 1~3 bits set, actual = %u",
+        ballotMatch ? L" - " : L"FAILED: ", tr60.ballot);
+
+
+    passed &= HelperLaneResultLogAndVerify(
+        L"!WaveReadLaneFirst(IsHelperLane()) && WaveIsFirstLane() in a "
+        L"waterfall loop",
+        countBits, tr60.waterfallLoopCount);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveActiveAllEqual(IsHelperLane())", 1, tr60.allEqual);
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveCountBits(true)",
+                                           countBits, tr60.countBits);
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveSum(4)", 4 * countBits,
+                                           tr60.sum);
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveProduct(4)", (unsigned)std::pow(4, countBits),
+                                           tr60.product);
+
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveBitAnd(!IsHelperLane())",
+                                           1, tr60.bitAnd);
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveBitOr(IsHelperLane())",
+                                           0, tr60.bitOr);
+    passed &= HelperLaneResultLogAndVerify(L"WaveActiveBitXor(IsHelperLane())",
+                                           0, tr60.bitXor);
+
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveActiveMin(IsHelperLane() ? 1 : 10)", 10, tr60.min);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveActiveMax(IsHelperLane() ? 10 : 1)", 1, tr60.max);
+
+    passed &= HelperLaneResultLogAndVerify(L"WavePrefixCountBits(1)",
+                                           countBits-1,
+                                           tr60.prefixCountBits);
+    passed &= HelperLaneResultLogAndVerify(L"WavePrefixProduct(4)",
+                                           (unsigned)std::pow(4, countBits - 1),
+                                           tr60.prefixProduct);
+    passed &= HelperLaneResultLogAndVerify(L"WavePrefixSum(2)",
+                                           2 * (countBits-1), tr60.prefixSum);
+  }
+
+  if (sm >= ExecutionTest::D3D_SHADER_MODEL_6_5) {
+    HelperLaneWaveTestResult65 &tr65 = testResults.sm65;
+
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMatch(true) has exactly 3 bits set", mask, tr65.match);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMultiPrefixCountBits(1, no_masked_bits)", countBits-1,
+        tr65.mpCountBits);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMultiPrefixSum(2, no_masked_bits)", 2*(countBits-1), tr65.mpSum);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMultiPrefixProduct(4, no_masked_bits)",
+        (unsigned)std::pow(4, countBits - 1),
+        tr65.mpProduct);
+
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMultiPrefixAnd(IsHelperLane() ? 0 : 1, no_masked_bits)",
+        1, tr65.mpBitAnd);
+    passed &= HelperLaneResultLogAndVerify(
+        L"WaveMultiPrefixOr(IsHelperLane() ? 1 : 0, no_masked_bits)",
+        0, tr65.mpBitOr);
+    passed &= HelperLaneResultLogAndVerify(
+        L"verify WaveMultiPrefixXor(IsHelperLane() ? 1 : 0, no_masked_bits)",
+        0, tr65.mpBitXor);
+  }
+  return passed;
+}
 
 void CleanUAVBuffer0Buffer(LPCSTR BufferName, std::vector<BYTE>& Data, st::ShaderOp* pShaderOp) {
   UNREFERENCED_PARAMETER(pShaderOp);
@@ -9868,7 +9963,7 @@ TEST_F(ExecutionTest, HelperLaneTestWave) {
       test->Test->GetReadBackData("UAVBuffer0", &uavData);
       HelperLaneWaveTestResult* pTestResults = (HelperLaneWaveTestResult*)uavData.data();
       LogCommentFmt(L"\r\nVertex shader");
-      smPassed &= VerifyHelperLaneWaveResults(sm, pTestResults[VS_INDEX], HelperLane_VS_ExpectedResults, false);
+      smPassed &= VerifyHelperLaneWaveResultsForVS(sm, pTestResults[VS_INDEX]);
       LogCommentFmt(L"\r\nPixel shader");
       smPassed &= VerifyHelperLaneWaveResults(sm, pTestResults[PS_INDEX], PS_ExpectedResults, true);
       LogCommentFmt(L"\r\nPixel shader with discarded pixel");