diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs index 68956c880..3e6667dbc 100644 --- a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs @@ -12,9 +12,9 @@ namespace SixLabors.ImageSharp.Benchmarks; public class PorterDuffBulkVsPixel { - private Configuration Configuration => Configuration.Default; + private static Configuration Configuration => Configuration.Default; - private void BulkVectorConvert( + private static void BulkVectorConvert( Span destination, Span background, Span source, @@ -31,18 +31,18 @@ public class PorterDuffBulkVsPixel Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToVector4(this.Configuration, background, backgroundSpan); - PixelOperations.Instance.ToVector4(this.Configuration, source, sourceSpan); + PixelOperations.Instance.ToVector4(Configuration, background, backgroundSpan); + PixelOperations.Instance.ToVector4(Configuration, source, sourceSpan); for (int i = 0; i < destination.Length; i++) { destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } - PixelOperations.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination); + PixelOperations.Instance.FromVector4Destructive(Configuration, destinationSpan, destination); } - private void BulkPixelConvert( + private static void BulkPixelConvert( Span destination, Span background, Span source, @@ -60,9 +60,9 @@ public class PorterDuffBulkVsPixel } [Benchmark(Description = "ImageSharp BulkVectorConvert")] - public Size BulkVectorConvert() + public static Size BulkVectorConvert() { - using var image = new Image(800, 800); + using Image image = new(800, 800); using IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width); amounts.GetSpan().Fill(1); @@ -70,23 +70,23 @@ public class PorterDuffBulkVsPixel for (int y = 0; y < image.Height; y++) { Span span = pixels.DangerousGetRowSpan(y); - this.BulkVectorConvert(span, span, span, amounts.GetSpan()); + BulkVectorConvert(span, span, span, amounts.GetSpan()); } return new Size(image.Width, image.Height); } [Benchmark(Description = "ImageSharp BulkPixelConvert")] - public Size BulkPixelConvert() + public static Size BulkPixelConvert() { - using var image = new Image(800, 800); + using Image image = new(800, 800); using IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width); amounts.GetSpan().Fill(1); Buffer2D pixels = image.GetRootFramePixelBuffer(); for (int y = 0; y < image.Height; y++) { Span span = pixels.DangerousGetRowSpan(y); - this.BulkPixelConvert(span, span, span, amounts.GetSpan()); + BulkPixelConvert(span, span, span, amounts.GetSpan()); } return new Size(image.Width, image.Height); diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsSingleVector.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsSingleVector.cs new file mode 100644 index 000000000..6727f1c91 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsSingleVector.cs @@ -0,0 +1,68 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats.PixelBlenders; + +namespace SixLabors.ImageSharp.Benchmarks.PixelBlenders; + +public class PorterDuffBulkVsSingleVector +{ + private Vector4[] backdrop; + private Vector4[] source; + + [GlobalSetup] + public void Setup() + { + this.backdrop = new Vector4[8 * 20]; + this.source = new Vector4[8 * 20]; + + FillRandom(this.backdrop); + FillRandom(this.source); + } + + private static void FillRandom(Vector4[] arr) + { + Random rng = new(); + for (int i = 0; i < arr.Length; i++) + { + arr[i].X = rng.NextSingle(); + arr[i].Y = rng.NextSingle(); + arr[i].Z = rng.NextSingle(); + arr[i].W = rng.NextSingle(); + } + } + + [Benchmark(Description = "Scalar")] + public Vector4 OverlayValueFunction_Scalar() + { + Vector4 result = default; + for (int i = 0; i < this.backdrop.Length; i++) + { + result = PorterDuffFunctions.NormalSrcOver(this.backdrop[i], this.source[i], .5F); + } + + return result; + } + + [Benchmark(Description = "Avx")] + public Vector256 OverlayValueFunction_Avx() + { + ref Vector256 backdrop = ref Unsafe.As>(ref MemoryMarshal.GetReference(this.backdrop)); + ref Vector256 source = ref Unsafe.As>(ref MemoryMarshal.GetReference(this.backdrop)); + + Vector256 result = default; + Vector256 opacity = Vector256.Create(.5F); + int count = this.backdrop.Length / 2; + for (int i = 0; i < count; i++) + { + result = PorterDuffFunctions.NormalSrcOver(Unsafe.Add(ref backdrop, i), Unsafe.Add(ref source, i), opacity); + } + + return result; + } +}