11// Copyright (c) Six Labors.
22// Licensed under the Six Labors Split License.
33
4- using System . Buffers ;
54using System . Numerics ;
65using System . Runtime . CompilerServices ;
76using System . Runtime . InteropServices ;
@@ -79,36 +78,22 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
7978 {
8079 Rectangle sourceRectangle = Rectangle . Intersect ( this . SourceRectangle , source . Bounds ) ;
8180
82- MemoryAllocator allocator = this . Configuration . MemoryAllocator ;
83-
84- // Convolution is memory-bandwidth-bound with low arithmetic intensity.
85- // Parallelization degrades performance due to cache line contention from
86- // overlapping source row reads. See #3111.
87-
8881 // Preliminary gamma highlight pass
8982 if ( this . gamma == 3F )
9083 {
9184 ApplyGamma3ExposureRowOperation gammaOperation = new ( sourceRectangle , source . PixelBuffer , this . Configuration ) ;
92-
93- using IMemoryOwner < Vector4 > gammaBuffer = allocator . Allocate < Vector4 > ( gammaOperation . GetRequiredBufferLength ( sourceRectangle ) ) ;
94- Span < Vector4 > gammaSpan = gammaBuffer . Memory . Span ;
95-
96- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
97- {
98- gammaOperation . Invoke ( y , gammaSpan ) ;
99- }
85+ ParallelRowIterator . IterateRows < ApplyGamma3ExposureRowOperation , Vector4 > (
86+ this . Configuration ,
87+ sourceRectangle ,
88+ in gammaOperation ) ;
10089 }
10190 else
10291 {
10392 ApplyGammaExposureRowOperation gammaOperation = new ( sourceRectangle , source . PixelBuffer , this . Configuration , this . gamma ) ;
104-
105- using IMemoryOwner < Vector4 > gammaBuffer = allocator . Allocate < Vector4 > ( gammaOperation . GetRequiredBufferLength ( sourceRectangle ) ) ;
106- Span < Vector4 > gammaSpan = gammaBuffer . Memory . Span ;
107-
108- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
109- {
110- gammaOperation . Invoke ( y , gammaSpan ) ;
111- }
93+ ParallelRowIterator . IterateRows < ApplyGammaExposureRowOperation , Vector4 > (
94+ this . Configuration ,
95+ sourceRectangle ,
96+ in gammaOperation ) ;
11297 }
11398
11499 // Create a 0-filled buffer to use to store the result of the component convolutions
@@ -121,20 +106,18 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
121106 if ( this . gamma == 3F )
122107 {
123108 ApplyInverseGamma3ExposureRowOperation operation = new ( sourceRectangle , source . PixelBuffer , processingBuffer , this . Configuration ) ;
124-
125- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
126- {
127- operation . Invoke ( y ) ;
128- }
109+ ParallelRowIterator . IterateRows (
110+ this . Configuration ,
111+ sourceRectangle ,
112+ in operation ) ;
129113 }
130114 else
131115 {
132116 ApplyInverseGammaExposureRowOperation operation = new ( sourceRectangle , source . PixelBuffer , processingBuffer , this . Configuration , this . gamma ) ;
133-
134- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
135- {
136- operation . Invoke ( y ) ;
137- }
117+ ParallelRowIterator . IterateRows (
118+ this . Configuration ,
119+ sourceRectangle ,
120+ in operation ) ;
138121 }
139122 }
140123
@@ -187,15 +170,10 @@ private void OnFrameApplyCore(
187170 kernel ,
188171 configuration ) ;
189172
190- using ( IMemoryOwner < Vector4 > hBuffer = configuration . MemoryAllocator . Allocate < Vector4 > ( horizontalOperation . GetRequiredBufferLength ( sourceRectangle ) ) )
191- {
192- Span < Vector4 > hSpan = hBuffer . Memory . Span ;
193-
194- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
195- {
196- horizontalOperation . Invoke ( y , hSpan ) ;
197- }
198- }
173+ ParallelRowIterator . IterateRows < FirstPassConvolutionRowOperation , Vector4 > (
174+ configuration ,
175+ sourceRectangle ,
176+ in horizontalOperation ) ;
199177
200178 // Vertical 1D convolutions to accumulate the partial results on the target buffer
201179 BokehBlurProcessor . SecondPassConvolutionRowOperation verticalOperation = new (
@@ -207,10 +185,10 @@ private void OnFrameApplyCore(
207185 parameters . Z ,
208186 parameters . W ) ;
209187
210- for ( int y = sourceRectangle . Top ; y < sourceRectangle . Bottom ; y ++ )
211- {
212- verticalOperation . Invoke ( y ) ;
213- }
188+ ParallelRowIterator . IterateRows (
189+ configuration ,
190+ sourceRectangle ,
191+ in verticalOperation ) ;
214192 }
215193 }
216194
0 commit comments