@@ -51,6 +51,16 @@ public WebGPUDrawingBackend()
5151 /// </summary>
5252 internal string ? TestingLastGPUInitializationFailure { get ; private set ; }
5353
54+ /// <summary>
55+ /// Gets a value indicating whether the last staged flush used chunked oversized-scene dispatch.
56+ /// </summary>
57+ internal bool TestingLastFlushUsedChunking { get ; private set ; }
58+
59+ /// <summary>
60+ /// Gets the chunkable binding-limit failure that selected the chunked path for the last staged flush.
61+ /// </summary>
62+ internal WebGPUSceneDispatch . BindingLimitBuffer TestingLastChunkingBindingFailure { get ; private set ; }
63+
5464 /// <summary>
5565 /// Gets a value indicating whether the last flush completed on the staged path.
5666 /// </summary>
@@ -61,6 +71,16 @@ public WebGPUDrawingBackend()
6171 /// </summary>
6272 public string ? DiagnosticLastSceneFailure => this . TestingLastGPUInitializationFailure ;
6373
74+ /// <summary>
75+ /// Gets a value indicating whether the last staged flush used the chunked oversized-scene path.
76+ /// </summary>
77+ public bool DiagnosticLastFlushUsedChunking => this . TestingLastFlushUsedChunking ;
78+
79+ /// <summary>
80+ /// Gets the chunkable binding-limit failure that selected the chunked oversized-scene path for the last staged flush.
81+ /// </summary>
82+ public string DiagnosticLastChunkingBindingFailure => this . TestingLastChunkingBindingFailure . ToString ( ) ;
83+
6484 /// <summary>
6585 /// Gets a value indicating whether WebGPU is available on the current system.
6686 /// This probes the runtime by attempting to acquire an adapter and device.
@@ -223,59 +243,71 @@ public void FlushCompositions<TPixel>(
223243
224244 this . TestingLastFlushUsedGPU = false ;
225245 this . TestingLastGPUInitializationFailure = null ;
246+ this . TestingLastFlushUsedChunking = false ;
247+ this . TestingLastChunkingBindingFailure = WebGPUSceneDispatch . BindingLimitBuffer . None ;
226248 WebGPUSceneBumpSizes currentBumpSizes = this . bumpSizes ;
227- for ( int attempt = 0 ; attempt < MaxDynamicGrowthAttempts ; attempt ++ )
249+ WebGPUSceneSchedulingArena schedulingArena = default ;
250+ try
228251 {
229- if ( ! WebGPUSceneDispatch . TryCreateStagedScene ( configuration , target , compositionScene , currentBumpSizes , out bool exceedsBindingLimit , out WebGPUSceneDispatch . BindingLimitFailure bindingLimitFailure , out WebGPUStagedScene stagedScene , out string ? error ) )
230- {
231- this . TestingLastGPUInitializationFailure = exceedsBindingLimit
232- ? error ?? "The staged WebGPU scene exceeded the current binding limits."
233- : error ?? "Failed to create the staged WebGPU scene." ;
234- this . FlushCompositionsFallback ( configuration , target , compositionScene , compositionBounds : null ) ;
235- return ;
236- }
237-
238- try
252+ for ( int attempt = 0 ; attempt < MaxDynamicGrowthAttempts ; attempt ++ )
239253 {
240- this . TestingLastFlushUsedGPU = true ;
241-
242- if ( stagedScene . EncodedScene . FillCount == 0 )
254+ if ( ! WebGPUSceneDispatch . TryCreateStagedScene ( configuration , target , compositionScene , currentBumpSizes , out bool exceedsBindingLimit , out WebGPUSceneDispatch . BindingLimitFailure bindingLimitFailure , out WebGPUStagedScene stagedScene , out string ? error ) )
243255 {
244- // Empty staged scenes still establish the flush-sized scratch-capacity baseline.
245- this . bumpSizes = stagedScene . Config . BumpSizes ;
256+ this . TestingLastGPUInitializationFailure = exceedsBindingLimit
257+ ? error ?? "The staged WebGPU scene exceeded the current binding limits."
258+ : error ?? "Failed to create the staged WebGPU scene." ;
259+ this . FlushCompositionsFallback ( configuration , target , compositionScene , compositionBounds : null ) ;
246260 return ;
247261 }
248262
249- if ( WebGPUSceneDispatch . TryRenderStagedScene ( ref stagedScene , out bool requiresGrowth , out WebGPUSceneBumpSizes grownBumpSizes , out error ) )
263+ try
250264 {
251- // Persist the last successful capacities so the next flush starts from the
252- // budget that actually worked on this device.
253- this . bumpSizes = stagedScene . Config . BumpSizes ;
254- return ;
255- }
265+ this . TestingLastFlushUsedGPU = true ;
266+ this . TestingLastFlushUsedChunking = stagedScene . BindingLimitFailure . Buffer != WebGPUSceneDispatch . BindingLimitBuffer . None ;
267+ this . TestingLastChunkingBindingFailure = stagedScene . BindingLimitFailure . Buffer ;
268+
269+ if ( stagedScene . EncodedScene . FillCount == 0 )
270+ {
271+ // Empty staged scenes still establish the flush-sized scratch-capacity baseline.
272+ this . bumpSizes = stagedScene . Config . BumpSizes ;
273+ return ;
274+ }
256275
257- this . TestingLastFlushUsedGPU = false ;
258- if ( requiresGrowth )
276+ if ( WebGPUSceneDispatch . TryRenderStagedScene ( ref stagedScene , ref schedulingArena , out bool requiresGrowth , out WebGPUSceneBumpSizes grownBumpSizes , out error ) )
277+ {
278+ // Persist the last successful capacities so the next flush starts from the
279+ // budget that actually worked on this device.
280+ this . bumpSizes = stagedScene . Config . BumpSizes ;
281+ return ;
282+ }
283+
284+ this . TestingLastFlushUsedGPU = false ;
285+ if ( requiresGrowth )
286+ {
287+ // Scheduling reported that one or more bump allocators overflowed. Retry the
288+ // same flush with the larger capacities read back from the GPU.
289+ currentBumpSizes = grownBumpSizes ;
290+ continue ;
291+ }
292+
293+ this . TestingLastGPUInitializationFailure = error ?? "The staged WebGPU scene dispatch failed." ;
294+ }
295+ finally
259296 {
260- // Scheduling reported that one or more bump allocators overflowed. Retry the
261- // same flush with the larger capacities read back from the GPU.
262- currentBumpSizes = grownBumpSizes ;
263- continue ;
297+ stagedScene . Dispose ( ) ;
264298 }
265299
266- this . TestingLastGPUInitializationFailure = error ?? "The staged WebGPU scene dispatch failed." ;
267- }
268- finally
269- {
270- stagedScene . Dispose ( ) ;
300+ this . FlushCompositionsFallback ( configuration , target , compositionScene , compositionBounds : null ) ;
301+ return ;
271302 }
272303
304+ this . TestingLastGPUInitializationFailure = "The staged WebGPU scene exceeded the current dynamic growth retry budget." ;
273305 this . FlushCompositionsFallback ( configuration , target , compositionScene , compositionBounds : null ) ;
274- return ;
275306 }
276-
277- this . TestingLastGPUInitializationFailure = "The staged WebGPU scene exceeded the current dynamic growth retry budget." ;
278- this . FlushCompositionsFallback ( configuration , target , compositionScene , compositionBounds : null ) ;
307+ finally
308+ {
309+ WebGPUSceneDispatch . DisposeSchedulingArena ( ref schedulingArena ) ;
310+ }
279311 }
280312
281313 /// <summary>
0 commit comments