From a4ad7b09fc8dda2f0efa9e0f7abcf4e6f0a4ac67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 14:20:24 +0200 Subject: [PATCH 1/8] Avoid length-check in pinning spans Only where it seems profitable. E.g. not when a UnmanagedMemoryStream is constructed of that pointer. --- .../ColorSpaces/Companding/SRgbCompanding.cs | 4 ++-- .../Common/Helpers/SimdUtils.HwIntrinsics.cs | 2 +- src/ImageSharp/Compression/Zlib/Adler32.cs | 2 +- src/ImageSharp/Compression/Zlib/Crc32.cs | 6 +++--- src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs | 9 ++++----- .../Formats/Webp/Lossless/PredictorEncoder.cs | 10 +++++----- src/ImageSharp/Formats/Webp/WebpCommonUtils.cs | 4 ++-- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 2a6fcb083..4c3923c88 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -167,7 +167,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandAvx2(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { var scale = Vector256.Create((float)Scale); Vector256 zero = Vector256.Zero; @@ -199,7 +199,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandScalar(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { Vector4 zero = Vector4.Zero; var scale = new Vector4(Scale); diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index ce6f335a8..7871eee6b 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -644,7 +644,7 @@ internal static partial class SimdUtils ReadOnlySpan source, Span dest) { - fixed (byte* sourceBase = source) + fixed (byte* sourceBase = &MemoryMarshal.GetReference(source)) { if (Avx2.IsSupported) { diff --git a/src/ImageSharp/Compression/Zlib/Adler32.cs b/src/ImageSharp/Compression/Zlib/Adler32.cs index dd8217541..3ecdf8153 100644 --- a/src/ImageSharp/Compression/Zlib/Adler32.cs +++ b/src/ImageSharp/Compression/Zlib/Adler32.cs @@ -387,7 +387,7 @@ internal static class Adler32 uint s1 = adler & 0xFFFF; uint s2 = (adler >> 16) & 0xFFFF; - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; uint length = (uint)buffer.Length; diff --git a/src/ImageSharp/Compression/Zlib/Crc32.cs b/src/ImageSharp/Compression/Zlib/Crc32.cs index 2d0a09bd4..e21621ab7 100644 --- a/src/ImageSharp/Compression/Zlib/Crc32.cs +++ b/src/ImageSharp/Compression/Zlib/Crc32.cs @@ -81,7 +81,7 @@ internal static partial class Crc32 int chunksize = buffer.Length & ~ChunksizeMask; int length = chunksize; - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { fixed (ulong* k05PolyPtr = K05Poly) { @@ -201,7 +201,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; @@ -248,7 +248,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm64(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index 8d64a09df..ab6e4cfcc 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -569,7 +569,7 @@ internal static unsafe class LosslessUtils Span pixelData, Span outputSpan) { - fixed (uint* inputFixed = pixelData) + fixed (uint* inputFixed = &MemoryMarshal.GetReference(pixelData)) { fixed (uint* outputFixed = outputSpan) { @@ -1474,8 +1474,7 @@ internal static unsafe class LosslessUtils { if (Sse2.IsSupported) { - Span output = scratch; - fixed (short* p = output) + fixed (short* ptr = &MemoryMarshal.GetReference(scratch)) { Vector128 a0 = Sse2.ConvertScalarToVector128UInt32(a).AsByte(); Vector128 b0 = Sse2.ConvertScalarToVector128UInt32(b).AsByte(); @@ -1489,8 +1488,8 @@ internal static unsafe class LosslessUtils Vector128 pa = Sse2.UnpackLow(ac, Vector128.Zero); // |a - c| Vector128 pb = Sse2.UnpackLow(bc, Vector128.Zero); // |b - c| Vector128 diff = Sse2.Subtract(pb.AsUInt16(), pa.AsUInt16()); - Sse2.Store((ushort*)p, diff); - int paMinusPb = output[3] + output[2] + output[1] + output[0]; + Sse2.Store((ushort*)ptr, diff); + int paMinusPb = ptr[3] + ptr[2] + ptr[1] + ptr[0]; return (paMinusPb <= 0) ? a : b; } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs index 689c63f5b..411357963 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs @@ -353,8 +353,8 @@ internal static unsafe class PredictorEncoder else { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* currentRow = currentRowSpan) - fixed (uint* upperRow = upperRowSpan) + fixed (uint* currentRow = &MemoryMarshal.GetReference(currentRowSpan)) + fixed (uint* upperRow = &MemoryMarshal.GetReference(upperRowSpan)) { for (int x = xStart; x < xEnd; x++) { @@ -664,9 +664,9 @@ internal static unsafe class PredictorEncoder Span scratch) { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* current = currentSpan) - fixed (uint* upper = upperSpan) - fixed (uint* outputFixed = outputSpan) + fixed (uint* current = &MemoryMarshal.GetReference(currentSpan)) + fixed (uint* upper = &MemoryMarshal.GetReference(upperSpan)) + fixed (uint* outputFixed = &MemoryMarshal.GetReference(outputSpan)) { uint* output = outputFixed; if (xStart == 0) diff --git a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs index 1a8fcbafc..735d0bf55 100644 --- a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs @@ -25,7 +25,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = rowBytes) + fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) { var alphaMaskVector256 = Vector256.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector256 all0x80Vector256 = Vector256.Create((byte)0x80).AsByte(); @@ -81,7 +81,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = rowBytes) + fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) { for (; i + 64 <= length; i += 64) { diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 2eb05ea93..31617c163 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -50,7 +50,7 @@ public static class Buffer2DExtensions Span span = MemoryMarshal.AsBytes(buffer.DangerousGetSingleMemory().Span); - fixed (byte* ptr = span) + fixed (byte* ptr = &MemoryMarshal.GetReference(span)) { byte* basePtr = ptr; for (int y = 0; y < buffer.Height; y++) From 45321948c837b675b6339dafaf7ac8d7fc5e9421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 14:19:26 +0200 Subject: [PATCH 2/8] Block8x8 set explicit size instead of (unused) fixed sized buffer field --- .../Formats/Jpeg/Components/Block8x8.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs index d119a18c8..b417a8c81 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs @@ -15,25 +15,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components; /// 8x8 matrix of coefficients. /// // ReSharper disable once InconsistentNaming -[StructLayout(LayoutKind.Explicit)] -internal unsafe partial struct Block8x8 +[StructLayout(LayoutKind.Explicit, Size = 2 * Size)] +internal partial struct Block8x8 { /// /// A number of scalar coefficients in a /// public const int Size = 64; -#pragma warning disable IDE0051 // Remove unused private member - /// - /// A placeholder buffer so the actual struct occupies exactly 64 * 2 bytes. - /// - /// - /// This is not used directly in the code. - /// - [FieldOffset(0)] - private fixed short data[Size]; -#pragma warning restore IDE0051 - /// /// Gets or sets a value at the given index /// From a534328dc482683834c6901d93da61cf0d053724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 14:34:07 +0200 Subject: [PATCH 3/8] Optimized Block8x8F --- .../Formats/Jpeg/Components/Block8x8F.cs | 25 +++++++------------ .../Block8x8F_MultiplyInPlaceBlock.cs | 4 +-- .../Formats/Jpg/Block8x8FTests.cs | 12 +++------ .../ImageSharp.Tests/Formats/Jpg/DCTTests.cs | 15 ++++------- ...ferenceImplementationsTests.AccurateDCT.cs | 3 +-- ...plementationsTests.FastFloatingPointDCT.cs | 3 +-- ...ceImplementations.LLM_FloatingPoint_DCT.cs | 6 ++--- 7 files changed, 23 insertions(+), 45 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 21971a8c7..d432e82d2 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -101,24 +101,17 @@ internal partial struct Block8x8F : IEquatable set => this[((uint)y * 8) + (uint)x] = value; } - public static Block8x8F Load(Span data) - { - Block8x8F result = default; - result.LoadFrom(data); - return result; - } - /// /// Load raw 32bit floating point data from source. /// - /// Source + /// Source [MethodImpl(InliningOptions.ShortMethod)] - public void LoadFrom(Span source) + public static Block8x8F Load(Span data) { - ref byte s = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); - ref byte d = ref Unsafe.As(ref this); + DebugGuard.MustBeGreaterThanOrEqualTo(data.Length, Size, "data is too small"); - Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float)); + ref byte src = ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + return Unsafe.ReadUnaligned(ref src); } /// @@ -144,10 +137,10 @@ internal partial struct Block8x8F : IEquatable [MethodImpl(InliningOptions.ShortMethod)] public unsafe void ScaledCopyTo(float[] dest) { - fixed (void* ptr = &this.V0L) - { - Marshal.Copy((IntPtr)ptr, dest, 0, Size); - } + DebugGuard.MustBeGreaterThanOrEqualTo(dest.Length, Size, "dest is too small"); + + ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(dest)); + Unsafe.WriteUnaligned(ref destRef, this); } public float[] ToArray() diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs index a5abeb3b6..722b09587 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs @@ -29,8 +29,6 @@ public class Block8x8F_MultiplyInPlaceBlock } } - var source = default(Block8x8F); - source.LoadFrom(result); - return source; + return Block8x8F.Load(result); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 3e4bcae6b..cde9e776b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -99,8 +99,7 @@ public partial class Block8x8FTests : JpegFixture Times, () => { - var b = default(Block8x8F); - b.LoadFrom(data); + Block8x8F b = Block8x8F.Load(data); b.ScaledCopyTo(mirror); }); @@ -117,8 +116,7 @@ public partial class Block8x8FTests : JpegFixture float[] expected = Create8x8FloatData(); ReferenceImplementations.Transpose8x8(expected); - var block8x8 = default(Block8x8F); - block8x8.LoadFrom(Create8x8FloatData()); + Block8x8F block8x8 = Block8x8F.Load(Create8x8FloatData()); block8x8.TransposeInplace(); @@ -153,9 +151,8 @@ public partial class Block8x8FTests : JpegFixture [Fact] public void NormalizeColors() { - var block = default(Block8x8F); float[] input = Create8x8ColorCropTestData(); - block.LoadFrom(input); + Block8x8F block = Block8x8F.Load(input); this.Output.WriteLine("Input:"); this.PrintLinearData(input); @@ -242,8 +239,7 @@ public partial class Block8x8FTests : JpegFixture { float[] data = Create8x8RandomFloatData(-1000, 1000); - var source = default(Block8x8F); - source.LoadFrom(data); + Block8x8F source = Block8x8F.Load(data); var dest = default(Block8x8); source.RoundInto(ref dest); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs index 5853ff37a..5a1488c41 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs @@ -114,8 +114,7 @@ public static class DCTTests int seed = FeatureTestRunner.Deserialize(serialized); Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -162,8 +161,7 @@ public static class DCTTests public void TranformIDCT_4x4(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 4, 4); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -224,8 +222,7 @@ public static class DCTTests public void TranformIDCT_2x2(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 2, 2); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -286,8 +283,7 @@ public static class DCTTests public void TranformIDCT_1x1(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 1, 1); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -330,8 +326,7 @@ public static class DCTTests int seed = FeatureTestRunner.Deserialize(serialized); Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); - var block = default(Block8x8F); - block.LoadFrom(src); + Block8x8F block = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp1 = new float[64]; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs index cd93adefd..c593a029a 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs @@ -25,8 +25,7 @@ public partial class ReferenceImplementationsTests { float[] data = Create8x8RandomFloatData(-1000, 1000, seed); - var b0 = default(Block8x8F); - b0.LoadFrom(data); + Block8x8F b0 = Block8x8F.Load(data); Block8x8F b1 = ReferenceImplementations.AccurateDCT.TransformFDCT(ref b0); Block8x8F b2 = ReferenceImplementations.AccurateDCT.TransformIDCT(ref b1); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs index 46c6ee2da..f5d7c159b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs @@ -70,8 +70,7 @@ public partial class ReferenceImplementationsTests { float[] floatData = Create8x8RandomFloatData(-1000, 1000); - Block8x8F source = default; - source.LoadFrom(floatData); + Block8x8F source = Block8x8F.Load(floatData); Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source); Block8x8F actual = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformFDCT_UpscaleBy8(ref source); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs index 9e0c62d13..0d5f3114d 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs @@ -36,8 +36,7 @@ internal static partial class ReferenceImplementations float[] temp = new float[64]; IDCT2D_llm(s, d, temp); - Block8x8F result = default; - result.LoadFrom(d); + Block8x8F result = Block8x8F.Load(d); return result; } @@ -49,8 +48,7 @@ internal static partial class ReferenceImplementations float[] temp = new float[64]; FDCT2D_llm(s, d, temp); - Block8x8F result = default; - result.LoadFrom(d); + Block8x8F result = Block8x8F.Load(d); return result; } From 77ffeeabd623b6331e1fafc3142a8a3132e8ce6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 17:03:29 +0200 Subject: [PATCH 4/8] Create vector constants inline and not via ROS --- .../Common/Helpers/SimdUtils.HwIntrinsics.cs | 113 +++++++++--------- .../PixelConversion_PackFromRgbPlanes.cs | 3 +- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index ce6f335a8..8eebf7fb9 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -13,33 +13,38 @@ internal static partial class SimdUtils { public static class HwIntrinsics { - public static ReadOnlySpan PermuteMaskDeinterleave8x32 => new byte[] { 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] // too much IL for JIT to inline, so give a hint + public static Vector256 PermuteMaskDeinterleave8x32() => Vector256.Create(0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0).AsInt32(); - public static ReadOnlySpan PermuteMaskEvenOdd8x32 => new byte[] { 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 PermuteMaskEvenOdd8x32() => Vector256.Create(0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0).AsUInt32(); - public static ReadOnlySpan PermuteMaskSwitchInnerDWords8x32 => new byte[] { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 PermuteMaskSwitchInnerDWords8x32() => Vector256.Create(0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0).AsUInt32(); - private static ReadOnlySpan MoveFirst24BytesToSeparateLanes => new byte[] { 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 MoveFirst24BytesToSeparateLanes() => Vector256.Create(0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0).AsUInt32(); - internal static ReadOnlySpan ExtractRgb => new byte[] { 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF, 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector256 ExtractRgb() => Vector256.Create(0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF, 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF); - private static ReadOnlySpan ShuffleMaskPad4Nx16 => new byte[] { 0, 1, 2, 0x80, 3, 4, 5, 0x80, 6, 7, 8, 0x80, 9, 10, 11, 0x80 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 ShuffleMaskPad4Nx16() => Vector128.Create(0, 1, 2, 0x80, 3, 4, 5, 0x80, 6, 7, 8, 0x80, 9, 10, 11, 0x80); - private static ReadOnlySpan ShuffleMaskSlice4Nx16 => new byte[] { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0x80, 0x80, 0x80, 0x80 }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 ShuffleMaskSlice4Nx16() => Vector128.Create(0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0x80, 0x80, 0x80, 0x80); - private static ReadOnlySpan ShuffleMaskShiftAlpha => - new byte[] - { - 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15, - 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15 - }; +#pragma warning disable SA1003, SA1116, SA1117 // Parameters should be on same line or separate lines + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 ShuffleMaskShiftAlpha() => Vector256.Create((byte) + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15, + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15); - public static ReadOnlySpan PermuteMaskShiftAlpha8x32 => - new byte[] - { - 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, - 5, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 - }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 PermuteMaskShiftAlpha8x32() => Vector256.Create( + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0).AsUInt32(); +#pragma warning restore SA1003, SA1116, SA1117 // Parameters should be on same line or separate lines /// /// Shuffle single-precision (32-bit) floating-point elements in @@ -189,7 +194,7 @@ internal static partial class SimdUtils { if (Ssse3.IsSupported) { - int remainder = source.Length % (Vector128.Count * 4); + int remainder = source.Length & (Vector128.Count * 4 - 1); // bit-hack for modulo int sourceCount = source.Length - remainder; int destCount = (int)((uint)sourceCount * 3 / 4); @@ -221,7 +226,7 @@ internal static partial class SimdUtils ref Vector256 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - nint n = (nint)(uint)(dest.Length / Vector256.Count); + nint n = (nint)((uint)dest.Length / (uint)Vector256.Count); nint m = Numerics.Modulo4(n); nint u = n - m; @@ -253,7 +258,7 @@ internal static partial class SimdUtils ref Vector128 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - nint n = (nint)(uint)dest.Length / Vector128.Count; + nint n = (nint)((uint)dest.Length / (uint)Vector128.Count); nint m = Numerics.Modulo4(n); nint u = n - m; @@ -306,7 +311,7 @@ internal static partial class SimdUtils ref Vector256 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - nint n = (nint)(uint)dest.Length / Vector256.Count; + nint n = (nint)((uint)dest.Length / (uint)Vector256.Count); nint m = Numerics.Modulo4(n); nint u = n - m; @@ -342,7 +347,7 @@ internal static partial class SimdUtils ref Vector128 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - nint n = (nint)(uint)dest.Length / Vector128.Count; + nint n = (nint)((uint)dest.Length / (uint)Vector128.Count); nint m = Numerics.Modulo4(n); nint u = n - m; @@ -375,10 +380,8 @@ internal static partial class SimdUtils { if (Ssse3.IsSupported) { - ref byte vmaskBase = ref MemoryMarshal.GetReference(ShuffleMaskPad4Nx16); - Vector128 vmask = Unsafe.As>(ref vmaskBase); - ref byte vmaskoBase = ref MemoryMarshal.GetReference(ShuffleMaskSlice4Nx16); - Vector128 vmasko = Unsafe.As>(ref vmaskoBase); + Vector128 vmask = ShuffleMaskPad4Nx16(); + Vector128 vmasko = ShuffleMaskSlice4Nx16(); Vector128 vmaske = Ssse3.AlignRight(vmasko, vmasko, 12); Span bytes = stackalloc byte[Vector128.Count]; @@ -440,8 +443,7 @@ internal static partial class SimdUtils { if (Ssse3.IsSupported) { - ref byte vmaskBase = ref MemoryMarshal.GetReference(ShuffleMaskPad4Nx16); - Vector128 vmask = Unsafe.As>(ref vmaskBase); + Vector128 vmask = ShuffleMaskPad4Nx16(); Vector128 vfill = Vector128.Create(0xff000000ff000000ul).AsByte(); Span bytes = stackalloc byte[Vector128.Count]; @@ -484,8 +486,7 @@ internal static partial class SimdUtils { if (Ssse3.IsSupported) { - ref byte vmaskoBase = ref MemoryMarshal.GetReference(ShuffleMaskSlice4Nx16); - Vector128 vmasko = Unsafe.As>(ref vmaskoBase); + Vector128 vmasko = ShuffleMaskSlice4Nx16(); Vector128 vmaske = Ssse3.AlignRight(vmasko, vmasko, 12); Span bytes = stackalloc byte[Vector128.Count]; @@ -542,9 +543,9 @@ internal static partial class SimdUtils /// The . [MethodImpl(InliningOptions.AlwaysInline)] public static Vector256 MultiplyAdd( - in Vector256 va, - in Vector256 vm0, - in Vector256 vm1) + Vector256 va, + Vector256 vm0, + Vector256 vm1) { if (Fma.IsSupported) { @@ -565,9 +566,9 @@ internal static partial class SimdUtils /// The . [MethodImpl(InliningOptions.ShortMethod)] public static Vector256 MultiplySubtract( - in Vector256 vs, - in Vector256 vm0, - in Vector256 vm1) + Vector256 vs, + Vector256 vm0, + Vector256 vm1) { if (Fma.IsSupported) { @@ -587,9 +588,9 @@ internal static partial class SimdUtils /// The . [MethodImpl(InliningOptions.ShortMethod)] public static Vector256 MultiplyAddNegated( - in Vector256 a, - in Vector256 b, - in Vector256 c) + Vector256 a, + Vector256 b, + Vector256 c) { if (Fma.IsSupported) { @@ -655,7 +656,7 @@ internal static partial class SimdUtils ref Vector256 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - var scale = Vector256.Create(1 / (float)byte.MaxValue); + Vector256 scale = Vector256.Create(1 / (float)byte.MaxValue); for (nuint i = 0; i < n; i++) { @@ -688,7 +689,7 @@ internal static partial class SimdUtils ref Vector128 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - var scale = Vector128.Create(1 / (float)byte.MaxValue); + Vector128 scale = Vector128.Create(1 / (float)byte.MaxValue); Vector128 zero = Vector128.Zero; for (nuint i = 0; i < n; i++) @@ -790,9 +791,8 @@ internal static partial class SimdUtils ref Vector256 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - var scale = Vector256.Create((float)byte.MaxValue); - ref byte maskBase = ref MemoryMarshal.GetReference(PermuteMaskDeinterleave8x32); - Vector256 mask = Unsafe.As>(ref maskBase); + Vector256 scale = Vector256.Create((float)byte.MaxValue); + Vector256 mask = PermuteMaskDeinterleave8x32(); for (nuint i = 0; i < n; i++) { @@ -829,7 +829,7 @@ internal static partial class SimdUtils ref Vector128 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - var scale = Vector128.Create((float)byte.MaxValue); + Vector128 scale = Vector128.Create((float)byte.MaxValue); for (nuint i = 0; i < n; i++) { @@ -866,14 +866,12 @@ internal static partial class SimdUtils nuint count = (uint)redChannel.Length / (uint)Vector256.Count; - ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32); - Vector256 control1 = Unsafe.As>(ref control1Bytes); + Vector256 control1 = PermuteMaskEvenOdd8x32(); - ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); - Vector256 control2 = Unsafe.As>(ref control2Bytes); - var a = Vector256.Create((byte)255); + Vector256 control2 = PermuteMaskShiftAlpha8x32(); + Vector256 a = Vector256.Create((byte)255); - Vector256 shuffleAlpha = Unsafe.As>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); + Vector256 shuffleAlpha = ShuffleMaskShiftAlpha(); for (nuint i = 0; i < count; i++) { @@ -937,9 +935,8 @@ internal static partial class SimdUtils ref Vector256 dBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination)); nuint count = (uint)redChannel.Length / (uint)Vector256.Count; - ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32); - Vector256 control1 = Unsafe.As>(ref control1Bytes); - var a = Vector256.Create((byte)255); + Vector256 control1 = PermuteMaskEvenOdd8x32(); + Vector256 a = Vector256.Create((byte)255); for (nuint i = 0; i < count; i++) { @@ -988,8 +985,8 @@ internal static partial class SimdUtils ref Vector256 destGRef = ref Unsafe.As>(ref MemoryMarshal.GetReference(greenChannel)); ref Vector256 destBRef = ref Unsafe.As>(ref MemoryMarshal.GetReference(blueChannel)); - Vector256 extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); - Vector256 extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); + Vector256 extractToLanesMask = MoveFirst24BytesToSeparateLanes(); + Vector256 extractRgbMask = ExtractRgb(); Vector256 rgb, rg, bx; Vector256 r, g, b; diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs index ddf192af8..a42c6c253 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs @@ -207,8 +207,7 @@ public unsafe class PixelConversion_PackFromRgbPlanes nuint count = (uint)this.Count / (uint)Vector256.Count; - ref byte control = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); - Vector256 vcontrol = Unsafe.As>(ref control); + Vector256 vcontrol = SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32().AsInt32(); var va = Vector256.Create(1F); From cdf6eed33b7392e1abccea2da277b22df8498945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 17:19:17 +0200 Subject: [PATCH 5/8] Fixed build --- src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index 8eebf7fb9..d4705fed7 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -194,7 +194,7 @@ internal static partial class SimdUtils { if (Ssse3.IsSupported) { - int remainder = source.Length & (Vector128.Count * 4 - 1); // bit-hack for modulo + int remainder = source.Length & ((Vector128.Count * 4) - 1); // bit-hack for modulo int sourceCount = source.Length - remainder; int destCount = (int)((uint)sourceCount * 3 / 4); From f348d704efac5bcb001cd8ba40b12d1cc7329d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Mon, 27 Mar 2023 18:34:02 +0200 Subject: [PATCH 6/8] Block8x8 Load and CopyTo simplified Similar to a534328dc482683834c6901d93da61cf0d053724 --- .../Formats/Jpeg/Components/Block8x8.cs | 27 ++++++------------- .../Formats/Jpg/Block8x8Tests.cs | 3 +-- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs index b417a8c81..01d112bd6 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs @@ -63,9 +63,10 @@ internal partial struct Block8x8 public static Block8x8 Load(Span data) { - Unsafe.SkipInit(out Block8x8 result); - result.LoadFrom(data); - return result; + DebugGuard.MustBeGreaterThanOrEqualTo(data.Length, Size, "data is too small"); + + ref byte src = ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + return Unsafe.ReadUnaligned(ref src); } /// @@ -93,9 +94,10 @@ internal partial struct Block8x8 /// public void CopyTo(Span destination) { - ref byte selfRef = ref Unsafe.As(ref this); - ref byte destRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destination)); - Unsafe.CopyBlockUnaligned(ref destRef, ref selfRef, Size * sizeof(short)); + DebugGuard.MustBeGreaterThanOrEqualTo(destination.Length, Size, "destination is too small"); + + ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destination)); + Unsafe.WriteUnaligned(ref destRef, this); } /// @@ -124,19 +126,6 @@ internal partial struct Block8x8 } } - /// - /// Load raw 16bit integers from source. - /// - /// Source - [MethodImpl(InliningOptions.ShortMethod)] - public void LoadFrom(Span source) - { - ref byte sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); - ref byte destRef = ref Unsafe.As(ref this); - - Unsafe.CopyBlockUnaligned(ref destRef, ref sourceRef, Size * sizeof(short)); - } - /// /// Cast and copy -s from the beginning of 'source' span. /// diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs index 798ea3040..b5d364dd3 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs @@ -269,8 +269,7 @@ public class Block8x8Tests : JpegFixture short[] expected = Create8x8ShortData(); ReferenceImplementations.Transpose8x8(expected); - var block8x8 = default(Block8x8); - block8x8.LoadFrom(Create8x8ShortData()); + Block8x8 block8x8 = Block8x8.Load(Create8x8ShortData()); block8x8.TransposeInplace(); From 4b84aecb94d37e934051273e2487ebe798424c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Mon, 27 Mar 2023 19:09:25 +0200 Subject: [PATCH 7/8] Reverted some pinning changes to have less verbose C# code --- .../Common/Helpers/SimdUtils.HwIntrinsics.cs | 2 +- src/ImageSharp/Compression/Zlib/Adler32.cs | 2 +- src/ImageSharp/Compression/Zlib/Crc32.cs | 6 +++--- src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs | 2 +- .../Formats/Webp/Lossless/PredictorEncoder.cs | 10 +++++----- src/ImageSharp/Formats/Webp/WebpCommonUtils.cs | 2 +- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index fd8a61350..8ba1b0912 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -673,7 +673,7 @@ internal static partial class SimdUtils ReadOnlySpan source, Span dest) { - fixed (byte* sourceBase = &MemoryMarshal.GetReference(source)) + fixed (byte* sourceBase = source) { if (Avx2.IsSupported) { diff --git a/src/ImageSharp/Compression/Zlib/Adler32.cs b/src/ImageSharp/Compression/Zlib/Adler32.cs index 3ecdf8153..dd8217541 100644 --- a/src/ImageSharp/Compression/Zlib/Adler32.cs +++ b/src/ImageSharp/Compression/Zlib/Adler32.cs @@ -387,7 +387,7 @@ internal static class Adler32 uint s1 = adler & 0xFFFF; uint s2 = (adler >> 16) & 0xFFFF; - fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + fixed (byte* bufferPtr = buffer) { byte* localBufferPtr = bufferPtr; uint length = (uint)buffer.Length; diff --git a/src/ImageSharp/Compression/Zlib/Crc32.cs b/src/ImageSharp/Compression/Zlib/Crc32.cs index e21621ab7..2d0a09bd4 100644 --- a/src/ImageSharp/Compression/Zlib/Crc32.cs +++ b/src/ImageSharp/Compression/Zlib/Crc32.cs @@ -81,7 +81,7 @@ internal static partial class Crc32 int chunksize = buffer.Length & ~ChunksizeMask; int length = chunksize; - fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + fixed (byte* bufferPtr = buffer) { fixed (ulong* k05PolyPtr = K05Poly) { @@ -201,7 +201,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + fixed (byte* bufferPtr = buffer) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; @@ -248,7 +248,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm64(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + fixed (byte* bufferPtr = buffer) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index ab6e4cfcc..024adb7c2 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -569,7 +569,7 @@ internal static unsafe class LosslessUtils Span pixelData, Span outputSpan) { - fixed (uint* inputFixed = &MemoryMarshal.GetReference(pixelData)) + fixed (uint* inputFixed = pixelData) { fixed (uint* outputFixed = outputSpan) { diff --git a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs index 411357963..689c63f5b 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs @@ -353,8 +353,8 @@ internal static unsafe class PredictorEncoder else { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* currentRow = &MemoryMarshal.GetReference(currentRowSpan)) - fixed (uint* upperRow = &MemoryMarshal.GetReference(upperRowSpan)) + fixed (uint* currentRow = currentRowSpan) + fixed (uint* upperRow = upperRowSpan) { for (int x = xStart; x < xEnd; x++) { @@ -664,9 +664,9 @@ internal static unsafe class PredictorEncoder Span scratch) { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* current = &MemoryMarshal.GetReference(currentSpan)) - fixed (uint* upper = &MemoryMarshal.GetReference(upperSpan)) - fixed (uint* outputFixed = &MemoryMarshal.GetReference(outputSpan)) + fixed (uint* current = currentSpan) + fixed (uint* upper = upperSpan) + fixed (uint* outputFixed = outputSpan) { uint* output = outputFixed; if (xStart == 0) diff --git a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs index 735d0bf55..4a7dc74ca 100644 --- a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs @@ -81,7 +81,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) + fixed (byte* src = rowBytes) { for (; i + 64 <= length; i += 64) { diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 31617c163..2eb05ea93 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -50,7 +50,7 @@ public static class Buffer2DExtensions Span span = MemoryMarshal.AsBytes(buffer.DangerousGetSingleMemory().Span); - fixed (byte* ptr = &MemoryMarshal.GetReference(span)) + fixed (byte* ptr = span) { byte* basePtr = ptr; for (int y = 0; y < buffer.Height; y++) From 66b2f327bed811d7abce65921148d797ee4fdbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Mon, 27 Mar 2023 19:19:02 +0200 Subject: [PATCH 8/8] Reverted Webp/WebpCommonUtils fixed-verbosity --- src/ImageSharp/Formats/Webp/WebpCommonUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs index 4a7dc74ca..1a8fcbafc 100644 --- a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs @@ -25,7 +25,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) + fixed (byte* src = rowBytes) { var alphaMaskVector256 = Vector256.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector256 all0x80Vector256 = Vector256.Create((byte)0x80).AsByte();