Skip to content

Commit

Permalink
Fix verification in ExecutionTest::ComputeSampleTest (microsoft#6405)
Browse files Browse the repository at this point in the history
The `ComputeSampleTest` is verifying `Sample` and
`CalculateLevelOfDetail` intrinsics calls on a texture in compute, mesh
and amplification shaders. The test is set up in a way that the reported
LOD values should be increasing as the X and Y coordinates increase.

However, since the test results are stored in quad z-order, and it is
perfectly valid for the X-derivative-LOD to decrease when going from
top-right to bottom-left pixel in a quad because in this case the X
coordinate decreases. Therefore, the test needs verify the LOD values
are increasing everywhere except for the bottom-left quad pixel (every
output with `index % 4 == 2`).

Previously, the test coincidentally worked for compute shaders because
it uses thread group of 336 and the 1/336 difference between 0 and pixel
1's X coordinate is not sufficient to change LODs. For mesh, however,
since the limit of a thread group size is 128, the validation is done
using the smaller range of 116, and 1/116 is sufficient to change LOD
for pixel 1.

This PR also fixes a couple of mismatched thread group dimensions in
`VerifySampleResults`.

The shader code for this test is at
[ShaderOpArith.xml](https://github.com/microsoft/DirectXShaderCompiler/blob/130877392c263888ef06bab768856d3dab1f1c9a/tools/clang/unittests/HLSLExec/ShaderOpArith.xml#L454)
line 454.

Fixes microsoft#4788 
Fixes microsoft#6181

---------

Co-authored-by: Greg Roth <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Mar 12, 2024
1 parent 1308773 commit 3fc84bf
Showing 1 changed file with 37 additions and 14 deletions.
51 changes: 37 additions & 14 deletions tools/clang/unittests/HLSLExec/ExecutionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4210,25 +4210,36 @@ void VerifySampleResults(const UINT *pPixels, UINT width) {
UINT ylod = 0;
// Each pixel contains 4 samples and 4 LOD calculations.
// 2 of these (called 'left' and 'right') have X values that vary and a
// constant Y 2 others (called 'top' and 'bot') have Y values that vary and a
// constant X Only of the X variant sample results and one of the Y variant
// results are actually reported for the pixel. The other 2 serve as "helpers"
// to the other pixels in the quad. On the left side of the quad, the 'left'
// samples are reported. Op the top of the quad, the 'top' samples are
// reported and so on. The varying coordinate values alternate between zero
// and a value whose magnitude increases with the index. As a result, the LOD
// level should steadily increas. Due to vagaries of implementation, the same
// derivatives in both directions might result in different levels for
// constant Y. 2 others (called 'top' and 'bot') have Y values that vary and a
// constant X. Only one of the X variant sample results and one of the Y
// variant results are actually reported for the pixel. The other 2 serve as
// "helpers" to the other pixels in the quad. On the left side of the quad,
// the 'left' samples are reported. On the top of the quad, the 'top' samples
// are reported and so on. The varying coordinate values alternate between
// zero and a value whose magnitude increases with the index. As a result, the
// LOD level should steadily increase. Due to vagaries of implementation, the
// same derivatives in both directions might result in different levels for
// different locations in the quad. So only comparisons between sample results
// and LOD calculations and ensuring that the LOD increased and reaches the
// max can be tested reliably.

// The results are stored in quad z-order (top-left (#0), top-right (#1),
// bottom-left (#2), bottom-right (#3)) and need to be evaluated as such.
// The X-derivative-LOD should not decrease when going from quad pixel #0->#1,
// #2->#3, or #3->#0. For #1->#2 the end of the typewriter "line" is reached
// and zags left resulting in a smaller x value. So, it is absolutely valid
// for the X-derivative-LOD to decrease. Therefore, the test skips
// verification of X-derivative-LOD on quad pixel #2.

for (unsigned i = 0; i < width; i++) {
// CalculateLOD and Sample from texture with mip levels containing LOD index
// should match
VERIFY_ARE_EQUAL(pPixels[4 * i + 0], pPixels[4 * i + 1]);
VERIFY_ARE_EQUAL(pPixels[4 * i + 2], pPixels[4 * i + 3]);
// Make sure LODs are ever climbing as magnitudes increase
VERIFY_IS_TRUE(pPixels[4 * i] >= xlod);
if (i % 4 != 2) { // skip X-derivative-LOD verification on quad pixel #2
VERIFY_IS_TRUE(pPixels[4 * i] >= xlod);
}
xlod = pPixels[4 * i];
VERIFY_IS_TRUE(pPixels[4 * i + 2] >= ylod);
ylod = pPixels[4 * i + 2];
Expand Down Expand Up @@ -4300,7 +4311,9 @@ TEST_F(ExecutionTest, ComputeSampleTest) {
test->Test->GetReadBackData("U0", &data);
const UINT *pPixels = (UINT *)data.data();

VerifySampleResults(pPixels, 84 * 4);
LogCommentFmt(L"Verifying 1D Compute Shader");
// CSMain1D has [NumThreads(336, 1, 1)]
VerifySampleResults(pPixels, 336);

// Test 2D compute shader
pShaderOp->CS = CS2;
Expand All @@ -4312,6 +4325,8 @@ TEST_F(ExecutionTest, ComputeSampleTest) {
test->Test->GetReadBackData("U0", &data);
pPixels = (UINT *)data.data();

LogCommentFmt(L"Verifying 2D Compute Shader");
// CSMain2D has [NumThreads(84, 4, 3)]
VerifySampleResults(pPixels, 84 * 4);

if (DoesDeviceSupportMeshAmpDerivatives(pDevice)) {
Expand All @@ -4322,12 +4337,16 @@ TEST_F(ExecutionTest, ComputeSampleTest) {
test->Test->GetReadBackData("U1", &data);
pPixels = (UINT *)data.data();

LogCommentFmt(L"Verifying 1D mesh shader");
// MSMain1D has [NumThreads(116, 1, 1)]
VerifySampleResults(pPixels, 116);

test->Test->GetReadBackData("U2", &data);
pPixels = (UINT *)data.data();

VerifySampleResults(pPixels, 84);
LogCommentFmt(L"Verifying 1D amplification shader");
// ASMain1D has [NumThreads(116, 1, 1)]
VerifySampleResults(pPixels, 116);

pShaderOp->AS = AS2;
pShaderOp->MS = MS2;
Expand All @@ -4336,12 +4355,16 @@ TEST_F(ExecutionTest, ComputeSampleTest) {
test->Test->GetReadBackData("U1", &data);
pPixels = (UINT *)data.data();

VerifySampleResults(pPixels, 116);
LogCommentFmt(L"Verifying 2D mesh shader");
// MSMain2D has [NumThreads(42, 2, 1)]
VerifySampleResults(pPixels, 42 * 2);

test->Test->GetReadBackData("U2", &data);
pPixels = (UINT *)data.data();

VerifySampleResults(pPixels, 84);
LogCommentFmt(L"Verifying 2D amplification shader");
// ASMain2D has [NumThreads(42, 2, 1)]
VerifySampleResults(pPixels, 42 * 2);
}
}

Expand Down

0 comments on commit 3fc84bf

Please sign in to comment.