[SM6.10][HLK] Add LinAlg execution test infrastructure with Load/Store/Splat tests#8285
[SM6.10][HLK] Add LinAlg execution test infrastructure with Load/Store/Splat tests#8285V-FEXrt wants to merge 8 commits intomicrosoft:mainfrom
Conversation
Introduce LinAlgTests.cpp with a new pattern for execution tests where ShaderOp objects are built programmatically in C++ no ShaderOpArith.xml entries required. Shader source, resources, and root signatures are all defined in the .cpp file. Each test compiles its shader via IDxcCompiler3 to validate the HLSL, then skips GPU dispatch if no SM 6.10 device is available. This ensures shader authoring correctness is always verified. Tests added: - LoadStoreRoundtrip_Wave_F32/I32: MatrixLoadFromDescriptor + MatrixStoreToDescriptor - SplatStore_Wave_F32/I32: FillMatrix + MatrixStoreToDescriptor Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
| if (!Device) { | ||
| hlsl_test::LogCommentFmt( | ||
| L"Shader compiled OK; skipping execution (no SM 6.10 device)"); | ||
| WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped); | ||
| return; | ||
| } |
There was a problem hiding this comment.
| if (!Device) { | |
| hlsl_test::LogCommentFmt( | |
| L"Shader compiled OK; skipping execution (no SM 6.10 device)"); | |
| WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped); | |
| return; | |
| } |
If we end up in here with no device something went wrong. We definitely don't want to skip. In the HLK this will effectively be a pass. Better to fail out when something tries to use it.
Generally, no skipping in HLK. And skipping in a TAEF test is usually reserved for "Does this system support my test? If not, skip"
There was a problem hiding this comment.
We don't want this test to fail when we run it outside of the HLK though, so we still need the skip in there. We could ifdef it for the HLK.
There was a problem hiding this comment.
So, we should handle that before we ever enter the test case? That is, skip in test class setup.
| } | ||
|
|
||
| std::vector<float> ExpectedFloats(NumElements, FillValue); | ||
| std::vector<int32_t> ExpectedInts(NumElements, |
|
|
||
| auto Op = | ||
| createComputeOp(SplatStoreShader, "cs_6_10", "UAV(u0)", Args.c_str()); | ||
| addUAVBuffer(Op.get(), "Output", BufferSize, true); |
There was a problem hiding this comment.
nit: We may want to consider adding addUAVBuffer and others to HLSLExecTestUtils.
And there may be potential to update the ShaderOpTest.cpp code to use those helpers.
For this PR I think just putting these generic helpers in HLSLExecTestUtils would be a good first step. They're likely to be useful for future tests looking to follow the same patterns in these tests.
| L"FailIfRequirementsNotMet is set."); | ||
| return false; | ||
| } | ||
| // No device — tests will compile shaders and skip execution. |
There was a problem hiding this comment.
| // No device — tests will compile shaders and skip execution. |
| // Try to create a device. In HLK mode, fail if unavailable. | ||
| // In dev mode, D3DDevice stays null and tests will compile shaders | ||
| // then skip GPU execution. | ||
| if (!D3D12SDK->createDevice(&D3DDevice, D3D_SHADER_MODEL_6_10, | ||
| /*SkipUnsupported=*/false)) { | ||
| if (FailIfRequirementsNotMet) { | ||
| hlsl_test::LogErrorFmt( | ||
| L"Device creation failed for SM 6.10, and " | ||
| L"FailIfRequirementsNotMet is set."); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
| // Try to create a device. In HLK mode, fail if unavailable. | |
| // In dev mode, D3DDevice stays null and tests will compile shaders | |
| // then skip GPU execution. | |
| if (!D3D12SDK->createDevice(&D3DDevice, D3D_SHADER_MODEL_6_10, | |
| /*SkipUnsupported=*/false)) { | |
| if (FailIfRequirementsNotMet) { | |
| hlsl_test::LogErrorFmt( | |
| L"Device creation failed for SM 6.10, and " | |
| L"FailIfRequirementsNotMet is set."); | |
| return false; | |
| } | |
| bool FailIfRequirementsNotMet = false; | |
| #ifdef _HLK_CONF | |
| FailIfRequirementsNotMet = true; | |
| #endif | |
| WEX::TestExecution::RuntimeParameters::TryGetValue( | |
| L"FailIfRequirementsNotMet", FailIfRequirementsNotMet); | |
| const bool SkipUnsupported = !FailIfRequirementsNotMet; | |
| if (!D3D12SDK->createDevice(&D3DDevice, D3D_SHADER_MODEL_6_10, | |
| SkipUnsupported)) { | |
| if (FailIfRequirementsNotMet) | |
| hlsl_test::LogErrorFmt( | |
| L"Device Creation failed, resulting in test failure, since " | |
| L"FailIfRequirementsNotMet is set. The expectation is that this " | |
| L"test will only be executed if something has previously " | |
| L"determined that the system meets the requirements of this " | |
| L"test."); | |
| return false; | |
| } |
There was a problem hiding this comment.
Line 392 of this should be SM 6_10, right?
| // Re-create device if it was lost. If we never had one, that's fine — | ||
| // tests compile shaders and skip GPU execution. |
There was a problem hiding this comment.
| // Re-create device if it was lost. If we never had one, that's fine — | |
| // tests compile shaders and skip GPU execution. |
| // Verification helpers | ||
| // =========================================================================== | ||
|
|
||
| static bool verifyFloatBuffer(const void *Actual, const float *Expected, |
There was a problem hiding this comment.
That might be a case of diminishing returns - the int one doesn't have a tolerance, and they use different format strings for logging them.
| // Try to create a device. In HLK mode, fail if unavailable. | ||
| // In dev mode, D3DDevice stays null and tests will compile shaders | ||
| // then skip GPU execution. | ||
| if (!D3D12SDK->createDevice(&D3DDevice, D3D_SHADER_MODEL_6_10, | ||
| /*SkipUnsupported=*/false)) { | ||
| if (FailIfRequirementsNotMet) { | ||
| hlsl_test::LogErrorFmt( | ||
| L"Device creation failed for SM 6.10, and " | ||
| L"FailIfRequirementsNotMet is set."); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Line 392 of this should be SM 6_10, right?
- Remove NOMINMAX block (not needed without std::min/max + windows.h) - Remove 'Unlike older execution tests...' paragraph from file header - Convert block comments to /// doc comment style - Remove unhelpful 'Always initialize DXC compiler' comment - Apply clang-format fixes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace custom ComponentType/MatrixUse/MatrixScope/MatrixLayout enums with hlsl::DXIL types from DxilConstants.h - Add elemSize() helper to eliminate duplicated element size logic in strideBytes() and totalBytes() - Make buildCompilerArgs take const MatrixParams& instead of individual params - Use switch statements for CompType dispatch instead of if-else chains Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| int ES = elemSize(CompType); | ||
| if (Layout == LinalgMatrixLayout::RowMajor) | ||
| return N * ES; | ||
| else |
There was a problem hiding this comment.
else after a return is unnecessary
- Update setupClass with SkipUnsupported variable and more informative error message following existing HLK test patterns - Update setupMethod with robust device-loss detection and recreation that fails hard (VERIFY) since a working device existed previously - Fix potential UB in runSplatStore by only constructing the expected int vector when CompType is I32 (avoids unconditional float-to-int cast) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| /// Return the byte size of a single element for the given component type. | ||
| static int elemSize(ComponentType CT) { | ||
| switch (CT) { | ||
| case ComponentType::F16: |
There was a problem hiding this comment.
How about the 8-bit component types I8, U8, F8_E4M3 and F8_E5M2?
|
|
||
| VERIFY_SUCCEEDED( | ||
| DxcSupport.InitializeForDll(dxc::kDxCompilerLib, "DxcCreateInstance")); | ||
|
|
||
| D3D12SDK = D3D12SDKSelector(); | ||
|
|
||
| WEX::TestExecution::RuntimeParameters::TryGetValue(L"VerboseLogging", | ||
| VerboseLogging); | ||
|
|
Introduce
LinAlgTests.cppwith a new pattern for execution tests where ShaderOp objects are built programmatically in C++ no ShaderOpArith.xml entries required. Shader source, resources, and root signatures are all defined in the.cppfile.Tests will currently be skipped since no driver reports SM6.10 support
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com