Browse Source

Update ShuffleNative (byte)

pull/2918/head
James Jackson-South 1 year ago
parent
commit
505ecce3fa
  1. 20
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  2. 35
      src/ImageSharp/Common/Helpers/Vector128Utilities.cs
  3. 2
      src/ImageSharp/Common/Helpers/Vector256Utilities.cs
  4. 1
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

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

@ -113,7 +113,7 @@ internal static partial class SimdUtils
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if ((Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeByte) || if ((Vector512.IsHardwareAccelerated && Vector512_.SupportsShuffleNativeByte) ||
(Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleByte) || (Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeByte) ||
(Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte)) (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte))
{ {
int remainder = 0; int remainder = 0;
@ -158,7 +158,7 @@ internal static partial class SimdUtils
ref Span<byte> destination, ref Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte && Vector128_.SupportsRightAlign) if (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte && Vector128_.SupportsAlignRight)
{ {
int remainder = source.Length % (Vector128<byte>.Count * 3); int remainder = source.Length % (Vector128<byte>.Count * 3);
@ -373,7 +373,7 @@ internal static partial class SimdUtils
} }
} }
} }
else if (Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleByte) else if (Vector256.IsHardwareAccelerated && Vector256_.SupportsShuffleNativeByte)
{ {
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);
@ -445,7 +445,9 @@ internal static partial class SimdUtils
Span<byte> destination, Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte && Vector128_.SupportsRightAlign) if (Vector128.IsHardwareAccelerated &&
Vector128_.SupportsShuffleNativeByte &&
Vector128_.SupportsAlignRight)
{ {
Vector128<byte> maskPad4Nx16 = ShuffleMaskPad4Nx16(); Vector128<byte> maskPad4Nx16 = ShuffleMaskPad4Nx16();
Vector128<byte> maskSlice4Nx16 = ShuffleMaskSlice4Nx16(); Vector128<byte> maskSlice4Nx16 = ShuffleMaskSlice4Nx16();
@ -505,7 +507,10 @@ internal static partial class SimdUtils
Span<byte> destination, Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte && Vector128_.SupportsShiftByte) if (Vector128.IsHardwareAccelerated &&
Vector128_.SupportsShuffleNativeByte &&
Vector128_.SupportsShiftByte &&
Vector128_.SupportsAlignRight)
{ {
Vector128<byte> maskPad4Nx16 = ShuffleMaskPad4Nx16(); Vector128<byte> maskPad4Nx16 = ShuffleMaskPad4Nx16();
Vector128<byte> fill = Vector128.Create(0xff000000ff000000ul).AsByte(); Vector128<byte> fill = Vector128.Create(0xff000000ff000000ul).AsByte();
@ -548,7 +553,10 @@ internal static partial class SimdUtils
Span<byte> destination, Span<byte> destination,
[ConstantExpected] byte control) [ConstantExpected] byte control)
{ {
if (Vector128.IsHardwareAccelerated && Vector128_.SupportsShuffleNativeByte && Vector128_.SupportsShiftByte) if (Vector128.IsHardwareAccelerated &&
Vector128_.SupportsShuffleNativeByte &&
Vector128_.SupportsShiftByte &&
Vector128_.SupportsAlignRight)
{ {
Vector128<byte> maskSlice4Nx16 = ShuffleMaskSlice4Nx16(); Vector128<byte> maskSlice4Nx16 = ShuffleMaskSlice4Nx16();
Vector128<byte> maskE = Vector128_.AlignRight(maskSlice4Nx16, maskSlice4Nx16, 12); Vector128<byte> maskE = Vector128_.AlignRight(maskSlice4Nx16, maskSlice4Nx16, 12);

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

@ -4,6 +4,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.Wasm;
@ -38,13 +39,26 @@ internal static class Vector128_
public static bool SupportsShuffleNativeByte public static bool SupportsShuffleNativeByte
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Ssse3.IsSupported || AdvSimd.Arm64.IsSupported || PackedSimd.IsSupported; get
{
if (Vector128.IsHardwareAccelerated)
{
if (RuntimeInformation.ProcessArchitecture is Architecture.X86 or Architecture.X64)
{
return Ssse3.IsSupported;
}
return true;
}
return false;
}
} }
/// <summary> /// <summary>
/// Gets a value indicating whether right align operations are supported. /// Gets a value indicating whether right align operations are supported.
/// </summary> /// </summary>
public static bool SupportsRightAlign public static bool SupportsAlignRight
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Ssse3.IsSupported || AdvSimd.IsSupported; get => Ssse3.IsSupported || AdvSimd.IsSupported;
@ -91,23 +105,16 @@ internal static class Vector128_
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<byte> ShuffleNative(Vector128<byte> vector, Vector128<byte> indices) public static Vector128<byte> ShuffleNative(Vector128<byte> vector, Vector128<byte> indices)
{ {
// For x64 we use the SSSE3 shuffle intrinsic to avoid additional instructions. 3 vs 1.
if (Ssse3.IsSupported) if (Ssse3.IsSupported)
{ {
return Ssse3.Shuffle(vector, indices); return Ssse3.Shuffle(vector, indices);
} }
if (AdvSimd.Arm64.IsSupported) // For ARM and WASM, codegen will be optimal.
{ // We don't throw for x86/x64 so we should never use this method without
return AdvSimd.Arm64.VectorTableLookup(vector, indices); // checking for support.
} return Vector128.Shuffle(vector, indices);
if (PackedSimd.IsSupported)
{
return PackedSimd.Swizzle(vector, indices);
}
ThrowUnreachableException();
return default;
} }
/// <summary> /// <summary>

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

@ -33,7 +33,7 @@ internal static class Vector256_
/// <summary> /// <summary>
/// Gets a value indicating whether shuffle byte operations are supported. /// Gets a value indicating whether shuffle byte operations are supported.
/// </summary> /// </summary>
public static bool SupportsShuffleByte public static bool SupportsShuffleNativeByte
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Avx2.IsSupported; get => Avx2.IsSupported;

1
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -5,7 +5,6 @@ using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using System.Text; using System.Text;
using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Common.Helpers;

Loading…
Cancel
Save