@@ -328,6 +328,7 @@ class ExecutionTest {
328328 TEST_METHOD(WaveIntrinsicsDDITest);
329329 TEST_METHOD(WaveIntrinsicsInPSTest);
330330 TEST_METHOD(WaveSizeTest);
331+ TEST_METHOD(WaveSizeRangeTest);
331332 TEST_METHOD(PartialDerivTest);
332333 TEST_METHOD(DerivativesTest);
333334 TEST_METHOD(ComputeSampleTest);
@@ -13220,22 +13221,208 @@ TEST_F(ExecutionTest, DynamicResourcesDynamicIndexingTest) {
1322013221
1322113222#define MAX_WAVESIZE 128
1322213223
13223- #define strinfigy2(arg) #arg
13224- #define strinfigy(arg) strinfigy2(arg)
13224+ #define stringify2(arg) #arg
13225+ #define stringify(arg) stringify2(arg)
13226+
13227+ void RunWaveSizeTest(UINT minWaveSize, UINT maxWaveSize,
13228+ std::shared_ptr<st::ShaderOpSet> ShaderOpSet,
13229+ CComPtr<ID3D12Device> pDevice,
13230+ dxc::DxcDllSupport &m_support) {
13231+ // format shader source
13232+ const char waveSizeTestShader[] =
13233+ R"(struct TestData {
13234+ uint count;
13235+ };
13236+ RWStructuredBuffer<TestData> data : register(u0);
13237+
13238+ // Note: WAVESIZE will be defined via compiler option -D
13239+ WAVE_SIZE_ATTR
13240+ [numthreads()" stringify(MAX_WAVESIZE) R"(*2,1,1)]
13241+ void main() {
13242+ data[0].count = WaveGetLaneCount();
13243+ })";
13244+
13245+ struct WaveSizeTestData {
13246+ uint32_t count;
13247+ };
13248+
13249+ for (UINT waveSize = minWaveSize; waveSize <= maxWaveSize; waveSize *= 2) {
13250+ // format compiler args
13251+ char compilerOptions[64];
13252+ VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
13253+ "-D WAVE_SIZE_ATTR=[wavesize(%d)]",
13254+ waveSize) != -1);
13255+
13256+ // run the shader
13257+ std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(
13258+ pDevice, m_support, "WaveSizeTest",
13259+ [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
13260+ VERIFY_IS_TRUE((0 == strncmp(Name, "UAVBuffer0", 10)));
13261+ pShaderOp->Shaders.at(0).Arguments = compilerOptions;
13262+ pShaderOp->Shaders.at(0).Text = waveSizeTestShader;
13263+
13264+ VERIFY_IS_TRUE(sizeof(WaveSizeTestData) * MAX_WAVESIZE <=
13265+ Data.size());
13266+ WaveSizeTestData *pInData = (WaveSizeTestData *)Data.data();
13267+ memset(pInData, 0, sizeof(WaveSizeTestData) * MAX_WAVESIZE);
13268+ },
13269+ ShaderOpSet);
13270+
13271+ // verify expected values
13272+ MappedData dataUav;
13273+ WaveSizeTestData *pOutData;
13274+
13275+ test->Test->GetReadBackData("UAVBuffer0", &dataUav);
13276+ VERIFY_ARE_EQUAL(sizeof(WaveSizeTestData) * MAX_WAVESIZE, dataUav.size());
13277+ pOutData = (WaveSizeTestData *)dataUav.data();
13278+
13279+ LogCommentFmt(L"Verifying test result for wave size %d", waveSize);
13280+
13281+ VERIFY_ARE_EQUAL(pOutData[0].count, waveSize);
13282+ }
13283+ }
13284+
13285+ bool TestShaderRangeAgainstRequirements(UINT shaderminws, UINT shadermaxws,
13286+ UINT minws, UINT maxws) {
13287+ if (shaderminws > maxws) {
13288+ return false;
13289+ }
13290+ if (shadermaxws < minws) {
13291+ return false;
13292+ }
13293+ return true;
13294+ }
13295+
13296+ void ExecuteWaveSizeRangeInstance(UINT minWaveSize, UINT maxWaveSize,
13297+ std::shared_ptr<st::ShaderOpSet> ShaderOpSet,
13298+ CComPtr<ID3D12Device> pDevice,
13299+ dxc::DxcDllSupport &m_support,
13300+ UINT minShaderWaveSize,
13301+ UINT maxShaderWaveSize,
13302+ UINT prefShaderWaveSize, bool usePreferred) {
13303+
13304+ // format shader source
13305+ const char waveSizeTestShader[] =
13306+ R"(struct TestData {
13307+ uint count;
13308+ };
13309+ RWStructuredBuffer<TestData> data : register(u0);
13310+
13311+ // Note: WAVE_SIZE_ATTR will be defined via compiler option -D
13312+ WAVE_SIZE_ATTR
13313+ [numthreads()" stringify(MAX_WAVESIZE) R"(*2,1,1)]
13314+ void main(uint3 tid : SV_DispatchThreadID) {
13315+ if (tid.x == 0 && tid.y == 0 && tid.z == 0) {
13316+ data[0].count = WaveGetLaneCount();
13317+ }
13318+ })";
13319+
13320+ // format compiler args
13321+ char compilerOptions[64];
13322+ if (usePreferred) {
13323+ // putting spaces in between the %d's below will cause compilation issues.
13324+ VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
13325+ "-D WAVE_SIZE_ATTR=[wavesize(%d,%d,%d)]",
13326+ minShaderWaveSize, maxShaderWaveSize,
13327+ prefShaderWaveSize) != -1);
13328+ LogCommentFmt(L"Verifying wave size range test results for (min, max, "
13329+ L"preferred): (%d, %d, %d)",
13330+ minShaderWaveSize, maxShaderWaveSize, prefShaderWaveSize);
13331+ } else {
13332+ VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
13333+ "-D WAVE_SIZE_ATTR=[wavesize(%d,%d)]",
13334+ minShaderWaveSize, maxShaderWaveSize) != -1);
13335+ LogCommentFmt(
13336+ L"Verifying wave size range test results for (min, max): (%d, %d)",
13337+ minShaderWaveSize, maxShaderWaveSize);
13338+ }
13339+
13340+ struct WaveSizeTestData {
13341+ uint32_t count;
13342+ };
13343+
13344+ // run the shader
13345+ std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(
13346+ pDevice, m_support, "WaveSizeTest",
13347+ [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
13348+ VERIFY_IS_TRUE((0 == strncmp(Name, "UAVBuffer0", 10)));
13349+ pShaderOp->Shaders.at(0).Arguments = compilerOptions;
13350+ pShaderOp->Shaders.at(0).Text = waveSizeTestShader;
13351+ pShaderOp->Shaders.at(0).Target = "cs_6_8";
13352+
13353+ VERIFY_IS_TRUE(sizeof(WaveSizeTestData) * MAX_WAVESIZE <= Data.size());
13354+ WaveSizeTestData *pInData = (WaveSizeTestData *)Data.data();
13355+ memset(pInData, 0, sizeof(WaveSizeTestData) * MAX_WAVESIZE);
13356+ },
13357+ ShaderOpSet);
13358+
13359+ // verify expected values
13360+ MappedData dataUav;
13361+ WaveSizeTestData *pOutData;
13362+
13363+ // at this point we assume that the waverange size that
13364+ // the shader specifies is legal.
13365+ test->Test->GetReadBackData("UAVBuffer0", &dataUav);
13366+ VERIFY_ARE_EQUAL(sizeof(WaveSizeTestData) * MAX_WAVESIZE, dataUav.size());
13367+ pOutData = (WaveSizeTestData *)dataUav.data();
13368+
13369+ unsigned count = pOutData[0].count;
13370+ if (usePreferred && prefShaderWaveSize >= minWaveSize &&
13371+ prefShaderWaveSize <= maxWaveSize) {
13372+ VERIFY_ARE_EQUAL(count, prefShaderWaveSize);
13373+ } else {
13374+ VERIFY_IS_GREATER_THAN_OR_EQUAL(count, minWaveSize);
13375+ VERIFY_IS_LESS_THAN_OR_EQUAL(count, maxWaveSize);
13376+ }
13377+ }
13378+
13379+ void RunWaveSizeRangeTest(UINT minWaveSize, UINT maxWaveSize,
13380+ std::shared_ptr<st::ShaderOpSet> ShaderOpSet,
13381+ CComPtr<ID3D12Device> pDevice,
13382+ dxc::DxcDllSupport &m_support) {
13383+
13384+ for (UINT minShaderWaveSize = 4; minShaderWaveSize <= maxWaveSize;
13385+ minShaderWaveSize *= 2) {
13386+ for (UINT maxShaderWaveSize = minShaderWaveSize * 2;
13387+ maxShaderWaveSize <= 128; maxShaderWaveSize *= 2) {
13388+ // Only allow valid shader wave ranges
13389+ bool AcceptedByRuntime = TestShaderRangeAgainstRequirements(
13390+ minShaderWaveSize, maxShaderWaveSize, minWaveSize, maxWaveSize);
13391+ if (!AcceptedByRuntime) {
13392+ continue;
13393+ }
13394+
13395+ ExecuteWaveSizeRangeInstance(
13396+ minWaveSize, maxWaveSize, ShaderOpSet, pDevice, m_support,
13397+ minShaderWaveSize, maxShaderWaveSize,
13398+ /* prefShaderWaveSize won't be used, so set it to minShaderWaveSize*/
13399+ minShaderWaveSize, false);
13400+
13401+ for (UINT prefShaderWaveSize = minShaderWaveSize;
13402+ prefShaderWaveSize <= maxShaderWaveSize; prefShaderWaveSize *= 2) {
13403+
13404+ ExecuteWaveSizeRangeInstance(
13405+ minWaveSize, maxWaveSize, ShaderOpSet, pDevice, m_support,
13406+ minShaderWaveSize, maxShaderWaveSize, prefShaderWaveSize, true);
13407+ }
13408+ }
13409+ }
13410+ }
1322513411
1322613412void ExecutionTest::WaveSizeTest() {
1322713413 WEX::TestExecution::SetVerifyOutput verifySettings(
1322813414 WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
1322913415
1323013416 CComPtr<ID3D12Device> pDevice;
13231- if (!CreateDevice(&pDevice, D3D_SHADER_MODEL_6_6)) {
13417+ if (!CreateDevice(&pDevice, D3D_SHADER_MODEL_6_6,
13418+ /*skipUnsupported*/ false)) {
1323213419 return;
1323313420 }
1323413421
1323513422 // Check Wave support
1323613423 if (!DoesDeviceSupportWaveOps(pDevice)) {
1323713424 // Optional feature, so it's correct to not support it if declared as such.
13238- WEX::Logging::Log::Comment(L"Device does not support wave operations." );
13425+ WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped );
1323913426 return;
1324013427 }
1324113428
@@ -13258,61 +13445,51 @@ void ExecutionTest::WaveSizeTest() {
1325813445 ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
1325913446 st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get());
1326013447
13261- // format shader source
13262- const char waveSizeTestShader[] =
13263- "struct TestData { \r\n"
13264- " uint count; \r\n"
13265- "}; \r\n"
13266- "RWStructuredBuffer<TestData> data : register(u0); \r\n"
13267- "\r\n"
13268- "// Note: WAVESIZE will be defined via compiler option -D\r\n"
13269- "[wavesize(WAVESIZE)]\r\n"
13270- "[numthreads(" strinfigy(
13271- MAX_WAVESIZE) "*2,1,1)]\r\n"
13272- "void main(uint3 tid : SV_DispatchThreadID ) { \r\n"
13273- " data[tid.x].count = WaveActiveSum(1); \r\n"
13274- "}\r\n";
13448+ LogCommentFmt(L"Testing WaveSize attribute for shader model 6.6.");
13449+ RunWaveSizeTest(minWaveSize, maxWaveSize, ShaderOpSet, pDevice, m_support);
13450+ }
1327513451
13276- struct WaveSizeTestData {
13277- uint32_t count;
13278- } ;
13452+ void ExecutionTest::WaveSizeRangeTest() {
13453+ WEX::TestExecution::SetVerifyOutput verifySettings(
13454+ WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures) ;
1327913455
13280- for (UINT waveSize = minWaveSize; waveSize <= maxWaveSize; waveSize *= 2) {
13281- // format compiler args
13282- char compilerOptions[32];
13283- VERIFY_IS_TRUE(sprintf_s(compilerOptions, sizeof(compilerOptions),
13284- "-D WAVESIZE=%d", waveSize) != -1);
13456+ CComPtr<ID3D12Device> pDevice;
13457+ if (!CreateDevice(&pDevice, D3D_SHADER_MODEL_6_8,
13458+ /*skipUnsupported*/ false)) {
13459+ return;
13460+ }
1328513461
13286- // run the shader
13287- std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(
13288- pDevice, m_support, "WaveSizeTest",
13289- [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
13290- VERIFY_IS_TRUE((0 == strncmp(Name, "UAVBuffer0", 10)));
13291- pShaderOp->Shaders.at(0).Arguments = compilerOptions;
13292- pShaderOp->Shaders.at(0).Text = waveSizeTestShader;
13462+ // Check Wave support
13463+ if (!DoesDeviceSupportWaveOps(pDevice)) {
13464+ // Optional feature, so it's correct to not support it if declared as such.
13465+ WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped);
13466+ return;
13467+ }
1329313468
13294- VERIFY_IS_TRUE(sizeof(WaveSizeTestData) * MAX_WAVESIZE <=
13295- Data.size());
13296- WaveSizeTestData *pInData = (WaveSizeTestData *)Data.data();
13297- memset(pInData, 0, sizeof(WaveSizeTestData) * MAX_WAVESIZE);
13298- },
13299- ShaderOpSet);
13469+ // Get supported wave sizes
13470+ D3D12_FEATURE_DATA_D3D12_OPTIONS1 waveOpts;
13471+ VERIFY_SUCCEEDED(
13472+ pDevice->CheckFeatureSupport((D3D12_FEATURE)D3D12_FEATURE_D3D12_OPTIONS1,
13473+ &waveOpts, sizeof(waveOpts)));
13474+ UINT minWaveSize = waveOpts.WaveLaneCountMin;
13475+ UINT maxWaveSize = waveOpts.WaveLaneCountMax;
1330013476
13301- // verify expected values
13302- MappedData dataUav ;
13303- WaveSizeTestData *pOutData ;
13477+ DXASSERT_NOMSG(minWaveSize <= maxWaveSize);
13478+ DXASSERT((minWaveSize & (minWaveSize - 1)) == 0, "must be a power of 2") ;
13479+ DXASSERT((maxWaveSize & (maxWaveSize - 1)) == 0, "must be a power of 2") ;
1330413480
13305- test->Test->GetReadBackData("UAVBuffer0", &dataUav);
13306- VERIFY_ARE_EQUAL(sizeof(WaveSizeTestData) * MAX_WAVESIZE, dataUav.size());
13307- pOutData = (WaveSizeTestData *)dataUav.data();
13481+ // read shader config
13482+ CComPtr<IStream> pStream;
13483+ std::shared_ptr<st::ShaderOpSet> ShaderOpSet =
13484+ std::make_shared<st::ShaderOpSet>();
13485+ ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
13486+ st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get());
1330813487
13309- LogCommentFmt(L"Verifying test result for wave size %d", waveSize);
13488+ LogCommentFmt(L"Testing WaveSize Range attribute for shader model 6.8.");
13489+ RunWaveSizeTest(minWaveSize, maxWaveSize, ShaderOpSet, pDevice, m_support);
1331013490
13311- for (unsigned i = 0; i < MAX_WAVESIZE; i++) {
13312- if (!VERIFY_ARE_EQUAL(pOutData[i].count, waveSize))
13313- break;
13314- }
13315- }
13491+ RunWaveSizeRangeTest(minWaveSize, maxWaveSize, ShaderOpSet, pDevice,
13492+ m_support);
1331613493}
1331713494
1331813495// Atomic operation testing
0 commit comments