Fix verification in ExecutionTest::ComputeSampleTest (#6405)

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](130877392c/tools/clang/unittests/HLSLExec/ShaderOpArith.xml (L454))
line 454.

Fixes #4788 
Fixes #6181

---------

Co-authored-by: Greg Roth <grroth@microsoft.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Helena Kotas 2024-03-12 16:09:25 -07:00 коммит произвёл GitHub
Родитель 130877392c
Коммит 3fc84bf941
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
1 изменённых файлов: 37 добавлений и 14 удалений

Просмотреть файл

@ -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];
@ -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;
@ -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)) {
@ -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;
@ -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);
}
}