Skip to content

Better DRED output for DX12 device-removal crashes - #63

Open
JohnGreenFC wants to merge 3 commits into
mainfrom
improved-dred-breadcrumbs
Open

Better DRED output for DX12 device-removal crashes#63
JohnGreenFC wants to merge 3 commits into
mainfrom
improved-dred-breadcrumbs

Conversation

@JohnGreenFC

Copy link
Copy Markdown

Improves DRED breadcrumb reporting so a device-removal log identifies exactly where the GPU stopped, instead of an unordered list of anonymous ops. Barrier flushes and render steps now emit markers that DRED attaches to the breadcrumb stream, so each resource barrier reports its resources and state transitions by name, and the dump tags the in-flight op, names the command list and queue. Fixes several bugs in the existing output loop.

Improves DRED breadcrumb reporting so a device-removal log identifies exactly where the GPU stopped, instead of an unordered list of anonymous ops. Barrier flushes and render steps now emit markers that DRED attaches to the breadcrumb stream, so each resource barrier reports its resources and state transitions by name, and the dump tags the in-flight op, names the command list and queue. Fixes several bugs in the existing output loop.
Copilot AI lite review requested due to automatic review settings August 14, 2026 14:45
@ccpgames-carbon

ccpgames-carbon commented Aug 14, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@JohnGreenFC
JohnGreenFC marked this pull request as ready for review August 14, 2026 14:46

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cpp-linter Review

Used clang-format v21.1.8

Click here for the full clang-format patch
diff --git a/trinity/TriDevice12.cpp b/trinity/TriDevice12.cpp
index ea6e507..3b7cc4b 100644
--- a/trinity/TriDevice12.cpp
+++ b/trinity/TriDevice12.cpp
@@ -226,4 +226,6 @@ void TriDevice::HandleRenderTick( Be::Time realTime, Be::Time simTime )
-							pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
-							pNode->pCommandList,
-							pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
-							lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );
+									pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
+									pNode->pCommandList,
+									pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
+									lastCompletedOp,
+									pNode->BreadcrumbCount,
+									pNode->BreadcrumbContextsCount );
@@ -256 +258,2 @@ void TriDevice::HandleRenderTick( Be::Time realTime, Be::Time simTime )
-							char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";
+							char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" :
+																														  "";
diff --git a/trinityal/dx12/Tr2RenderContextDx12.cpp b/trinityal/dx12/Tr2RenderContextDx12.cpp
index c848840..c743f08 100644
--- a/trinityal/dx12/Tr2RenderContextDx12.cpp
+++ b/trinityal/dx12/Tr2RenderContextDx12.cpp
@@ -1581,3 +1581,3 @@ void SetDredMarker( ID3D12GraphicsCommandList* commandList, const char* text )
-	blob[0] = PIXEvent_SetMarker_NoArgs << 10;                  // timestamp 0, event type
-	blob[1] = 0xFF000000;                                       // ARGB color
-	blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 );    // string info: copy chunk 8, isANSI
+	blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
+	blob[1] = 0xFF000000; // ARGB color
+	blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI
@@ -1763 +1763,2 @@ void EmitBarrierBreadcrumb( ID3D12GraphicsCommandList* commandList, const D3D12_
-		ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;
+		ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter :
+																																									barrier.Transition.pResource;

Have any feedback or feature suggestions? Share it here.

Comment thread trinity/TriDevice12.cpp
Comment on lines +226 to +229
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp,
pNode->BreadcrumbCount,
pNode->BreadcrumbContextsCount );

Comment thread trinity/TriDevice12.cpp

char const* opName = DredBreadcrumbOpName( breadcrumbOp );
CCP_LOGERR( "\tOp: %d, %s%ls%s", op, opName, contextString.c_str(), ( op + 1 == lastCompletedOp ) ? " - Last completed" : "" );
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" :
"";

Comment on lines +1581 to +1583
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI

for( size_t i = 0; i < count && pos < sizeof( buf ) - 1; ++i )
{
const auto& barrier = barriers[i];
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter :
barrier.Transition.pResource;

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves DirectX 12 device-removal diagnostics by enabling DRED breadcrumb context strings and emitting richer GPU markers (including barrier details) so breadcrumb dumps can identify what the GPU was doing at the time of removal.

Changes:

  • Adds a global toggle (g_dredBreadcrumbsEnabled) and enables DRED breadcrumb contexts when the DX12 debug layer is requested.
  • Names key DX12 objects (command list, primary direct queue) to improve DRED output.
  • Emits PIX3-blob markers for DRED contexts, including barrier-specific breadcrumb strings, and improves the DRED dump loop output formatting.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
trinityal/Tr2RenderContextEnum.cpp Adds global flag to gate DRED breadcrumb-context marker emission.
trinityal/dx12/Tr2RenderContextDx12.cpp Adds PIX3-blob marker emission and barrier breadcrumb context strings; names the DX12 command list.
trinityal/dx12/Tr2PrimaryRenderContextDx12.cpp Enables DRED breadcrumb contexts under debug-layer option; names the primary command queue.
trinity/TriDevice12.cpp Improves DRED breadcrumb dump iteration and output to include queue/list names and context strings in a bounded window.

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

Comment on lines +1771 to +1782
if( barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION )
{
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(0x%x->0x%x)", name, barrier.Transition.StateBefore, barrier.Transition.StateAfter ) );
}
else if( barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV )
{
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " UAV(%s)", name ) );
}
else
{
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " Alias(%s)", name ) );
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I will take a look

@github-actions
github-actions Bot dismissed their stale review August 18, 2026 16:07

outdated suggestion

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cpp-linter Review

Used clang-format v21.1.8

Click here for the full clang-format patch
diff --git a/trinity/TriDevice12.cpp b/trinity/TriDevice12.cpp
index 20bbeef..9d54772 100644
--- a/trinity/TriDevice12.cpp
+++ b/trinity/TriDevice12.cpp
@@ -226,4 +226,6 @@ void TriDevice::HandleRenderTick( Be::Time realTime, Be::Time simTime )
-							pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
-							pNode->pCommandList,
-							pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
-							lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );
+									pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
+									pNode->pCommandList,
+									pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
+									lastCompletedOp,
+									pNode->BreadcrumbCount,
+									pNode->BreadcrumbContextsCount );
@@ -257 +259,2 @@ void TriDevice::HandleRenderTick( Be::Time realTime, Be::Time simTime )
-							char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";
+							char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" :
+																														  "";
diff --git a/trinityal/dx12/Tr2RenderContextDx12.cpp b/trinityal/dx12/Tr2RenderContextDx12.cpp
index d693ee5..97a3a51 100644
--- a/trinityal/dx12/Tr2RenderContextDx12.cpp
+++ b/trinityal/dx12/Tr2RenderContextDx12.cpp
@@ -1581,3 +1581,3 @@ void SetDredMarker( ID3D12GraphicsCommandList* commandList, const char* text )
-	blob[0] = PIXEvent_SetMarker_NoArgs << 10;                  // timestamp 0, event type
-	blob[1] = 0xFF000000;                                       // ARGB color
-	blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 );    // string info: copy chunk 8, isANSI
+	blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
+	blob[1] = 0xFF000000; // ARGB color
+	blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI
@@ -1811 +1811,2 @@ void EmitBarrierBreadcrumb( ID3D12GraphicsCommandList* commandList, const D3D12_
-		ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;
+		ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter :
+																																									barrier.Transition.pResource;
@@ -1822,3 +1823 @@ void EmitBarrierBreadcrumb( ID3D12GraphicsCommandList* commandList, const D3D12_
-			pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(%s->%s)", name,
-				FormatResourceStates( before, sizeof( before ), barrier.Transition.StateBefore ),
-				FormatResourceStates( after, sizeof( after ), barrier.Transition.StateAfter ) ) );
+			pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(%s->%s)", name, FormatResourceStates( before, sizeof( before ), barrier.Transition.StateBefore ), FormatResourceStates( after, sizeof( after ), barrier.Transition.StateAfter ) ) );

Have any feedback or feature suggestions? Share it here.

Comment thread trinity/TriDevice12.cpp
Comment on lines +226 to +229
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp, pNode->BreadcrumbCount, pNode->BreadcrumbContextsCount );
pNode->pCommandListDebugNameA ? pNode->pCommandListDebugNameA : "<unnamed>",
pNode->pCommandList,
pNode->pCommandQueueDebugNameA ? pNode->pCommandQueueDebugNameA : "<unnamed>",
lastCompletedOp,
pNode->BreadcrumbCount,
pNode->BreadcrumbContextsCount );

Comment thread trinity/TriDevice12.cpp
CCP_LOGERR( "\tOp: %d, %s%ls%s", op, opName, contextString.c_str(), ( op + 1 == lastCompletedOp ) ? " - Last completed" : "" );
// Markers with a context string are our own annotations, not GPU work
char const* opName = breadcrumbOp == D3D12_AUTO_BREADCRUMB_OP_SETMARKER && !contextString.empty() ? "[Trinity]" : DredBreadcrumbOpName( breadcrumbOp );
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" : "";
char const* status = op == lastCompletedOp ? " - IN FLIGHT" : ( op + 1 == lastCompletedOp ) ? " - Last completed" :
"";

Comment on lines +1581 to +1583
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI
blob[0] = PIXEvent_SetMarker_NoArgs << 10; // timestamp 0, event type
blob[1] = 0xFF000000; // ARGB color
blob[2] = ( UINT64( 8 ) << 55 ) | ( UINT64( 1 ) << 54 ); // string info: copy chunk 8, isANSI

for( size_t i = 0; i < count && pos < sizeof( buf ) - 1; ++i )
{
const auto& barrier = barriers[i];
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter : barrier.Transition.pResource;
ID3D12Resource* resource = barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV ? barrier.UAV.pResource : barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_ALIASING ? barrier.Aliasing.pResourceAfter :
barrier.Transition.pResource;

Comment on lines +1822 to +1824
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(%s->%s)", name,
FormatResourceStates( before, sizeof( before ), barrier.Transition.StateBefore ),
FormatResourceStates( after, sizeof( after ), barrier.Transition.StateAfter ) ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clang-format suggestion

Suggested change
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(%s->%s)", name,
FormatResourceStates( before, sizeof( before ), barrier.Transition.StateBefore ),
FormatResourceStates( after, sizeof( after ), barrier.Transition.StateAfter ) ) );
pos += size_t( snprintf( buf + pos, sizeof( buf ) - pos, " %s(%s->%s)", name, FormatResourceStates( before, sizeof( before ), barrier.Transition.StateBefore ), FormatResourceStates( after, sizeof( after ), barrier.Transition.StateAfter ) ) );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants