From 87c7d3f89c5a563befde2b759b8e8c966ba75562 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Oct 2020 23:06:32 +0100 Subject: [PATCH 01/41] Update test 3rd party libraries --- tests/Directory.Build.targets | 6 +++--- tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs | 6 +++--- .../ReferenceCodecs/MagickReferenceDecoder.cs | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index 335f3d106c..b4e815eb42 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -29,12 +29,12 @@ - + - + - + diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs index 0f76d99317..58ed31e610 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Image image, bool useExactComparer = true, float compareTolerance = 0.01f) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { string path = TestImageProvider.GetFilePathOrNull(provider); if (path == null) @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga } public static Image DecodeWithMagick(Configuration configuration, FileInfo fileInfo) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { using (var magickImage = new MagickImage(fileInfo)) { @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Assert.True(result.TryGetSinglePixelSpan(out Span resultPixels)); - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { byte[] data = pixels.ToByteArray(PixelMapping.RGBA); diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index de8278a33e..bb8407f19b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder(); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } private static void FromRgba64Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -48,17 +48,17 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } public Task> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel => Task.FromResult(this.Decode(configuration, stream)); public Image Decode(Configuration configuration, Stream stream) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { using var magickImage = new MagickImage(stream); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { if (magickImage.Depth == 8) { From 8f94dc29c7a06c3694d6bb18c07a5d0dda81f43c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Oct 2020 23:13:55 +0100 Subject: [PATCH 02/41] Update Test SDK. --- tests/Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index b4e815eb42..7a2ed70615 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -31,7 +31,7 @@ - + From cb87ae166480321a3cf28df5d7411170ddc5b388 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Oct 2020 23:42:15 +0100 Subject: [PATCH 03/41] Tweak decode cancel timings --- tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 78218aec90..0884215491 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -129,10 +129,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [InlineData(TestImages.Jpeg.Baseline.Jpeg420Small, 0)] [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 1)] - [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 10)] + [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 15)] [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 30)] [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 1)] - [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 10)] + [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 15)] [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 30)] public async Task Decode_IsCancellable(string fileName, int cancellationDelayMs) { From ad21822ff9a63ff0a3267b58b2b7555ca534c4ea Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Oct 2020 23:42:22 +0100 Subject: [PATCH 04/41] Bump src deps. --- Directory.Build.targets | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 4e7ab9e6b7..91d5a5d1fd 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -24,16 +24,12 @@ - + - - + From e356bdecac2d344d010797fe19f38a4ae01226bb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 13 Oct 2020 00:19:23 +0100 Subject: [PATCH 05/41] Fix missing dll.config file The file only exists if there are binding redirects. --- tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs index 1375b5763e..48728faf0e 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs @@ -170,7 +170,10 @@ namespace SixLabors.ImageSharp.Tests } string testProjectConfigPath = TestAssemblyFile.FullName + ".config"; - File.Copy(testProjectConfigPath, remoteExecutorConfigPath); + if (File.Exists(testProjectConfigPath)) + { + File.Copy(testProjectConfigPath, remoteExecutorConfigPath); + } if (Is64BitProcess) { From 31f7480c29c42d649606fa2db2b6c781dfe327fb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 13 Oct 2020 00:19:35 +0100 Subject: [PATCH 06/41] Update xunit runner --- tests/Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index 7a2ed70615..f9efbf79fe 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -37,7 +37,7 @@ - + From c15a552f9aaf2019783f453c83081d5adcd4bd93 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 13 Oct 2020 18:04:03 +0100 Subject: [PATCH 07/41] Try System.Drawing BMP Decoder everywhere. --- .../TestUtilities/TestEnvironment.Formats.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 6e204e2d48..5370506dda 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -69,7 +69,10 @@ namespace SixLabors.ImageSharp.Tests cfg.ConfigureCodecs( BmpFormat.Instance, - IsWindows ? (IImageDecoder)SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, + + // Try SD Bitmap decoder everywhere. + // IsWindows ? (IImageDecoder)SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, + SystemDrawingReferenceDecoder.Instance, bmpEncoder, new BmpImageFormatDetector()); From 9ab1200f4c0e00d8e9c12a5cda66439548e971bd Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 13 Oct 2020 21:06:33 +0100 Subject: [PATCH 08/41] Revert "Try System.Drawing BMP Decoder everywhere." This reverts commit 94ba508fd7d07beec309af00fbd0bcbd409dcc09. --- .../TestUtilities/TestEnvironment.Formats.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 5370506dda..6e204e2d48 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -69,10 +69,7 @@ namespace SixLabors.ImageSharp.Tests cfg.ConfigureCodecs( BmpFormat.Instance, - - // Try SD Bitmap decoder everywhere. - // IsWindows ? (IImageDecoder)SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, - SystemDrawingReferenceDecoder.Instance, + IsWindows ? (IImageDecoder)SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, bmpEncoder, new BmpImageFormatDetector()); From 7c4a8a1a6fbf0364f9651c737991552468e57ce2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 13 Oct 2020 23:41:29 +0100 Subject: [PATCH 09/41] Skip tests on Linux with known Magick issue --- .runsettings | 6 ++++++ Directory.Build.props | 1 + ImageSharp.sln | 1 + tests/Directory.Build.targets | 5 +++-- tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 1 + tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs | 6 ++++++ tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 1 + 7 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 .runsettings diff --git a/.runsettings b/.runsettings new file mode 100644 index 0000000000..7af0056c81 --- /dev/null +++ b/.runsettings @@ -0,0 +1,6 @@ + + + + category!=failing + + diff --git a/Directory.Build.props b/Directory.Build.props index c4610d0ed3..bb97810a8f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,6 +15,7 @@ $(MSBuildThisFileDirectory)artifacts/ $(SixLaborsProjectCategory)/$(MSBuildProjectName) https://github.com/SixLabors/ImageSharp/ + $(MSBuildThisFileDirectory)/.runsettings diff --git a/ImageSharp.sln b/ImageSharp.sln index 509dcf96bf..b1d3176ad2 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .gitattributes = .gitattributes .gitignore = .gitignore .gitmodules = .gitmodules + .runsettings = .runsettings ci-build.ps1 = ci-build.ps1 ci-pack.ps1 = ci-pack.ps1 ci-test.ps1 = ci-test.ps1 diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index f9efbf79fe..1f699c9dd1 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -26,11 +26,12 @@ - + - + + diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 3f767620a6..5015faa701 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -339,6 +339,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv2, PixelTypes.Rgba32)] [WithFile(CoreHeader, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index b05486e356..d6839198d7 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -152,18 +152,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp public void Encode_16Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)] public void Encode_8BitGray_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) @@ -173,6 +176,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: false); + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)] public void Encode_8BitGray_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) @@ -182,6 +186,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: true); + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit32Rgb, PixelTypes.Rgba32)] public void Encode_8BitColor_WithWuQuantizer(TestImageProvider provider) @@ -208,6 +213,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } + [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit32Rgb, PixelTypes.Rgba32)] public void Encode_8BitColor_WithOctreeQuantizer(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index ba849ab251..07ade97d5d 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -20,6 +20,7 @@ + From 4454395cd8b2407627f542749f9f5d564a5eb3ff Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 00:13:05 +0100 Subject: [PATCH 10/41] Add rule to coverlet settings. --- .runsettings | 1 + tests/coverlet.runsettings | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.runsettings b/.runsettings index 7af0056c81..ca48342bd6 100644 --- a/.runsettings +++ b/.runsettings @@ -1,3 +1,4 @@ + diff --git a/tests/coverlet.runsettings b/tests/coverlet.runsettings index ee408a5f04..cffce3540b 100644 --- a/tests/coverlet.runsettings +++ b/tests/coverlet.runsettings @@ -1,5 +1,9 @@ + + + category!=failing + From 722a014f12c1e3136cb14b1bbd30a1b7611b3ee3 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Wed, 14 Oct 2020 11:51:33 +0200 Subject: [PATCH 11/41] Upgraded Magick.NET. --- tests/Directory.Build.targets | 2 +- .../Formats/Tga/TgaTestUtils.cs | 6 +++--- .../ReferenceCodecs/MagickReferenceDecoder.cs | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index 335f3d106c..ef67b122ed 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -29,7 +29,7 @@ - + diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs index 0f76d99317..58ed31e610 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Image image, bool useExactComparer = true, float compareTolerance = 0.01f) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { string path = TestImageProvider.GetFilePathOrNull(provider); if (path == null) @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga } public static Image DecodeWithMagick(Configuration configuration, FileInfo fileInfo) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { using (var magickImage = new MagickImage(fileInfo)) { @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Assert.True(result.TryGetSinglePixelSpan(out Span resultPixels)); - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { byte[] data = pixels.ToByteArray(PixelMapping.RGBA); diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index de8278a33e..615e918900 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ImageMagick; +using ImageMagick.Formats.Bmp; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder(); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -33,7 +34,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } private static void FromRgba64Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -48,17 +49,25 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } public Task> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel => Task.FromResult(this.Decode(configuration, stream)); public Image Decode(Configuration configuration, Stream stream) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { + var bmpReadDefines = new BmpReadDefines + { + IgnoreFileSize = true + }; + + var settings = new MagickReadSettings(); + settings.SetDefines(bmpReadDefines); + using var magickImage = new MagickImage(stream); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { if (magickImage.Depth == 8) { From 97d6413640e062c3453c076b47f8c2d1e859ef0a Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Wed, 14 Oct 2020 12:22:58 +0200 Subject: [PATCH 12/41] Use settings in the constructor. --- .../TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 615e918900..d4c35a1ad0 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs var settings = new MagickReadSettings(); settings.SetDefines(bmpReadDefines); - using var magickImage = new MagickImage(stream); + using var magickImage = new MagickImage(stream, settings); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; From 08771fe8abb5085ffbfddbd2ec1b4df3ca11f37e Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Wed, 14 Oct 2020 13:53:32 +0000 Subject: [PATCH 13/41] Update tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs Co-authored-by: James Jackson-South --- .../TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index d4c35a1ad0..dda5f751c6 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -56,6 +56,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { var bmpReadDefines = new BmpReadDefines + { + // See https://github.com/SixLabors/ImageSharp/issues/1380 + // Validation fails on Ubuntu despite identical header generation + // on all platforms. + IgnoreFileSize = !TestEnvironment.IsWindows + }; { IgnoreFileSize = true }; From b7185acf454a88130d53a329618512e4fad0c666 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 15:50:13 +0100 Subject: [PATCH 14/41] Fix bad merge --- .../TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index dda5f751c6..8efc9a0235 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -62,9 +62,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs // on all platforms. IgnoreFileSize = !TestEnvironment.IsWindows }; - { - IgnoreFileSize = true - }; var settings = new MagickReadSettings(); settings.SetDefines(bmpReadDefines); From 4992c87323916803ad35f095a33bb2ca8aa1b9ec Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 16:56:48 +0100 Subject: [PATCH 15/41] Remove ActiveIssue filters --- tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 1 - tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs | 6 ------ 2 files changed, 7 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 5015faa701..3f767620a6 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -339,7 +339,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv2, PixelTypes.Rgba32)] [WithFile(CoreHeader, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index d6839198d7..b05486e356 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -152,21 +152,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp public void Encode_16Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : unmanaged, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)] public void Encode_8BitGray_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) @@ -176,7 +173,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: false); - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)] public void Encode_8BitGray_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) @@ -186,7 +182,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: true); - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit32Rgb, PixelTypes.Rgba32)] public void Encode_8BitColor_WithWuQuantizer(TestImageProvider provider) @@ -213,7 +208,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } - [ActiveIssue("https://github.com/SixLabors/ImageSharp/issues/1380", TestPlatforms.Linux)] [Theory] [WithFile(Bit32Rgb, PixelTypes.Rgba32)] public void Encode_8BitColor_WithOctreeQuantizer(TestImageProvider provider) From 11f2c9666734779daa99d7a43c5e6bb31b4f5846 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Wed, 14 Oct 2020 18:25:17 +0200 Subject: [PATCH 16/41] Reverted using the read defines. --- .../ReferenceCodecs/MagickReferenceDecoder.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 8efc9a0235..bb8407f19b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -7,7 +7,6 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ImageMagick; -using ImageMagick.Formats.Bmp; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -55,18 +54,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public Image Decode(Configuration configuration, Stream stream) where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { - var bmpReadDefines = new BmpReadDefines - { - // See https://github.com/SixLabors/ImageSharp/issues/1380 - // Validation fails on Ubuntu despite identical header generation - // on all platforms. - IgnoreFileSize = !TestEnvironment.IsWindows - }; - - var settings = new MagickReadSettings(); - settings.SetDefines(bmpReadDefines); - - using var magickImage = new MagickImage(stream, settings); + using var magickImage = new MagickImage(stream); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; From bf7c00441cac8104e648fdff70b898f64aa31ed1 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Wed, 14 Oct 2020 18:25:50 +0200 Subject: [PATCH 17/41] The colorPaletteSize is also part of the file size. --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index eb29c44050..454440f634 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp var fileHeader = new BmpFileHeader( type: BmpConstants.TypeMarkers.Bitmap, - fileSize: BmpFileHeader.Size + infoHeaderSize + infoHeader.ImageSize, + fileSize: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize + infoHeader.ImageSize, reserved: 0, offset: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize); From 8d12e539a94e41eb44db11392371711809a1dc49 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 21:02:50 +0100 Subject: [PATCH 18/41] Allow selectively bypassing bmp verification. --- .../Formats/Bmp/BmpDecoderTests.cs | 4 +++- .../Formats/Bmp/BmpEncoderTests.cs | 22 +++++++++++++++--- .../ReferenceCodecs/MagickReferenceDecoder.cs | 23 ++++++++++++++++++- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 3f767620a6..0c7c9a0077 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -348,7 +348,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp using (Image image = provider.GetImage(BmpDecoder)) { image.DebugSave(provider); - image.CompareToOriginal(provider); + + // Do not validate. Reference files will fail validation. + image.CompareToOriginal(provider, new MagickReferenceDecoder(false)); } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index b05486e356..83b67a01af 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -10,7 +10,7 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - +using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; using Xunit.Abstractions; @@ -200,10 +200,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp Quantizer = new WuQuantizer() }; string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + + // Use the default decoder to test our encoded image. This verifies the content. + // We do not verify the reference image though as some are invalid. IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + extension: "bmp", + appendPixelTypeToFileName: false, + decoder: new MagickReferenceDecoder(false)); } } } @@ -226,10 +234,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp Quantizer = new OctreeQuantizer() }; string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + + // Use the default decoder to test our encoded image. This verifies the content. + // We do not verify the reference image though as some are invalid. IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + extension: "bmp", + appendPixelTypeToFileName: false, + decoder: new MagickReferenceDecoder(false)); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index bb8407f19b..d20e7d2a7e 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ImageMagick; +using ImageMagick.Formats.Bmp; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -15,6 +16,18 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { public class MagickReferenceDecoder : IImageDecoder { + private readonly bool validate; + + public MagickReferenceDecoder() + : this(true) + { + } + + public MagickReferenceDecoder(bool validate) + { + this.validate = validate; + } + public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder(); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) @@ -54,7 +67,15 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public Image Decode(Configuration configuration, Stream stream) where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { - using var magickImage = new MagickImage(stream); + var bmpReadDefines = new BmpReadDefines + { + IgnoreFileSize = !this.validate + }; + + var settings = new MagickReadSettings(); + settings.SetDefines(bmpReadDefines); + + using var magickImage = new MagickImage(stream, settings); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; From 7909bc1e6529c913ead01fca055193d1af21940f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 22:25:50 +0100 Subject: [PATCH 19/41] Disable failing RemoteExecutor tests on NETFX. --- Directory.Build.targets | 2 +- .../Formats/Gif/GifDecoderTests.cs | 1 + .../Jpg/JpegDecoderTests.Progressive.cs | 1 + .../Formats/Png/PngDecoderTests.cs | 1 + .../Formats/Png/PngEncoderTests.cs | 1 + .../Formats/Tga/TgaDecoderTests.cs | 1 + .../Processors/Convolution/BokehBlurTest.cs | 59 +++++-------------- 7 files changed, 20 insertions(+), 46 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 91d5a5d1fd..2a7d25b977 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -18,7 +18,7 @@ - + diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 63aae5c559..2e2da8d6ab 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -195,6 +195,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif Assert.IsType(ex.InnerException); } + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Kumin, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index e29d8f158b..62873a1c76 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -13,6 +13,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg"; + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32, false)] [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, true)] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 5b6adfe1af..80ca747191 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -401,6 +401,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png Assert.IsType(ex.InnerException); } + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] [WithFile(TestImages.Png.Bike, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index b9f5f16fa5..47419d47b3 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -534,6 +534,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs index 5fb15541ec..7514823fe3 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs @@ -744,6 +744,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Assert.IsType(ex.InnerException); } + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(Bit24BottomLeft, PixelTypes.Rgba32)] [WithFile(Bit32BottomLeft, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs index 50b8782e47..6c48cf843d 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs @@ -138,21 +138,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution public void BokehBlurFilterProcessor(TestImageProvider provider, BokehBlurInfo value) where TPixel : unmanaged, IPixel { - static void RunTest(string providerDump, string infoDump) - { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - BokehBlurInfo value = BasicSerializer.Deserialize(infoDump); - - provider.RunValidatingProcessorTest( - x => x.BokehBlur(value.Radius, value.Components, value.Gamma), - testOutputDetails: value.ToString(), - appendPixelTypeToFileName: false); - } - - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider), BasicSerializer.Serialize(value)) - .Dispose(); + provider.RunValidatingProcessorTest( + x => x.BokehBlur(value.Radius, value.Components, value.Gamma), + testOutputDetails: value.ToString(), + appendPixelTypeToFileName: false); } [Theory] @@ -164,18 +153,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution public void BokehBlurFilterProcessor_WorksWithAllPixelTypes(TestImageProvider provider) where TPixel : unmanaged, IPixel { - static void RunTest(string providerDump) - { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - provider.RunValidatingProcessorTest( + provider.RunValidatingProcessorTest( x => x.BokehBlur(8, 2, 3), appendSourceFileOrDescription: false); - } - - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider)) - .Dispose(); } [Theory] @@ -183,26 +163,15 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution public void BokehBlurFilterProcessor_Bounded(TestImageProvider provider, BokehBlurInfo value) where TPixel : unmanaged, IPixel { - static void RunTest(string providerDump, string infoDump) - { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - BokehBlurInfo value = BasicSerializer.Deserialize(infoDump); - - provider.RunValidatingProcessorTest( - x => - { - Size size = x.GetCurrentSize(); - var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2); - x.BokehBlur(value.Radius, value.Components, value.Gamma, bounds); - }, - testOutputDetails: value.ToString(), - appendPixelTypeToFileName: false); - } - - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider), BasicSerializer.Serialize(value)) - .Dispose(); + provider.RunValidatingProcessorTest( + x => + { + Size size = x.GetCurrentSize(); + var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2); + x.BokehBlur(value.Radius, value.Components, value.Gamma, bounds); + }, + testOutputDetails: value.ToString(), + appendPixelTypeToFileName: false); } [Theory] From 21b0982327ad6a57245a310a9f8ec5a5b2f008ea Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 22:48:56 +0100 Subject: [PATCH 20/41] Split out progressive jpeg decoding tests --- .../Formats/Gif/GifDecoderTests.cs | 2 +- .../Jpg/JpegDecoderTests.Progressive.cs | 27 +++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 2e2da8d6ab..1256520e6b 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); using Image image = provider.GetImage(GifDecoder); - image.DebugSave(provider); + image.DebugSave(provider, nonContiguousBuffersStr); image.CompareToOriginal(provider); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index 62873a1c76..5bf80580e3 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -13,11 +13,25 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg"; + [Theory] + [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32)] + public void DecodeProgressiveJpeg(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(JpegDecoder); + image.DebugSave(provider); + + provider.Utility.TestName = DecodeProgressiveJpegOutputName; + image.CompareToReferenceOutput( + GetImageComparer(provider), + provider, + appendPixelTypeToFileName: false); + } + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] - [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32, false)] - [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, true)] - public void DecodeProgressiveJpeg(TestImageProvider provider, bool enforceDiscontiguousBuffers) + [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32)] + public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) where TPixel : unmanaged, IPixel { static void RunTest(string providerDump, string nonContiguousBuffersStr) @@ -25,10 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); - if (!string.IsNullOrEmpty(nonContiguousBuffersStr)) - { - provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); - } + provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); using Image image = provider.GetImage(JpegDecoder); image.DebugSave(provider, nonContiguousBuffersStr); @@ -45,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg RemoteExecutor.Invoke( RunTest, providerDump, - enforceDiscontiguousBuffers ? "Disco" : string.Empty) + "Disco") .Dispose(); } } From 586f2dca750037d918cfa6572ed40ef1483628f7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 23:02:33 +0100 Subject: [PATCH 21/41] Skip limited buffer bitmap test on NETFX --- .../Formats/Bmp/BmpDecoderTests.cs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 0c7c9a0077..e56ffa143a 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -39,22 +39,34 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp }; [Theory] - [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32, false)] - [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32, true)] - public void BmpDecoder_CanDecode_MiscellaneousBitmaps(TestImageProvider provider, bool enforceDiscontiguousBuffers) + [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_MiscellaneousBitmaps(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(BmpDecoder); + image.DebugSave(provider); + + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + + [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] + [Theory] + [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_MiscellaneousBitmaps_WithLimitedAllocatorBufferCapacity( + TestImageProvider provider) where TPixel : unmanaged, IPixel { static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); - if (!string.IsNullOrEmpty(nonContiguousBuffersStr)) - { - provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - } + provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); using Image image = provider.GetImage(BmpDecoder); - image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); + image.DebugSave(provider, nonContiguousBuffersStr); if (TestEnvironment.IsWindows) { @@ -66,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp RemoteExecutor.Invoke( RunTest, providerDump, - enforceDiscontiguousBuffers ? "Disco" : string.Empty) + "Disco") .Dispose(); } From 147aea2448ace014ff669901d653cba0af6eb412 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Oct 2020 23:50:04 +0100 Subject: [PATCH 22/41] Add skip for dotnet xunit --- .../ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 6 ++++++ .../ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs | 6 ++++++ .../Formats/Jpg/JpegDecoderTests.Progressive.cs | 6 ++++++ .../ImageSharp.Tests/Formats/Png/PngDecoderTests.cs | 12 ++++++++++++ .../ImageSharp.Tests/Formats/Png/PngEncoderTests.cs | 6 ++++++ .../ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs | 6 ++++++ 6 files changed, 42 insertions(+) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index e56ffa143a..68a3213d3a 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -59,6 +59,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 1256520e6b..b76ea264ce 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -202,6 +202,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index 5bf80580e3..1edbe5ba98 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -34,6 +34,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 80ca747191..8511154789 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -396,6 +396,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png public void PngDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + provider.LimitAllocatorBufferCapacity().InPixelsSqrt(10); InvalidImageContentException ex = Assert.Throws(() => provider.GetImage(PngDecoder)); Assert.IsType(ex.InnerException); @@ -408,6 +414,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png public void PngDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 47419d47b3..8c4f17f02b 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -540,6 +540,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump) { TestImageProvider provider = diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs index 7514823fe3..8fff47719b 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs @@ -751,6 +751,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) where TPixel : unmanaged, IPixel { + // dotnet xunit doesn't respect filter. + if (TestEnvironment.IsFramework) + { + return; + } + static void RunTest(string providerDump, string nonContiguousBuffersStr) { TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); From 45f303d094e60798f9ffe1650bf86fca92074b13 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 02:19:35 +0100 Subject: [PATCH 23/41] Don't use generics. Could have saved myself days of issues if i'd just thought of this first. --- .../Formats/Bmp/BmpDecoderTests.cs | 16 ++++----------- .../Formats/Gif/GifDecoderTests.cs | 16 +++++---------- .../Jpg/JpegDecoderTests.Progressive.cs | 20 ++++++------------- .../Formats/Png/PngDecoderTests.cs | 20 +++---------------- .../Formats/Png/PngEncoderTests.cs | 14 +++---------- .../Formats/Tga/TgaDecoderTests.cs | 14 +++---------- 6 files changed, 24 insertions(+), 76 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 68a3213d3a..f98fa3c7f3 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -52,26 +52,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] - public void BmpDecoder_CanDecode_MiscellaneousBitmaps_WithLimitedAllocatorBufferCapacity( - TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void BmpDecoder_CanDecode_MiscellaneousBitmaps_WithLimitedAllocatorBufferCapacity( + TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(BmpDecoder); + using Image image = provider.GetImage(BmpDecoder); image.DebugSave(provider, nonContiguousBuffersStr); if (TestEnvironment.IsWindows) diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index b76ea264ce..eb2643b8cd 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -195,26 +195,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif Assert.IsType(ex.InnerException); } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Kumin, PixelTypes.Rgba32)] - public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity( + TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider + = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(GifDecoder); + using Image image = provider.GetImage(GifDecoder); image.DebugSave(provider, nonContiguousBuffersStr); image.CompareToOriginal(provider); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index 1edbe5ba98..98421ca5d4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -28,26 +28,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg appendPixelTypeToFileName: false); } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32)] - public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = + BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); - using Image image = provider.GetImage(JpegDecoder); + using Image image = provider.GetImage(JpegDecoder); image.DebugSave(provider, nonContiguousBuffersStr); provider.Utility.TestName = DecodeProgressiveJpegOutputName; @@ -62,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg RemoteExecutor.Invoke( RunTest, providerDump, - "Disco") - .Dispose(); + "Disco") + .Dispose(); } } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 8511154789..2164975df0 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -396,37 +396,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png public void PngDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException(TestImageProvider provider) where TPixel : unmanaged, IPixel { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - provider.LimitAllocatorBufferCapacity().InPixelsSqrt(10); InvalidImageContentException ex = Assert.Throws(() => provider.GetImage(PngDecoder)); Assert.IsType(ex.InnerException); } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] [WithFile(TestImages.Png.Bike, PixelTypes.Rgba32)] - public void PngDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void PngDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(PngDecoder); + using Image image = provider.GetImage(PngDecoder); image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); image.CompareToOriginal(provider); } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 8c4f17f02b..b35e55887c 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -534,22 +534,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] - public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = + BasicSerializer.Deserialize>(providerDump); #if SUPPORTS_RUNTIME_INTRINSICS Assert.False(Ssse3.IsSupported); #endif diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs index 8fff47719b..edb43aa126 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs @@ -744,26 +744,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Assert.IsType(ex.InnerException); } - [ActiveIssue("https://github.com/dotnet/arcade/issues/6393", TargetFrameworkMonikers.NetFramework)] [Theory] [WithFile(Bit24BottomLeft, PixelTypes.Rgba32)] [WithFile(Bit32BottomLeft, PixelTypes.Rgba32)] - public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { - // dotnet xunit doesn't respect filter. - if (TestEnvironment.IsFramework) - { - return; - } - static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(TgaDecoder); + using Image image = provider.GetImage(TgaDecoder); image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); if (TestEnvironment.IsWindows) From 310710e3113223b976b638334b0290549da67bae Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 21:32:37 +0100 Subject: [PATCH 24/41] Add FeatureTestRunner --- .../FeatureTesting/FeatureTestRunner.cs | 266 ++++++++++++++++++ .../Tests/FeatureTestRunnerTests.cs | 237 ++++++++++++++++ 2 files changed, 503 insertions(+) create mode 100644 tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs create mode 100644 tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs diff --git a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs new file mode 100644 index 0000000000..57ed85a182 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs @@ -0,0 +1,266 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.DotNet.RemoteExecutor; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.TestUtilities +{ + /// + /// Allows the testing against specific feature sets. + /// + public static class FeatureTestRunner + { + private static readonly char[] SplitChars = new[] { ',', ' ' }; + + /// + /// Allows the deserialization of parameters passed to the feature test. + /// + /// + /// This is required because does not allow + /// marshalling of fields so we cannot pass a wrapped + /// allowing automatic deserialization. + /// + /// + /// + /// The type to deserialize to. + /// The string value to deserialize. + /// The value. + public static T Deserialize(string value) + where T : IXunitSerializable + => BasicSerializer.Deserialize(value); + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics) + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + + RemoteExecutor.Invoke( + action, + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// + /// The test action to run. + /// The parameter passed will be a string representing the currently testing . + /// The intrinsics features. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics) + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + + RemoteExecutor.Invoke( + action, + intrinsic.Key.ToString(), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(intrinsic.Key.ToString()); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + /// The value to pass as a parameter to the test action. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics, + T serializable) + where T : IXunitSerializable + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + + RemoteExecutor.Invoke( + action, + BasicSerializer.Serialize(serializable), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(BasicSerializer.Serialize(serializable)); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + /// The value to pass as a parameter to the test action. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics, + T serializable) + where T : IXunitSerializable + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + + RemoteExecutor.Invoke( + action, + BasicSerializer.Serialize(serializable), + intrinsic.Key.ToString(), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(BasicSerializer.Serialize(serializable), intrinsic.Key.ToString()); + } + } + } + + internal static Dictionary ToFeatureKeyValueCollection(this HwIntrinsics intrinsics) + { + // Loop through and translate the given values into COMPlus equivaluents + var features = new Dictionary(); + foreach (string intrinsic in intrinsics.ToString("G").Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)) + { + var key = (HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic); + switch (intrinsic) + { + case nameof(HwIntrinsics.DisableSIMD): + features.Add(key, "FeatureSIMD"); + break; + + case nameof(HwIntrinsics.AllowAll): + + // Not a COMPlus value. We filter in calling method. + features.Add(key, nameof(HwIntrinsics.AllowAll)); + break; + + default: + features.Add(key, intrinsic.Replace("Disable", "Enable")); + break; + } + } + + return features; + } + } + + /// + /// See + /// + /// ends up impacting all SIMD support(including System.Numerics) + /// but not things like , , and . + /// + /// + [Flags] +#pragma warning disable RCS1135 // Declare enum member with zero value (when enum has FlagsAttribute). + public enum HwIntrinsics +#pragma warning restore RCS1135 // Declare enum member with zero value (when enum has FlagsAttribute). + { + // Use flags so we can pass multiple values without using params. + // Don't base on 0 or use inverse for All as that doesn't translate to string values. + DisableSIMD = 1 << 0, + DisableHWIntrinsic = 1 << 1, + DisableSSE = 1 << 2, + DisableSSE2 = 1 << 3, + DisableAES = 1 << 4, + DisablePCLMULQDQ = 1 << 5, + DisableSSE3 = 1 << 6, + DisableSSSE3 = 1 << 7, + DisableSSE41 = 1 << 8, + DisableSSE42 = 1 << 9, + DisablePOPCNT = 1 << 10, + DisableAVX = 1 << 11, + DisableFMA = 1 << 12, + DisableAVX2 = 1 << 13, + DisableBMI1 = 1 << 14, + DisableBMI2 = 1 << 15, + DisableLZCNT = 1 << 16, + AllowAll = 1 << 17 + } +} diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs new file mode 100644 index 0000000000..9852ba3478 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -0,0 +1,237 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests +{ + public class FeatureTestRunnerTests + { + public static TheoryData Intrinsics => + new TheoryData + { + { HwIntrinsics.DisableAES | HwIntrinsics.AllowAll, new string[] { "EnableAES", "AllowAll" } }, + { HwIntrinsics.DisableSIMD | HwIntrinsics.DisableHWIntrinsic, new string[] { "FeatureSIMD", "EnableHWIntrinsic" } }, + { HwIntrinsics.DisableSSE42 | HwIntrinsics.DisableAVX, new string[] { "EnableSSE42", "EnableAVX" } } + }; + + [Theory] + [MemberData(nameof(Intrinsics))] + public void ToFeatureCollectionReturnsExpectedResult(HwIntrinsics expectedItrinsics, string[] expectedValues) + { + Dictionary features = expectedItrinsics.ToFeatureKeyValueCollection(); + HwIntrinsics[] keys = features.Keys.ToArray(); + + HwIntrinsics actualIntrinsics = keys[0]; + for (int i = 1; i < keys.Length; i++) + { + actualIntrinsics |= keys[i]; + } + + Assert.Equal(expectedItrinsics, actualIntrinsics); + + IEnumerable actualValues = features.Select(x => x.Value); + Assert.Equal(expectedValues, actualValues); + } + + [Fact] + public void AllowsAllHwIntrinsicFeatures() + { + FeatureTestRunner.RunWithHwIntrinsicsFeature( + () => Assert.True(Vector.IsHardwareAccelerated), + HwIntrinsics.AllowAll); + } + + [Fact] + public void CanLimitHwIntrinsicFeatures() + { + FeatureTestRunner.RunWithHwIntrinsicsFeature( + () => Assert.False(Vector.IsHardwareAccelerated), + HwIntrinsics.DisableSIMD); + } + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) + { + Assert.NotNull(intrinsic); + + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Vector.IsHardwareAccelerated); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } + + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); + } + } + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + +#if SUPPORTS_RUNTIME_INTRINSICS + Assert.False(Sse.IsSupported); +#endif + } + + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature( + AssertHwIntrinsicsFeatureDisabled, + HwIntrinsics.DisableSSE, + new FakeSerializable()); + } + } + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Vector.IsHardwareAccelerated); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } + + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); + } + } + + public class FakeSerializable : IXunitSerializable + { + public void Deserialize(IXunitSerializationInfo info) + { + } + + public void Serialize(IXunitSerializationInfo info) + { + } + } + } +} From 9380dd5b1e3487837c9494247a5bf8e6cc548c66 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 21:36:51 +0100 Subject: [PATCH 25/41] Use single Block8x8F.TransponseInto test --- .../Formats/Jpg/Block8x8FTests.cs | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 73a68063c0..5482380885 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -5,10 +5,9 @@ // #define BENCHMARKING using System; using System.Diagnostics; - using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; - +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; using Xunit.Abstractions; @@ -163,42 +162,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } [Fact] - public void TransposeIntoFallback() + public void TransposeInto() { - float[] expected = Create8x8FloatData(); - ReferenceImplementations.Transpose8x8(expected); - - var source = default(Block8x8F); - source.LoadFrom(Create8x8FloatData()); - - var dest = default(Block8x8F); - source.TransposeIntoFallback(ref dest); - - float[] actual = new float[64]; - dest.ScaledCopyTo(actual); - - Assert.Equal(expected, actual); - } + static void RunTest() + { + float[] expected = Create8x8FloatData(); + ReferenceImplementations.Transpose8x8(expected); -#if SUPPORTS_RUNTIME_INTRINSICS - [Fact] - public void TransposeIntoAvx() - { - float[] expected = Create8x8FloatData(); - ReferenceImplementations.Transpose8x8(expected); + var source = default(Block8x8F); + source.LoadFrom(Create8x8FloatData()); - var source = default(Block8x8F); - source.LoadFrom(Create8x8FloatData()); + var dest = default(Block8x8F); + source.TransposeInto(ref dest); - var dest = default(Block8x8F); - source.TransposeIntoAvx(ref dest); + float[] actual = new float[64]; + dest.ScaledCopyTo(actual); - float[] actual = new float[64]; - dest.ScaledCopyTo(actual); + Assert.Equal(expected, actual); + } - Assert.Equal(expected, actual); + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } -#endif private class BufferHolder { From 86198504ee6d3ea9841be70e638d8f307fca4e94 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 21:58:24 +0100 Subject: [PATCH 26/41] Ensure remoteexecutor tests run --- .github/workflows/build-and-test.yml | 32 +++++++++---------- .../Tests/FeatureTestRunnerTests.cs | 8 +++++ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index c8f3997946..ecb5ceb0ef 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,23 +17,23 @@ jobs: - os: ubuntu-latest framework: netcoreapp3.1 runtime: -x64 - codecov: true - - os: windows-latest - framework: netcoreapp3.1 - runtime: -x64 - codecov: false - - os: windows-latest - framework: netcoreapp2.1 - runtime: -x64 - codecov: false - - os: windows-latest - framework: net472 - runtime: -x64 - codecov: false - - os: windows-latest - framework: net472 - runtime: -x86 codecov: false + # - os: windows-latest + # framework: netcoreapp3.1 + # runtime: -x64 + # codecov: false + # - os: windows-latest + # framework: netcoreapp2.1 + # runtime: -x64 + # codecov: false + # - os: windows-latest + # framework: net472 + # runtime: -x64 + # codecov: false + # - os: windows-latest + # framework: net472 + # runtime: -x86 + # codecov: false runs-on: ${{matrix.options.os}} if: "!contains(github.event.head_commit.message, '[skip ci]')" diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 9852ba3478..070f205748 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -23,6 +23,14 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { HwIntrinsics.DisableSSE42 | HwIntrinsics.DisableAVX, new string[] { "EnableSSE42", "EnableAVX" } } }; + [Fact] + public void TempAssertThrow() + { + FeatureTestRunner.RunWithHwIntrinsicsFeature( + () => Assert.True(false), + HwIntrinsics.DisableAVX); + } + [Theory] [MemberData(nameof(Intrinsics))] public void ToFeatureCollectionReturnsExpectedResult(HwIntrinsics expectedItrinsics, string[] expectedValues) From d3208ad354b14a253f217c1bf79c2271beb36b5e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:12:40 +0100 Subject: [PATCH 27/41] Increment tests --- .../Tests/FeatureTestRunnerTests.cs | 340 +++++++++--------- 1 file changed, 166 insertions(+), 174 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 070f205748..023679b2e0 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -23,14 +23,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { HwIntrinsics.DisableSSE42 | HwIntrinsics.DisableAVX, new string[] { "EnableSSE42", "EnableAVX" } } }; - [Fact] - public void TempAssertThrow() - { - FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.True(false), - HwIntrinsics.DisableAVX); - } - [Theory] [MemberData(nameof(Intrinsics))] public void ToFeatureCollectionReturnsExpectedResult(HwIntrinsics expectedItrinsics, string[] expectedValues) @@ -54,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests public void AllowsAllHwIntrinsicFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.True(Vector.IsHardwareAccelerated), + () => Assert.True(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), HwIntrinsics.AllowAll); } @@ -62,174 +54,174 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests public void CanLimitHwIntrinsicFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.False(Vector.IsHardwareAccelerated), + () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), HwIntrinsics.DisableSIMD); } - [Fact] - public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() - { - static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) - { - Assert.NotNull(intrinsic); - - switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) - { - case HwIntrinsics.DisableSIMD: - Assert.False(Vector.IsHardwareAccelerated); - break; -#if SUPPORTS_RUNTIME_INTRINSICS - case HwIntrinsics.DisableHWIntrinsic: - Assert.False(Vector.IsHardwareAccelerated); - break; - case HwIntrinsics.DisableSSE: - Assert.False(Sse.IsSupported); - break; - case HwIntrinsics.DisableSSE2: - Assert.False(Sse2.IsSupported); - break; - case HwIntrinsics.DisableAES: - Assert.False(Aes.IsSupported); - break; - case HwIntrinsics.DisablePCLMULQDQ: - Assert.False(Pclmulqdq.IsSupported); - break; - case HwIntrinsics.DisableSSE3: - Assert.False(Sse3.IsSupported); - break; - case HwIntrinsics.DisableSSSE3: - Assert.False(Ssse3.IsSupported); - break; - case HwIntrinsics.DisableSSE41: - Assert.False(Sse41.IsSupported); - break; - case HwIntrinsics.DisableSSE42: - Assert.False(Sse42.IsSupported); - break; - case HwIntrinsics.DisablePOPCNT: - Assert.False(Popcnt.IsSupported); - break; - case HwIntrinsics.DisableAVX: - Assert.False(Avx.IsSupported); - break; - case HwIntrinsics.DisableFMA: - Assert.False(Fma.IsSupported); - break; - case HwIntrinsics.DisableAVX2: - Assert.False(Avx2.IsSupported); - break; - case HwIntrinsics.DisableBMI1: - Assert.False(Bmi1.IsSupported); - break; - case HwIntrinsics.DisableBMI2: - Assert.False(Bmi2.IsSupported); - break; - case HwIntrinsics.DisableLZCNT: - Assert.False(Lzcnt.IsSupported); - break; -#endif - } - } - - foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - { - FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); - } - } - - [Fact] - public void CanLimitHwIntrinsicFeaturesWithSerializableParam() - { - static void AssertHwIntrinsicsFeatureDisabled(string serializable) - { - Assert.NotNull(serializable); - Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); - -#if SUPPORTS_RUNTIME_INTRINSICS - Assert.False(Sse.IsSupported); -#endif - } - - foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - { - FeatureTestRunner.RunWithHwIntrinsicsFeature( - AssertHwIntrinsicsFeatureDisabled, - HwIntrinsics.DisableSSE, - new FakeSerializable()); - } - } - - [Fact] - public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() - { - static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) - { - Assert.NotNull(serializable); - Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); - - switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) - { - case HwIntrinsics.DisableSIMD: - Assert.False(Vector.IsHardwareAccelerated); - break; -#if SUPPORTS_RUNTIME_INTRINSICS - case HwIntrinsics.DisableHWIntrinsic: - Assert.False(Vector.IsHardwareAccelerated); - break; - case HwIntrinsics.DisableSSE: - Assert.False(Sse.IsSupported); - break; - case HwIntrinsics.DisableSSE2: - Assert.False(Sse2.IsSupported); - break; - case HwIntrinsics.DisableAES: - Assert.False(Aes.IsSupported); - break; - case HwIntrinsics.DisablePCLMULQDQ: - Assert.False(Pclmulqdq.IsSupported); - break; - case HwIntrinsics.DisableSSE3: - Assert.False(Sse3.IsSupported); - break; - case HwIntrinsics.DisableSSSE3: - Assert.False(Ssse3.IsSupported); - break; - case HwIntrinsics.DisableSSE41: - Assert.False(Sse41.IsSupported); - break; - case HwIntrinsics.DisableSSE42: - Assert.False(Sse42.IsSupported); - break; - case HwIntrinsics.DisablePOPCNT: - Assert.False(Popcnt.IsSupported); - break; - case HwIntrinsics.DisableAVX: - Assert.False(Avx.IsSupported); - break; - case HwIntrinsics.DisableFMA: - Assert.False(Fma.IsSupported); - break; - case HwIntrinsics.DisableAVX2: - Assert.False(Avx2.IsSupported); - break; - case HwIntrinsics.DisableBMI1: - Assert.False(Bmi1.IsSupported); - break; - case HwIntrinsics.DisableBMI2: - Assert.False(Bmi2.IsSupported); - break; - case HwIntrinsics.DisableLZCNT: - Assert.False(Lzcnt.IsSupported); - break; -#endif - } - } - - foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - { - FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); - } - } + // [Fact] + // public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() + // { + // static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) + // { + // Assert.NotNull(intrinsic); + + // switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + // { + // case HwIntrinsics.DisableSIMD: + // Assert.False(Vector.IsHardwareAccelerated); + // break; + //#if SUPPORTS_RUNTIME_INTRINSICS + // case HwIntrinsics.DisableHWIntrinsic: + // Assert.False(Vector.IsHardwareAccelerated); + // break; + // case HwIntrinsics.DisableSSE: + // Assert.False(Sse.IsSupported); + // break; + // case HwIntrinsics.DisableSSE2: + // Assert.False(Sse2.IsSupported); + // break; + // case HwIntrinsics.DisableAES: + // Assert.False(Aes.IsSupported); + // break; + // case HwIntrinsics.DisablePCLMULQDQ: + // Assert.False(Pclmulqdq.IsSupported); + // break; + // case HwIntrinsics.DisableSSE3: + // Assert.False(Sse3.IsSupported); + // break; + // case HwIntrinsics.DisableSSSE3: + // Assert.False(Ssse3.IsSupported); + // break; + // case HwIntrinsics.DisableSSE41: + // Assert.False(Sse41.IsSupported); + // break; + // case HwIntrinsics.DisableSSE42: + // Assert.False(Sse42.IsSupported); + // break; + // case HwIntrinsics.DisablePOPCNT: + // Assert.False(Popcnt.IsSupported); + // break; + // case HwIntrinsics.DisableAVX: + // Assert.False(Avx.IsSupported); + // break; + // case HwIntrinsics.DisableFMA: + // Assert.False(Fma.IsSupported); + // break; + // case HwIntrinsics.DisableAVX2: + // Assert.False(Avx2.IsSupported); + // break; + // case HwIntrinsics.DisableBMI1: + // Assert.False(Bmi1.IsSupported); + // break; + // case HwIntrinsics.DisableBMI2: + // Assert.False(Bmi2.IsSupported); + // break; + // case HwIntrinsics.DisableLZCNT: + // Assert.False(Lzcnt.IsSupported); + // break; + //#endif + // } + // } + + // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + // { + // FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); + // } + // } + + // [Fact] + // public void CanLimitHwIntrinsicFeaturesWithSerializableParam() + // { + // static void AssertHwIntrinsicsFeatureDisabled(string serializable) + // { + // Assert.NotNull(serializable); + // Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + + //#if SUPPORTS_RUNTIME_INTRINSICS + // Assert.False(Sse.IsSupported); + //#endif + // } + + // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + // { + // FeatureTestRunner.RunWithHwIntrinsicsFeature( + // AssertHwIntrinsicsFeatureDisabled, + // HwIntrinsics.DisableSSE, + // new FakeSerializable()); + // } + // } + + // [Fact] + // public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() + // { + // static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) + // { + // Assert.NotNull(serializable); + // Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + + // switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + // { + // case HwIntrinsics.DisableSIMD: + // Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); + // break; + //#if SUPPORTS_RUNTIME_INTRINSICS + // case HwIntrinsics.DisableHWIntrinsic: + // Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); + // break; + // case HwIntrinsics.DisableSSE: + // Assert.False(Sse.IsSupported); + // break; + // case HwIntrinsics.DisableSSE2: + // Assert.False(Sse2.IsSupported); + // break; + // case HwIntrinsics.DisableAES: + // Assert.False(Aes.IsSupported); + // break; + // case HwIntrinsics.DisablePCLMULQDQ: + // Assert.False(Pclmulqdq.IsSupported); + // break; + // case HwIntrinsics.DisableSSE3: + // Assert.False(Sse3.IsSupported); + // break; + // case HwIntrinsics.DisableSSSE3: + // Assert.False(Ssse3.IsSupported); + // break; + // case HwIntrinsics.DisableSSE41: + // Assert.False(Sse41.IsSupported); + // break; + // case HwIntrinsics.DisableSSE42: + // Assert.False(Sse42.IsSupported); + // break; + // case HwIntrinsics.DisablePOPCNT: + // Assert.False(Popcnt.IsSupported); + // break; + // case HwIntrinsics.DisableAVX: + // Assert.False(Avx.IsSupported); + // break; + // case HwIntrinsics.DisableFMA: + // Assert.False(Fma.IsSupported); + // break; + // case HwIntrinsics.DisableAVX2: + // Assert.False(Avx2.IsSupported); + // break; + // case HwIntrinsics.DisableBMI1: + // Assert.False(Bmi1.IsSupported); + // break; + // case HwIntrinsics.DisableBMI2: + // Assert.False(Bmi2.IsSupported); + // break; + // case HwIntrinsics.DisableLZCNT: + // Assert.False(Lzcnt.IsSupported); + // break; + //#endif + // } + // } + + // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + // { + // FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); + // } + // } public class FakeSerializable : IXunitSerializable { From 5e53e8363d7d5f27bfa07ac561b5a4f63dbaf95e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:22:08 +0100 Subject: [PATCH 28/41] Fix COMPlus environmental parameters --- .../TestUtilities/FeatureTesting/FeatureTestRunner.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs index 57ed85a182..a053471394 100644 --- a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs +++ b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; RemoteExecutor.Invoke( action, @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; RemoteExecutor.Invoke( action, @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; RemoteExecutor.Invoke( action, @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_Enable{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; RemoteExecutor.Invoke( action, From e794901bf6cf802f90d9c5fd8dac9e4bf0f4272d Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:30:11 +0100 Subject: [PATCH 29/41] Test another property to be sure --- .../TestUtilities/Tests/FeatureTestRunnerTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 023679b2e0..13a0806129 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -50,13 +50,15 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests HwIntrinsics.AllowAll); } +#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CanLimitHwIntrinsicFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), - HwIntrinsics.DisableSIMD); + () => Assert.False(Sse.IsSupported, nameof(Sse.IsSupported)), + HwIntrinsics.DisableSSE); } +#endif // [Fact] // public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() From 54836a623bf27c2b97e8abbc159cd60fe077dbfe Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:44:35 +0100 Subject: [PATCH 30/41] Fix COMPlus value properly. --- .../TestUtilities/FeatureTesting/FeatureTestRunner.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs index a053471394..eb1714baad 100644 --- a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs +++ b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; RemoteExecutor.Invoke( action, @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; RemoteExecutor.Invoke( action, @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; RemoteExecutor.Invoke( action, @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities var processStartInfo = new ProcessStartInfo(); if (intrinsic.Key != HwIntrinsics.AllowAll) { - processStartInfo.Environment[$"COMPlus_{intrinsic}"] = "0"; + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; RemoteExecutor.Invoke( action, From 13b570dd02c57caa059fdcb169124a26d641dae6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:50:22 +0100 Subject: [PATCH 31/41] Test FeatureSIMD --- .../TestUtilities/Tests/FeatureTestRunnerTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 13a0806129..eb6f82885f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -55,8 +55,8 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests public void CanLimitHwIntrinsicFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.False(Sse.IsSupported, nameof(Sse.IsSupported)), - HwIntrinsics.DisableSSE); + () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), + HwIntrinsics.DisableSIMD); } #endif From b90cac23dfa8214aa2ffb91e73326d2741984f12 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 22:55:46 +0100 Subject: [PATCH 32/41] Now test both disable values. --- .../TestUtilities/Tests/FeatureTestRunnerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index eb6f82885f..0f6cdc066a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { FeatureTestRunner.RunWithHwIntrinsicsFeature( () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), - HwIntrinsics.DisableSIMD); + HwIntrinsics.DisableSIMD | HwIntrinsics.DisableHWIntrinsic); } #endif From 54ea7d669099b55d1421b9bf94e141958d02e6d6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 23:08:27 +0100 Subject: [PATCH 33/41] Split base disabled checks --- .../Tests/FeatureTestRunnerTests.cs | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 0f6cdc066a..8eb5c9fd62 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -50,13 +50,40 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests HwIntrinsics.AllowAll); } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] - public void CanLimitHwIntrinsicFeatures() + public void CanLimitHwIntrinsicSIMDFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), - HwIntrinsics.DisableSIMD | HwIntrinsics.DisableHWIntrinsic); + HwIntrinsics.DisableSIMD); + } + +#if SUPPORTS_RUNTIME_INTRINSICS + [Fact] + public void CanLimitHwIntrinsicBaseFeatures() + { + static void AssertDisabled() + { + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + AssertDisabled, + HwIntrinsics.DisableHWIntrinsic); } #endif From 911d28993cfd3a30304afb2b9e327f941a8afc35 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 23:16:00 +0100 Subject: [PATCH 34/41] Enable additional tests --- .../Tests/FeatureTestRunnerTests.cs | 341 ++++++++++-------- 1 file changed, 183 insertions(+), 158 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index 8eb5c9fd62..eea22592bc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests public void AllowsAllHwIntrinsicFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.True(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), + () => Assert.True(Vector.IsHardwareAccelerated), HwIntrinsics.AllowAll); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests public void CanLimitHwIntrinsicSIMDFeatures() { FeatureTestRunner.RunWithHwIntrinsicsFeature( - () => Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)), + () => Assert.False(Vector.IsHardwareAccelerated), HwIntrinsics.DisableSIMD); } @@ -87,170 +87,195 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests } #endif - // [Fact] - // public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() - // { - // static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) - // { - // Assert.NotNull(intrinsic); + [Fact] + public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) + { + Assert.NotNull(intrinsic); - // switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) - // { - // case HwIntrinsics.DisableSIMD: - // Assert.False(Vector.IsHardwareAccelerated); - // break; - //#if SUPPORTS_RUNTIME_INTRINSICS - // case HwIntrinsics.DisableHWIntrinsic: - // Assert.False(Vector.IsHardwareAccelerated); - // break; - // case HwIntrinsics.DisableSSE: - // Assert.False(Sse.IsSupported); - // break; - // case HwIntrinsics.DisableSSE2: - // Assert.False(Sse2.IsSupported); - // break; - // case HwIntrinsics.DisableAES: - // Assert.False(Aes.IsSupported); - // break; - // case HwIntrinsics.DisablePCLMULQDQ: - // Assert.False(Pclmulqdq.IsSupported); - // break; - // case HwIntrinsics.DisableSSE3: - // Assert.False(Sse3.IsSupported); - // break; - // case HwIntrinsics.DisableSSSE3: - // Assert.False(Ssse3.IsSupported); - // break; - // case HwIntrinsics.DisableSSE41: - // Assert.False(Sse41.IsSupported); - // break; - // case HwIntrinsics.DisableSSE42: - // Assert.False(Sse42.IsSupported); - // break; - // case HwIntrinsics.DisablePOPCNT: - // Assert.False(Popcnt.IsSupported); - // break; - // case HwIntrinsics.DisableAVX: - // Assert.False(Avx.IsSupported); - // break; - // case HwIntrinsics.DisableFMA: - // Assert.False(Fma.IsSupported); - // break; - // case HwIntrinsics.DisableAVX2: - // Assert.False(Avx2.IsSupported); - // break; - // case HwIntrinsics.DisableBMI1: - // Assert.False(Bmi1.IsSupported); - // break; - // case HwIntrinsics.DisableBMI2: - // Assert.False(Bmi2.IsSupported); - // break; - // case HwIntrinsics.DisableLZCNT: - // Assert.False(Lzcnt.IsSupported); - // break; - //#endif - // } - // } + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } - // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - // { - // FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); - // } - // } + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); + } + } - // [Fact] - // public void CanLimitHwIntrinsicFeaturesWithSerializableParam() - // { - // static void AssertHwIntrinsicsFeatureDisabled(string serializable) - // { - // Assert.NotNull(serializable); - // Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); - //#if SUPPORTS_RUNTIME_INTRINSICS - // Assert.False(Sse.IsSupported); - //#endif - // } +#if SUPPORTS_RUNTIME_INTRINSICS + Assert.False(Sse.IsSupported); +#endif + } - // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - // { - // FeatureTestRunner.RunWithHwIntrinsicsFeature( - // AssertHwIntrinsicsFeatureDisabled, - // HwIntrinsics.DisableSSE, - // new FakeSerializable()); - // } - // } + FeatureTestRunner.RunWithHwIntrinsicsFeature( + AssertHwIntrinsicsFeatureDisabled, + HwIntrinsics.DisableSSE, + new FakeSerializable()); + } - // [Fact] - // public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() - // { - // static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) - // { - // Assert.NotNull(serializable); - // Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.Deserialize(serializable)); - // switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) - // { - // case HwIntrinsics.DisableSIMD: - // Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); - // break; - //#if SUPPORTS_RUNTIME_INTRINSICS - // case HwIntrinsics.DisableHWIntrinsic: - // Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); - // break; - // case HwIntrinsics.DisableSSE: - // Assert.False(Sse.IsSupported); - // break; - // case HwIntrinsics.DisableSSE2: - // Assert.False(Sse2.IsSupported); - // break; - // case HwIntrinsics.DisableAES: - // Assert.False(Aes.IsSupported); - // break; - // case HwIntrinsics.DisablePCLMULQDQ: - // Assert.False(Pclmulqdq.IsSupported); - // break; - // case HwIntrinsics.DisableSSE3: - // Assert.False(Sse3.IsSupported); - // break; - // case HwIntrinsics.DisableSSSE3: - // Assert.False(Ssse3.IsSupported); - // break; - // case HwIntrinsics.DisableSSE41: - // Assert.False(Sse41.IsSupported); - // break; - // case HwIntrinsics.DisableSSE42: - // Assert.False(Sse42.IsSupported); - // break; - // case HwIntrinsics.DisablePOPCNT: - // Assert.False(Popcnt.IsSupported); - // break; - // case HwIntrinsics.DisableAVX: - // Assert.False(Avx.IsSupported); - // break; - // case HwIntrinsics.DisableFMA: - // Assert.False(Fma.IsSupported); - // break; - // case HwIntrinsics.DisableAVX2: - // Assert.False(Avx2.IsSupported); - // break; - // case HwIntrinsics.DisableBMI1: - // Assert.False(Bmi1.IsSupported); - // break; - // case HwIntrinsics.DisableBMI2: - // Assert.False(Bmi2.IsSupported); - // break; - // case HwIntrinsics.DisableLZCNT: - // Assert.False(Lzcnt.IsSupported); - // break; - //#endif - // } - // } + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } - // foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) - // { - // FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); - // } - // } + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); + } + } public class FakeSerializable : IXunitSerializable { From e6c73e4b2b28a0e99b6e5f688d4536acd5da2be3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Oct 2020 23:31:56 +0100 Subject: [PATCH 35/41] Update PngEncoderTests.cs --- .../Formats/Png/PngEncoderTests.cs | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index b35e55887c..9ba956d722 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -2,13 +2,8 @@ // Licensed under the Apache License, Version 2.0. // ReSharper disable InconsistentNaming -using System.Diagnostics; using System.IO; using System.Linq; -#if SUPPORTS_RUNTIME_INTRINSICS -using System.Runtime.Intrinsics.X86; -#endif -using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Metadata; @@ -16,7 +11,6 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png @@ -538,13 +532,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) { - static void RunTest(string providerDump) + static void RunTest(string serialized) { TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); -#if SUPPORTS_RUNTIME_INTRINSICS - Assert.False(Ssse3.IsSupported); -#endif + FeatureTestRunner.Deserialize>(serialized); foreach (PngInterlaceMode interlaceMode in InterlaceMode) { @@ -559,19 +550,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } - string providerDump = BasicSerializer.Serialize(provider); - - var processStartInfo = new ProcessStartInfo(); - processStartInfo.Environment[TestEnvironment.Features.EnableSSE3] = TestEnvironment.Features.Off; - - RemoteExecutor.Invoke( + FeatureTestRunner.RunWithHwIntrinsicsFeature( RunTest, - providerDump, - new RemoteInvokeOptions - { - StartInfo = processStartInfo - }) - .Dispose(); + HwIntrinsics.DisableSSSE3, + provider); } private static void TestPngEncoderCore( From ec36095092e207ba51267444d3dedbee11aed76f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 00:06:31 +0100 Subject: [PATCH 36/41] Use envonment aware benchmarking for intrinsics. --- .../BlockOperations/Block8x8F_Transpose.cs | 16 +--- .../Config.HwIntrinsics.cs | 81 +++++++++++++++++++ tests/ImageSharp.Benchmarks/Config.cs | 2 +- .../TestUtilities/TestEnvironment.Features.cs | 54 ------------- 4 files changed, 86 insertions(+), 67 deletions(-) create mode 100644 tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs delete mode 100644 tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs index ae1b23df92..814c910383 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs @@ -6,26 +6,18 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations { + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class Block8x8F_Transpose { private static readonly Block8x8F Source = Create8x8FloatData(); - [Benchmark(Baseline=true)] - public void TransposeIntoVector4() + [Benchmark(Baseline = true)] + public void TransposeInto() { var dest = default(Block8x8F); - Source.TransposeIntoFallback(ref dest); + Source.TransposeInto(ref dest); } -#if SUPPORTS_RUNTIME_INTRINSICS - [Benchmark] - public void TransposeIntoAvx() - { - var dest = default(Block8x8F); - Source.TransposeIntoAvx(ref dest); - } -#endif - private static Block8x8F Create8x8FloatData() { var result = new float[64]; diff --git a/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs new file mode 100644 index 0000000000..e860c5491f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs @@ -0,0 +1,81 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif +using BenchmarkDotNet.Environments; +using BenchmarkDotNet.Jobs; + +namespace SixLabors.ImageSharp.Benchmarks +{ + public partial class Config + { + private const string On = "1"; + private const string Off = "0"; + + // See https://github.com/SixLabors/ImageSharp/pull/1229#discussion_r440477861 + // * EnableHWIntrinsic + // * EnableSSE + // * EnableSSE2 + // * EnableAES + // * EnablePCLMULQDQ + // * EnableSSE3 + // * EnableSSSE3 + // * EnableSSE41 + // * EnableSSE42 + // * EnablePOPCNT + // * EnableAVX + // * EnableFMA + // * EnableAVX2 + // * EnableBMI1 + // * EnableBMI2 + // * EnableLZCNT + // + // `FeatureSIMD` ends up impacting all SIMD support(including `System.Numerics`) but not things + // like `LZCNT`, `BMI1`, or `BMI2` + // `EnableSSE3_4` is a legacy switch that exists for compat and is basically the same as `EnableSSE3` + private const string EnableAES = "COMPlus_EnableAES"; + private const string EnableAVX = "COMPlus_EnableAVX"; + private const string EnableAVX2 = "COMPlus_EnableAVX2"; + private const string EnableBMI1 = "COMPlus_EnableBMI1"; + private const string EnableBMI2 = "COMPlus_EnableBMI2"; + private const string EnableFMA = "COMPlus_EnableFMA"; + private const string EnableHWIntrinsic = "COMPlus_EnableHWIntrinsic"; + private const string EnableLZCNT = "COMPlus_EnableLZCNT"; + private const string EnablePCLMULQDQ = "COMPlus_EnablePCLMULQDQ"; + private const string EnablePOPCNT = "COMPlus_EnablePOPCNT"; + private const string EnableSSE = "COMPlus_EnableSSE"; + private const string EnableSSE2 = "COMPlus_EnableSSE2"; + private const string EnableSSE3 = "COMPlus_EnableSSE3"; + private const string EnableSSE3_4 = "COMPlus_EnableSSE3_4"; + private const string EnableSSE41 = "COMPlus_EnableSSE41"; + private const string EnableSSE42 = "COMPlus_EnableSSE42"; + private const string EnableSSSE3 = "COMPlus_EnableSSSE3"; + private const string FeatureSIMD = "COMPlus_FeatureSIMD"; + + public class HwIntrinsics_SSE_AVX : Config + { + public HwIntrinsics_SSE_AVX() + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithId("AVX").AsBaseline()); + } + + if (Sse.IsSupported) + { + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithEnvironmentVariables(new EnvironmentVariable(EnableAVX, Off)) + .WithId("SSE")); + } +#endif + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithEnvironmentVariables(new EnvironmentVariable(EnableHWIntrinsic, Off)) + .WithId("No HwIntrinsics")); + } + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Config.cs b/tests/ImageSharp.Benchmarks/Config.cs index f9240779b9..53271f522d 100644 --- a/tests/ImageSharp.Benchmarks/Config.cs +++ b/tests/ImageSharp.Benchmarks/Config.cs @@ -12,7 +12,7 @@ using BenchmarkDotNet.Jobs; namespace SixLabors.ImageSharp.Benchmarks { - public class Config : ManualConfig + public partial class Config : ManualConfig { public Config() { diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs deleted file mode 100644 index 3568c1e5dc..0000000000 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Tests -{ - public static partial class TestEnvironment - { - internal static class Features - { - public const string On = "1"; - public const string Off = "0"; - - // See https://github.com/SixLabors/ImageSharp/pull/1229#discussion_r440477861 - // * EnableHWIntrinsic - // * EnableSSE - // * EnableSSE2 - // * EnableAES - // * EnablePCLMULQDQ - // * EnableSSE3 - // * EnableSSSE3 - // * EnableSSE41 - // * EnableSSE42 - // * EnablePOPCNT - // * EnableAVX - // * EnableFMA - // * EnableAVX2 - // * EnableBMI1 - // * EnableBMI2 - // * EnableLZCNT - // - // `FeatureSIMD` ends up impacting all SIMD support(including `System.Numerics`) but not things - // like `LZCNT`, `BMI1`, or `BMI2` - // `EnableSSE3_4` is a legacy switch that exists for compat and is basically the same as `EnableSSE3` - public const string EnableAES = "COMPlus_EnableAES"; - public const string EnableAVX = "COMPlus_EnableAVX"; - public const string EnableAVX2 = "COMPlus_EnableAVX2"; - public const string EnableBMI1 = "COMPlus_EnableBMI1"; - public const string EnableBMI2 = "COMPlus_EnableBMI2"; - public const string EnableFMA = "COMPlus_EnableFMA"; - public const string EnableHWIntrinsic = "COMPlus_EnableHWIntrinsic"; - public const string EnableLZCNT = "COMPlus_EnableLZCNT"; - public const string EnablePCLMULQDQ = "COMPlus_EnablePCLMULQDQ"; - public const string EnablePOPCNT = "COMPlus_EnablePOPCNT"; - public const string EnableSSE = "COMPlus_EnableSSE"; - public const string EnableSSE2 = "COMPlus_EnableSSE2"; - public const string EnableSSE3 = "COMPlus_EnableSSE3"; - public const string EnableSSE3_4 = "COMPlus_EnableSSE3_4"; - public const string EnableSSE41 = "COMPlus_EnableSSE41"; - public const string EnableSSE42 = "COMPlus_EnableSSE42"; - public const string EnableSSSE3 = "COMPlus_EnableSSSE3"; - public const string FeatureSIMD = "COMPlus_FeatureSIMD"; - } - } -} From 75e0ffc522bd28245384fe81ee6e2af459662dd1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 00:14:47 +0100 Subject: [PATCH 37/41] Use a single method for Block8x8F.TransposeInto. --- .../Jpeg/Components/Block8x8F.Generated.cs | 80 ------- .../Jpeg/Components/Block8x8F.Generated.tt | 32 --- .../Formats/Jpeg/Components/Block8x8F.cs | 211 +++++++++++------- 3 files changed, 135 insertions(+), 188 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 10cbee5e6f..6a336ad2b4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -10,86 +10,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - /// - /// Fallback method to transpose a block into the destination block on non AVX supported CPUs. - /// - /// The destination block - [MethodImpl(InliningOptions.ShortMethod)] - public void TransposeIntoFallback(ref Block8x8F d) - { - d.V0L.X = V0L.X; - d.V1L.X = V0L.Y; - d.V2L.X = V0L.Z; - d.V3L.X = V0L.W; - d.V4L.X = V0R.X; - d.V5L.X = V0R.Y; - d.V6L.X = V0R.Z; - d.V7L.X = V0R.W; - - d.V0L.Y = V1L.X; - d.V1L.Y = V1L.Y; - d.V2L.Y = V1L.Z; - d.V3L.Y = V1L.W; - d.V4L.Y = V1R.X; - d.V5L.Y = V1R.Y; - d.V6L.Y = V1R.Z; - d.V7L.Y = V1R.W; - - d.V0L.Z = V2L.X; - d.V1L.Z = V2L.Y; - d.V2L.Z = V2L.Z; - d.V3L.Z = V2L.W; - d.V4L.Z = V2R.X; - d.V5L.Z = V2R.Y; - d.V6L.Z = V2R.Z; - d.V7L.Z = V2R.W; - - d.V0L.W = V3L.X; - d.V1L.W = V3L.Y; - d.V2L.W = V3L.Z; - d.V3L.W = V3L.W; - d.V4L.W = V3R.X; - d.V5L.W = V3R.Y; - d.V6L.W = V3R.Z; - d.V7L.W = V3R.W; - - d.V0R.X = V4L.X; - d.V1R.X = V4L.Y; - d.V2R.X = V4L.Z; - d.V3R.X = V4L.W; - d.V4R.X = V4R.X; - d.V5R.X = V4R.Y; - d.V6R.X = V4R.Z; - d.V7R.X = V4R.W; - - d.V0R.Y = V5L.X; - d.V1R.Y = V5L.Y; - d.V2R.Y = V5L.Z; - d.V3R.Y = V5L.W; - d.V4R.Y = V5R.X; - d.V5R.Y = V5R.Y; - d.V6R.Y = V5R.Z; - d.V7R.Y = V5R.W; - - d.V0R.Z = V6L.X; - d.V1R.Z = V6L.Y; - d.V2R.Z = V6L.Z; - d.V3R.Z = V6L.W; - d.V4R.Z = V6R.X; - d.V5R.Z = V6R.Y; - d.V6R.Z = V6R.Z; - d.V7R.Z = V6R.W; - - d.V0R.W = V7L.X; - d.V1R.W = V7L.Y; - d.V2R.W = V7L.Z; - d.V3R.W = V7L.W; - d.V4R.W = V7R.X; - d.V5R.W = V7R.Y; - d.V6R.W = V7R.Z; - d.V7R.W = V7R.W; - } - /// /// Level shift by +maximum/2, clip to [0, maximum] /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index f47d9106ee..26cd5c2ac4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -23,38 +23,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - /// - /// Fallback method to transpose a block into the destination block on non AVX supported CPUs. - /// - /// The destination block - [MethodImpl(InliningOptions.ShortMethod)] - public void TransposeIntoFallback(ref Block8x8F d) - { - <# - PushIndent(" "); - - for (int i = 0; i < 8; i++) - { - char destCoord = coordz[i % 4]; - char destSide = (i / 4) % 2 == 0 ? 'L' : 'R'; - - for (int j = 0; j < 8; j++) - { - if(i > 0 && j == 0){ - WriteLine(""); - } - - char srcCoord = coordz[j % 4]; - char srcSide = (j / 4) % 2 == 0 ? 'L' : 'R'; - - var expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord};\r\n"; - Write(expression); - } - } - PopIndent(); - #> - } - /// /// Level shift by +maximum/2, clip to [0, maximum] /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 547e116230..ccdba48857 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -611,87 +611,146 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components #if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { - this.TransposeIntoAvx(ref d); + // https://stackoverflow.com/questions/25622745/transpose-an-8x8-float-using-avx-avx2/25627536#25627536 + Vector256 r0 = Avx.InsertVector128( + Unsafe.As>(ref this.V0L).ToVector256(), + Unsafe.As>(ref this.V4L), + 1); + + Vector256 r1 = Avx.InsertVector128( + Unsafe.As>(ref this.V1L).ToVector256(), + Unsafe.As>(ref this.V5L), + 1); + + Vector256 r2 = Avx.InsertVector128( + Unsafe.As>(ref this.V2L).ToVector256(), + Unsafe.As>(ref this.V6L), + 1); + + Vector256 r3 = Avx.InsertVector128( + Unsafe.As>(ref this.V3L).ToVector256(), + Unsafe.As>(ref this.V7L), + 1); + + Vector256 r4 = Avx.InsertVector128( + Unsafe.As>(ref this.V0R).ToVector256(), + Unsafe.As>(ref this.V4R), + 1); + + Vector256 r5 = Avx.InsertVector128( + Unsafe.As>(ref this.V1R).ToVector256(), + Unsafe.As>(ref this.V5R), + 1); + + Vector256 r6 = Avx.InsertVector128( + Unsafe.As>(ref this.V2R).ToVector256(), + Unsafe.As>(ref this.V6R), + 1); + + Vector256 r7 = Avx.InsertVector128( + Unsafe.As>(ref this.V3R).ToVector256(), + Unsafe.As>(ref this.V7R), + 1); + + Vector256 t0 = Avx.UnpackLow(r0, r1); + Vector256 t2 = Avx.UnpackLow(r2, r3); + Vector256 v = Avx.Shuffle(t0, t2, 0x4E); + Unsafe.As>(ref d.V0L) = Avx.Blend(t0, v, 0xCC); + Unsafe.As>(ref d.V1L) = Avx.Blend(t2, v, 0x33); + + Vector256 t4 = Avx.UnpackLow(r4, r5); + Vector256 t6 = Avx.UnpackLow(r6, r7); + v = Avx.Shuffle(t4, t6, 0x4E); + Unsafe.As>(ref d.V4L) = Avx.Blend(t4, v, 0xCC); + Unsafe.As>(ref d.V5L) = Avx.Blend(t6, v, 0x33); + + Vector256 t1 = Avx.UnpackHigh(r0, r1); + Vector256 t3 = Avx.UnpackHigh(r2, r3); + v = Avx.Shuffle(t1, t3, 0x4E); + Unsafe.As>(ref d.V2L) = Avx.Blend(t1, v, 0xCC); + Unsafe.As>(ref d.V3L) = Avx.Blend(t3, v, 0x33); + + Vector256 t5 = Avx.UnpackHigh(r4, r5); + Vector256 t7 = Avx.UnpackHigh(r6, r7); + v = Avx.Shuffle(t5, t7, 0x4E); + Unsafe.As>(ref d.V6L) = Avx.Blend(t5, v, 0xCC); + Unsafe.As>(ref d.V7L) = Avx.Blend(t7, v, 0x33); } else #endif { - this.TransposeIntoFallback(ref d); + d.V0L.X = this.V0L.X; + d.V1L.X = this.V0L.Y; + d.V2L.X = this.V0L.Z; + d.V3L.X = this.V0L.W; + d.V4L.X = this.V0R.X; + d.V5L.X = this.V0R.Y; + d.V6L.X = this.V0R.Z; + d.V7L.X = this.V0R.W; + + d.V0L.Y = this.V1L.X; + d.V1L.Y = this.V1L.Y; + d.V2L.Y = this.V1L.Z; + d.V3L.Y = this.V1L.W; + d.V4L.Y = this.V1R.X; + d.V5L.Y = this.V1R.Y; + d.V6L.Y = this.V1R.Z; + d.V7L.Y = this.V1R.W; + + d.V0L.Z = this.V2L.X; + d.V1L.Z = this.V2L.Y; + d.V2L.Z = this.V2L.Z; + d.V3L.Z = this.V2L.W; + d.V4L.Z = this.V2R.X; + d.V5L.Z = this.V2R.Y; + d.V6L.Z = this.V2R.Z; + d.V7L.Z = this.V2R.W; + + d.V0L.W = this.V3L.X; + d.V1L.W = this.V3L.Y; + d.V2L.W = this.V3L.Z; + d.V3L.W = this.V3L.W; + d.V4L.W = this.V3R.X; + d.V5L.W = this.V3R.Y; + d.V6L.W = this.V3R.Z; + d.V7L.W = this.V3R.W; + + d.V0R.X = this.V4L.X; + d.V1R.X = this.V4L.Y; + d.V2R.X = this.V4L.Z; + d.V3R.X = this.V4L.W; + d.V4R.X = this.V4R.X; + d.V5R.X = this.V4R.Y; + d.V6R.X = this.V4R.Z; + d.V7R.X = this.V4R.W; + + d.V0R.Y = this.V5L.X; + d.V1R.Y = this.V5L.Y; + d.V2R.Y = this.V5L.Z; + d.V3R.Y = this.V5L.W; + d.V4R.Y = this.V5R.X; + d.V5R.Y = this.V5R.Y; + d.V6R.Y = this.V5R.Z; + d.V7R.Y = this.V5R.W; + + d.V0R.Z = this.V6L.X; + d.V1R.Z = this.V6L.Y; + d.V2R.Z = this.V6L.Z; + d.V3R.Z = this.V6L.W; + d.V4R.Z = this.V6R.X; + d.V5R.Z = this.V6R.Y; + d.V6R.Z = this.V6R.Z; + d.V7R.Z = this.V6R.W; + + d.V0R.W = this.V7L.X; + d.V1R.W = this.V7L.Y; + d.V2R.W = this.V7L.Z; + d.V3R.W = this.V7L.W; + d.V4R.W = this.V7R.X; + d.V5R.W = this.V7R.Y; + d.V6R.W = this.V7R.Z; + d.V7R.W = this.V7R.W; } } - -#if SUPPORTS_RUNTIME_INTRINSICS - /// - /// AVX-only variant for executing . - /// - /// - [MethodImpl(InliningOptions.ShortMethod)] - public void TransposeIntoAvx(ref Block8x8F d) - { - Vector256 r0 = Avx.InsertVector128( - Unsafe.As>(ref this.V0L).ToVector256(), - Unsafe.As>(ref this.V4L), - 1); - - Vector256 r1 = Avx.InsertVector128( - Unsafe.As>(ref this.V1L).ToVector256(), - Unsafe.As>(ref this.V5L), - 1); - - Vector256 r2 = Avx.InsertVector128( - Unsafe.As>(ref this.V2L).ToVector256(), - Unsafe.As>(ref this.V6L), - 1); - - Vector256 r3 = Avx.InsertVector128( - Unsafe.As>(ref this.V3L).ToVector256(), - Unsafe.As>(ref this.V7L), - 1); - - Vector256 r4 = Avx.InsertVector128( - Unsafe.As>(ref this.V0R).ToVector256(), - Unsafe.As>(ref this.V4R), - 1); - - Vector256 r5 = Avx.InsertVector128( - Unsafe.As>(ref this.V1R).ToVector256(), - Unsafe.As>(ref this.V5R), - 1); - - Vector256 r6 = Avx.InsertVector128( - Unsafe.As>(ref this.V2R).ToVector256(), - Unsafe.As>(ref this.V6R), - 1); - - Vector256 r7 = Avx.InsertVector128( - Unsafe.As>(ref this.V3R).ToVector256(), - Unsafe.As>(ref this.V7R), - 1); - - Vector256 t0 = Avx.UnpackLow(r0, r1); - Vector256 t2 = Avx.UnpackLow(r2, r3); - Vector256 v = Avx.Shuffle(t0, t2, 0x4E); - Unsafe.As>(ref d.V0L) = Avx.Blend(t0, v, 0xCC); - Unsafe.As>(ref d.V1L) = Avx.Blend(t2, v, 0x33); - - Vector256 t4 = Avx.UnpackLow(r4, r5); - Vector256 t6 = Avx.UnpackLow(r6, r7); - v = Avx.Shuffle(t4, t6, 0x4E); - Unsafe.As>(ref d.V4L) = Avx.Blend(t4, v, 0xCC); - Unsafe.As>(ref d.V5L) = Avx.Blend(t6, v, 0x33); - - Vector256 t1 = Avx.UnpackHigh(r0, r1); - Vector256 t3 = Avx.UnpackHigh(r2, r3); - v = Avx.Shuffle(t1, t3, 0x4E); - Unsafe.As>(ref d.V2L) = Avx.Blend(t1, v, 0xCC); - Unsafe.As>(ref d.V3L) = Avx.Blend(t3, v, 0x33); - - Vector256 t5 = Avx.UnpackHigh(r4, r5); - Vector256 t7 = Avx.UnpackHigh(r6, r7); - v = Avx.Shuffle(t5, t7, 0x4E); - Unsafe.As>(ref d.V6L) = Avx.Blend(t5, v, 0xCC); - Unsafe.As>(ref d.V7L) = Avx.Blend(t7, v, 0x33); - } -#endif } } From a79e6d3425a53a17891997b6cc3147d5c0b5f02b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 00:20:41 +0100 Subject: [PATCH 38/41] Enable all test platforms --- .github/workflows/build-and-test.yml | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ecb5ceb0ef..c8f3997946 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,23 +17,23 @@ jobs: - os: ubuntu-latest framework: netcoreapp3.1 runtime: -x64 + codecov: true + - os: windows-latest + framework: netcoreapp3.1 + runtime: -x64 + codecov: false + - os: windows-latest + framework: netcoreapp2.1 + runtime: -x64 + codecov: false + - os: windows-latest + framework: net472 + runtime: -x64 + codecov: false + - os: windows-latest + framework: net472 + runtime: -x86 codecov: false - # - os: windows-latest - # framework: netcoreapp3.1 - # runtime: -x64 - # codecov: false - # - os: windows-latest - # framework: netcoreapp2.1 - # runtime: -x64 - # codecov: false - # - os: windows-latest - # framework: net472 - # runtime: -x64 - # codecov: false - # - os: windows-latest - # framework: net472 - # runtime: -x86 - # codecov: false runs-on: ${{matrix.options.os}} if: "!contains(github.event.head_commit.message, '[skip ci]')" From aad4c1e89e6372e4a0dc066aca85caa78d6127eb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 00:36:39 +0100 Subject: [PATCH 39/41] Remove method baseline property --- .../Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs index 814c910383..1d103cd1a0 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations { private static readonly Block8x8F Source = Create8x8FloatData(); - [Benchmark(Baseline = true)] + [Benchmark] public void TransposeInto() { var dest = default(Block8x8F); From 7b53df11c82e6500596a598b5769aa7c0f48c1ec Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 01:05:40 +0100 Subject: [PATCH 40/41] Fix incorrect test on NET 32bit --- .../TestUtilities/Tests/FeatureTestRunnerTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index eea22592bc..646000120f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -45,6 +45,11 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests [Fact] public void AllowsAllHwIntrinsicFeatures() { + if (!Vector.IsHardwareAccelerated) + { + return; + } + FeatureTestRunner.RunWithHwIntrinsicsFeature( () => Assert.True(Vector.IsHardwareAccelerated), HwIntrinsics.AllowAll); From 102876b60d417a1513eecbaf0d4c50f0cb856a7c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Oct 2020 22:18:00 +0100 Subject: [PATCH 41/41] Disable NetNative optimization on UWP. Fix #1204 --- ...lHistogramEqualizationProcessor{TPixel}.cs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index 19514c4b6f..274376671b 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -106,15 +106,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// +#if NETSTANDARD2_0 + // https://github.com/SixLabors/ImageSharp/issues/1204 + [MethodImpl(MethodImplOptions.NoOptimization)] +#else [MethodImpl(InliningOptions.ShortMethod)] +#endif public void Invoke(int y) { ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan()); ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + int levels = this.luminanceLevels; for (int x = 0; x < this.bounds.Width; x++) { - int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels); + // TODO: We should bulk convert here. + var vector = Unsafe.Add(ref pixelBase, x).ToVector4(); + int luminance = ImageMaths.GetBT709Luminance(ref vector, levels); Unsafe.Add(ref histogramBase, luminance)++; } } @@ -147,18 +155,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// +#if NETSTANDARD2_0 + // https://github.com/SixLabors/ImageSharp/issues/1204 + [MethodImpl(MethodImplOptions.NoOptimization)] +#else [MethodImpl(InliningOptions.ShortMethod)] +#endif public void Invoke(int y) { ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan()); ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + int levels = this.luminanceLevels; + float noOfPixelsMinusCdfMin = this.numberOfPixelsMinusCdfMin; for (int x = 0; x < this.bounds.Width; x++) { + // TODO: We should bulk convert here. ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); - int luminance = GetLuminance(pixel, this.luminanceLevels); - float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin; - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + var vector = pixel.ToVector4(); + int luminance = ImageMaths.GetBT709Luminance(ref vector, levels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / noOfPixelsMinusCdfMin; + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, vector.W)); } } }