Browse Source

Port most of the function components.

pull/2359/head
James Jackson-South 3 years ago
parent
commit
517ec80280
  1. 9
      src/ImageSharp/Common/Constants.cs
  2. 20
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  3. 2
      src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs
  4. 253
      src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs

9
src/ImageSharp/Common/Constants.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp; namespace SixLabors.ImageSharp;
/// <summary> /// <summary>
@ -13,6 +15,11 @@ internal static class Constants
/// </summary> /// </summary>
public static readonly float Epsilon = 0.001F; public static readonly float Epsilon = 0.001F;
/// <summary>
/// The epsilon value for comparing floating point numbers.
/// </summary>
public static readonly Vector256<float> Epsilon256 = Vector256.Create(0.001F);
/// <summary> /// <summary>
/// The epsilon squared value for comparing floating point numbers. /// The epsilon squared value for comparing floating point numbers.
/// </summary> /// </summary>

20
src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs

@ -532,7 +532,7 @@ internal static partial class SimdUtils
} }
/// <summary> /// <summary>
/// Performs a multiplication and an addition of the <see cref="Vector256{T}"/>. /// Performs a multiplication and an addition of the <see cref="Vector256{Single}"/>.
/// </summary> /// </summary>
/// <remarks>ret = (vm0 * vm1) + va</remarks> /// <remarks>ret = (vm0 * vm1) + va</remarks>
/// <param name="va">The vector to add to the intermediate result.</param> /// <param name="va">The vector to add to the intermediate result.</param>
@ -549,22 +549,20 @@ internal static partial class SimdUtils
{ {
return Fma.MultiplyAdd(vm1, vm0, va); return Fma.MultiplyAdd(vm1, vm0, va);
} }
else
{ return Avx.Add(Avx.Multiply(vm0, vm1), va);
return Avx.Add(Avx.Multiply(vm0, vm1), va);
}
} }
/// <summary> /// <summary>
/// Performs a multiplication and a substraction of the <see cref="Vector256{T}"/>. /// Performs a multiplication and a subtraction of the <see cref="Vector256{Single}"/>.
/// </summary> /// </summary>
/// <remarks>ret = (vm0 * vm1) - vs</remarks> /// <remarks>ret = (vm0 * vm1) - vs</remarks>
/// <param name="vs">The vector to substract from the intermediate result.</param> /// <param name="vs">The vector to subtract from the intermediate result.</param>
/// <param name="vm0">The first vector to multiply.</param> /// <param name="vm0">The first vector to multiply.</param>
/// <param name="vm1">The second vector to multiply.</param> /// <param name="vm1">The second vector to multiply.</param>
/// <returns>The <see cref="Vector256{T}"/>.</returns> /// <returns>The <see cref="Vector256{T}"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public static Vector256<float> MultiplySubstract( public static Vector256<float> MultiplySubtract(
in Vector256<float> vs, in Vector256<float> vs,
in Vector256<float> vm0, in Vector256<float> vm0,
in Vector256<float> vm1) in Vector256<float> vm1)
@ -573,10 +571,8 @@ internal static partial class SimdUtils
{ {
return Fma.MultiplySubtract(vm1, vm0, vs); return Fma.MultiplySubtract(vm1, vm0, vs);
} }
else
{ return Avx.Subtract(Avx.Multiply(vm0, vm1), vs);
return Avx.Subtract(Avx.Multiply(vm0, vm1), vs);
}
} }
/// <summary> /// <summary>

2
src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs

@ -99,7 +99,7 @@ internal static partial class FloatingPointDCT
var mm256_F_1_4142 = Vector256.Create(1.414213562f); var mm256_F_1_4142 = Vector256.Create(1.414213562f);
Vector256<float> tmp13 = Avx.Add(tmp1, tmp3); Vector256<float> tmp13 = Avx.Add(tmp1, tmp3);
Vector256<float> tmp12 = SimdUtils.HwIntrinsics.MultiplySubstract(tmp13, Avx.Subtract(tmp1, tmp3), mm256_F_1_4142); Vector256<float> tmp12 = SimdUtils.HwIntrinsics.MultiplySubtract(tmp13, Avx.Subtract(tmp1, tmp3), mm256_F_1_4142);
tmp0 = Avx.Add(tmp10, tmp13); tmp0 = Avx.Add(tmp10, tmp13);
tmp3 = Avx.Subtract(tmp10, tmp13); tmp3 = Avx.Subtract(tmp10, tmp13);

253
src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs

@ -3,6 +3,8 @@
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders; namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders;
@ -27,9 +29,17 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Normal(Vector4 backdrop, Vector4 source) public static Vector4 Normal(Vector4 backdrop, Vector4 source)
{ => source;
return source;
} /// <summary>
/// Returns the result of the "Normal" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Normal(Vector256<float> backdrop, Vector256<float> source)
=> source;
/// <summary> /// <summary>
/// Returns the result of the "Multiply" compositing equation. /// Returns the result of the "Multiply" compositing equation.
@ -39,9 +49,17 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Multiply(Vector4 backdrop, Vector4 source) public static Vector4 Multiply(Vector4 backdrop, Vector4 source)
{ => backdrop * source;
return backdrop * source;
} /// <summary>
/// Returns the result of the "Multiply" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Multiply(Vector256<float> backdrop, Vector256<float> source)
=> Avx.Multiply(backdrop, source);
/// <summary> /// <summary>
/// Returns the result of the "Add" compositing equation. /// Returns the result of the "Add" compositing equation.
@ -51,9 +69,17 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Add(Vector4 backdrop, Vector4 source) public static Vector4 Add(Vector4 backdrop, Vector4 source)
{ => Vector4.Min(Vector4.One, backdrop + source);
return Vector4.Min(Vector4.One, backdrop + source);
} /// <summary>
/// Returns the result of the "Add" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Add(Vector256<float> backdrop, Vector256<float> source)
=> Avx.Min(Vector256.Create(1F), Avx.Add(backdrop, source));
/// <summary> /// <summary>
/// Returns the result of the "Subtract" compositing equation. /// Returns the result of the "Subtract" compositing equation.
@ -63,9 +89,17 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Subtract(Vector4 backdrop, Vector4 source) public static Vector4 Subtract(Vector4 backdrop, Vector4 source)
{ => Vector4.Max(Vector4.Zero, backdrop - source);
return Vector4.Max(Vector4.Zero, backdrop - source);
} /// <summary>
/// Returns the result of the "Subtract" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Subtract(Vector256<float> backdrop, Vector256<float> source)
=> Avx.Min(Vector256.Create(1F), Avx.Subtract(backdrop, source));
/// <summary> /// <summary>
/// Returns the result of the "Screen" compositing equation. /// Returns the result of the "Screen" compositing equation.
@ -75,8 +109,19 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Screen(Vector4 backdrop, Vector4 source) public static Vector4 Screen(Vector4 backdrop, Vector4 source)
=> Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source));
/// <summary>
/// Returns the result of the "Screen" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Screen(Vector256<float> backdrop, Vector256<float> source)
{ {
return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); Vector256<float> vOne = Vector256.Create(1F);
return Avx.Subtract(vOne, Avx.Multiply(Avx.Subtract(vOne, backdrop), Avx.Subtract(vOne, source)));
} }
/// <summary> /// <summary>
@ -87,9 +132,17 @@ internal static partial class PorterDuffFunctions
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Darken(Vector4 backdrop, Vector4 source) public static Vector4 Darken(Vector4 backdrop, Vector4 source)
{ => Vector4.Min(backdrop, source);
return Vector4.Min(backdrop, source);
} /// <summary>
/// Returns the result of the "Darken" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Darken(Vector256<float> backdrop, Vector256<float> source)
=> Avx.Min(backdrop, source);
/// <summary> /// <summary>
/// Returns the result of the "Lighten" compositing equation. /// Returns the result of the "Lighten" compositing equation.
@ -98,10 +151,17 @@ internal static partial class PorterDuffFunctions
/// <param name="source">The source vector.</param> /// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Lighten(Vector4 backdrop, Vector4 source) public static Vector4 Lighten(Vector4 backdrop, Vector4 source) => Vector4.Max(backdrop, source);
{
return Vector4.Max(backdrop, source); /// <summary>
} /// Returns the result of the "Lighten" compositing equation.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Lighten(Vector256<float> backdrop, Vector256<float> source)
=> Avx.Max(backdrop, source);
/// <summary> /// <summary>
/// Returns the result of the "Overlay" compositing equation. /// Returns the result of the "Overlay" compositing equation.
@ -136,16 +196,14 @@ internal static partial class PorterDuffFunctions
} }
/// <summary> /// <summary>
/// Helper function for Overlay andHardLight modes /// Helper function for Overlay and HardLight modes
/// </summary> /// </summary>
/// <param name="backdrop">Backdrop color element</param> /// <param name="backdrop">Backdrop color element</param>
/// <param name="source">Source color element</param> /// <param name="source">Source color element</param>
/// <returns>Overlay value</returns> /// <returns>Overlay value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float OverlayValueFunction(float backdrop, float source) private static float OverlayValueFunction(float backdrop, float source)
{ => backdrop <= 0.5f ? (2 * backdrop * source) : 1 - (2 * (1 - source) * (1 - backdrop));
return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - (2 * (1 - source) * (1 - backdrop));
}
/// <summary> /// <summary>
/// Returns the result of the "Over" compositing equation. /// Returns the result of the "Over" compositing equation.
@ -175,6 +233,40 @@ internal static partial class PorterDuffFunctions
return color; return color;
} }
/// <summary>
/// Returns the result of the "Over" compositing equation.
/// </summary>
/// <param name="destination">The destination vector.</param>
/// <param name="source">The source vector.</param>
/// <param name="blend">The amount to blend. Range 0..1</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Over(Vector256<float> destination, Vector256<float> source, Vector256<float> blend)
{
const int blendAlphaControl = 0b_10_00_10_00;
const int shuffleAlphaControl = 0b_11_11_11_11;
// calculate weights
Vector256<float> sW = Avx.Shuffle(source, source, shuffleAlphaControl);
Vector256<float> dW = Avx.Shuffle(destination, destination, shuffleAlphaControl);
Vector256<float> blendW = Avx.Multiply(sW, dW);
Vector256<float> dstW = Avx.Subtract(dW, blendW);
Vector256<float> srcW = Avx.Subtract(sW, blendW);
// calculate final alpha
Vector256<float> alpha = Avx.Add(dstW, sW);
// calculate final color
Vector256<float> color = Avx.Multiply(destination, dstW);
color = SimdUtils.HwIntrinsics.MultiplyAdd(source, srcW, color);
color = SimdUtils.HwIntrinsics.MultiplyAdd(blend, blendW, color);
// unpremultiply
color = Avx.Divide(color, Avx.Max(alpha, Constants.Epsilon256));
return Avx.Blend(color, alpha, blendAlphaControl);
}
/// <summary> /// <summary>
/// Returns the result of the "Atop" compositing equation. /// Returns the result of the "Atop" compositing equation.
/// </summary> /// </summary>
@ -202,6 +294,36 @@ internal static partial class PorterDuffFunctions
return color; return color;
} }
/// <summary>
/// Returns the result of the "Atop" compositing equation.
/// </summary>
/// <param name="destination">The destination vector.</param>
/// <param name="source">The source vector.</param>
/// <param name="blend">The amount to blend. Range 0..1</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Atop(Vector256<float> destination, Vector256<float> source, Vector256<float> blend)
{
// calculate weights
const int blendAlphaControl = 0b_10_00_10_00;
const int shuffleAlphaControl = 0b_11_11_11_11;
// calculate final alpha
Vector256<float> alpha = Avx.Shuffle(destination, destination, shuffleAlphaControl);
// calculate weights
Vector256<float> sW = Avx.Shuffle(source, source, shuffleAlphaControl);
Vector256<float> blendW = Avx.Multiply(sW, alpha);
Vector256<float> dstW = Avx.Subtract(alpha, blendW);
// calculate final color
Vector256<float> color = SimdUtils.HwIntrinsics.MultiplyAdd(destination, dstW, Avx.Multiply(blend, blendW));
// unpremultiply
color = Avx.Divide(color, Avx.Max(alpha, Constants.Epsilon256));
return Avx.Blend(color, alpha, blendAlphaControl);
}
/// <summary> /// <summary>
/// Returns the result of the "In" compositing equation. /// Returns the result of the "In" compositing equation.
/// </summary> /// </summary>
@ -220,6 +342,31 @@ internal static partial class PorterDuffFunctions
return color; return color;
} }
/// <summary>
/// Returns the result of the "In" compositing equation.
/// </summary>
/// <param name="destination">The destination vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> In(Vector256<float> destination, Vector256<float> source)
{
const int blendAlphaControl = 0b_10_00_10_00;
const int shuffleAlphaControl = 0b_11_11_11_11;
// calculate alpha
Vector256<float> sW = Avx.Shuffle(source, source, shuffleAlphaControl);
Vector256<float> dW = Avx.Shuffle(destination, destination, shuffleAlphaControl);
Vector256<float> alpha = Avx.Multiply(sW, dW);
// premultiply
Vector256<float> color = Avx.Multiply(source, alpha);
// unpremultiply
color = Avx.Divide(color, Avx.Max(alpha, Constants.Epsilon256));
return Avx.Blend(color, alpha, blendAlphaControl);
}
/// <summary> /// <summary>
/// Returns the result of the "Out" compositing equation. /// Returns the result of the "Out" compositing equation.
/// </summary> /// </summary>
@ -238,6 +385,31 @@ internal static partial class PorterDuffFunctions
return color; return color;
} }
/// <summary>
/// Returns the result of the "Out" compositing equation.
/// </summary>
/// <param name="destination">The destination vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> Out(Vector256<float> destination, Vector256<float> source)
{
const int blendAlphaControl = 0b_10_00_10_00;
const int shuffleAlphaControl = 0b_11_11_11_11;
// calculate alpha
Vector256<float> sW = Avx.Shuffle(source, source, shuffleAlphaControl);
Vector256<float> dW = Avx.Shuffle(destination, destination, shuffleAlphaControl);
Vector256<float> alpha = Avx.Multiply(Avx.Subtract(Vector256.Create(1F), dW), sW);
// premultiply
Vector256<float> color = Avx.Multiply(source, alpha);
// unpremultiply
color = Avx.Divide(color, Avx.Max(alpha, Constants.Epsilon256));
return Avx.Blend(color, alpha, blendAlphaControl);
}
/// <summary> /// <summary>
/// Returns the result of the "XOr" compositing equation. /// Returns the result of the "XOr" compositing equation.
/// </summary> /// </summary>
@ -260,9 +432,38 @@ internal static partial class PorterDuffFunctions
return color; return color;
} }
/// <summary>
/// Returns the result of the "XOr" compositing equation.
/// </summary>
/// <param name="destination">The destination vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector4 Clear(Vector4 backdrop, Vector4 source) public static Vector256<float> Xor(Vector256<float> destination, Vector256<float> source)
{ {
return Vector4.Zero; const int blendAlphaControl = 0b_10_00_10_00;
const int shuffleAlphaControl = 0b_11_11_11_11;
// calculate weights
Vector256<float> sW = Avx.Shuffle(source, source, shuffleAlphaControl);
Vector256<float> dW = Avx.Shuffle(destination, destination, shuffleAlphaControl);
Vector256<float> vOne = Vector256.Create(1F);
Vector256<float> srcW = Avx.Subtract(vOne, dW);
Vector256<float> dstW = Avx.Subtract(vOne, sW);
// calculate alpha
Vector256<float> alpha = SimdUtils.HwIntrinsics.MultiplyAdd(sW, srcW, Avx.Multiply(dW, dstW));
Vector256<float> color = SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(sW, source), srcW, Avx.Multiply(Avx.Multiply(dW, destination), dstW));
// unpremultiply
color = Avx.Divide(color, Avx.Max(alpha, Constants.Epsilon256));
return Avx.Blend(color, alpha, blendAlphaControl);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector4 Clear(Vector4 backdrop, Vector4 source) => Vector4.Zero;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector256<float> Clear(Vector256<float> backdrop, Vector256<float> source) => Vector256<float>.Zero;
} }

Loading…
Cancel
Save