Skip to content

[PIX] Inline helper functions before shader debugging - #8853

Open
Damyan Pepper (damyanp) wants to merge 1 commit into
users/damyanp/pix-fixes-11from
users/damyanp/pix-fixes-12
Open

[PIX] Inline helper functions before shader debugging#8853
Damyan Pepper (damyanp) wants to merge 1 commit into
users/damyanp/pix-fixes-11from
users/damyanp/pix-fixes-12

Conversation

@damyanp

@damyanp Damyan Pepper (damyanp) commented Aug 28, 2026

Copy link
Copy Markdown
Member

Part 12 of 14 in the PIX instrumentation stack. It targets users/damyanp/pix-fixes-11. Its content depends on PR 10 for the textual-IR test support, and on PR 2.

PIX maps one shader invocation to one record stream in the debug UAV, and one stream to exactly one function. A [noinline] helper instrumented as its own function looks like a second invocation of a thread that runs once. PIX discards those records, and you cannot step into the helper.

The debug instrumentation always emits RawBufferStore. That operation is legal only from shader model 6.2, so shader models 6.0 and 6.1 get an invalid module.

The pass creates the tools UAV before it knows whether there is anything to instrument. A library that contains only helpers therefore gains a UAV although the pass reports that it changed nothing.

Inlining happens before the pass numbers instructions or creates shadow storage. Every prepass does it, so the debug, non-uniform-resource-index, and debug-break pipelines all see the same module shape. A library module is left alone, because each exported function is its own invocation. The runtime invokes the patch-constant function of a hull shader directly. That function therefore survives inlining, and the pass instruments it. The pass selects an invocation of it by primitive alone, because OutputControlPointID is valid only in the control point phase.

A function that survives inlining is named in the pass report as UninlinedFunction:, so PIX does not offer a range with no records. The pass reports it and continues, instead of stopping the process.

Assisted-by: Copilot

This changes only the PIX instrumentation, so it needs no release note.


Stack created with GitHub Stacks CLIGive Feedback 💬

PIX maps one shader invocation to one record stream in the debug UAV, and one stream to exactly one function. A [noinline] helper instrumented as its own function looks like a second invocation of a thread that runs once. PIX discards those records, and you cannot step into the helper.

The debug instrumentation always emits RawBufferStore. That operation is legal only from shader model 6.2, so shader models 6.0 and 6.1 get an invalid module.

The pass creates the tools UAV before it knows whether there is anything to instrument. A library that contains only helpers therefore gains a UAV although the pass reports that it changed nothing.

Inlining happens before the pass numbers instructions or creates shadow storage. Every prepass does it, so the debug, non-uniform-resource-index, and debug-break pipelines all see the same module shape. A library module is left alone, because each exported function is its own invocation. The runtime invokes the patch-constant function of a hull shader directly. That function therefore survives inlining, and the pass instruments it. The pass selects an invocation of it by primitive alone, because OutputControlPointID is valid only in the control point phase.

A function that survives inlining is named in the pass report as UninlinedFunction:<name>, so PIX does not offer a range with no records. The pass reports it and continues, instead of stopping the process.

Assisted-by: Copilot

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ac42a8d8-c740-45a3-9a2d-7cfc39b92853

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates PIX instrumentation to inline helper functions, support older shader models, and avoid unnecessary debug UAVs.

Changes:

  • Inlines non-entry helpers before PIX prepasses and reports survivors.
  • Instruments hull patch-constant functions.
  • Uses BufferStore before shader model 6.2 and adds regression coverage.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/clang/unittests/HLSL/PixTest.cpp Adds PIX regression tests and helpers.
tools/clang/test/HLSLFileCheck/pix/NonUniformResourceIndexInHelperFunction.hlsl Tests resource indexing after helper inlining.
tools/clang/test/HLSLFileCheck/pix/DebugStoreOpcodeByShaderModel.hlsl Tests store opcode selection.
tools/clang/test/HLSLFileCheck/pix/DebugNoInlineHelperFunction.hlsl Tests debug information after inlining.
tools/clang/test/HLSLFileCheck/pix/DebugHullPatchConstantFunction.hlsl Tests hull patch-constant instrumentation.
tools/clang/test/HLSLFileCheck/pix/DebugBreakInstrumentationInHelperFunction.hlsl Tests debug-break helper inlining.
lib/DxilPIXPasses/PixPassHelpers.h Declares the inlining helper.
lib/DxilPIXPasses/PixPassHelpers.cpp Implements helper inlining and survivor collection.
lib/DxilPIXPasses/DxilDebugInstrumentation.cpp Updates instrumentation targets and store operations.
lib/DxilPIXPasses/DxilDbgValueToDbgDeclare.cpp Runs inlining before shadow-storage generation.
lib/DxilPIXPasses/DxilAnnotateWithVirtualRegister.cpp Runs inlining before annotation and reports survivors.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +605 to 612
if (M.HasDxilModule() ||
M.getNamedMetadata(hlsl::DxilMDHelper::kDxilVersionMDName) != nullptr) {
PIXPassHelpers::InlineNonEntryFunctions(M.GetOrCreateDxilModule());
}

auto GlobalEmbeddedArrayStorage = GatherGlobalEmbeddedArrayStorage(M);

bool Changed = false;
// llvm::InlineFunction is the mechanical inliner and ignores inlining
// attributes. Clear the attribute so the module carries no claim that
// contradicts its own shape.
function->removeFnAttr(llvm::Attribute::NoInline);
Comment on lines +133 to +135
llvm::SmallVector<llvm::Function *, 4> UninlinedFunctions;
PIXPassHelpers::InlineNonEntryFunctions(M.GetOrCreateDxilModule(),
&UninlinedFunctions);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

3 participants