@@ -170,8 +170,7 @@ public static bool TryCreateStagedScene<TPixel>(
170170 }
171171
172172 encodedScene = createdScene ;
173- WebGPUSceneBumpSizes sceneBumpSizes = bumpSizes . WithSceneLowerBounds ( encodedScene ) ;
174- WebGPUSceneConfig config = WebGPUSceneConfig . Create ( encodedScene , sceneBumpSizes ) ;
173+ WebGPUSceneConfig config = WebGPUSceneConfig . Create ( encodedScene , bumpSizes ) ;
175174 uint baseColor = 0U ;
176175 bool segmentChunkingRequired = false ;
177176 if ( ! TryValidateBindingSizes ( encodedScene , config , flushContext . DeviceState . MaxStorageBufferBindingSize , out bindingLimitFailure , out error ) )
@@ -967,6 +966,8 @@ public static unsafe bool TryRenderStagedScene(
967966 {
968967 requiresGrowth = true ;
969968 grownBumpSizes = GrowBumpSizes ( stagedScene . Config . BumpSizes , in bumpAllocators ) ;
969+ WebGPUSceneBumpSizes cfg = stagedScene . Config . BumpSizes ;
970+ System . IO . File . AppendAllText ( "bump_debug.log" , $ "[BUMP OVERFLOW] failed={ bumpAllocators . Failed : X} | had: lines={ cfg . Lines } bin={ cfg . Binning } tiles={ cfg . PathTiles } segc={ cfg . SegCounts } segs={ cfg . Segments } blend={ cfg . BlendSpill } ptcl={ cfg . Ptcl } | gpu: lines={ bumpAllocators . Lines } bin={ bumpAllocators . Binning } tiles={ bumpAllocators . Tile } segc={ bumpAllocators . SegCounts } segs={ bumpAllocators . Segments } blend={ bumpAllocators . BlendSpill } ptcl={ bumpAllocators . Ptcl } | grown: lines={ grownBumpSizes . Lines } bin={ grownBumpSizes . Binning } tiles={ grownBumpSizes . PathTiles } segc={ grownBumpSizes . SegCounts } segs={ grownBumpSizes . Segments } blend={ grownBumpSizes . BlendSpill } ptcl={ grownBumpSizes . Ptcl } \n ") ;
970971 error = "The staged WebGPU scene needs larger scratch buffers and will be retried." ;
971972 return false ;
972973 }
@@ -978,7 +979,18 @@ public static unsafe bool TryRenderStagedScene(
978979 return false ;
979980 }
980981
981- // Scheduling passed. Submit the pre-recorded fine + copy. Fire-and-forget.
982+ // Scheduling passed. Persist the actual GPU usage so the next flush starts
983+ // from sizes that are known to work, eliminating retries for similar scenes.
984+ grownBumpSizes = new WebGPUSceneBumpSizes (
985+ Math . Max ( bumpAllocators . Lines , stagedScene . Config . BumpSizes . Lines ) ,
986+ Math . Max ( bumpAllocators . Binning , stagedScene . Config . BumpSizes . Binning ) ,
987+ Math . Max ( bumpAllocators . Tile , stagedScene . Config . BumpSizes . PathTiles ) ,
988+ Math . Max ( bumpAllocators . SegCounts , stagedScene . Config . BumpSizes . SegCounts ) ,
989+ Math . Max ( bumpAllocators . Segments , stagedScene . Config . BumpSizes . Segments ) ,
990+ Math . Max ( bumpAllocators . BlendSpill , stagedScene . Config . BumpSizes . BlendSpill ) ,
991+ Math . Max ( bumpAllocators . Ptcl , stagedScene . Config . BumpSizes . Ptcl ) ) ;
992+
993+ // Submit the pre-recorded fine + copy. Fire-and-forget.
982994 return WebGPUDrawingBackend . TrySubmit ( flushContext ) ;
983995 }
984996
@@ -1061,11 +1073,13 @@ private static unsafe bool TryRenderSegmentChunkedStagedScene(
10611073 WebGPUSceneConfig chunkConfig = WebGPUSceneConfig . Create ( encodedScene , chunkBumpSize , chunkWindow ) ;
10621074 if ( ! TryValidateBindingSizes ( encodedScene , chunkConfig , maxStorageBufferBindingSize , out BindingLimitFailure bindingLimitFailure , out error ) )
10631075 {
1076+ System . IO . File . AppendAllText ( "bump_debug.log" , $ "[CHUNK VALIDATION FAIL] buffer={ bindingLimitFailure . Buffer } required={ bindingLimitFailure . RequiredBytes } limit={ bindingLimitFailure . LimitBytes } chunkTileH={ requestedTileHeight } totalTileH={ totalTileHeight } tiles={ chunkBumpSize . PathTiles } segc={ chunkBumpSize . SegCounts } segs={ chunkBumpSize . Segments } srcTiles={ stagedScene . Config . BumpSizes . PathTiles } srcSegc={ stagedScene . Config . BumpSizes . SegCounts } \n ") ;
10641077 if ( IsChunkableBindingFailure ( bindingLimitFailure . Buffer ) )
10651078 {
10661079 uint smallerTileHeight = ShrinkChunkTileHeight ( requestedTileHeight , remainingTileHeight , bindingLimitFailure ) ;
10671080 if ( smallerTileHeight >= requestedTileHeight )
10681081 {
1082+ System . IO . File . AppendAllText ( "bump_debug.log" , $ "[CHUNK SHRINK STUCK] smallerH={ smallerTileHeight } requestedH={ requestedTileHeight } \n ") ;
10691083 return false ;
10701084 }
10711085
@@ -1293,18 +1307,17 @@ private static WebGPUSceneChunkWindow CreateChunkWindow(uint tileYStart, uint re
12931307 private static WebGPUSceneBumpSizes ScaleChunkBumpSizes ( WebGPUSceneBumpSizes sourceBumpSizes , WebGPUEncodedScene scene , uint chunkTileHeight )
12941308 {
12951309 uint fullTileHeight = checked ( ( uint ) scene . TileCountY ) ;
1296- uint chunkTileBufferHeight = AlignUp ( chunkTileHeight , 16U ) ;
1297- uint pathTileFloor = AddSizingSlack ( ScaleCount ( ( uint ) Math . Max ( scene . TotalTileMembershipCount , scene . PathCount ) , chunkTileBufferHeight , fullTileHeight ) ) ;
1298- uint segmentFloor = AddSizingSlack ( ScaleCount ( ( uint ) scene . LineCount , chunkTileBufferHeight , fullTileHeight ) ) ;
1310+ uint pathTileFloor = AddSizingSlack ( ScaleCount ( ( uint ) Math . Max ( scene . TotalTileMembershipCount , scene . PathCount ) , chunkTileHeight , fullTileHeight ) ) ;
1311+ uint segmentFloor = AddSizingSlack ( ScaleCount ( ( uint ) scene . LineCount , chunkTileHeight , fullTileHeight ) ) ;
12991312
13001313 return new WebGPUSceneBumpSizes (
13011314 sourceBumpSizes . Lines ,
13021315 sourceBumpSizes . Binning ,
1303- Math . Max ( ScaleCount ( sourceBumpSizes . PathTiles , chunkTileBufferHeight , fullTileHeight ) , pathTileFloor ) ,
1304- Math . Max ( ScaleCount ( sourceBumpSizes . SegCounts , chunkTileBufferHeight , fullTileHeight ) , segmentFloor ) ,
1305- Math . Max ( ScaleCount ( sourceBumpSizes . Segments , chunkTileBufferHeight , fullTileHeight ) , segmentFloor ) ,
1306- ScaleCount ( sourceBumpSizes . BlendSpill , chunkTileBufferHeight , fullTileHeight ) ,
1307- ScaleCount ( sourceBumpSizes . Ptcl , chunkTileBufferHeight , fullTileHeight ) ) ;
1316+ Math . Max ( ScaleCount ( sourceBumpSizes . PathTiles , chunkTileHeight , fullTileHeight ) , pathTileFloor ) ,
1317+ Math . Max ( ScaleCount ( sourceBumpSizes . SegCounts , chunkTileHeight , fullTileHeight ) , segmentFloor ) ,
1318+ Math . Max ( ScaleCount ( sourceBumpSizes . Segments , chunkTileHeight , fullTileHeight ) , segmentFloor ) ,
1319+ ScaleCount ( sourceBumpSizes . BlendSpill , chunkTileHeight , fullTileHeight ) ,
1320+ ScaleCount ( sourceBumpSizes . Ptcl , chunkTileHeight , fullTileHeight ) ) ;
13081321 }
13091322
13101323 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -1448,8 +1461,8 @@ private static uint GrowBumpSize(uint currentSize, uint requiredSize)
14481461 return currentSize ;
14491462 }
14501463
1451- uint nextSize = checked ( requiredSize + Math . Max ( requiredSize / 2U , 4096U ) ) ;
1452- return nextSize > currentSize ? nextSize : checked ( currentSize + 1U ) ;
1464+ // Use the GPU-reported size doubled so one retry is always enough.
1465+ return checked ( requiredSize * 2U ) ;
14531466 }
14541467
14551468 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -1839,14 +1852,25 @@ void Callback(BufferMapAsyncStatus status, void* userData)
18391852 {
18401853 GpuSceneBumpAllocators bumpAllocators = statuses [ i ] ;
18411854 WebGPUSceneBumpSizes currentSizes = chunkBumpSizes [ i ] ;
1855+ WebGPUSceneBumpSizes chunkActuals = new (
1856+ Math . Max ( bumpAllocators . Lines , currentSizes . Lines ) ,
1857+ Math . Max ( bumpAllocators . Binning , currentSizes . Binning ) ,
1858+ Math . Max ( bumpAllocators . Tile , currentSizes . PathTiles ) ,
1859+ Math . Max ( bumpAllocators . SegCounts , currentSizes . SegCounts ) ,
1860+ Math . Max ( bumpAllocators . Segments , currentSizes . Segments ) ,
1861+ Math . Max ( bumpAllocators . BlendSpill , currentSizes . BlendSpill ) ,
1862+ Math . Max ( bumpAllocators . Ptcl , currentSizes . Ptcl ) ) ;
1863+ WebGPUSceneBumpSizes expandedActuals = ExpandChunkBumpSizesToSceneBudget ( chunkActuals , fullTileHeight , chunkTileHeights [ i ] ) ;
1864+ grownBumpSizes = MaxBumpSizes ( grownBumpSizes , expandedActuals ) ;
1865+
18421866 if ( ! RequiresScratchReallocation ( in bumpAllocators , currentSizes ) )
18431867 {
18441868 continue ;
18451869 }
18461870
18471871 WebGPUSceneBumpSizes grownChunkBumpSizes = GrowBumpSizes ( currentSizes , in bumpAllocators ) ;
18481872 WebGPUSceneBumpSizes grownSourceBumpSizes = ExpandChunkBumpSizesToSceneBudget ( grownChunkBumpSizes , fullTileHeight , chunkTileHeights [ i ] ) ;
1849- grownBumpSizes = requiresGrowth ? MaxBumpSizes ( grownBumpSizes , grownSourceBumpSizes ) : grownSourceBumpSizes ;
1873+ grownBumpSizes = MaxBumpSizes ( grownBumpSizes , grownSourceBumpSizes ) ;
18501874 requiresGrowth = true ;
18511875 }
18521876
0 commit comments