diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs index 073a5a9f6..7cbb5bfe3 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs @@ -25,6 +25,13 @@ namespace SixLabors.ImageSharp public static bool HasVector8 { get; } = Vector.IsHardwareAccelerated && Vector.Count == 8 && Vector.Count == 8; + /// + /// Gets a value indicating whether code is being JIT-ed to SSE instructions + /// where float and integer registers are of size 128 byte. + /// + public static bool HasVector4 { get; } = + Vector.IsHardwareAccelerated && Vector.Count == 4; + public static bool HasAvx2 { get diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs index ef144fc1c..90ebce3b8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs @@ -1,10 +1,6 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -#if SUPPORTS_RUNTIME_INTRINSICS -using System.Runtime.Intrinsics.X86; -#endif - namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs index a9e3e5b51..f9334de73 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs similarity index 94% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs index 65a7c42d8..193d7e71e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs @@ -11,14 +11,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromYCbCrVector : VectorizedJpegColorConverter + internal sealed class FromYCbCrVector4 : VectorizedJpegColorConverter { - public FromYCbCrVector(int precision) + public FromYCbCrVector4(int precision) : base(JpegColorSpace.YCbCr, precision, 8) { } - protected override bool IsAvailable => true; + protected override bool IsAvailable => SimdUtils.HasVector4; protected override void ConvertCoreVectorized(in ComponentValues values, Span result) { @@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters tmp.MultiplyInplace(1.772F); b.AddInplace(ref tmp); - if (Vector.Count == 4) + if (SimdUtils.HasVector4) { // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector is terrible?) r.RoundAndDownscalePreVector8(maxValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 7afc09ff5..b794e3a26 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -62,8 +62,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, int precision) { - JpegColorConverter converter = Array.Find(Converters, c => c.ColorSpace == colorSpace - && c.Precision == precision); + JpegColorConverter converter = Array.Find( + Converters, + c => c.ColorSpace == colorSpace + && c.Precision == precision); if (converter is null) { @@ -94,7 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters converters.AddRange(GetGrayScaleConverters(8)); converters.AddRange(GetRgbConverters(8)); - // 8-bit converters + // 12-bit converters converters.AddRange(GetYCbCrConverters(12)); converters.AddRange(GetYccKConverters(12)); converters.AddRange(GetCmykConverters(12)); @@ -109,9 +111,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetYCbCrConverters(int precision) { +#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromYCbCrAvx2(precision); +#endif yield return new FromYCbCrVector8(precision); - yield return new FromYCbCrVector(precision); + yield return new FromYCbCrVector4(precision); yield return new FromYCbCrBasic(precision); } @@ -120,7 +124,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetYccKConverters(int precision) { +#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromYccKAvx2(precision); +#endif yield return new FromYccKVector8(precision); yield return new FromYccKBasic(precision); } @@ -130,7 +136,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetCmykConverters(int precision) { +#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromCmykAvx2(precision); +#endif yield return new FromCmykVector8(precision); yield return new FromCmykBasic(precision); } @@ -140,7 +148,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetGrayScaleConverters(int precision) { +#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromGrayscaleAvx2(precision); +#endif yield return new FromGrayscaleBasic(precision); } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs index c17f14fe6..94b28e4d9 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - new JpegColorConverter.FromYCbCrVector(8).ConvertToRgba(values, this.output); + new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgba(values, this.output); } [Benchmark] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index bcc52de14..68210caea 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -54,10 +54,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [MemberData(nameof(CommonConversionData))] - public void FromYCbCrVector(int inputBufferLength, int resultBufferLength, int seed) + public void FromYCbCrVector4(int inputBufferLength, int resultBufferLength, int seed) { + if (!SimdUtils.HasVector4) + { + this.Output.WriteLine("No SSE present, skipping test!"); + return; + } + ValidateConversion( - new JpegColorConverter.FromYCbCrVector(8), + new JpegColorConverter.FromYCbCrVector4(8), 3, inputBufferLength, resultBufferLength, @@ -346,7 +352,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); var result = new Vector4[count]; - JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrVector(8) : new JpegColorConverter.FromYCbCrBasic(8); + JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrVector4(8) : new JpegColorConverter.FromYCbCrBasic(8); // Warm up: converter.ConvertToRgba(values, result);