Skip to content

Commit 6482ac9

Browse files
author
Greg Roth
authored
DerivativesTest: quad2D layout and refactor (#3506)
Refactor Derivatives test to be clearer, more correct, and more in keeping with the original intent. Center index is now nearer the center. Conversion of 2D index to 1D is now correct for the quad layout. Dispatch sizes are separated by CS, Mesh, and undefined results to make testing easier and more complete. Also adds the 2D quad formats while adapting 1D variants to be correct with the latest spec
1 parent deacf03 commit 6482ac9

2 files changed

Lines changed: 157 additions & 88 deletions

File tree

tools/clang/test/HLSL/ShaderOpArith.xml

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
{32.0f, 64.0f, 128.0f, 256.0f},
110110
{256.0f, 512.0f, 1024.0f, 2048.0f}
111111
</Resource>
112-
<Resource Name="RTarget" Dimension="TEXTURE2D" Width="32" Height="32" Format="R32G32B32A32_FLOAT" Flags="ALLOW_RENDER_TARGET" InitialResourceState="COPY_DEST" ReadBack="true" />
112+
<Resource Name="RTarget" Dimension="TEXTURE2D" Width="64" Height="64" Format="R32G32B32A32_FLOAT" Flags="ALLOW_RENDER_TARGET" InitialResourceState="COPY_DEST" ReadBack="true" />
113113
<Resource Name="U0" Dimension="BUFFER" Width="16384"
114114
Flags="ALLOW_UNORDERED_ACCESS" InitialResourceState="COPY_DEST"
115115
Init="Zero" ReadBack="true" />
@@ -203,17 +203,66 @@
203203
{ 1.0f, 0.0f },
204204
{ 1.0f, 1.0f }};
205205
206-
[NumThreads(MESHDISPATCHX, MESHDISPATCHY, MESHDISPATCHZ)]
207-
void ASMain(uint ix : SV_GroupIndex) {
206+
uint convert2Dto1D(uint x, uint y, uint width) {
207+
// Convert 2D coords to 1D for testing
208+
// All completed rows of quads
209+
uint prevRows = (y/2)*2*width;
210+
// All previous full quads on this quad row
211+
uint prevQuads = (x/2)*4;
212+
// index into current quad
213+
uint quadIx = (y&1)*2 + (x&1);
214+
return prevRows + prevQuads + quadIx;
215+
}
216+
217+
float4 PSMain(PSInput input) : SV_TARGET {
218+
// Convert from texcoords into a groupIndex equivalent
219+
int width = 64;
220+
int height = 64;
221+
int2 uv = int2(input.uv.x*width, input.uv.y*height);
222+
223+
uint ix = convert2Dto1D(uv.x, uv.y, DISPATCHX);
224+
225+
float4 res = 0.0;
226+
if (uv.x < DISPATCHX && uv.y < DISPATCHY) {
227+
res = DerivTest(uv);
228+
g_bufMain[ix] = res;
229+
}
230+
return res;
231+
}
232+
233+
[NumThreads(DISPATCHX, DISPATCHY, DISPATCHZ)]
234+
void CSMain(uint3 id : SV_GroupThreadID, uint ix : SV_GroupIndex) {
235+
if (DISPATCHY == 1 && DISPATCHZ == 1)
236+
g_bufMain[ix] = DerivTest(ix);
237+
else
238+
g_bufMain[convert2Dto1D(id.x, id.y, DISPATCHX)] = DerivTest(id.xy);
239+
}
240+
241+
#if DISPATCHX * DISPATCHY * DISPATCHZ > 128
242+
#undef DISPATCHX
243+
#undef DISPATCHY
244+
#undef DISPATCHZ
245+
246+
#define DISPATCHX 1
247+
#define DISPATCHY 1
248+
#define DISPATCHZ 1
249+
#endif
250+
251+
[NumThreads(DISPATCHX, DISPATCHY, DISPATCHZ)]
252+
void ASMain(uint3 id : SV_GroupThreadID, uint ix : SV_GroupIndex) {
208253
Payload payload;
209-
g_bufAmp[ix] = DerivTest(ix);
254+
if (DISPATCHY == 1 && DISPATCHZ == 1)
255+
g_bufAmp[ix] = DerivTest(ix);
256+
else
257+
g_bufAmp[convert2Dto1D(id.x, id.y, DISPATCHX)] = DerivTest(id.xy);
210258
payload.nothing = 0;
211259
DispatchMesh(1, 1, 1, payload);
212260
}
213261
214-
[NumThreads(MESHDISPATCHX, MESHDISPATCHY, MESHDISPATCHZ)]
262+
[NumThreads(DISPATCHX, DISPATCHY, DISPATCHZ)]
215263
[OutputTopology("triangle")]
216264
void MSMain(
265+
uint3 id : SV_GroupThreadID,
217266
uint ix : SV_GroupIndex,
218267
in payload Payload payload,
219268
out vertices PSInput verts[6],
@@ -224,23 +273,12 @@
224273
verts[ix%6].uv = g_UV[ix%6];
225274
tris[ix&1] = uint3((ix&1)*3, (ix&1)*3 + 1, (ix&1)*3 + 2);
226275
g_bufMesh[ix] = DerivTest(ix);
227-
}
228-
float4 PSMain(PSInput input) : SV_TARGET {
229-
// Convert from texcoords into a groupIndex equivalent
230-
int width = DISPATCHX;
231-
int height = DISPATCHY;
232-
int2 uv = int2(input.uv.x*width, input.uv.y*height);
233-
uint ix = ((uv.y/4)*(width/4))*16 + (uv.x/4)*16 + (((uv.x & 0x2) << 1) | (uv.x & 0x1) | ((uv.y & 0x2) << 2) | ((uv.y & 0x1) << 1));
234-
235-
float4 res = DerivTest(ix);
236-
g_bufMain[ix] = res;
237-
return res;
276+
if (DISPATCHY == 1 && DISPATCHZ == 1)
277+
g_bufMesh[ix] = DerivTest(ix);
278+
else
279+
g_bufMesh[convert2Dto1D(id.x, id.y, DISPATCHX)] = DerivTest(id.xy);
238280
}
239281
240-
[NumThreads(DISPATCHX, DISPATCHY, DISPATCHZ)]
241-
void CSMain(uint ix : SV_GroupIndex) {
242-
g_bufMain[ix] = DerivTest(ix);
243-
}
244282
]]>
245283
</Shader>
246284
</ShaderOp>

tools/clang/unittests/HLSL/ExecutionTest.cpp

Lines changed: 99 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,7 +3059,40 @@ TEST_F(ExecutionTest, PartialDerivTest) {
30593059
VerifyDerivResults(pPixels, offsetCenter);
30603060
}
30613061

3062+
struct Dispatch {
3063+
int width, height, depth;
3064+
};
3065+
3066+
std::shared_ptr<st::ShaderOpTest>
3067+
RunDispatch(ID3D12Device *pDevice, dxc::DxcDllSupport &support,
3068+
st::ShaderOp *pShaderOp, const Dispatch D) {
3069+
char compilerOptions[256];
3070+
3071+
std::shared_ptr<st::ShaderOpTest> test = std::make_shared<st::ShaderOpTest>();
3072+
test->SetDxcSupport(&support);
3073+
test->SetInitCallback(nullptr);
3074+
test->SetDevice(pDevice);
3075+
3076+
// format compiler args
3077+
VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
3078+
"-D DISPATCHX=%d -D DISPATCHY=%d -D DISPATCHZ=%d ",
3079+
D.width, D.height, D.depth));
3080+
3081+
for (st::ShaderOpShader &S : pShaderOp->Shaders)
3082+
S.Arguments = compilerOptions;
3083+
3084+
pShaderOp->DispatchX = D.width;
3085+
pShaderOp->DispatchY = D.height;
3086+
pShaderOp->DispatchZ = D.depth;
3087+
3088+
test->RunShaderOp(pShaderOp);
3089+
3090+
return test;
3091+
}
3092+
30623093
TEST_F(ExecutionTest, DerivativesTest) {
3094+
const UINT pixelSize = 4; // always float4
3095+
30633096
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
30643097
CComPtr<IStream> pStream;
30653098
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
@@ -3074,99 +3107,97 @@ TEST_F(ExecutionTest, DerivativesTest) {
30743107

30753108
st::ShaderOp *pShaderOp = ShaderOpSet->GetShaderOp("Derivatives");
30763109

3077-
LPCSTR CS = pShaderOp->CS;
3078-
3079-
struct Dispatch {
3080-
int x, y, z;
3081-
int mx, my, mz;
3082-
};
30833110
std::vector<Dispatch> dispatches =
30843111
{
3085-
{32, 32, 1, 8, 8, 1},
3086-
{64, 4, 1, 64, 2, 1},
3087-
{1, 4, 64, 1, 4, 32},
3088-
{64, 1, 1, 64, 1, 1},
3089-
{1, 64, 1, 1, 64, 1},
3090-
{1, 1, 64, 1, 1, 64},
3091-
{16, 16, 3, 4, 4, 3},
3092-
{32, 3, 8, 8, 3, 2},
3093-
{3, 1, 64, 3, 1, 32}
3112+
{40, 1, 1},
3113+
{1000, 1, 1},
3114+
{32, 32, 1},
3115+
{16, 64, 1},
3116+
{4, 12, 4},
3117+
{4, 64, 1},
3118+
{16, 16, 3},
3119+
{32, 8, 2}
30943120
};
30953121

3096-
char compilerOptions[256];
3097-
for (Dispatch &D : dispatches) {
3098-
3099-
UINT width = D.x;
3100-
UINT height = D.y;
3101-
UINT depth = D.z;
3102-
3103-
UINT mwidth = D.mx;
3104-
UINT mheight = D.my;
3105-
UINT mdepth = D.mz;
3106-
UINT pixelSize = 4; // always float4
3122+
std::vector<Dispatch> meshDispatches =
3123+
{
3124+
{60, 1, 1},
3125+
{128, 1, 1},
3126+
{8, 8, 1},
3127+
{32, 8, 1},
3128+
{8, 16, 4},
3129+
{8, 64, 1},
3130+
{8, 8, 3},
3131+
};
31073132

3108-
// format compiler args
3109-
VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
3110-
"-D DISPATCHX=%d -D DISPATCHY=%d -D DISPATCHZ=%d "
3111-
"-D MESHDISPATCHX=%d -D MESHDISPATCHY=%d -D MESHDISPATCHZ=%d",
3112-
width, height, depth, mwidth, mheight, mdepth));
3133+
std::vector<Dispatch> badDispatches =
3134+
{
3135+
{16, 3, 1},
3136+
{2, 16, 1},
3137+
{33, 1, 1}
3138+
};
31133139

3114-
for (st::ShaderOpShader &S : pShaderOp->Shaders)
3115-
S.Arguments = compilerOptions;
3140+
pShaderOp->UseWarpDevice = GetTestParamUseWARP(true);
3141+
LPCSTR CS = pShaderOp->CS;
31163142

3117-
pShaderOp->DispatchX = width;
3118-
pShaderOp->DispatchY = height;
3119-
pShaderOp->DispatchZ = depth;
3143+
MappedData data;
31203144

3145+
for (Dispatch &D : dispatches) {
31213146
// Test Compute Shader
3122-
pShaderOp->CS = CS;
3123-
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(pDevice, m_support, "Derivatives", nullptr, ShaderOpSet);
3124-
MappedData data;
3147+
std::shared_ptr<st::ShaderOpTest> test = RunDispatch(pDevice, m_support, pShaderOp, D);
31253148

3126-
test->Test->GetReadBackData("U0", &data);
3127-
const float *pPixels = (float *)data.data();
3149+
test->GetReadBackData("U0", &data);
3150+
3151+
float *pPixels = (float *)data.data();;
31283152

3129-
// To find roughly the center for compute, divide the pixel count in half,
3130-
// truncate to next lowest power of 16 (4x4), which is the repeating period
3131-
// and then add 10 to reach the point the test expects
3132-
UINT centerIndex = (((UINT64)(width * height * depth)/2) & ~0xF) + 10;
3153+
UINT centerIndex = 0;
3154+
if (D.height == 1) {
3155+
centerIndex = (((UINT64)(D.width * D.height * D.depth) / 2) & ~0xF) + 10;
3156+
} else {
3157+
// To find roughly the center for compute, divide the height and width in half,
3158+
// truncate to the previous multiple of 4 to get to the start of the repeating pattern
3159+
// and then add 2 rows to get to the second row of quads and 2 to get to the first texel
3160+
// of the second row of that quad row
3161+
UINT centerRow = ((D.height/2UL) & ~0x3) + 2;
3162+
UINT centerCol = ((D.width/2UL) & ~0x3) + 2;
3163+
centerIndex = centerRow * D.width + centerCol;
3164+
}
31333165
UINT offsetCenter = centerIndex * pixelSize;
31343166
LogCommentFmt(L"Verifying derivatives in compute shader results");
31353167
VerifyDerivResults(pPixels, offsetCenter);
3168+
}
31363169

3137-
if (DoesDeviceSupportMeshAmpDerivatives(pDevice)) {
3138-
// Disable CS so mesh goes forward
3139-
pShaderOp->CS = nullptr;
3140-
test = RunShaderOpTestAfterParse(pDevice, m_support, "Derivatives", nullptr, ShaderOpSet);
3141-
test->Test->GetReadBackData("U1", &data);
3142-
pPixels = (float *)data.data();
3143-
centerIndex = (((UINT64)(mwidth * mheight * mdepth)/2) & ~0xF) + 10;
3144-
offsetCenter = centerIndex * pixelSize;
3170+
if (DoesDeviceSupportMeshAmpDerivatives(pDevice)) {
3171+
// Disable CS so mesh goes forward
3172+
pShaderOp->CS = nullptr;
3173+
3174+
for (Dispatch &D : meshDispatches) {
3175+
std::shared_ptr<st::ShaderOpTest> test = RunDispatch(pDevice, m_support, pShaderOp, D);
3176+
3177+
test->GetReadBackData("U1", &data);
3178+
const float *pPixels = (float *)data.data();
3179+
UINT centerIndex = (((UINT64)(D.width * D.height * D.depth)/2) & ~0xF) + 10;
3180+
UINT offsetCenter = centerIndex * pixelSize;
31453181
LogCommentFmt(L"Verifying derivatives in mesh shader results");
31463182
VerifyDerivResults(pPixels, offsetCenter);
31473183

3148-
test->Test->GetReadBackData("U2", &data);
3184+
test->GetReadBackData("U2", &data);
31493185
pPixels = (float *)data.data();
31503186
LogCommentFmt(L"Verifying derivatives in amplification shader results");
31513187
VerifyDerivResults(pPixels, offsetCenter);
31523188
}
31533189
}
31543190

3155-
// Final test with not divisible by 4 dispatch size just to make sure it runs
3156-
for (st::ShaderOpShader &S : pShaderOp->Shaders)
3157-
S.Arguments = "-D DISPATCHX=3 -D DISPATCHY=3 -D DISPATCHZ=3 "
3158-
"-D MESHDISPATCHX=3 -D MESHDISPATCHY=3 -D MESHDISPATCHZ=3";
3159-
3160-
pShaderOp->DispatchX = 3;
3161-
pShaderOp->DispatchY = 3;
3162-
pShaderOp->DispatchZ = 3;
3191+
// Final tests with invalid dispatch size just to make sure they run
3192+
for (Dispatch &D : badDispatches) {
3193+
// Test Compute Shader
3194+
pShaderOp->CS = CS;
3195+
std::shared_ptr<st::ShaderOpTest> test = RunDispatch(pDevice, m_support, pShaderOp, D);
31633196

3164-
// Test Compute Shader
3165-
pShaderOp->CS = CS;
3166-
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(pDevice, m_support, "Derivatives", nullptr, ShaderOpSet);
3167-
if (DoesDeviceSupportMeshAmpDerivatives(pDevice)) {
3168-
pShaderOp->CS = nullptr;
3169-
test = RunShaderOpTestAfterParse(pDevice, m_support, "Derivatives", nullptr, ShaderOpSet);
3197+
if (DoesDeviceSupportMeshAmpDerivatives(pDevice)) {
3198+
pShaderOp->CS = nullptr;
3199+
test = RunDispatch(pDevice, m_support, pShaderOp, D);
3200+
}
31703201
}
31713202
}
31723203

0 commit comments

Comments
 (0)