@@ -56,7 +56,7 @@ internal Buffer2D(MemoryGroup<T> memoryGroup, int width, int height)
5656 /// It's public counterpart is <see cref="MemoryGroup"/>,
5757 /// which only exposes the view of the MemoryGroup.
5858 /// </remarks>
59- internal MemoryGroup < T > FastMemoryGroup { get ; }
59+ internal MemoryGroup < T > FastMemoryGroup { get ; private set ; }
6060
6161 /// <summary>
6262 /// Gets a reference to the element at the specified position.
@@ -97,35 +97,37 @@ internal Buffer2D(MemoryGroup<T> memoryGroup, int width, int height)
9797 [ MethodImpl ( InliningOptions . ShortMethod ) ]
9898 public Span < T > DangerousGetRowSpan ( int y )
9999 {
100- DebugGuard . MustBeGreaterThanOrEqualTo ( y , 0 , nameof ( y ) ) ;
101- DebugGuard . MustBeLessThan ( y , this . Height , nameof ( y ) ) ;
100+ if ( ( uint ) y >= ( uint ) this . Height )
101+ {
102+ this . ThrowYOutOfRangeException ( y ) ;
103+ }
102104
103- return this . GetRowMemoryCore ( y ) . Span ;
105+ return this . FastMemoryGroup . GetRowSpanCoreUnsafe ( y , this . Width ) ;
104106 }
105107
106- internal bool TryGetPaddedRowSpan ( int y , int padding , out Span < T > paddedSpan )
108+ internal bool DangerousTryGetPaddedRowSpan ( int y , int padding , out Span < T > paddedSpan )
107109 {
108110 DebugGuard . MustBeGreaterThanOrEqualTo ( y , 0 , nameof ( y ) ) ;
109111 DebugGuard . MustBeLessThan ( y , this . Height , nameof ( y ) ) ;
110112
111113 int stride = this . Width + padding ;
112114
113- Memory < T > memory = this . FastMemoryGroup . GetRemainingSliceOfBuffer ( y * ( long ) this . Width ) ;
115+ Span < T > slice = this . FastMemoryGroup . GetRemainingSliceOfBuffer ( y * ( long ) this . Width ) ;
114116
115- if ( memory . Length < stride )
117+ if ( slice . Length < stride )
116118 {
117119 paddedSpan = default ;
118120 return false ;
119121 }
120122
121- paddedSpan = memory . Span . Slice ( 0 , stride ) ;
123+ paddedSpan = slice . Slice ( 0 , stride ) ;
122124 return true ;
123125 }
124126
125127 [ MethodImpl ( InliningOptions . ShortMethod ) ]
126128 internal ref T GetElementUnsafe ( int x , int y )
127129 {
128- Span < T > span = this . GetRowMemoryCore ( y ) . Span ;
130+ Span < T > span = this . FastMemoryGroup . GetRowSpanCoreUnsafe ( y , this . Width ) ;
129131 return ref span [ x ] ;
130132 }
131133
@@ -139,7 +141,7 @@ internal Memory<T> GetSafeRowMemory(int y)
139141 {
140142 DebugGuard . MustBeGreaterThanOrEqualTo ( y , 0 , nameof ( y ) ) ;
141143 DebugGuard . MustBeLessThan ( y , this . Height , nameof ( y ) ) ;
142- return this . FastMemoryGroup . View . GetBoundedSlice ( y * ( long ) this . Width , this . Width ) ;
144+ return this . FastMemoryGroup . View . GetBoundedMemorySlice ( y * ( long ) this . Width , this . Width ) ;
143145 }
144146
145147 /// <summary>
@@ -168,25 +170,36 @@ internal Memory<T> GetSafeRowMemory(int y)
168170 /// Swaps the contents of 'destination' with 'source' if the buffers are owned (1),
169171 /// copies the contents of 'source' to 'destination' otherwise (2). Buffers should be of same size in case 2!
170172 /// </summary>
171- internal static void SwapOrCopyContent ( Buffer2D < T > destination , Buffer2D < T > source )
172- {
173- MemoryGroup < T > . SwapOrCopyContent ( destination . FastMemoryGroup , source . FastMemoryGroup ) ;
174- SwapOwnData ( destination , source ) ;
175- }
176-
177- [ MethodImpl ( InliningOptions . ShortMethod ) ]
178- private Memory < T > GetRowMemoryCore ( int y ) => this . FastMemoryGroup . GetBoundedSlice ( y * ( long ) this . Width , this . Width ) ;
179-
180- private static void SwapOwnData ( Buffer2D < T > a , Buffer2D < T > b )
173+ internal static bool SwapOrCopyContent ( Buffer2D < T > destination , Buffer2D < T > source )
181174 {
182- Size aSize = a . Size ( ) ;
183- Size bSize = b . Size ( ) ;
175+ bool swapped = false ;
176+ if ( MemoryGroup < T > . CanSwapContent ( destination . FastMemoryGroup , source . FastMemoryGroup ) )
177+ {
178+ ( destination . FastMemoryGroup , source . FastMemoryGroup ) =
179+ ( source . FastMemoryGroup , destination . FastMemoryGroup ) ;
180+ destination . FastMemoryGroup . RecreateViewAfterSwap ( ) ;
181+ source . FastMemoryGroup . RecreateViewAfterSwap ( ) ;
182+ swapped = true ;
183+ }
184+ else
185+ {
186+ if ( destination . FastMemoryGroup . TotalLength != source . FastMemoryGroup . TotalLength )
187+ {
188+ throw new InvalidMemoryOperationException (
189+ "Trying to copy/swap incompatible buffers. This is most likely caused by applying an unsupported processor to wrapped-memory images." ) ;
190+ }
184191
185- b . Width = aSize . Width ;
186- b . Height = aSize . Height ;
192+ source . FastMemoryGroup . CopyTo ( destination . MemoryGroup ) ;
193+ }
187194
188- a . Width = bSize . Width ;
189- a . Height = bSize . Height ;
195+ ( destination . Width , source . Width ) = ( source . Width , destination . Width ) ;
196+ ( destination . Height , source . Height ) = ( source . Height , destination . Height ) ;
197+ return swapped ;
190198 }
199+
200+ [ MethodImpl ( InliningOptions . ColdPath ) ]
201+ private void ThrowYOutOfRangeException ( int y ) =>
202+ throw new ArgumentOutOfRangeException (
203+ $ "DangerousGetRowSpan({ y } ). Y was out of range. Height={ this . Height } ") ;
191204 }
192205}
0 commit comments