@@ -71,9 +71,20 @@ public void FlushCompositions<TPixel>(
7171 compositionScene . Commands ,
7272 target . Bounds ) ;
7373
74- for ( int i = 0 ; i < preparedBatches . Count ; i ++ )
74+ // A single reusable scratch is maintained across the batch loop so sequential-path
75+ // commands (single-tile or multi-band) avoid repeated pool allocation round-trips.
76+ // The parallel multi-tile path creates its own per-worker scratch and ignores this one.
77+ DefaultRasterizer . WorkerScratch ? reusableScratch = null ;
78+ try
79+ {
80+ for ( int i = 0 ; i < preparedBatches . Count ; i ++ )
81+ {
82+ this . FlushPreparedBatch ( configuration , target , preparedBatches [ i ] , ref reusableScratch ) ;
83+ }
84+ }
85+ finally
7586 {
76- this . FlushPreparedBatch ( configuration , target , preparedBatches [ i ] ) ;
87+ reusableScratch ? . Dispose ( ) ;
7788 }
7889 }
7990
@@ -136,6 +147,18 @@ internal void FlushPreparedBatch<TPixel>(
136147 ICanvasFrame < TPixel > target ,
137148 CompositionBatch compositionBatch )
138149 where TPixel : unmanaged, IPixel < TPixel >
150+ {
151+ DefaultRasterizer . WorkerScratch ? noScratch = null ;
152+ this . FlushPreparedBatch ( configuration , target , compositionBatch , ref noScratch ) ;
153+ noScratch ? . Dispose ( ) ;
154+ }
155+
156+ private void FlushPreparedBatch < TPixel > (
157+ Configuration configuration ,
158+ ICanvasFrame < TPixel > target ,
159+ CompositionBatch compositionBatch ,
160+ ref DefaultRasterizer . WorkerScratch ? reusableScratch )
161+ where TPixel : unmanaged, IPixel < TPixel >
139162 {
140163 if ( compositionBatch . Commands . Count == 0 )
141164 {
@@ -177,7 +200,8 @@ internal void FlushPreparedBatch<TPixel>(
177200 definition . Path ,
178201 definition . RasterizerOptions ,
179202 configuration . MemoryAllocator ,
180- operation . InvokeCoverageRow ) ;
203+ operation . InvokeCoverageRow ,
204+ ref reusableScratch ) ;
181205 }
182206 finally
183207 {
0 commit comments