@@ -40,6 +40,23 @@ public unsafe partial class GraphicsDevice
4040 // Set by the callback when a draw-relevant validation message arrives within a scope.
4141 // Consumed by DrainDebugMessages at the next scope-empty transition.
4242
43+ // GBV message IDs from D3D12_MESSAGE_ID, populated lazily via reflection so the scan
44+ // only runs in debug mode (callback never fires in release → Value is never queried).
45+ // Robust against SDK additions to the GBV enum range.
46+ private static readonly Lazy < System . Collections . Generic . HashSet < MessageID > > gbvMessageIds = new ( BuildGbvMessageIdSet ) ;
47+
48+ private static System . Collections . Generic . HashSet < MessageID > BuildGbvMessageIdSet ( )
49+ {
50+ var set = new System . Collections . Generic . HashSet < MessageID > ( ) ;
51+ foreach ( var name in Enum . GetNames < MessageID > ( ) )
52+ {
53+ if ( name . Contains ( "Gpubased" , StringComparison . OrdinalIgnoreCase )
54+ && Enum . TryParse < MessageID > ( name , out var id ) )
55+ set . Add ( id ) ;
56+ }
57+ return set ;
58+ }
59+
4360 /// <summary>
4461 /// Concurrent pool for lists of Graphics Resources that are used for staging operations.
4562 /// </summary>
@@ -910,10 +927,11 @@ private static void OnDebugMessageCallback(MessageCategory category, MessageSeve
910927 or MessageCategory . Execution
911928 or MessageCategory . ResourceManipulation ;
912929
913- // GPU-based validation messages arrive asynchronously — the active scope at callback
914- // time isn't the one that issued the offending command. Skip leaf attribution and
915- // scope prefix in that mode to avoid misleading the user.
916- bool attributable = ! device . DebugGpuValidationEnabled ;
930+ // GBV messages arrive asynchronously, so leaf attribution would be wrong. We detect
931+ // them by ID via the reflection-built set. The DebugGpuValidationEnabled override
932+ // is a kill switch for cases the heuristic misses.
933+ bool isGbv = device . DebugGpuValidationEnabled || gbvMessageIds . Value . Contains ( id ) ;
934+ bool attributable = ! isGbv ;
917935 var leafName = attributable ? device . GetDebugLeafScopeName ( ) : null ;
918936 var scope = leafName is not null ? $ "[{ leafName } ]: " : "" ;
919937
@@ -922,18 +940,20 @@ or MessageCategory.Execution
922940 // chain of "Down2" passes).
923941 var leaf = attributable ? device . debugCurrentFrame : null ;
924942
943+ // Tree dump only fires for attributable messages — a tree without [!] markers is
944+ // noise, so GBV-only frames stay quiet (just the log lines).
925945 switch ( severity )
926946 {
927947 case MessageSeverity . Corruption :
928948 case MessageSeverity . Error :
929949 DebugLog . Error ( $ "{ scope } { desc } ") ;
930950 if ( leaf is not null ) leaf . Errors ++ ;
931- if ( isDrawCategory ) device . debugSawDrawIssue = true ;
951+ if ( isDrawCategory && attributable ) device . debugSawDrawIssue = true ;
932952 break ;
933953 case MessageSeverity . Warning :
934954 DebugLog . Warning ( $ "{ scope } { desc } ") ;
935955 if ( leaf is not null ) leaf . Warnings ++ ;
936- if ( isDrawCategory ) device . debugSawDrawIssue = true ;
956+ if ( isDrawCategory && attributable ) device . debugSawDrawIssue = true ;
937957 break ;
938958 }
939959 }
@@ -982,9 +1002,11 @@ internal void FlushDebugMessages()
9821002 bool isDrawCategory = message ->Category is MessageCategory . StateSetting
9831003 or MessageCategory . Execution
9841004 or MessageCategory . ResourceManipulation ;
1005+ bool isGbv = DebugGpuValidationEnabled || gbvMessageIds . Value . Contains ( message ->ID ) ;
1006+ bool attributable = ! isGbv ;
9851007
9861008 string prefix = null ;
987- if ( isDrawCategory )
1009+ if ( isDrawCategory && attributable )
9881010 {
9891011 var leafName = GetDebugLeafScopeName ( ) ;
9901012 prefix = leafName is not null ? $ "[{ leafName } ]: " : null ;
@@ -995,11 +1017,11 @@ or MessageCategory.Execution
9951017 case MessageSeverity . Corruption :
9961018 case MessageSeverity . Error :
9971019 DebugLog . Error ( $ "{ prefix } { description } ") ;
998- if ( isDrawCategory ) sawDrawIssue = true ;
1020+ if ( isDrawCategory && attributable ) sawDrawIssue = true ;
9991021 break ;
10001022 case MessageSeverity . Warning :
10011023 DebugLog . Warning ( $ "{ prefix } { description } ") ;
1002- if ( isDrawCategory ) sawDrawIssue = true ;
1024+ if ( isDrawCategory && attributable ) sawDrawIssue = true ;
10031025 break ;
10041026 }
10051027 }
0 commit comments