diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index 00c0d89f0..caeb694a9 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -577,6 +577,24 @@ namespace SixLabors.ImageSharp } } + /// + /// Scales 8x8 matrix to 4x2 using 2x2 average + /// + /// Input matrix consisting of 4 256bit vectors, first row: (v[0], v[2]), second row: (v[1], v[3]) + /// 256bit vector containing upper and lower scaled parts of the input matrix + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Scale16x2_8x1(ReadOnlySpan> v) + { + DebugGuard.IsTrue(v.Length == 4, "Input span must consist of 4 elements"); + + var f025 = Vector256.Create(0.25f); + + Vector256 left = Avx.Add(v[0], v[2]); + Vector256 right = Avx.Add(v[1], v[3]); + Vector256 avg2x2 = Avx.Multiply(Avx.HorizontalAdd(left, right), f025); + + return Avx2.Permute4x64(avg2x2.AsDouble(), 0b11_01_10_00).AsSingle(); + } /// /// as many elements as possible, slicing them down (keeping the remainder). diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs index 49b974404..56da8acc7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs @@ -221,9 +221,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder bDataLanes[j] = b; } - r = Scale_8x4_4x2(rDataLanes); - g = Scale_8x4_4x2(gDataLanes); - b = Scale_8x4_4x2(bDataLanes); + r = SimdUtils.HwIntrinsics.Scale16x2_8x1(rDataLanes); + g = SimdUtils.HwIntrinsics.Scale16x2_8x1(gDataLanes); + b = SimdUtils.HwIntrinsics.Scale16x2_8x1(bDataLanes); // 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)) Unsafe.Add(ref destCbRef, i) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f05, b), fn0331264, g), fn0168736, r)); @@ -233,27 +233,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder } #endif } - -#if SUPPORTS_RUNTIME_INTRINSICS - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Scale_8x4_4x2(Span> v) - { - Vector256 switchInnerDoubleWords = Unsafe.As>(ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskSwitchInnerDWords8x32)); - var f025 = Vector256.Create(0.25f); - - Vector256 topPairSum = SumHorizontalPairs(v[0], v[2]); - Vector256 botPairSum = SumHorizontalPairs(v[1], v[3]); - - return Avx2.PermuteVar8x32(Avx.Multiply(SumVerticalPairs(topPairSum, botPairSum), f025), switchInnerDoubleWords); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 SumHorizontalPairs(Vector256 v0, Vector256 v1) - => Avx.Add(Avx.Shuffle(v0, v1, 0b10_00_10_00), Avx.Shuffle(v0, v1, 0b11_01_11_01)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 SumVerticalPairs(Vector256 v0, Vector256 v1) - => Avx.Add(Avx.Shuffle(v0, v1, 0b01_00_01_00), Avx.Shuffle(v0, v1, 0b11_10_11_10)); -#endif } }