[SM6.7] QuadAny/All execution test (1/2) (#4264)

* [SM6.7] QuadAny/All execution test (1/2)

This adds a first set of execution tests for QuadAny and QuadAll to test
compute, mesh, and amplification shaders. A separate execution test will
be coming for pixel shaders.

* Fixing QuadAny/All fallback expansion

The initial implementation missed one of the required bitwise
operations.

* Updating test case to reduce scope to compute only

This gets the test passing for SM 6.0 using the fallback implementation.

* Fixing mangled extra code
This commit is contained in:
Chris B 2022-02-16 22:25:44 -06:00 коммит произвёл GitHub
Родитель e98f8cbc8b
Коммит a4b864751c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 122 добавлений и 4 удалений

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

@ -648,11 +648,13 @@ public:
if (OpKind == (uint64_t)DXIL::QuadVoteOpKind::All) {
Value *XY = B.CreateAnd(X, Y);
Result = B.CreateAnd(XY, Z);
Value *XYZ = B.CreateAnd(XY, Z);
Result = B.CreateAnd(XYZ, Cond);
} else {
DXASSERT_NOMSG(OpKind == (uint64_t)DXIL::QuadVoteOpKind::Any);
Value *XY = B.CreateOr(X, Y);
Result = B.CreateOr(XY, Z);
Value *XYZ = B.CreateOr(XY, Z);
Result = B.CreateOr(XYZ, Cond);
}
Value *Res = B.CreateTrunc(Result, Type::getInt1Ty(M.getContext()));
CI->replaceAllUsesWith(Res);

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

@ -2930,6 +2930,42 @@
g_TestResults[CS_INDEX] = tr;
}
}
]]>
</Shader>
</ShaderOp>
<ShaderOp Name="QuadAnyAll" CS="CS" DispatchX="8" DispatchY="8">
<RootSignature>RootFlags(0), UAV(u0)</RootSignature>
<Resource Name="UAVBuffer0" Dimension="BUFFER" Width="1024" InitialResourceState="COPY_DEST" Init="Zero" Flags="ALLOW_UNORDERED_ACCESS" ReadBack="true" />
<RootValues>
<RootValue Index="0" ResName="UAVBuffer0"/>
</RootValues>
<Shader Name="CS67" Target="cs_6_7" EntryPoint="main" Text="@CS"/>
<Shader Name="CS" Target="cs_6_0" EntryPoint="main">
<![CDATA[
RWStructuredBuffer<int2> Values;
groupshared uint WaveOffset = 0;
[numthreads(8, 8, 1)]
void main(uint TID: SV_GroupIndex) {
if (TID == 0)
WaveOffset = 0;
GroupMemoryBarrierWithGroupSync();
uint Offset = 0;
uint QuadElem = WaveGetLaneIndex() & 3;
if (QuadElem == 0)
Offset = WavePrefixSum(4);
Offset = QuadReadLaneAt(Offset, 0) + QuadElem;
uint LocalWaveOffset = 0;
if (WaveGetLaneIndex() == 0) {
InterlockedAdd(WaveOffset, WaveGetLaneCount(), LocalWaveOffset);
}
uint Idx = Offset + WaveReadLaneFirst(LocalWaveOffset);
uint2 ID = {Idx / 8, Idx % 8};
uint QuadId = Idx / 4;
uint QuadMask = 0x1U << QuadElem;
bool ThreadBool = (QuadMask & QuadId) != 0;
Values[Idx].x = QuadAny(ThreadBool) ? 1 : 2;
Values[Idx].y = QuadAll(ThreadBool) ? 3 : 4;
}
]]>
</Shader>
</ShaderOp>

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

@ -10,7 +10,8 @@
// SM66-NEXT: [[y:%[a-zA-Z0-9]+]] = call i32 @dx.op.quadOp.i32(i32 123, i32 [[cond]], i8 1)
// SM66-NEXT: [[z:%[a-zA-Z0-9]+]] = call i32 @dx.op.quadOp.i32(i32 123, i32 [[cond]], i8 2)
// SM66-NEXT: [[xy:%[a-z0-9]+]] = or i32 [[x]], [[y]]
// SM66-NEXT: [[wide:%[a-z0-9]+]] = or i32 [[xy]], [[z]]
// SM66-NEXT: [[xyz:%[a-z0-9]+]] = or i32 [[xy]], [[z]]
// SM66-NEXT: [[wide:%[a-z0-9]+]] = or i32 [[xyz]], [[cond]]
// SM66-NEXT: [[any:%[a-z0-9]+]] = trunc i32 [[wide]] to i1
// SM67: [[cond:%[a-z0-9]+]] = icmp ne i1 %{{[a-z0-9]+}}, false
@ -24,7 +25,8 @@
// SM66-NEXT: [[y:%[a-zA-Z0-9]+]] = call i32 @dx.op.quadOp.i32(i32 123, i32 [[cond]], i8 1)
// SM66-NEXT: [[z:%[a-zA-Z0-9]+]] = call i32 @dx.op.quadOp.i32(i32 123, i32 [[cond]], i8 2)
// SM66-NEXT: [[xy:%[a-z0-9]+]] = and i32 [[x]], [[y]]
// SM66-NEXT: [[wide:%[a-z0-9]+]] = and i32 [[xy]], [[z]]
// SM66-NEXT: [[xyz:%[a-z0-9]+]] = and i32 [[xy]], [[z]]
// SM66-NEXT: [[wide:%[a-z0-9]+]] = and i32 [[xyz]], [[cond]]
// SM66-NEXT: [[all:%[a-z0-9]+]] = trunc i32 [[wide]] to i1
// SM67: [[cond:%[a-z0-9]+]] = icmp ne i1 %{{[a-z0-9]+}}, false

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

@ -314,6 +314,7 @@ public:
TEST_METHOD(SignatureResourcesTest)
TEST_METHOD(DynamicResourcesTest)
TEST_METHOD(QuadReadTest)
TEST_METHOD(QuadAnyAll);
TEST_METHOD(CBufferTestHalf);
@ -9566,6 +9567,83 @@ TEST_F(ExecutionTest, HelperLaneTestWave) {
VERIFY_ARE_EQUAL(testPassed, true);
}
struct int2 {
int x;
int y;
};
bool VerifyQuadAnyAllResults(int2 *Res) {
int Idx = 0;
for ( ; Idx < 4; ++Idx) {
if (Res[Idx].x != 2) return false;
if (Res[Idx].y != 4) return false;
}
for ( ; Idx < 60; ++Idx) {
if (Res[Idx].x != 1) return false;
if (Res[Idx].y != 4) return false;
}
for ( ; Idx < 64; ++Idx) {
if (Res[Idx].x != 1) return false;
if (Res[Idx].y != 3) return false;
}
return true;
}
TEST_F(ExecutionTest, QuadAnyAll) {
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
CComPtr<IStream> pStream;
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
std::shared_ptr<st::ShaderOpSet> ShaderOpSet = std::make_shared<st::ShaderOpSet>();
st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get());
st::ShaderOp* pShaderOp = ShaderOpSet->GetShaderOp("QuadAnyAll");
LPCSTR args = "/Od";
if (args[0]) {
for (st::ShaderOpShader& S : pShaderOp->Shaders)
S.Arguments = args;
}
bool Skipped = true;
D3D_SHADER_MODEL TestShaderModels[] = { D3D_SHADER_MODEL_6_0, D3D_SHADER_MODEL_6_7 };
for (unsigned i = 0; i < _countof(TestShaderModels); i++) {
D3D_SHADER_MODEL sm = TestShaderModels[i];
LogCommentFmt(L"\r\nVerifying QuadAny/QuadAll using Wave intrinsics in shader model 6.%1u", ((UINT)sm & 0x0f));
if (sm == D3D_SHADER_MODEL_6_7) {
pShaderOp->CS = "CS67";
}
CComPtr<ID3D12Device> pDevice;
if (!CreateDevice(&pDevice, sm, false /* skipUnsupported */)) {
continue;
}
if (IsDeviceBasicAdapter(pDevice)) {
WEX::Logging::Log::Comment(L"QuadAny/All fails on basic render driver.");
continue;
}
if (!DoesDeviceSupportWaveOps(pDevice)) {
LogCommentFmt(L"Device does not support wave operations in shader model 6.%1u", ((UINT)sm & 0x0f));
continue;
}
Skipped = false;
// test compute
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(pDevice, m_support, "QuadAnyAll",
CleanUAVBuffer0Buffer, ShaderOpSet);
MappedData uavData;
test->Test->GetReadBackData("UAVBuffer0", &uavData);
bool Result = VerifyQuadAnyAllResults((int2*)uavData.data());
VERIFY_IS_TRUE(Result);
}
if (Skipped)
WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped);
}
#ifndef _HLK_CONF
static void WriteReadBackDump(st::ShaderOp *pShaderOp, st::ShaderOpTest *pTest,
char **pReadBackDump) {