Browse Source

Remove restrictions from vector utilities

pull/2933/head
James Jackson-South 1 year ago
parent
commit
6b5392bc3d
  1. 18
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  2. 4
      src/ImageSharp/Common/Helpers/Vector128Utilities.cs
  3. 37
      src/ImageSharp/Common/Helpers/Vector256Utilities.cs
  4. 37
      src/ImageSharp/Common/Helpers/Vector512Utilities.cs
  5. 2
      src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs

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

@ -66,9 +66,9 @@ internal static partial class SimdUtils
ref Span<float> destination, ref Span<float> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if ((Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeFloat) || if (Vector512.IsHardwareAccelerated ||
(Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeFloat) || Vector256.IsHardwareAccelerated ||
Vector128.IsHardwareAccelerated) Vector128.IsHardwareAccelerated)
{ {
int remainder = 0; int remainder = 0;
if (Vector512.IsHardwareAccelerated) if (Vector512.IsHardwareAccelerated)
@ -112,8 +112,8 @@ internal static partial class SimdUtils
ref Span<byte> destination, ref Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if ((Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeByte) || if (Vector512.IsHardwareAccelerated ||
(Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeByte) || Vector256.IsHardwareAccelerated ||
Vector128.IsHardwareAccelerated) Vector128.IsHardwareAccelerated)
{ {
int remainder = 0; int remainder = 0;
@ -249,7 +249,7 @@ internal static partial class SimdUtils
Span<float> destination, Span<float> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeFloat) if (Vector512.IsHardwareAccelerated)
{ {
ref Vector512<float> sourceBase = ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(source)); ref Vector512<float> sourceBase = ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(source));
ref Vector512<float> destinationBase = ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(destination)); ref Vector512<float> destinationBase = ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(destination));
@ -277,7 +277,7 @@ internal static partial class SimdUtils
} }
} }
} }
else if (Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeFloat) else if (Vector256.IsHardwareAccelerated)
{ {
ref Vector256<float> sourceBase = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(source)); ref Vector256<float> sourceBase = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(source));
ref Vector256<float> destinationBase = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(destination)); ref Vector256<float> destinationBase = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(destination));
@ -341,7 +341,7 @@ internal static partial class SimdUtils
Span<byte> destination, Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeByte) if (Vector512.IsHardwareAccelerated)
{ {
Span<byte> temp = stackalloc byte[Vector512<byte>.Count]; Span<byte> temp = stackalloc byte[Vector512<byte>.Count];
Shuffle.MMShuffleSpan(ref temp, control); Shuffle.MMShuffleSpan(ref temp, control);
@ -373,7 +373,7 @@ internal static partial class SimdUtils
} }
} }
} }
else if (Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeByte) else if (Vector256.IsHardwareAccelerated)
{ {
Span<byte> temp = stackalloc byte[Vector256<byte>.Count]; Span<byte> temp = stackalloc byte[Vector256<byte>.Count];
Shuffle.MMShuffleSpan(ref temp, control); Shuffle.MMShuffleSpan(ref temp, control);

4
src/ImageSharp/Common/Helpers/Vector128Utilities.cs

@ -1323,7 +1323,9 @@ internal static class Vector128_
{ {
// https://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon // https://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon
Vector128<byte> powers = Vector128.Create(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128); Vector128<byte> powers = Vector128.Create(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128);
Vector128<byte> masked = value & powers; Vector128<byte> msbMask = Vector128.Create((byte)0x80);
Vector128<byte> normalized = AdvSimd.CompareEqual(value & msbMask, msbMask); // 0xFF or 0x00
Vector128<byte> masked = normalized & powers;
Vector128<ushort> sum8 = AdvSimd.AddPairwiseWidening(masked); Vector128<ushort> sum8 = AdvSimd.AddPairwiseWidening(masked);
Vector128<uint> sum16 = AdvSimd.AddPairwiseWidening(sum8); Vector128<uint> sum16 = AdvSimd.AddPairwiseWidening(sum8);

37
src/ImageSharp/Common/Helpers/Vector256Utilities.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -21,24 +20,6 @@ namespace SixLabors.ImageSharp.Common.Helpers;
internal static class Vector256_ internal static class Vector256_
#pragma warning restore SA1649 // File name should match first type name #pragma warning restore SA1649 // File name should match first type name
{ {
/// <summary>
/// Gets a value indicating whether shuffle byte operations are supported.
/// </summary>
public static bool SupportsShuffleNativeFloat
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Avx.IsSupported;
}
/// <summary>
/// Gets a value indicating whether shuffle byte operations are supported.
/// </summary>
public static bool SupportsShuffleNativeByte
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Avx2.IsSupported;
}
/// <summary> /// <summary>
/// Creates a new vector by selecting values from an input vector using a set of indices. /// Creates a new vector by selecting values from an input vector using a set of indices.
/// </summary> /// </summary>
@ -47,15 +28,7 @@ internal static class Vector256_
/// <returns>The <see cref="Vector256{Single}"/>.</returns> /// <returns>The <see cref="Vector256{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<float> ShuffleNative(Vector256<float> vector, [ConstantExpected] byte control) public static Vector256<float> ShuffleNative(Vector256<float> vector, [ConstantExpected] byte control)
{ => Avx.Shuffle(vector, vector, control);
if (Avx.IsSupported)
{
return Avx.Shuffle(vector, vector, control);
}
ThrowUnreachableException();
return default;
}
/// <summary> /// <summary>
/// Creates a new vector by selecting values from an input vector using a set of indices.</summary> /// Creates a new vector by selecting values from an input vector using a set of indices.</summary>
@ -73,8 +46,9 @@ internal static class Vector256_
return Avx2.Shuffle(vector, indices); return Avx2.Shuffle(vector, indices);
} }
ThrowUnreachableException(); return Vector256.Create(
return default; Vector128_.ShuffleNative(vector.GetLower(), indices.GetLower()),
Vector128_.ShuffleNative(vector.GetUpper(), indices.GetUpper()));
} }
/// <summary> /// <summary>
@ -508,7 +482,4 @@ internal static class Vector256_
int hiMask = Vector128_.MoveMask(value.GetUpper()); int hiMask = Vector128_.MoveMask(value.GetUpper());
return loMask | (hiMask << 16); return loMask | (hiMask << 16);
} }
[DoesNotReturn]
private static void ThrowUnreachableException() => throw new UnreachableException();
} }

37
src/ImageSharp/Common/Helpers/Vector512Utilities.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -21,24 +20,6 @@ namespace SixLabors.ImageSharp.Common.Helpers;
internal static class Vector512_ internal static class Vector512_
#pragma warning restore SA1649 // File name should match first type name #pragma warning restore SA1649 // File name should match first type name
{ {
/// <summary>
/// Gets a value indicating whether shuffle float operations are supported.
/// </summary>
public static bool SupportsShuffleNativeFloat
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Avx512F.IsSupported;
}
/// <summary>
/// Gets a value indicating whether shuffle byte operations are supported.
/// </summary>
public static bool SupportsShuffleNativeByte
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Avx512BW.IsSupported;
}
/// <summary> /// <summary>
/// Creates a new vector by selecting values from an input vector using the control. /// Creates a new vector by selecting values from an input vector using the control.
/// </summary> /// </summary>
@ -47,15 +28,7 @@ internal static class Vector512_
/// <returns>The <see cref="Vector512{Single}"/>.</returns> /// <returns>The <see cref="Vector512{Single}"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<float> ShuffleNative(Vector512<float> vector, [ConstantExpected] byte control) public static Vector512<float> ShuffleNative(Vector512<float> vector, [ConstantExpected] byte control)
{ => Avx512F.Shuffle(vector, vector, control);
if (Avx512F.IsSupported)
{
return Avx512F.Shuffle(vector, vector, control);
}
ThrowUnreachableException();
return default;
}
/// <summary> /// <summary>
/// Creates a new vector by selecting values from an input vector using a set of indices. /// Creates a new vector by selecting values from an input vector using a set of indices.
@ -73,8 +46,9 @@ internal static class Vector512_
return Avx512BW.Shuffle(vector, indices); return Avx512BW.Shuffle(vector, indices);
} }
ThrowUnreachableException(); return Vector512.Create(
return default; Vector256_.ShuffleNative(vector.GetLower(), indices.GetLower()),
Vector256_.ShuffleNative(vector.GetUpper(), indices.GetUpper()));
} }
/// <summary> /// <summary>
@ -175,7 +149,4 @@ internal static class Vector512_
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<T> Clamp<T>(Vector512<T> value, Vector512<T> min, Vector512<T> max) public static Vector512<T> Clamp<T>(Vector512<T> value, Vector512<T> min, Vector512<T> max)
=> Vector512.Min(Vector512.Max(value, min), max); => Vector512.Min(Vector512.Max(value, min), max);
[DoesNotReturn]
private static void ThrowUnreachableException() => throw new UnreachableException();
} }

2
src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs

@ -12,7 +12,7 @@ internal static class ColorSpaceTransformUtils
{ {
public static void CollectColorBlueTransforms(Span<uint> bgra, int stride, int tileWidth, int tileHeight, int greenToBlue, int redToBlue, Span<int> histo) public static void CollectColorBlueTransforms(Span<uint> bgra, int stride, int tileWidth, int tileHeight, int greenToBlue, int redToBlue, Span<int> histo)
{ {
if (Vector256_.SupportsShuffleNativeByte && tileWidth >= 16) if (Vector256.IsHardwareAccelerated && tileWidth >= 16)
{ {
const int span = 16; const int span = 16;
Span<ushort> values = stackalloc ushort[span]; Span<ushort> values = stackalloc ushort[span];

Loading…
Cancel
Save