Hahah color lerp.

This commit is contained in:
Pieter-Jan Briers
2019-08-11 00:21:50 +02:00
parent 8b593d28c6
commit 7b9038e6da

View File

@@ -1,15 +1,20 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
#if NETCOREAPP
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
using BenchmarkDotNet.Attributes;
using Robust.Shared.Maths;
using SysVector4 = System.Numerics.Vector4;
namespace Content.Benchmarks
{
[DisassemblyDiagnoser]
public class ColorInterpolateBenchmark
{
private readonly List<(Color, Color)> _colors = new List<(Color, Color)>();
private (Color, Color)[] _colors;
private Color[] _output;
[Params(100)] public int N { get; set; }
@@ -18,6 +23,9 @@ namespace Content.Benchmarks
{
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();
@@ -30,123 +38,122 @@ namespace Content.Benchmarks
var b2 = random.NextFloat();
var a2 = random.NextFloat();
_colors.Add((new Color(r1, g1, b1, a1), new Color(r2, g2, b2, a2)));
_colors[i] = (new Color(r1, g1, b1, a1), new Color(r2, g2, b2, a2));
}
}
[Benchmark]
public void BenchSimple()
{
foreach (var (a, b) in _colors)
for (var i = 0; i < N; i++)
{
InterpolateSimple(a, b, 0.5f);
ref var tuple = ref _colors[i];
_output[i] = InterpolateSimple(tuple.Item1, tuple.Item2, 0.5f);
}
}
//[Benchmark]
public void BenchSysVector4()
{
foreach (var (a, b) in _colors)
{
InterpolateSysVector4(a, b, 0.5f);
}
}
//[Benchmark]
public void BenchSysVector4Blit()
[Benchmark]
public void BenchSysVector4In()
{
foreach (var (a, b) in _colors)
for (var i = 0; i < N; i++)
{
InterpolateSysVector4Blit(a, b, 0.5f);
}
}
//[Benchmark]
public void BenchSysVector4BlitNoException()
{
foreach (var (a, b) in _colors)
{
InterpolateSysVector4BlitNoException(a, b, 0.5f);
ref var tuple = ref _colors[i];
_output[i] = InterpolateSysVector4In(tuple.Item1, tuple.Item2, 0.5f);
}
}
[Benchmark]
public void BenchSysVector4AsRefNoException()
public void BenchSysVector4()
{
foreach (var (a, b) in _colors)
for (var i = 0; i < N; i++)
{
InterpolateSysVector4BlitNoExceptionAsRef(a, b, 0.5f);
ref var tuple = ref _colors[i];
_output[i] = InterpolateSysVector4(tuple.Item1, tuple.Item2, 0.5f);
}
}
public static Color InterpolateSimple(Color endPoint1, Color endPoint2, float lambda)
#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(MethodImplOptions.AggressiveOptimization)]
public static Color InterpolateSimple(Color a, Color b, float lambda)
{
if (lambda < 0 || lambda > 1)
throw new ArgumentOutOfRangeException(nameof(lambda));
return new Color(
endPoint1.R * lambda + endPoint2.R * (1 - lambda),
endPoint1.G * lambda + endPoint2.G * (1 - lambda),
endPoint1.B * lambda + endPoint2.B * (1 - lambda),
endPoint1.A * lambda + endPoint2.A * (1 - lambda)
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
);
}
public static Color InterpolateSysVector4(Color endPoint1, Color endPoint2, float lambda)
{
if (lambda < 0 || lambda > 1)
throw new ArgumentOutOfRangeException(nameof(lambda));
var vec1 = new SysVector4(endPoint1.R, endPoint1.G, endPoint1.B, endPoint1.A);
var vec2 = new SysVector4(endPoint2.R, endPoint2.G, endPoint2.B, endPoint2.A);
var res = SysVector4.Lerp(vec1, vec2, 1 - lambda);
return new Color(
res.X, res.Y, res.Z, res.W);
}
public static unsafe Color InterpolateSysVector4Blit(in Color endPoint1, in Color endPoint2, float lambda)
{
if (lambda < 0 || lambda > 1)
throw new ArgumentOutOfRangeException(nameof(lambda));
fixed (Color* p1 = &endPoint1)
fixed (Color* p2 = &endPoint2)
{
var vp1 = (SysVector4*) p1;
var vp2 = (SysVector4*) p2;
var res = SysVector4.Lerp(*vp1, *vp2, 1 - lambda);
return *(Color*) (&res);
}
}
public static unsafe Color InterpolateSysVector4BlitNoException(in Color endPoint1, in Color endPoint2,
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static Color InterpolateSysVector4(Color a, Color b,
float lambda)
{
fixed (Color* p1 = &endPoint1)
fixed (Color* p2 = &endPoint2)
{
var vp1 = (SysVector4*) p1;
var vp2 = (SysVector4*) p2;
ref var sva = ref Unsafe.As<Color, SysVector4>(ref a);
ref var svb = ref Unsafe.As<Color, SysVector4>(ref b);
var res = SysVector4.Lerp(*vp2, *vp1, lambda);
return *(Color*) (&res);
}
}
public static unsafe Color InterpolateSysVector4BlitNoExceptionAsRef(in Color endPoint1, in Color endPoint2,
float lambda)
{
ref var sv1 = ref Unsafe.As<Color, SysVector4>(ref Unsafe.AsRef(endPoint1));
ref var sv2 = ref Unsafe.As<Color, SysVector4>(ref Unsafe.AsRef(endPoint2));
var res = SysVector4.Lerp(sv2, sv1, lambda);
var res = SysVector4.Lerp(sva, svb, lambda);
return Unsafe.As<SysVector4, Color>(ref res);
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
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(MethodImplOptions.AggressiveOptimization)]
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(MethodImplOptions.AggressiveOptimization)]
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
}
}