@@ -192,6 +192,10 @@ class PixTest {
192192 TEST_METHOD (DiaCompileArgs)
193193 TEST_METHOD (PixDebugCompileInfo)
194194
195+ TEST_METHOD (CheckSATPassFor66_NoDynamicAccess)
196+ TEST_METHOD (CheckSATPassFor66_DynamicFromRootSig)
197+ TEST_METHOD (CheckSATPassFor66_DynamicFromHeap)
198+
195199 TEST_METHOD (PixStructAnnotation_Simple)
196200 TEST_METHOD (PixStructAnnotation_CopiedStruct)
197201 TEST_METHOD (PixStructAnnotation_MixedSizes)
@@ -978,7 +982,8 @@ class PixTest {
978982
979983 TestableResults TestStructAnnotationCase (const char * hlsl, const wchar_t * optimizationLevel, bool validateCoverage = true );
980984 void ValidateAllocaWrite (std::vector<AllocaWrite> const & allocaWrites, size_t index, const char * name);
981-
985+ std::string RunShaderAccessTrackingPassAndReturnOutputMessages (IDxcBlob* blob);
986+ CComPtr<IDxcBlob> Compile (const char * hlsl, const wchar_t * profile);
982987};
983988
984989
@@ -1640,6 +1645,130 @@ TEST_F(PixTest, PixDebugCompileInfo) {
16401645 VERIFY_ARE_EQUAL (std::wstring (profile), std::wstring (hlslTarget));
16411646}
16421647
1648+ CComPtr<IDxcBlob> PixTest::Compile (const char * hlsl, const wchar_t * profile)
1649+ {
1650+
1651+ CComPtr<IDxcLibrary> pLib;
1652+ VERIFY_SUCCEEDED (m_dllSupport.CreateInstance (CLSID_DxcLibrary, &pLib));
1653+
1654+ CComPtr<IDxcCompiler> pCompiler;
1655+ CComPtr<IDxcCompiler2> pCompiler2;
1656+
1657+ CComPtr<IDxcOperationResult> pResult;
1658+ CComPtr<IDxcBlobEncoding> pSource;
1659+ CComPtr<IDxcBlob> pProgram;
1660+ CComPtr<IDxcBlob> pPdbBlob;
1661+ WCHAR *pDebugName = nullptr ;
1662+
1663+ VERIFY_SUCCEEDED (CreateCompiler (&pCompiler));
1664+ VERIFY_SUCCEEDED (pCompiler.QueryInterface (&pCompiler2));
1665+ CreateBlobFromText (hlsl, &pSource);
1666+ LPCWSTR args[] = {L" /Zi" , L" /Qembed_debug" };
1667+ VERIFY_SUCCEEDED (pCompiler2->CompileWithDebug (
1668+ pSource, L" source.hlsl" , L" main" , profile, args, _countof (args),
1669+ nullptr , 0 , nullptr , &pResult, &pDebugName, &pPdbBlob));
1670+
1671+ HRESULT hr;
1672+ VERIFY_SUCCEEDED (pResult->GetStatus (&hr));
1673+ if (FAILED (hr))
1674+ {
1675+ CComPtr<IDxcBlobEncoding> pErrors;
1676+ pResult->GetErrorBuffer (&pErrors);
1677+
1678+ if (pErrors && pErrors->GetBufferSize () > 0 ) {
1679+ auto errorMessages =
1680+ reinterpret_cast <const char *>(pErrors->GetBufferPointer ());
1681+ std::wstring wideErrrors;
1682+ wideErrrors.assign (errorMessages,
1683+ errorMessages + pErrors->GetBufferSize ());
1684+ WEX::Logging::Log::Comment (L" Compilation failed. Error messages:" );
1685+ WEX::Logging::Log::Comment (wideErrrors.c_str ());
1686+ }
1687+
1688+ VERIFY_SUCCEEDED (hr);
1689+ }
1690+ VERIFY_SUCCEEDED (pResult->GetResult (&pProgram));
1691+
1692+ return pProgram;
1693+ }
1694+
1695+ std::string PixTest::RunShaderAccessTrackingPassAndReturnOutputMessages (IDxcBlob* blob)
1696+ {
1697+ CComPtr<IDxcBlob> dxil = FindModule (DFCC_ShaderDebugInfoDXIL, blob);
1698+ CComPtr<IDxcOptimizer> pOptimizer;
1699+ VERIFY_SUCCEEDED (
1700+ m_dllSupport.CreateInstance (CLSID_DxcOptimizer, &pOptimizer));
1701+ std::vector<LPCWSTR> Options;
1702+ Options.push_back (L" -opt-mod-passes" );
1703+ Options.push_back (L" -hlsl-dxil-pix-shader-access-instrumentation,config=,checkForDynamicIndexing=1" );
1704+
1705+ CComPtr<IDxcBlob> pOptimizedModule;
1706+ CComPtr<IDxcBlobEncoding> pText;
1707+ VERIFY_SUCCEEDED (pOptimizer->RunOptimizer (
1708+ dxil, Options.data (), Options.size (), &pOptimizedModule, &pText));
1709+
1710+ std::string outputText;
1711+ if (pText->GetBufferSize () != 0 ) {
1712+ outputText = reinterpret_cast <const char *>(pText->GetBufferPointer ());
1713+ }
1714+
1715+ return outputText;
1716+ }
1717+
1718+ TEST_F (PixTest, CheckSATPassFor66_NoDynamicAccess) {
1719+
1720+ const char *noDynamicAccess = R"(
1721+ [RootSignature("")]
1722+ float main(float pos : A) : SV_Target {
1723+ float x = abs(pos);
1724+ float y = sin(pos);
1725+ float z = x + y;
1726+ return z;
1727+ }
1728+ )" ;
1729+
1730+ auto compiled = Compile (noDynamicAccess, L" ps_6_6" );
1731+ auto satResults = RunShaderAccessTrackingPassAndReturnOutputMessages (compiled);
1732+ VERIFY_IS_TRUE (satResults.empty ());
1733+ }
1734+
1735+ TEST_F (PixTest, CheckSATPassFor66_DynamicFromRootSig) {
1736+
1737+ const char *dynamicTextureAccess = R"x(
1738+ Texture1D<float4> tex[5] : register(t3);
1739+ SamplerState SS[3] : register(s2);
1740+
1741+ [RootSignature("DescriptorTable(SRV(t3, numDescriptors=5)),\
1742+ DescriptorTable(Sampler(s2, numDescriptors=3))")]
1743+ float4 main(int i : A, float j : B) : SV_TARGET
1744+ {
1745+ float4 r = tex[i].Sample(SS[i], i);
1746+ return r;
1747+ }
1748+ )x" ;
1749+
1750+ auto compiled = Compile (dynamicTextureAccess, L" ps_6_6" );
1751+ auto satResults = RunShaderAccessTrackingPassAndReturnOutputMessages (compiled);
1752+ VERIFY_IS_TRUE (satResults.find (" FoundDynamicIndexing" ) != string::npos);
1753+ }
1754+
1755+ TEST_F (PixTest, CheckSATPassFor66_DynamicFromHeap) {
1756+
1757+ const char *dynamicResourceDecriptorHeapAccess = R"(
1758+ static sampler sampler0 = SamplerDescriptorHeap[0];
1759+ float4 main(int input : INPUT) : SV_Target
1760+ {
1761+ Texture2D texture = ResourceDescriptorHeap[input];
1762+ return texture.Sample(sampler0, float2(0,0));
1763+ }
1764+ )" ;
1765+
1766+ auto compiled = Compile (dynamicResourceDecriptorHeapAccess, L" ps_6_6" );
1767+ auto satResults =
1768+ RunShaderAccessTrackingPassAndReturnOutputMessages (compiled);
1769+ VERIFY_IS_TRUE (satResults.find (" FoundDynamicIndexing" ) != string::npos);
1770+ }
1771+
16431772// This function lives in lib\DxilPIXPasses\DxilAnnotateWithVirtualRegister.cpp
16441773// Declared here so we can test it.
16451774uint32_t CountStructMembers (llvm::Type const * pType);
0 commit comments