Skip to content

Commit

Permalink
PIX: Make shader access tracking pass return whether or not it modifi…
Browse files Browse the repository at this point in the history
…ed anything (microsoft#7010)

The SAT pass will now report a string when it finds that no resource
access was performed by a module.

This solves two issues.
-The SAT pass, when operating on a shader that has no resource access,
will add a resource declaration for the PIX output UAV. This becomes a
problem for PIX in terms of juggling root signatures and/or root
parameters.
-SAT is a notoriously time-consuming operation in PIX, so if the SAT
pass can report that its results do not need to be re-packaged into a
new container for passing to the d3d API, then PIX can avoid the
overhead of doing so.

But of course we need to be careful that the SAT pass doesn't
erroneously report that it didn't modify the module when in fact it did,
cuz then PIX would fail to notice some dynamic resource accesses. That's
what the tests are for.

(cherry picked from commit 848b7c4)
  • Loading branch information
jeffnn committed Dec 4, 2024
1 parent bbeb9f7 commit fb1a164
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
3 changes: 3 additions & 0 deletions lib/DxilPIXPasses/DxilShaderAccessTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,9 @@ bool DxilShaderAccessTracking::runOnModule(Module &M) {
// Done with these guys:
m_GEPOperandAsInstructionDestroyers.clear();

if (OSOverride != nullptr && !Modified) {
*OSOverride << "\nNotModified\n";
}
return Modified;
}
char DxilShaderAccessTracking::ID = 0;
Expand Down
80 changes: 74 additions & 6 deletions tools/clang/unittests/HLSL/PixTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ class PixTest : public ::testing::Test {
TEST_METHOD(SignatureModification_VertexIdAlready)
TEST_METHOD(SignatureModification_SomethingElseFirst)

TEST_METHOD(AccessTracking_ModificationReport_Nothing)
TEST_METHOD(AccessTracking_ModificationReport_Read)
TEST_METHOD(AccessTracking_ModificationReport_Write)
TEST_METHOD(AccessTracking_ModificationReport_SM66)

TEST_METHOD(PixStructAnnotation_Lib_DualRaygen)
TEST_METHOD(PixStructAnnotation_Lib_RaygenAllocaStructAlignment)

Expand Down Expand Up @@ -351,6 +356,8 @@ class PixTest : public ::testing::Test {
*ppNewShaderOut = pNewContainer.Detach();
}

void ValidateAccessTrackingMods(const char *hlsl, bool modsExpected);

class ModuleAndHangersOn {
std::unique_ptr<llvm::LLVMContext> llvmContext;
std::unique_ptr<llvm::Module> llvmModule;
Expand Down Expand Up @@ -432,7 +439,7 @@ class PixTest : public ::testing::Test {
const wchar_t *profile = L"as_6_5");
void ValidateAllocaWrite(std::vector<AllocaWrite> const &allocaWrites,
size_t index, const char *name);
CComPtr<IDxcBlob> RunShaderAccessTrackingPass(IDxcBlob *blob);
PassOutput RunShaderAccessTrackingPass(IDxcBlob *blob);
std::string RunDxilPIXAddTidToAmplificationShaderPayloadPass(IDxcBlob *blob);
CComPtr<IDxcBlob> RunDxilPIXMeshShaderOutputPass(IDxcBlob *blob);
CComPtr<IDxcBlob> RunDxilPIXDXRInvocationsLog(IDxcBlob *blob);
Expand Down Expand Up @@ -580,13 +587,14 @@ TEST_F(PixTest, CompileDebugDisasmPDB) {
VERIFY_SUCCEEDED(pCompiler->Disassemble(pPdbBlob, &pDisasm));
}

CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
PassOutput PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
CComPtr<IDxcOptimizer> pOptimizer;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcOptimizer, &pOptimizer));
std::vector<LPCWSTR> Options;
Options.push_back(L"-opt-mod-passes");
Options.push_back(L"-hlsl-dxil-pix-shader-access-instrumentation,config=");
Options.push_back(L"-hlsl-dxil-pix-shader-access-instrumentation,config=U0:0:"
L"10i0;U0:1:2i0;.0;0;0.");

CComPtr<IDxcBlob> pOptimizedModule;
CComPtr<IDxcBlobEncoding> pText;
Expand All @@ -608,7 +616,12 @@ CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
CComPtr<IDxcBlob> pNewContainer;
VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pNewContainer));

return pNewContainer;
PassOutput ret;
ret.blob = pNewContainer;
std::string outputText = BlobToUtf8(pText);
ret.lines = Tokenize(outputText.c_str(), "\n");

return ret;
}

CComPtr<IDxcBlob> PixTest::RunDxilPIXMeshShaderOutputPass(IDxcBlob *blob) {
Expand Down Expand Up @@ -820,6 +833,61 @@ TEST_F(PixTest, SignatureModification_SomethingElseFirst) {
VERIFY_ARE_EQUAL(sig.GetElement(2).GetStartRow(), 2);
}

void PixTest::ValidateAccessTrackingMods(const char *hlsl, bool modsExpected) {
auto code = Compile(m_dllSupport, hlsl, L"ps_6_6", {L"-Od"}, L"main");
auto result = RunShaderAccessTrackingPass(code).lines;
bool hasMods = true;
for (auto const &line : result)
if (line.find("NotModified") != std::string::npos)
hasMods = false;
VERIFY_ARE_EQUAL(modsExpected, hasMods);
}

TEST_F(PixTest, AccessTracking_ModificationReport_Nothing) {
const char *hlsl = R"(
float main() : SV_Target
{
return 0;
}
)";
ValidateAccessTrackingMods(hlsl, false);
}

TEST_F(PixTest, AccessTracking_ModificationReport_Read) {
const char *hlsl = R"(
RWByteAddressBuffer g_texture;
float main() : SV_Target
{
return g_texture.Load(0);
}
)";
ValidateAccessTrackingMods(hlsl, true);
}

TEST_F(PixTest, AccessTracking_ModificationReport_Write) {
const char *hlsl = R"(
RWByteAddressBuffer g_texture;
float main() : SV_Target
{
g_texture.Store(0, 0);
return 0;
}
)";
ValidateAccessTrackingMods(hlsl, true);
}

TEST_F(PixTest, AccessTracking_ModificationReport_SM66) {
const char *hlsl = R"(
float main() : SV_Target
{
RWByteAddressBuffer g_texture = ResourceDescriptorHeap[0];
g_texture.Store(0, 0);
return 0;
}
)";
ValidateAccessTrackingMods(hlsl, true);
}

TEST_F(PixTest, AddToASGroupSharedPayload) {

const char *hlsl = R"(
Expand Down Expand Up @@ -2734,7 +2802,7 @@ void MyMiss(inout MyPayload payload)
CComPtr<IDxcBlob> compiled;
VERIFY_SUCCEEDED(pResult->GetResult(&compiled));

auto optimizedContainer = RunShaderAccessTrackingPass(compiled);
auto optimizedContainer = RunShaderAccessTrackingPass(compiled).blob;

const char *pBlobContent =
reinterpret_cast<const char *>(optimizedContainer->GetBufferPointer());
Expand Down Expand Up @@ -2804,7 +2872,7 @@ float4 main(int i : A, float j : B) : SV_TARGET
)x";

auto compiled = Compile(m_dllSupport, dynamicTextureAccess, L"ps_6_6");
auto pOptimizedContainer = RunShaderAccessTrackingPass(compiled);
auto pOptimizedContainer = RunShaderAccessTrackingPass(compiled).blob;

const char *pBlobContent =
reinterpret_cast<const char *>(pOptimizedContainer->GetBufferPointer());
Expand Down

0 comments on commit fb1a164

Please sign in to comment.