diff --git a/src/ImageSharp/Common/Helpers/Vector128Utilities.cs b/src/ImageSharp/Common/Helpers/Vector128Utilities.cs
index 8f4ea6292c..6b05818518 100644
--- a/src/ImageSharp/Common/Helpers/Vector128Utilities.cs
+++ b/src/ImageSharp/Common/Helpers/Vector128Utilities.cs
@@ -244,16 +244,6 @@ internal static class Vector128Utilities
return Fma.MultiplyAdd(vm1, vm0, va);
}
- if (AdvSimd.IsSupported)
- {
- return AdvSimd.Add(AdvSimd.Multiply(vm0, vm1), va);
- }
-
- if (Sse.IsSupported)
- {
- return Sse.Add(Sse.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
new file mode 100644
index 0000000000..3b4c6d4849
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector128.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
+
+internal abstract partial class JpegColorConverterBase
+{
+ internal sealed class CmykVector128 : JpegColorConverterVector128
+ {
+ public CmykVector128(int precision)
+ : base(JpegColorSpace.Cmyk, precision)
+ {
+ }
+
+ ///
+ public override void ConvertToRgbInPlace(in ComponentValues values)
+ {
+ ref Vector128 c0Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector128 c1Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector128 c2Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector128 c3Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ // Used for the color conversion
+ Vector128 scale = Vector128.Create(1 / (this.MaximumValue * this.MaximumValue));
+
+ nuint n = values.Component0.Vector128Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ ref Vector128 c = ref Unsafe.Add(ref c0Base, i);
+ ref Vector128 m = ref Unsafe.Add(ref c1Base, i);
+ ref Vector128 y = ref Unsafe.Add(ref c2Base, i);
+ Vector128 k = Unsafe.Add(ref c3Base, i);
+
+ k *= scale;
+ c *= k;
+ m *= k;
+ y *= k;
+ }
+ }
+
+ ///
+ public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
+ => ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
+
+ public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span rLane, Span gLane, Span bLane)
+ {
+ ref Vector128 destC =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector128 destM =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector128 destY =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector128 destK =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ ref Vector128 srcR =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
+ ref Vector128 srcG =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
+ ref Vector128 srcB =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
+
+ Vector128 scale = Vector128.Create(maxValue);
+
+ nuint n = values.Component0.Vector128Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ Vector128 ctmp = scale - Unsafe.Add(ref srcR, i);
+ Vector128 mtmp = scale - Unsafe.Add(ref srcG, i);
+ 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);
+
+ Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
+ Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
+ Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
+ Unsafe.Add(ref destK, i) = scale - ktmp;
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs
new file mode 100644
index 0000000000..77531c8fc4
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector256.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
+
+internal abstract partial class JpegColorConverterBase
+{
+ internal sealed class CmykVector256 : JpegColorConverterVector256
+ {
+ public CmykVector256(int precision)
+ : base(JpegColorSpace.Cmyk, precision)
+ {
+ }
+
+ ///
+ public override void ConvertToRgbInPlace(in ComponentValues values)
+ {
+ ref Vector256 c0Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector256 c1Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector256 c2Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector256 c3Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ // Used for the color conversion
+ Vector256 scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
+
+ nuint n = values.Component0.Vector256Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ ref Vector256 c = ref Unsafe.Add(ref c0Base, i);
+ ref Vector256 m = ref Unsafe.Add(ref c1Base, i);
+ ref Vector256 y = ref Unsafe.Add(ref c2Base, i);
+ Vector256 k = Unsafe.Add(ref c3Base, i);
+
+ k *= scale;
+ c *= k;
+ m *= k;
+ y *= k;
+ }
+ }
+
+ ///
+ public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
+ => ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
+
+ public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span rLane, Span gLane, Span bLane)
+ {
+ ref Vector256 destC =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector256 destM =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector256 destY =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector256 destK =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ ref Vector256 srcR =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
+ ref Vector256 srcG =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
+ ref Vector256 srcB =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
+
+ Vector256 scale = Vector256.Create(maxValue);
+
+ nuint n = values.Component0.Vector256Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ Vector256 ctmp = scale - Unsafe.Add(ref srcR, i);
+ Vector256 mtmp = scale - Unsafe.Add(ref srcG, i);
+ 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);
+
+ Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
+ Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
+ Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
+ Unsafe.Add(ref destK, i) = scale - ktmp;
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs
new file mode 100644
index 0000000000..f5c479db22
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykVector512.cs
@@ -0,0 +1,98 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
+
+internal abstract partial class JpegColorConverterBase
+{
+ internal sealed class CmykVector512 : JpegColorConverterVector512
+ {
+ public CmykVector512(int precision)
+ : base(JpegColorSpace.Cmyk, precision)
+ {
+ }
+
+ ///
+ protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values)
+ {
+ ref Vector512 c0Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector512 c1Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector512 c2Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector512 c3Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ // Used for the color conversion
+ Vector512 scale = Vector512.Create(1 / (this.MaximumValue * this.MaximumValue));
+
+ nuint n = values.Component0.Vector512Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ ref Vector512 c = ref Unsafe.Add(ref c0Base, i);
+ ref Vector512 m = ref Unsafe.Add(ref c1Base, i);
+ ref Vector512 y = ref Unsafe.Add(ref c2Base, i);
+ Vector512 k = Unsafe.Add(ref c3Base, i);
+
+ k *= scale;
+ c *= k;
+ m *= k;
+ y *= k;
+ }
+ }
+
+ ///
+ protected override void ConvertFromRgbVectorized(in ComponentValues values, Span rLane, Span gLane, Span bLane)
+ {
+ ref Vector512 destC =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector512 destM =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector512 destY =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector512 destK =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ ref Vector512 srcR =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
+ ref Vector512 srcG =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
+ ref Vector512 srcB =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
+
+ Vector512 scale = Vector512.Create(this.MaximumValue);
+
+ nuint n = values.Component0.Vector512Count();
+ for (nuint i = 0; i < n; i++)
+ {
+ Vector512 ctmp = scale - Unsafe.Add(ref srcR, i);
+ Vector512 mtmp = scale - Unsafe.Add(ref srcG, i);
+ 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);
+
+ Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
+ Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
+ Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
+ Unsafe.Add(ref destK, i) = scale - ktmp;
+ }
+ }
+
+ ///
+ protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
+ => CmykScalar.ConvertToRgbInplace(values, this.MaximumValue);
+
+ ///
+ protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span rLane, Span gLane, Span bLane)
+ => CmykScalar.ConvertFromRgb(values, this.MaximumValue, rLane, gLane, bLane);
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
deleted file mode 100644
index 92ff71b101..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// ReSharper disable ImpureMethodCallOnReadonlyValueField
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class YCbCrVector : JpegColorConverterVector
- {
- public YCbCrVector(int precision)
- : base(JpegColorSpace.YCbCr, precision)
- {
- }
-
- ///
- protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values)
- {
- ref Vector c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- Vector chromaOffset = new(-this.HalfValue);
-
- Vector scale = new(1 / this.MaximumValue);
- Vector rCrMult = new(YCbCrScalar.RCrMult);
- Vector gCbMult = new(-YCbCrScalar.GCbMult);
- Vector gCrMult = new(-YCbCrScalar.GCrMult);
- Vector bCbMult = new(YCbCrScalar.BCbMult);
-
- nuint n = values.Component0.VectorCount();
- for (nuint i = 0; i < n; i++)
- {
- // y = yVals[i];
- // cb = cbVals[i] - 128F;
- // cr = crVals[i] - 128F;
- ref Vector c0 = ref Unsafe.Add(ref c0Base, i);
- ref Vector c1 = ref Unsafe.Add(ref c1Base, i);
- ref Vector c2 = ref Unsafe.Add(ref c2Base, i);
- Vector y = Unsafe.Add(ref c0Base, i);
- Vector cb = Unsafe.Add(ref c1Base, i) + chromaOffset;
- Vector cr = Unsafe.Add(ref c2Base, i) + chromaOffset;
-
- // r = y + (1.402F * cr);
- // g = y - (0.344136F * cb) - (0.714136F * cr);
- // b = y + (1.772F * cb);
- Vector r = y + (cr * rCrMult);
- Vector g = y + (cb * gCbMult) + (cr * gCrMult);
- Vector b = y + (cb * bCbMult);
-
- r = r.RoundToNearestInteger();
- g = g.RoundToNearestInteger();
- b = b.RoundToNearestInteger();
- r *= scale;
- g *= scale;
- b *= scale;
-
- c0 = r;
- c1 = g;
- c2 = b;
- }
- }
-
- ///
- protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
- => YCbCrScalar.ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue);
-
- ///
- protected override void ConvertFromRgbVectorized(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- ref Vector destY =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector destCb =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector destCr =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- ref Vector srcR =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector srcG =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector srcB =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- Vector chromaOffset = new(this.HalfValue);
-
- Vector rYMult = new(0.299f);
- Vector gYMult = new(0.587f);
- Vector bYMult = new(0.114f);
-
- Vector rCbMult = new(0.168736f);
- Vector gCbMult = new(0.331264f);
- Vector bCbMult = new(0.5f);
-
- Vector rCrMult = new(0.5f);
- Vector gCrMult = new(0.418688f);
- Vector bCrMult = new(0.081312f);
-
- nuint n = values.Component0.VectorCount();
- for (nuint i = 0; i < n; i++)
- {
- Vector r = Unsafe.Add(ref srcR, i);
- Vector g = Unsafe.Add(ref srcG, i);
- Vector b = Unsafe.Add(ref srcB, i);
-
- // y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
- // cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
- // cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
- Unsafe.Add(ref destY, i) = (rYMult * r) + (gYMult * g) + (bYMult * b);
- Unsafe.Add(ref destCb, i) = chromaOffset - (rCbMult * r) - (gCbMult * g) + (bCbMult * b);
- Unsafe.Add(ref destCr, i) = chromaOffset + (rCrMult * r) - (gCrMult * g) - (bCrMult * b);
- }
- }
-
- ///
- protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- => YCbCrScalar.ConvertFromRgb(values, this.HalfValue, rLane, gLane, bLane);
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs
index 5681153a10..6ad62b682f 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs
@@ -131,11 +131,6 @@ internal abstract partial class JpegColorConverterBase
return new YCbCrVector128(precision);
}
- if (JpegColorConverterVector.IsSupported)
- {
- return new YCbCrVector(precision);
- }
-
return new YCbCrScalar(precision);
}
@@ -159,9 +154,19 @@ internal abstract partial class JpegColorConverterBase
/// The precision in bits.
private static JpegColorConverterBase GetCmykConverter(int precision)
{
- if (JpegColorConverterVector.IsSupported)
+ if (JpegColorConverterVector512.IsSupported)
+ {
+ return new CmykVector512(precision);
+ }
+
+ if (JpegColorConverterVector256.IsSupported)
+ {
+ return new CmykVector256(precision);
+ }
+
+ if (JpegColorConverterVector128.IsSupported)
{
- return new CmykVector(precision);
+ return new CmykVector128(precision);
}
return new CmykScalar(precision);
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs
index e377a6f97e..a1ba3fb8d6 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs
@@ -17,16 +17,32 @@ public class CmykColorConversion : ColorConversionBenchmark
[Benchmark(Baseline = true)]
public void Scalar()
{
- var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
+ JpegColorConverterBase.ComponentValues values = new(this.Input, 0);
new JpegColorConverterBase.CmykScalar(8).ConvertToRgbInPlace(values);
}
[Benchmark]
- public void SimdVector8()
+ public void SimdVector128()
{
- var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
+ JpegColorConverterBase.ComponentValues values = new(this.Input, 0);
- new JpegColorConverterBase.CmykVector(8).ConvertToRgbInPlace(values);
+ new JpegColorConverterBase.CmykVector128(8).ConvertToRgbInPlace(values);
+ }
+
+ [Benchmark]
+ public void SimdVector256()
+ {
+ JpegColorConverterBase.ComponentValues values = new(this.Input, 0);
+
+ new JpegColorConverterBase.CmykVector256(8).ConvertToRgbInPlace(values);
+ }
+
+ [Benchmark]
+ public void SimdVector512()
+ {
+ JpegColorConverterBase.ComponentValues values = new(this.Input, 0);
+
+ new JpegColorConverterBase.CmykVector512(8).ConvertToRgbInPlace(values);
}
}
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs
index 897ef9375d..fbd762af41 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs
@@ -22,14 +22,6 @@ public class YCbCrColorConversion : ColorConversionBenchmark
new JpegColorConverterBase.YCbCrScalar(8).ConvertToRgbInPlace(values);
}
- [Benchmark]
- public void SimdVector8()
- {
- JpegColorConverterBase.ComponentValues values = new(this.Input, 0);
-
- new JpegColorConverterBase.YCbCrVector(8).ConvertToRgbInPlace(values);
- }
-
[Benchmark]
public void SimdVector128()
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
index 69faa0bf41..41ab3b8316 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
using SixLabors.ImageSharp.ColorProfiles;
@@ -22,7 +21,7 @@ public class JpegColorConverterTests
private const int TestBufferLength = 40;
- private const HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2;
+ private const HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2;
private static readonly ApproximateColorProfileComparer ColorSpaceComparer = new(epsilon: Precision);
@@ -148,17 +147,17 @@ public class JpegColorConverterTests
{
// arrange
Type expectedType = typeof(JpegColorConverterBase.CmykScalar);
- if (Avx.IsSupported)
+ if (JpegColorConverterBase.JpegColorConverterVector512.IsSupported)
{
- expectedType = typeof(JpegColorConverterBase.CmykVector);
+ expectedType = typeof(JpegColorConverterBase.CmykVector512);
}
- else if (Sse2.IsSupported)
+ else if (JpegColorConverterBase.JpegColorConverterVector256.IsSupported)
{
- expectedType = typeof(JpegColorConverterBase.CmykVector);
+ expectedType = typeof(JpegColorConverterBase.CmykVector256);
}
- else if (AdvSimd.Arm64.IsSupported)
+ else if (JpegColorConverterBase.JpegColorConverterVector128.IsSupported)
{
- expectedType = typeof(JpegColorConverterBase.CmykVector);
+ expectedType = typeof(JpegColorConverterBase.CmykVector128);
}
// act
@@ -175,7 +174,7 @@ public class JpegColorConverterTests
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
@@ -193,14 +192,6 @@ public class JpegColorConverterTests
{
expectedType = typeof(JpegColorConverterBase.YCbCrVector128);
}
- else if (Sse2.IsSupported)
- {
- expectedType = typeof(JpegColorConverterBase.YCbCrVector);
- }
- else if (AdvSimd.IsSupported)
- {
- expectedType = typeof(JpegColorConverterBase.YCbCrVector);
- }
// act
JpegColorConverterBase converter = JpegColorConverterBase.GetConverter(JpegColorSpace.YCbCr, 8);
@@ -216,7 +207,7 @@ public class JpegColorConverterTests
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
@@ -266,29 +257,60 @@ public class JpegColorConverterTests
[Theory]
[MemberData(nameof(Seeds))]
- public void FromYCbCrVector(int seed)
- {
- JpegColorConverterBase.YCbCrVector converter = new(8);
+ public void FromYCbCrVector512(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.YCbCrVector512(8),
+ 3,
+ seed,
+ new JpegColorConverterBase.YCbCrScalar(8));
- if (!converter.IsAvailable)
- {
- this.Output.WriteLine(
- $"Skipping test - {converter.GetType().Name} is not supported on current hardware.");
- return;
- }
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromYCbCrVector256(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.YCbCrVector256(8),
+ 3,
+ seed,
+ new JpegColorConverterBase.YCbCrScalar(8));
- FeatureTestRunner.RunWithHwIntrinsicsFeature(
- RunTest,
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromYCbCrVector128(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.YCbCrVector128(8),
+ 3,
seed,
- IntrinsicsConfig);
+ new JpegColorConverterBase.YCbCrScalar(8));
- static void RunTest(string arg) =>
- ValidateConversionToRgb(
- new JpegColorConverterBase.YCbCrVector(8),
- 3,
- FeatureTestRunner.Deserialize(arg),
- new JpegColorConverterBase.YCbCrScalar(8));
- }
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToYCbCrVector512(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.YCbCrVector512(8),
+ 3,
+ seed,
+ new JpegColorConverterBase.YCbCrScalar(8),
+ precision: 2);
+
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToYCbCrVector256(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.YCbCrVector256(8),
+ 3,
+ seed,
+ new JpegColorConverterBase.YCbCrScalar(8),
+ precision: 2);
+
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToYCbCrVector128(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.YCbCrVector128(8),
+ 3,
+ seed,
+ new JpegColorConverterBase.YCbCrScalar(8),
+ precision: 2);
[Theory]
[MemberData(nameof(Seeds))]
@@ -297,29 +319,60 @@ public class JpegColorConverterTests
[Theory]
[MemberData(nameof(Seeds))]
- public void FromCmykVector(int seed)
- {
- JpegColorConverterBase.CmykVector converter = new(8);
+ public void FromCmykVector512(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.CmykVector512(8),
+ 4,
+ seed,
+ new JpegColorConverterBase.CmykScalar(8));
- if (!converter.IsAvailable)
- {
- this.Output.WriteLine(
- $"Skipping test - {converter.GetType().Name} is not supported on current hardware.");
- return;
- }
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromCmykVector256(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.CmykVector256(8),
+ 4,
+ seed,
+ new JpegColorConverterBase.CmykScalar(8));
- FeatureTestRunner.RunWithHwIntrinsicsFeature(
- RunTest,
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromCmykVector128(int seed) =>
+ this.TestConversionToRgb(
+ new JpegColorConverterBase.CmykVector128(8),
+ 4,
seed,
- IntrinsicsConfig);
+ new JpegColorConverterBase.CmykScalar(8));
- static void RunTest(string arg) =>
- ValidateConversionToRgb(
- new JpegColorConverterBase.CmykVector(8),
- 4,
- FeatureTestRunner.Deserialize(arg),
- new JpegColorConverterBase.CmykScalar(8));
- }
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToCmykVector512(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.CmykVector512(8),
+ 4,
+ seed,
+ new JpegColorConverterBase.CmykScalar(8),
+ precision: 2);
+
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToCmykVector256(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.CmykVector256(8),
+ 4,
+ seed,
+ new JpegColorConverterBase.CmykScalar(8),
+ precision: 2);
+
+ [Theory]
+ [MemberData(nameof(Seeds))]
+ public void FromRgbToCmykVector128(int seed) =>
+ this.TestConversionFromRgb(
+ new JpegColorConverterBase.CmykVector128(8),
+ 4,
+ seed,
+ new JpegColorConverterBase.CmykScalar(8),
+ precision: 2);
[Theory]
[MemberData(nameof(Seeds))]
@@ -434,6 +487,28 @@ public class JpegColorConverterTests
baseLineConverter);
}
+ private void TestConversionFromRgb(
+ JpegColorConverterBase converter,
+ int componentCount,
+ int seed,
+ JpegColorConverterBase baseLineConverter,
+ int precision)
+ {
+ if (!converter.IsAvailable)
+ {
+ this.Output.WriteLine(
+ $"Skipping test - {converter.GetType().Name} is not supported on current hardware.");
+ return;
+ }
+
+ ValidateConversionFromRgb(
+ converter,
+ componentCount,
+ seed,
+ baseLineConverter,
+ precision);
+ }
+
private static JpegColorConverterBase.ComponentValues CreateRandomValues(
int length,
int componentCount,