@@ -611,7 +611,38 @@ protected static void RunGameTest(GameTestBase game)
611611
612612 game . ScreenShotAutomationEnabled = ! ForceInteractiveMode ;
613613
614- GameTester . RunGameTest ( game ) ;
614+ // Track GPU validation errors and warnings during the test
615+ var gpuValidationErrors = new List < string > ( ) ;
616+ var gpuValidationWarnings = new List < string > ( ) ;
617+ void OnGlobalMessage ( ILogMessage msg )
618+ {
619+ if ( msg . Module != nameof ( GraphicsDevice ) )
620+ return ;
621+ if ( msg . Type == LogMessageType . Error )
622+ gpuValidationErrors . Add ( msg . Text ) ;
623+ else if ( msg . Type == LogMessageType . Warning && ! IsKnownHarmlessWarning ( msg . Text ) )
624+ gpuValidationWarnings . Add ( msg . Text ) ;
625+ }
626+ GlobalLogger . GlobalMessageLogged += OnGlobalMessage ;
627+
628+ try
629+ {
630+ GameTester . RunGameTest ( game ) ;
631+ }
632+ finally
633+ {
634+ GlobalLogger . GlobalMessageLogged -= OnGlobalMessage ;
635+ }
636+
637+ // Assert no GPU validation errors
638+ if ( gpuValidationErrors . Count > 0 )
639+ Assert . Fail ( $ "GPU validation reported { gpuValidationErrors . Count } error(s):" + Environment . NewLine
640+ + string . Join ( Environment . NewLine , gpuValidationErrors ) ) ;
641+
642+ // Assert no GPU validation warnings
643+ if ( gpuValidationWarnings . Count > 0 )
644+ Assert . Fail ( $ "GPU validation reported { gpuValidationWarnings . Count } warning(s):" + Environment . NewLine
645+ + string . Join ( Environment . NewLine , gpuValidationWarnings ) ) ;
615646
616647 // If there were comparison failures, assert them now
617648 if ( game . ScreenShotAutomationEnabled )
@@ -637,6 +668,21 @@ void AssertMissingComparisonImages()
637668 }
638669 }
639670
671+ /// <summary>
672+ /// Filters out known harmless D3D11 debug layer warnings that cannot be avoided
673+ /// without significant refactoring.
674+ /// </summary>
675+ private static bool IsKnownHarmlessWarning ( string text )
676+ {
677+ return false
678+ // || text.Contains("still bound on input") // D3D11: RT set while SRV still bound (auto-unbinds)
679+ // || text.Contains("Forcing PS shader resource") // D3D11: consequence of the above
680+ || text . Contains ( "SetPrivateData" ) // D3D11: debug name size mismatch on reuse
681+ || text . Contains ( "NULL Sampler maps to default" ) // D3D11: unbound sampler uses default state
682+ || text . Contains ( "Live " ) // D3D11/D3D12: ReportLiveObjects at shutdown
683+ || text . Contains ( "SetPrivateData" ) ; // D3D11: debug name size mismatch on reuse
684+ }
685+
640686 /// <summary>
641687 /// Searches for the root folder of the Stride solution by traversing upward from the test's binary directory.
642688 /// </summary>
0 commit comments