Skip to content

[Exec] Enable the D3D12 debug layer on the Agility device factory - #8708

Merged
JoeCitizen merged 4 commits into
microsoft:mainfrom
JoeCitizen:linalg-hlk-agility-debug-layer
Jul 29, 2026
Merged

[Exec] Enable the D3D12 debug layer on the Agility device factory#8708
JoeCitizen merged 4 commits into
microsoft:mainfrom
JoeCitizen:linalg-hlk-agility-debug-layer

Conversation

@JoeCitizen

@JoeCitizen JoeCitizen commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

The HLSLExec harness logged Debug layer enabled on every run, but the D3D12 debug layer was never active on the device under test and no validation message ever reached the test log.

This enables the debug layer on the code path the harness actually uses, and routes its messages into the test log.

Why this is needed

Two defects made the debug layer silently inert.

Ordering. enableDebugLayer() ran as the first statement of the D3D12SDKSelector constructor, before SetSDKVersion or CreateDeviceFactory. With no Agility redirection in effect yet, D3D12GetDebugInterface bound the inbox D3D12Core.

Scope. When D3D12SDKPath resolves to an Agility SDK, D3D12SDKSelector takes the ID3D12DeviceFactory path. A factory hosts its own D3D12Core, so process-global debug state never reaches the devices it creates; it must be enabled through ID3D12DeviceFactory::GetConfigurationInterface(CLSID_D3D12Debug, ...).

The inbox call succeeded, so the harness reported success. The follow-up QueryInterface<ID3D12InfoQueue> on the real device failed, but had no else branch, so every log claimed the debug layer was fine while it did nothing.

Separately, the debug layer only emits through OutputDebugString, which is invisible outside a debugger. SetMuteDebugOutput(FALSE) un-mutes that channel but nothing pumped it into the test log.

The practical cost: two long-standing LinAlg failures presented only as DXGI_ERROR_DEVICE_REMOVED (0x887a0005) at CreateCommandQueue, with no indication of cause.

What changed

  • enableDebugLayerOnFactory() enables the layer through the device factory's configuration interface, called from createDeviceFactorySDK.
  • The global path (renamed enableGlobalDebugLayer) moved to after Agility SDK selection, so it binds the D3D12Core that actually services device creation.
  • An ID3D12InfoQueue1 message callback writes debug layer messages to the test log. Diagnostic only: they are logged as comments and never alter a test outcome.
  • Previously silent ID3D12InfoQueue / ID3D12InfoQueue1 QueryInterface failures are now reported.
  • Two runtime parameters:
/p:D3D12DebugLayer=true|false
/p:D3D12DebugMessageSeverity=none|corruption|error|warning|info|message

Default

On for developer builds, off for HLK conformance builds (_HLK_CONF). /p:D3D12DebugLayer overrides it either way.

Errors and corruption are reported by default. Warnings repeat per resource and per PSO, so they need D3D12DebugMessageSeverity.

Validation

Built Release, run on WARP against an SM6.10 Agility SDK.

Suite Unmodified main This PR
ExecutionTest::* 207 total, 204 passed, 3 failed identical, same 3
LinAlg::DxilConf_SM610_LinAlg::* 22 total, 19 passed, 2 failed, 1 skipped identical, same 2
Full ExecHLSLTests - 1190 total, 1184 passed, 5 failed, 1 skipped (the 5 above)

The 3 ExecutionTest failures are pre-existing and unrelated: D3D12_FEATURE_D3D12_OPTIONS_PREVIEW returns E_INVALIDARG on this D3D12Core.

Both SDK selection paths were exercised, and D3D12DebugLayer verified for absent, true, false and an invalid value. Test outcomes are identical in every case. clang-format clean.

Refs #7841

Closes #8709


Assisted-by: GitHub Copilot

The HLSLExec harness logs "Debug layer enabled" on every run, but the debug
layer was never active on the device under test and no validation message ever
reached the test log. Two independent defects caused this.

Ordering: enableDebugLayer() calls the exported D3D12GetDebugInterface and ran
as the first statement of the D3D12SDKSelector constructor, before either
SetSDKVersion or CreateDeviceFactory. With no Agility SDK redirection yet in
effect, that call binds the inbox D3D12Core.

Scope: when D3D12SDKPath resolves to an Agility SDK, D3D12SDKSelector takes the
ID3D12DeviceFactory path. A device factory hosts its own D3D12Core instance, so
process-global debug state does not reach the devices it creates. The debug
layer has to be enabled through the factory's own configuration interface.

Enable the debug layer via ID3D12DeviceFactory::GetConfigurationInterface on the
factory path, and move the global call to after Agility SDK selection so that it
binds the D3D12Core which will actually service device creation.

Even once enabled, the debug layer only emits through OutputDebugString, which
is invisible outside a debugger. Register an ID3D12InfoQueue1 message callback
so messages reach the test log. Reporting is diagnostic only and deliberately
does not alter the outcome of any test. Errors and corruption are reported by
default because they indicate a real defect and are near-zero volume; the
D3D12DebugMessageSeverity runtime parameter accepts none, corruption, error,
warning, info or message to adjust the threshold.

The previously silent QueryInterface failures for ID3D12InfoQueue and
ID3D12InfoQueue1 are now reported, so a harness that cannot surface messages
says so rather than appearing healthy.

Verified on WARP against the SM6.10 Agility SDK. ExecutionTest (207 tests) and
LinAlg (22 tests) produce identical pass, fail and skip sets before and after
this change. Both the device factory and global configuration paths were
exercised. With the fix, the two long-standing LinAlg accumulate failures are
diagnosed directly in the log as DXIL intrinsic overload validation errors,
instead of surfacing only as DXGI_ERROR_DEVICE_REMOVED at command queue
creation.

Refs microsoft#7841

Assisted-by: GitHub Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 83725f5d-8e98-4c1d-91ee-ad47629e007b
Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Addresses review feedback: enabling the debug layer by default is unexpected
for HLK conformance runs.

This matters more than it first appears. Before this PR the harness already
called enableDebugLayer() unconditionally, so "on by default" was the existing
intent -- it simply never worked, because the call bound the inbox D3D12Core
and never reached the device factory. Fixing that would have silently turned
the debug layer on for every HLK run, with its Graphics Tools dependency,
runtime overhead and behavioural differences.

The debug layer is now off unless /p:D3D12DebugLayer is passed, so relative to
main an HLK run gets strictly less debug layer involvement than before, not
more. Development and debugging runs are expected to pass the parameter.

GetTestParamBool is deliberately not used to read it. Despite the name it
matches its value as a pattern against the current test name, which is why
existing callers pass "=*" rather than "=true", and it asserts on TestName
being retrievable. The SDK selector is constructed during class setup where no
test name is available, so a plain value reader is used instead. It accepts
true, 1, * or an empty value to enable, false or 0 to disable, and warns on
anything else.

Verified on WARP against the SM6.10 Agility SDK. With the parameter absent,
ExecutionTest (207) and LinAlg (22) produce non-passing sets identical to
unmodified main and emit no debug layer output at all. With the parameter set,
the layer attaches on both the device factory and global paths and messages are
reported as before. Parameter values absent, true, false, *, and an invalid one
were each confirmed, and the test outcome is identical in every case, which
also confirms the two LinAlg accumulate failures are runtime validation
failures rather than anything the debug layer induces.

Assisted-by: GitHub Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 83725f5d-8e98-4c1d-91ee-ad47629e007b
@JoeCitizen
JoeCitizen marked this pull request as ready for review July 28, 2026 21:11
@damyanp
damyanp requested a review from alsepkow July 28, 2026 21:18
@damyanp

damyanp commented Jul 28, 2026

Copy link
Copy Markdown
Member

This is quite a large change; I'd like @alsepkow to have a chance to review this and understand how it interacts with the "real" HLKs.

Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Comment on lines +361 to +363
LogWarningFmt(L"The debug layer was enabled but this device does not "
L"expose ID3D12InfoQueue. D3D12 debug layer messages will "
L"not be reported.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When can this happen?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

If the debug layer was requested but the tools weren't installed on the target machine i.e. d3d12SDKLayers.dll is unavailable. Shouldn't really happen but better than failing silently

Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Review feedback on microsoft#8708.

The debug layer now defaults on for developer builds and off for HLK
conformance builds. /p:D3D12DebugLayer still overrides the default in
either direction, so HLK runs can opt in and developers can opt out.

/p:D3D12DebugLayer now accepts only "true" or "false"; the previous
"1", "0", "*" and empty-value spellings are gone. Anything else warns
and leaves the default in place.

Also trims the comments added by this PR to describe the code as it
stands, and folds isDebugLayerRequested() into useDebugIfaces().

Assisted-by: GitHub Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 83725f5d-8e98-4c1d-91ee-ad47629e007b

@alsepkow alsepkow 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.

Just some minor comments. Outside of those it lgtm.

I can't think of any issues this would cause in the 'real' HLK environment.

Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Comment thread tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp Outdated
Review feedback from @alsepkow on microsoft#8708.

Read D3D12DebugLayer as a bool and let TAEF do the conversion, rather
than parsing the string ourselves. TAEF accepts "true", "false", "1" and
"0", leaves the caller's default in place for anything it cannot convert,
and warns on its own, so the hand-rolled parsing and warning were both
redundant. This matches how RITP, VerboseLogging and EnableFallback are
already read elsewhere in these tests.

Move the info queue setup out of createDevice into logDebugLayerMessages()
and flip it to early returns. createDevice was already long.

Assisted-by: GitHub Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 83725f5d-8e98-4c1d-91ee-ad47629e007b
@JoeCitizen
JoeCitizen merged commit da2277c into microsoft:main Jul 29, 2026
14 checks passed
@github-project-automation github-project-automation Bot moved this from New to Done in HLSL Roadmap Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

LinAlg HLK: Enable the D3D12 debug layer on the Agility device factory

5 participants