From 5b94795559c90869267d14285f41063cb7b4b5ff Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 May 2025 09:49:50 +1000 Subject: [PATCH] Address feedback --- src/ImageSharp/Common/Helpers/SimdUtils.cs | 16 ++++++++++++++++ .../Common/Helpers/Vector128Utilities.cs | 5 +++++ .../Common/Helpers/Vector256Utilities.cs | 5 ----- .../JpegColorConverter.CmykVector128.cs | 10 ++++++---- .../JpegColorConverter.CmykVector256.cs | 10 ++++++---- .../JpegColorConverter.CmykVector512.cs | 10 ++++++---- .../JpegColorConverterVector128.cs | 2 +- .../JpegColorConverterVector256.cs | 2 +- .../JpegColorConverterVector512.cs | 2 +- 9 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs index ea5a4c07e..7f98c8375 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace SixLabors.ImageSharp; @@ -40,6 +41,7 @@ internal static partial class SimdUtils [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector FastRound(this Vector v) { + // .NET9+ has a built-in method for this Vector.Round if (Avx2.IsSupported && Vector.Count == Vector256.Count) { ref Vector256 v256 = ref Unsafe.As, Vector256>(ref v); @@ -47,6 +49,20 @@ internal static partial class SimdUtils return Unsafe.As, Vector>(ref vRound); } + if (Sse41.IsSupported && Vector.Count == Vector128.Count) + { + ref Vector128 v128 = ref Unsafe.As, Vector128>(ref v); + Vector128 vRound = Sse41.RoundToNearestInteger(v128); + return Unsafe.As, Vector>(ref vRound); + } + + if (AdvSimd.IsSupported && Vector.Count == Vector128.Count) + { + ref Vector128 v128 = ref Unsafe.As, Vector128>(ref v); + Vector128 vRound = AdvSimd.RoundToNearest(v128); + return Unsafe.As, Vector>(ref vRound); + } + // https://github.com/g-truc/glm/blob/master/glm/simd/common.h#L11 Vector sign = v & new Vector(-0F); Vector val_2p23_f32 = sign | new Vector(8388608F); diff --git a/src/ImageSharp/Common/Helpers/Vector128Utilities.cs b/src/ImageSharp/Common/Helpers/Vector128Utilities.cs index 6b0581851..765737906 100644 --- a/src/ImageSharp/Common/Helpers/Vector128Utilities.cs +++ b/src/ImageSharp/Common/Helpers/Vector128Utilities.cs @@ -244,6 +244,11 @@ internal static class Vector128Utilities return Fma.MultiplyAdd(vm1, vm0, va); } + if (AdvSimd.IsSupported) + { + return AdvSimd.FusedMultiplyAdd(va, vm0, vm1); + } + return va + (vm0 * vm1); } diff --git a/src/ImageSharp/Common/Helpers/Vector256Utilities.cs b/src/ImageSharp/Common/Helpers/Vector256Utilities.cs index 9928b529e..4c12cb272 100644 --- a/src/ImageSharp/Common/Helpers/Vector256Utilities.cs +++ b/src/ImageSharp/Common/Helpers/Vector256Utilities.cs @@ -149,11 +149,6 @@ internal static class Vector256Utilities return Fma.MultiplyAdd(vm0, vm1, va); } - if (Avx.IsSupported) - { - return Avx.Add(Avx.Multiply(vm0, vm1), va); - } - return va + (vm0 * vm1); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector128.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector128.cs index 3b4c6d484..0a935cca4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector128.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector128.cs @@ -78,10 +78,12 @@ internal abstract partial class JpegColorConverterBase Vector128 ytmp = scale - Unsafe.Add(ref srcB, i); Vector128 ktmp = Vector128.Min(ctmp, Vector128.Min(mtmp, ytmp)); - Vector128 kMask = Vector128.Equals(ktmp, scale); - ctmp = Vector128.AndNot((ctmp - ktmp) / (scale - ktmp), kMask); - mtmp = Vector128.AndNot((mtmp - ktmp) / (scale - ktmp), kMask); - ytmp = Vector128.AndNot((ytmp - ktmp) / (scale - ktmp), kMask); + Vector128 kMask = ~Vector128.Equals(ktmp, scale); + Vector128 divisor = scale - ktmp; + + ctmp = ((ctmp - ktmp) / divisor) & kMask; + mtmp = ((mtmp - ktmp) / divisor) & kMask; + ytmp = ((ytmp - ktmp) / divisor) & kMask; Unsafe.Add(ref destC, i) = scale - (ctmp * scale); Unsafe.Add(ref destM, i) = scale - (mtmp * scale); diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs index 77531c8fc..3cef262ec 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs @@ -78,10 +78,12 @@ internal abstract partial class JpegColorConverterBase Vector256 ytmp = scale - Unsafe.Add(ref srcB, i); Vector256 ktmp = Vector256.Min(ctmp, Vector256.Min(mtmp, ytmp)); - Vector256 kMask = Vector256.Equals(ktmp, scale); - ctmp = Vector256.AndNot((ctmp - ktmp) / (scale - ktmp), kMask); - mtmp = Vector256.AndNot((mtmp - ktmp) / (scale - ktmp), kMask); - ytmp = Vector256.AndNot((ytmp - ktmp) / (scale - ktmp), kMask); + Vector256 kMask = ~Vector256.Equals(ktmp, scale); + Vector256 divisor = scale - ktmp; + + ctmp = ((ctmp - ktmp) / divisor) & kMask; + mtmp = ((mtmp - ktmp) / divisor) & kMask; + ytmp = ((ytmp - ktmp) / divisor) & kMask; Unsafe.Add(ref destC, i) = scale - (ctmp * scale); Unsafe.Add(ref destM, i) = scale - (mtmp * scale); diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs index 54ebe89df..f57ad4352 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs @@ -86,10 +86,12 @@ internal abstract partial class JpegColorConverterBase Vector512 ytmp = scale - Unsafe.Add(ref srcB, i); Vector512 ktmp = Vector512.Min(ctmp, Vector512.Min(mtmp, ytmp)); - Vector512 kMask = Vector512.Equals(ktmp, scale); - ctmp = Vector512.AndNot((ctmp - ktmp) / (scale - ktmp), kMask); - mtmp = Vector512.AndNot((mtmp - ktmp) / (scale - ktmp), kMask); - ytmp = Vector512.AndNot((ytmp - ktmp) / (scale - ktmp), kMask); + Vector512 kMask = ~Vector512.Equals(ktmp, scale); + Vector512 divisor = scale - ktmp; + + ctmp = ((ctmp - ktmp) / divisor) & kMask; + mtmp = ((mtmp - ktmp) / divisor) & kMask; + ytmp = ((ytmp - ktmp) / divisor) & kMask; Unsafe.Add(ref destC, i) = scale - (ctmp * scale); Unsafe.Add(ref destM, i) = scale - (mtmp * scale); diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector128.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector128.cs index 35458a9a0..5cbb376c7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector128.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector128.cs @@ -25,7 +25,7 @@ internal abstract partial class JpegColorConverterBase { } - public static bool IsSupported => Vector128.IsHardwareAccelerated && Vector128.IsSupported; + public static bool IsSupported => Vector128.IsHardwareAccelerated; public sealed override bool IsAvailable => IsSupported; diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector256.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector256.cs index 14442383a..61c37d846 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector256.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector256.cs @@ -25,7 +25,7 @@ internal abstract partial class JpegColorConverterBase { } - public static bool IsSupported => Vector256.IsHardwareAccelerated && Vector256.IsSupported; + public static bool IsSupported => Vector256.IsHardwareAccelerated; public sealed override bool IsAvailable => IsSupported; diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector512.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector512.cs index e916ea5aa..0c7d032d4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector512.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterVector512.cs @@ -19,7 +19,7 @@ internal abstract partial class JpegColorConverterBase { } - public static bool IsSupported => Vector512.IsHardwareAccelerated && Vector512.IsSupported; + public static bool IsSupported => Vector512.IsHardwareAccelerated; /// public override bool IsAvailable => IsSupported;