Browse Source

Update benchmarks

pull/2645/head
James Jackson-South 2 years ago
parent
commit
7b93ee74d5
  1. 8
      tests/ImageSharp.Benchmarks/General/PixelConversion/ITestPixel.cs
  2. 184
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
  3. 37
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromVector4.cs
  4. 95
      tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs
  5. 69
      tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs
  6. 51
      tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgbaVector.cs

8
tests/ImageSharp.Benchmarks/General/PixelConversion/ITestPixel.cs

@ -11,19 +11,23 @@ public interface ITestPixel<T>
{
void FromRgba32(Rgba32 source);
static abstract T StaticFromRgba32(Rgba32 source);
void FromRgba32(ref Rgba32 source);
void FromBytes(byte r, byte g, byte b, byte a);
void FromVector4(Vector4 source);
static abstract T StaticFromVector4(Vector4 source);
void FromVector4(ref Vector4 source);
Rgba32 ToRgba32();
void CopyToRgba32(ref Rgba32 dest);
void CopyToRgba32(ref Rgba32 destination);
Vector4 ToVector4();
void CopyToVector4(ref Vector4 dest);
void CopyToVector4(ref Vector4 destination);
}

184
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs

@ -13,25 +13,25 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
public abstract class PixelConversion_ConvertFromRgba32
{
internal struct ConversionRunner<T>
internal readonly struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
public readonly T[] Dest;
public readonly T[] Destination;
public readonly Rgba32[] Source;
public ConversionRunner(int count)
{
this.Dest = new T[count];
this.Destination = new T[count];
this.Source = new Rgba32[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByRefConversion()
public readonly void RunByRefConversion()
{
int count = this.Dest.Length;
int count = this.Destination.Length;
ref T destBaseRef = ref this.Dest[0];
ref T destBaseRef = ref this.Destination[0];
ref Rgba32 sourceBaseRef = ref this.Source[0];
for (nuint i = 0; i < (uint)count; i++)
@ -41,11 +41,11 @@ public abstract class PixelConversion_ConvertFromRgba32
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByValConversion()
public readonly void RunByValConversion()
{
int count = this.Dest.Length;
int count = this.Destination.Length;
ref T destBaseRef = ref this.Dest[0];
ref T destBaseRef = ref this.Destination[0];
ref Rgba32 sourceBaseRef = ref this.Source[0];
for (nuint i = 0; i < (uint)count; i++)
@ -55,11 +55,25 @@ public abstract class PixelConversion_ConvertFromRgba32
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunFromBytesConversion()
public readonly void RunStaticByValConversion()
{
int count = this.Dest.Length;
int count = this.Destination.Length;
ref T destBaseRef = ref this.Dest[0];
ref T destBaseRef = ref this.Destination[0];
ref Rgba32 sourceBaseRef = ref this.Source[0];
for (nuint i = 0; i < (uint)count; i++)
{
Unsafe.Add(ref destBaseRef, i) = T.StaticFromRgba32(Unsafe.Add(ref sourceBaseRef, i));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void RunFromBytesConversion()
{
int count = this.Destination.Length;
ref T destBaseRef = ref this.Destination[0];
ref Rgba32 sourceBaseRef = ref this.Source[0];
for (nuint i = 0; i < (uint)count; i++)
@ -74,6 +88,8 @@ public abstract class PixelConversion_ConvertFromRgba32
internal ConversionRunner<TestArgb> PermutedRunnerRgbaToArgb;
internal ConversionRunner<TestRgbaVector> RunnerRgbaToRgbaVector;
[Params(256, 2048)]
public int Count { get; set; }
@ -82,34 +98,29 @@ public abstract class PixelConversion_ConvertFromRgba32
{
this.CompatibleMemLayoutRunner = new ConversionRunner<TestRgba>(this.Count);
this.PermutedRunnerRgbaToArgb = new ConversionRunner<TestArgb>(this.Count);
this.RunnerRgbaToRgbaVector = new ConversionRunner<TestRgbaVector>(this.Count);
}
}
public class PixelConversion_ConvertFromRgba32_Compatible : PixelConversion_ConvertFromRgba32
{
[Benchmark(Baseline = true)]
public void ByRef()
{
this.CompatibleMemLayoutRunner.RunByRefConversion();
}
public void ByRef() => this.CompatibleMemLayoutRunner.RunByRefConversion();
[Benchmark]
public void ByVal()
{
this.CompatibleMemLayoutRunner.RunByValConversion();
}
public void ByVal() => this.CompatibleMemLayoutRunner.RunByValConversion();
[Benchmark]
public void FromBytes()
{
this.CompatibleMemLayoutRunner.RunFromBytesConversion();
}
public void StaticByVal() => this.CompatibleMemLayoutRunner.RunStaticByValConversion();
[Benchmark]
public void FromBytes() => this.CompatibleMemLayoutRunner.RunFromBytesConversion();
[Benchmark]
public void Inline()
{
ref Rgba32 sBase = ref this.CompatibleMemLayoutRunner.Source[0];
ref Rgba32 dBase = ref Unsafe.As<TestRgba, Rgba32>(ref this.CompatibleMemLayoutRunner.Dest[0]);
ref Rgba32 dBase = ref Unsafe.As<TestRgba, Rgba32>(ref this.CompatibleMemLayoutRunner.Destination[0]);
for (nuint i = 0; i < (uint)this.Count; i++)
{
@ -120,50 +131,46 @@ public class PixelConversion_ConvertFromRgba32_Compatible : PixelConversion_Conv
/*
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.100
[Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
| Method | Count | Mean | Error | StdDev | Ratio |
|---------- |------ |-----------:|--------:|--------:|------:|
| ByRef | 256 | 102.5 ns | 0.44 ns | 0.39 ns | 1.00 |
| ByVal | 256 | 102.2 ns | 0.30 ns | 0.25 ns | 1.00 |
| FromBytes | 256 | 200.5 ns | 1.01 ns | 0.90 ns | 1.96 |
| Inline | 256 | 107.0 ns | 0.90 ns | 0.84 ns | 1.04 |
| | | | | | |
| ByRef | 2048 | 770.8 ns | 3.22 ns | 2.86 ns | 1.00 |
| ByVal | 2048 | 770.3 ns | 2.05 ns | 1.92 ns | 1.00 |
| FromBytes | 2048 | 1,546.8 ns | 7.51 ns | 6.66 ns | 2.01 |
| Inline | 2048 | 797.6 ns | 2.90 ns | 2.26 ns | 1.03 |
.NET SDK 8.0.200-preview.23624.5
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
| Method | Count | Mean | Error | StdDev | Ratio |
|------------ |------ |-----------:|--------:|--------:|------:|
| ByRef | 256 | 103.4 ns | 0.52 ns | 0.46 ns | 1.00 |
| ByVal | 256 | 103.3 ns | 1.48 ns | 1.38 ns | 1.00 |
| StaticByVal | 256 | 104.0 ns | 0.36 ns | 0.30 ns | 1.01 |
| FromBytes | 256 | 201.8 ns | 1.30 ns | 1.15 ns | 1.95 |
| Inline | 256 | 106.6 ns | 0.40 ns | 0.34 ns | 1.03 |
| | | | | | |
| ByRef | 2048 | 771.5 ns | 3.68 ns | 3.27 ns | 1.00 |
| ByVal | 2048 | 769.7 ns | 3.39 ns | 2.83 ns | 1.00 |
| StaticByVal | 2048 | 773.2 ns | 3.95 ns | 3.50 ns | 1.00 |
| FromBytes | 2048 | 1,555.3 ns | 9.24 ns | 8.19 ns | 2.02 |
| Inline | 2048 | 799.5 ns | 5.91 ns | 4.93 ns | 1.04 |
*/
}
public class PixelConversion_ConvertFromRgba32_Permuted_RgbaToArgb : PixelConversion_ConvertFromRgba32
{
[Benchmark(Baseline = true)]
public void ByRef()
{
this.PermutedRunnerRgbaToArgb.RunByRefConversion();
}
public void ByRef() => this.PermutedRunnerRgbaToArgb.RunByRefConversion();
[Benchmark]
public void ByVal()
{
this.PermutedRunnerRgbaToArgb.RunByValConversion();
}
public void ByVal() => this.PermutedRunnerRgbaToArgb.RunByValConversion();
[Benchmark]
public void FromBytes()
{
this.PermutedRunnerRgbaToArgb.RunFromBytesConversion();
}
public void StaticByVal() => this.PermutedRunnerRgbaToArgb.RunStaticByValConversion();
[Benchmark]
public void FromBytes() => this.PermutedRunnerRgbaToArgb.RunFromBytesConversion();
[Benchmark]
public void InlineShuffle()
{
ref Rgba32 sBase = ref this.PermutedRunnerRgbaToArgb.Source[0];
ref TestArgb dBase = ref this.PermutedRunnerRgbaToArgb.Dest[0];
ref TestArgb dBase = ref this.PermutedRunnerRgbaToArgb.Destination[0];
for (nuint i = 0; i < (uint)this.Count; i++)
{
@ -181,25 +188,64 @@ public class PixelConversion_ConvertFromRgba32_Permuted_RgbaToArgb : PixelConver
public void PixelConverter_Rgba32_ToArgb32()
{
Span<byte> source = MemoryMarshal.Cast<Rgba32, byte>(this.PermutedRunnerRgbaToArgb.Source);
Span<byte> dest = MemoryMarshal.Cast<TestArgb, byte>(this.PermutedRunnerRgbaToArgb.Dest);
Span<byte> dest = MemoryMarshal.Cast<TestArgb, byte>(this.PermutedRunnerRgbaToArgb.Destination);
PixelConverter.FromRgba32.ToArgb32(source, dest);
}
/*
RESULTS:
| Method | Count | Mean | Error | StdDev | Median | Ratio | RatioSD |
|------------------------------- |------ |------------:|----------:|----------:|------------:|------:|--------:|
| ByRef | 256 | 288.84 ns | 19.601 ns | 52.319 ns | 268.10 ns | 1.00 | 0.00 |
| ByVal | 256 | 267.97 ns | 1.831 ns | 1.713 ns | 267.85 ns | 0.77 | 0.18 |
| FromBytes | 256 | 266.81 ns | 2.427 ns | 2.270 ns | 266.47 ns | 0.76 | 0.18 |
| InlineShuffle | 256 | 291.41 ns | 5.820 ns | 5.444 ns | 290.17 ns | 0.83 | 0.19 |
| PixelConverter_Rgba32_ToArgb32 | 256 | 38.62 ns | 0.431 ns | 0.403 ns | 38.68 ns | 0.11 | 0.03 |
| | | | | | | | |
| ByRef | 2048 | 2,197.69 ns | 15.826 ns | 14.804 ns | 2,197.25 ns | 1.00 | 0.00 |
| ByVal | 2048 | 2,226.81 ns | 44.266 ns | 62.054 ns | 2,197.17 ns | 1.03 | 0.04 |
| FromBytes | 2048 | 2,181.35 ns | 18.033 ns | 16.868 ns | 2,185.97 ns | 0.99 | 0.01 |
| InlineShuffle | 2048 | 2,233.10 ns | 27.673 ns | 24.531 ns | 2,229.78 ns | 1.02 | 0.01 |
| PixelConverter_Rgba32_ToArgb32 | 2048 | 139.90 ns | 2.152 ns | 3.825 ns | 138.70 ns | 0.06 | 0.00 |
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.200-preview.23624.5
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
|------------------------------- |------ |------------:|----------:|---------:|------:|--------:|
| ByRef | 256 | 203.48 ns | 3.318 ns | 3.104 ns | 1.00 | 0.00 |
| ByVal | 256 | 201.46 ns | 2.242 ns | 1.872 ns | 0.99 | 0.02 |
| StaticByVal | 256 | 201.45 ns | 0.791 ns | 0.701 ns | 0.99 | 0.02 |
| FromBytes | 256 | 200.76 ns | 1.365 ns | 1.140 ns | 0.99 | 0.01 |
| InlineShuffle | 256 | 221.65 ns | 2.104 ns | 1.968 ns | 1.09 | 0.02 |
| PixelConverter_Rgba32_ToArgb32 | 256 | 26.23 ns | 0.277 ns | 0.231 ns | 0.13 | 0.00 |
| | | | | | | |
| ByRef | 2048 | 1,561.54 ns | 11.208 ns | 8.751 ns | 1.00 | 0.00 |
| ByVal | 2048 | 1,554.26 ns | 9.607 ns | 8.517 ns | 1.00 | 0.01 |
| StaticByVal | 2048 | 1,562.48 ns | 8.937 ns | 8.360 ns | 1.00 | 0.01 |
| FromBytes | 2048 | 1,552.68 ns | 7.445 ns | 5.812 ns | 0.99 | 0.01 |
| InlineShuffle | 2048 | 1,711.28 ns | 7.559 ns | 6.312 ns | 1.10 | 0.01 |
| PixelConverter_Rgba32_ToArgb32 | 2048 | 94.43 ns | 0.363 ns | 0.322 ns | 0.06 | 0.00 |
*/
}
public class PixelConversion_ConvertFromRgba32_RgbaToRgbaVector : PixelConversion_ConvertFromRgba32
{
[Benchmark(Baseline = true)]
public void ByRef() => this.RunnerRgbaToRgbaVector.RunByRefConversion();
[Benchmark]
public void ByVal() => this.RunnerRgbaToRgbaVector.RunByValConversion();
[Benchmark]
public void StaticByVal() => this.RunnerRgbaToRgbaVector.RunStaticByValConversion();
/*
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.200-preview.23624.5
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
|------------ |------ |-----------:|---------:|---------:|------:|--------:|
| ByRef | 256 | 448.5 ns | 4.86 ns | 4.06 ns | 1.00 | 0.00 |
| ByVal | 256 | 447.0 ns | 1.55 ns | 1.21 ns | 1.00 | 0.01 |
| StaticByVal | 256 | 447.4 ns | 1.67 ns | 1.30 ns | 1.00 | 0.01 |
| | | | | | | |
| ByRef | 2048 | 3,577.7 ns | 53.80 ns | 47.69 ns | 1.00 | 0.00 |
| ByVal | 2048 | 3,590.5 ns | 43.59 ns | 36.40 ns | 1.00 | 0.02 |
| StaticByVal | 2048 | 3,604.6 ns | 16.19 ns | 14.36 ns | 1.01 | 0.01 |
*/
}

37
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromVector4.cs

@ -13,43 +13,6 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
public class PixelConversion_ConvertFromVector4
{
[StructLayout(LayoutKind.Sequential)]
private struct TestRgbaVector : ITestPixel<TestRgbaVector>
{
private Vector4 v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
{
this.v = p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
{
this.v = p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4() => this.v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToVector4(ref Vector4 dest)
{
dest = this.v;
}
public void FromRgba32(Rgba32 source) => throw new System.NotImplementedException();
public void FromRgba32(ref Rgba32 source) => throw new System.NotImplementedException();
public void FromBytes(byte r, byte g, byte b, byte a) => throw new System.NotImplementedException();
public Rgba32 ToRgba32() => throw new System.NotImplementedException();
public void CopyToRgba32(ref Rgba32 dest) => throw new System.NotImplementedException();
}
private struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{

95
tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs

@ -4,6 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
@ -16,26 +17,20 @@ public struct TestArgb : ITestPixel<TestArgb>
public byte G;
public byte B;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 p)
{
this.R = p.R;
this.G = p.G;
this.B = p.B;
this.A = p.A;
}
private static readonly Vector4 MaxBytes = Vector128.Create(255f).AsVector4();
private static readonly Vector4 Half = Vector128.Create(.5f).AsVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 p)
private TestArgb(Rgba32 source)
{
this.R = p.R;
this.G = p.G;
this.B = p.B;
this.A = p.A;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
private TestArgb(byte r, byte g, byte b, byte a)
{
this.R = r;
this.G = g;
@ -44,50 +39,70 @@ public struct TestArgb : ITestPixel<TestArgb>
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
public void FromRgba32(Rgba32 source)
{
this.R = (byte)p.X;
this.G = (byte)p.Y;
this.B = (byte)p.Z;
this.A = (byte)p.W;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
public void FromRgba32(ref Rgba32 source)
{
this.R = (byte)p.X;
this.G = (byte)p.Y;
this.B = (byte)p.Z;
this.A = (byte)p.W;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return new Rgba32(this.R, this.G, this.B, this.A);
}
public static TestArgb StaticFromRgba32(Rgba32 source) => new(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
public void FromBytes(byte r, byte g, byte b, byte a)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
this.R = r;
this.G = g;
this.B = b;
this.A = a;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
public void FromVector4(Vector4 source) => this = Pack(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TestArgb StaticFromVector4(Vector4 source) => Pack(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 source) => this = Pack(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Rgba32 ToRgba32() => new(this.R, this.G, this.B, this.A);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void CopyToRgba32(ref Rgba32 destination)
{
return new Vector4(this.R, this.G, this.B, this.A);
destination.R = this.R;
destination.G = this.G;
destination.B = this.B;
destination.A = this.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToVector4(ref Vector4 dest)
public readonly Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void CopyToVector4(ref Vector4 destination) => destination = this.ToVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static TestArgb Pack(Vector4 vector)
{
dest.X = this.R;
dest.Y = this.G;
dest.Z = this.B;
dest.W = this.A;
vector *= MaxBytes;
vector += Half;
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
Vector128<byte> result = Vector128.ConvertToInt32(vector.AsVector128()).AsByte();
return new(result.GetElement(0), result.GetElement(4), result.GetElement(8), result.GetElement(12));
}
}

69
tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs

@ -4,6 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
@ -16,17 +17,29 @@ public struct TestRgba : ITestPixel<TestRgba>
public byte B;
public byte A;
private static readonly Vector4 MaxBytes = Vector128.Create(255f).AsVector4();
private static readonly Vector4 Half = Vector128.Create(.5f).AsVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 source)
private TestRgba(byte r, byte g, byte b, byte a)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
this.R = r;
this.G = g;
this.B = b;
this.A = a;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 source)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
}
private TestRgba(Rgba32 source) => this = Unsafe.As<Rgba32, TestRgba>(ref source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 source) => this = Unsafe.As<Rgba32, TestRgba>(ref source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TestRgba StaticFromRgba32(Rgba32 source) => new(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 source) => this = Unsafe.As<Rgba32, TestRgba>(ref source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
@ -37,39 +50,35 @@ public struct TestRgba : ITestPixel<TestRgba>
this.A = a;
}
public void FromVector4(Vector4 source)
{
throw new System.NotImplementedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 source) => this = Pack(source);
public void FromVector4(ref Vector4 source)
{
throw new System.NotImplementedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TestRgba StaticFromVector4(Vector4 source) => Pack(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return Unsafe.As<TestRgba, Rgba32>(ref this);
}
public void FromVector4(ref Vector4 source) => this = Pack(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
{
dest = Unsafe.As<TestRgba, Rgba32>(ref this);
}
public Rgba32 ToRgba32() => Unsafe.As<TestRgba, Rgba32>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A) * new Vector4(1f / 255f);
}
public void CopyToRgba32(ref Rgba32 destination) => destination = Unsafe.As<TestRgba, Rgba32>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToVector4(ref Vector4 dest)
public readonly void CopyToVector4(ref Vector4 destination) => destination = this.ToVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static TestRgba Pack(Vector4 vector)
{
var tmp = new Vector4(this.R, this.G, this.B, this.A);
tmp *= new Vector4(1f / 255f);
dest = tmp;
vector *= MaxBytes;
vector += Half;
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
Vector128<byte> result = Vector128.ConvertToInt32(vector.AsVector128()).AsByte();
return new(result.GetElement(0), result.GetElement(4), result.GetElement(8), result.GetElement(12));
}
}

51
tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgbaVector.cs

@ -0,0 +1,51 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
[StructLayout(LayoutKind.Sequential)]
public struct TestRgbaVector : ITestPixel<TestRgbaVector>
{
private Vector4 v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private TestRgbaVector(Vector4 source) => this.v = source;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 source) => this.v = source;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TestRgbaVector StaticFromVector4(Vector4 source) => new(source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 source) => this.v = source;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector4 ToVector4() => this.v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void CopyToVector4(ref Vector4 destination) => destination = this.v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 source) => this.v = source.ToScaledVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TestRgbaVector StaticFromRgba32(Rgba32 source) => new(source.ToScaledVector4());
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 source) => this.v = source.ToScaledVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a) => this.v = new Rgba32(r, g, b, a).ToScaledVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Rgba32 ToRgba32() => Rgba32.FromScaledVector4(this.v);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void CopyToRgba32(ref Rgba32 destination) => destination = Rgba32.FromScaledVector4(this.v);
}
Loading…
Cancel
Save