Files
tbd-station-14/Content.Benchmarks/ColorInterpolateBenchmark.cs
DrSmugleaf 5c0cf1b1a0 Use 'new' expression in places where the type is evident for content (#2590)
* Content.Client

* Content.Benchmarks

* Content.IntegrationTests

* Content.Server

* Content.Server.Database

* Content.Shared

* Content.Tests

* Merge fixes

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2020-11-27 21:00:49 +11:00

167 lines
4.9 KiB
C#

#if NETCOREAPP
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
using System;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using Robust.Shared.Maths;
using Robust.Shared.Random;
using SysVector4 = System.Numerics.Vector4;
namespace Content.Benchmarks
{
[DisassemblyDiagnoser]
public class ColorInterpolateBenchmark
{
#if NETCOREAPP
private const MethodImplOptions AggressiveOpt = MethodImplOptions.AggressiveOptimization;
#else
private const MethodImplOptions AggressiveOpt = default;
#endif
private (Color, Color)[] _colors;
private Color[] _output;
[Params(100)] public int N { get; set; }
[GlobalSetup]
public void Setup()
{
var random = new Random(3005);
_colors = new (Color, Color)[N];
_output = new Color[N];
for (var i = 0; i < N; i++)
{
var r1 = random.NextFloat();
var g1 = random.NextFloat();
var b1 = random.NextFloat();
var a1 = random.NextFloat();
var r2 = random.NextFloat();
var g2 = random.NextFloat();
var b2 = random.NextFloat();
var a2 = random.NextFloat();
_colors[i] = (new Color(r1, g1, b1, a1), new Color(r2, g2, b2, a2));
}
}
[Benchmark]
public void BenchSimple()
{
for (var i = 0; i < N; i++)
{
ref var tuple = ref _colors[i];
_output[i] = InterpolateSimple(tuple.Item1, tuple.Item2, 0.5f);
}
}
[Benchmark]
public void BenchSysVector4In()
{
for (var i = 0; i < N; i++)
{
ref var tuple = ref _colors[i];
_output[i] = InterpolateSysVector4In(tuple.Item1, tuple.Item2, 0.5f);
}
}
[Benchmark]
public void BenchSysVector4()
{
for (var i = 0; i < N; i++)
{
ref var tuple = ref _colors[i];
_output[i] = InterpolateSysVector4(tuple.Item1, tuple.Item2, 0.5f);
}
}
#if NETCOREAPP
[Benchmark]
public void BenchSimd()
{
for (var i = 0; i < N; i++)
{
ref var tuple = ref _colors[i];
_output[i] = InterpolateSimd(tuple.Item1, tuple.Item2, 0.5f);
}
}
[Benchmark]
public void BenchSimdIn()
{
for (var i = 0; i < N; i++)
{
ref var tuple = ref _colors[i];
_output[i] = InterpolateSimdIn(tuple.Item1, tuple.Item2, 0.5f);
}
}
#endif
[MethodImpl(AggressiveOpt)]
public static Color InterpolateSimple(Color a, Color b, float lambda)
{
return new(
a.R + (b.R - a.R) * lambda,
a.G + (b.G - a.G) * lambda,
a.B + (b.G - a.B) * lambda,
a.A + (b.A - a.A) * lambda
);
}
[MethodImpl(AggressiveOpt)]
public static Color InterpolateSysVector4(Color a, Color b,
float lambda)
{
ref var sva = ref Unsafe.As<Color, SysVector4>(ref a);
ref var svb = ref Unsafe.As<Color, SysVector4>(ref b);
var res = SysVector4.Lerp(sva, svb, lambda);
return Unsafe.As<SysVector4, Color>(ref res);
}
[MethodImpl(AggressiveOpt)]
public static Color InterpolateSysVector4In(in Color endPoint1, in Color endPoint2,
float lambda)
{
ref var sva = ref Unsafe.As<Color, SysVector4>(ref Unsafe.AsRef(endPoint1));
ref var svb = ref Unsafe.As<Color, SysVector4>(ref Unsafe.AsRef(endPoint2));
var res = SysVector4.Lerp(svb, sva, lambda);
return Unsafe.As<SysVector4, Color>(ref res);
}
#if NETCOREAPP
[MethodImpl(AggressiveOpt)]
public static Color InterpolateSimd(Color a, Color b,
float lambda)
{
var vecA = Unsafe.As<Color, Vector128<float>>(ref a);
var vecB = Unsafe.As<Color, Vector128<float>>(ref b);
vecB = Fma.MultiplyAdd(Sse.Subtract(vecB, vecA), Vector128.Create(lambda), vecA);
return Unsafe.As<Vector128<float>, Color>(ref vecB);
}
[MethodImpl(AggressiveOpt)]
public static Color InterpolateSimdIn(in Color a, in Color b,
float lambda)
{
var vecA = Unsafe.As<Color, Vector128<float>>(ref Unsafe.AsRef(a));
var vecB = Unsafe.As<Color, Vector128<float>>(ref Unsafe.AsRef(b));
vecB = Fma.MultiplyAdd(Sse.Subtract(vecB, vecA), Vector128.Create(lambda), vecA);
return Unsafe.As<Vector128<float>, Color>(ref vecB);
}
#endif
}
}