Skip to content

Commit 3969525

Browse files
Port shuffle4
1 parent 77cf848 commit 3969525

File tree

15 files changed

+302
-219
lines changed

15 files changed

+302
-219
lines changed

src/ImageSharp/Common/Helpers/Numerics.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Runtime.CompilerServices;
66
using System.Runtime.InteropServices;
77
using System.Runtime.Intrinsics;
8-
using System.Runtime.Intrinsics.Arm;
98
using System.Runtime.Intrinsics.X86;
109

1110
namespace SixLabors.ImageSharp;
@@ -61,6 +60,12 @@ public static int LeastCommonMultiple(int a, int b)
6160
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6261
public static nint Modulo4(nint x) => x & 3;
6362

63+
/// <summary>
64+
/// Calculates <paramref name="x"/> % 4
65+
/// </summary>
66+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
67+
public static nuint Modulo4(nuint x) => x & 3;
68+
6469
/// <summary>
6570
/// Calculates <paramref name="x"/> % 8
6671
/// </summary>

src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,49 +19,48 @@ namespace SixLabors.ImageSharp;
1919
internal interface IComponentShuffle
2020
{
2121
/// <summary>
22-
/// Shuffles then slices 8-bit integers within 128-bit lanes in <paramref name="source"/>
23-
/// using the control and store the results in <paramref name="dest"/>.
22+
/// Shuffles then slices 8-bit integers in <paramref name="source"/>
23+
/// using the control and store the results in <paramref name="destination"/>.
24+
/// If successful, this method will reduce the length of <paramref name="source"/> length
25+
/// by the shuffle amount.
2426
/// </summary>
2527
/// <param name="source">The source span of bytes.</param>
26-
/// <param name="dest">The destination span of bytes.</param>
27-
void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest);
28+
/// <param name="destination">The destination span of bytes.</param>
29+
void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination);
2830

2931
/// <summary>
30-
/// Shuffle 8-bit integers within 128-bit lanes in <paramref name="source"/>
31-
/// using the control and store the results in <paramref name="dest"/>.
32+
/// Shuffle 8-bit integers in <paramref name="source"/>
33+
/// using the control and store the results in <paramref name="destination"/>.
3234
/// </summary>
3335
/// <param name="source">The source span of bytes.</param>
34-
/// <param name="dest">The destination span of bytes.</param>
36+
/// <param name="destination">The destination span of bytes.</param>
3537
/// <remarks>
36-
/// Implementation can assume that source.Length is less or equal than dest.Length.
38+
/// Implementation can assume that source.Length is less or equal than destination.Length.
3739
/// Loops should iterate using source.Length.
3840
/// </remarks>
39-
void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest);
41+
void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination);
4042
}
4143

4244
/// <inheritdoc/>
4345
internal interface IShuffle4 : IComponentShuffle
4446
{
4547
}
4648

47-
internal readonly struct DefaultShuffle4 : IShuffle4
49+
internal readonly struct DefaultShuffle4(byte control) : IShuffle4
4850
{
49-
public DefaultShuffle4(byte control)
50-
=> this.Control = control;
51-
52-
public byte Control { get; }
51+
public byte Control { get; } = control;
5352

5453
[MethodImpl(InliningOptions.ShortMethod)]
55-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
56-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, this.Control);
54+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
55+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, this.Control);
5756

5857
[MethodImpl(InliningOptions.ShortMethod)]
59-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
58+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
6059
{
6160
ref byte sBase = ref MemoryMarshal.GetReference(source);
62-
ref byte dBase = ref MemoryMarshal.GetReference(dest);
61+
ref byte dBase = ref MemoryMarshal.GetReference(destination);
6362

64-
Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
63+
SimdUtils.Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
6564

6665
for (nuint i = 0; i < (uint)source.Length; i += 4)
6766
{
@@ -76,14 +75,14 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
7675
internal readonly struct WXYZShuffle4 : IShuffle4
7776
{
7877
[MethodImpl(InliningOptions.ShortMethod)]
79-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
80-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle2103);
78+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
79+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle2103);
8180

8281
[MethodImpl(InliningOptions.ShortMethod)]
83-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
82+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
8483
{
8584
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
86-
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
85+
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(destination));
8786
uint n = (uint)source.Length / 4;
8887

8988
for (nuint i = 0; i < n; i++)
@@ -100,14 +99,14 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
10099
internal readonly struct WZYXShuffle4 : IShuffle4
101100
{
102101
[MethodImpl(InliningOptions.ShortMethod)]
103-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
104-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle0123);
102+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
103+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle0123);
105104

106105
[MethodImpl(InliningOptions.ShortMethod)]
107-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
106+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
108107
{
109108
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
110-
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
109+
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(destination));
111110
uint n = (uint)source.Length / 4;
112111

113112
for (nuint i = 0; i < n; i++)
@@ -124,14 +123,14 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
124123
internal readonly struct YZWXShuffle4 : IShuffle4
125124
{
126125
[MethodImpl(InliningOptions.ShortMethod)]
127-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
128-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle0321);
126+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
127+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle0321);
129128

130129
[MethodImpl(InliningOptions.ShortMethod)]
131-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
130+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
132131
{
133132
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
134-
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
133+
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(destination));
135134
uint n = (uint)source.Length / 4;
136135

137136
for (nuint i = 0; i < n; i++)
@@ -148,14 +147,14 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
148147
internal readonly struct ZYXWShuffle4 : IShuffle4
149148
{
150149
[MethodImpl(InliningOptions.ShortMethod)]
151-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
152-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle3012);
150+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
151+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle3012);
153152

154153
[MethodImpl(InliningOptions.ShortMethod)]
155-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
154+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
156155
{
157156
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
158-
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
157+
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(destination));
159158
uint n = (uint)source.Length / 4;
160159

161160
for (nuint i = 0; i < n; i++)
@@ -179,14 +178,14 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
179178
internal readonly struct XWZYShuffle4 : IShuffle4
180179
{
181180
[MethodImpl(InliningOptions.ShortMethod)]
182-
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
183-
=> HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle1230);
181+
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> destination)
182+
=> HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle1230);
184183

185184
[MethodImpl(InliningOptions.ShortMethod)]
186-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
185+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> destination)
187186
{
188187
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
189-
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
188+
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(destination));
190189
uint n = (uint)source.Length / 4;
191190

192191
for (nuint i = 0; i < n; i++)

src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
2424
=> HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, this.Control);
2525

2626
[MethodImpl(InliningOptions.ShortMethod)]
27-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
27+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> dest)
2828
{
2929
ref byte sBase = ref MemoryMarshal.GetReference(source);
3030
ref byte dBase = ref MemoryMarshal.GetReference(dest);
3131

32-
Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
32+
SimdUtils.Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
3333

3434
Span<byte> temp = stackalloc byte[4];
3535
ref byte t = ref MemoryMarshal.GetReference(temp);
@@ -52,10 +52,10 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
5252
{
5353
[MethodImpl(InliningOptions.ShortMethod)]
5454
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
55-
=> HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle3210);
55+
=> HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, SimdUtils.Shuffle.MMShuffle3210);
5656

5757
[MethodImpl(InliningOptions.ShortMethod)]
58-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
58+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> dest)
5959
{
6060
ref byte sBase = ref MemoryMarshal.GetReference(source);
6161
ref byte dBase = ref MemoryMarshal.GetReference(dest);

src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
2424
=> HwIntrinsics.Shuffle3Reduce(ref source, ref dest, this.Control);
2525

2626
[MethodImpl(InliningOptions.ShortMethod)]
27-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
27+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> dest)
2828
{
2929
ref byte sBase = ref MemoryMarshal.GetReference(source);
3030
ref byte dBase = ref MemoryMarshal.GetReference(dest);
3131

32-
Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
32+
SimdUtils.Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
3333

3434
for (nuint i = 0; i < (uint)source.Length; i += 3)
3535
{

src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
2424
=> HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, this.Control);
2525

2626
[MethodImpl(InliningOptions.ShortMethod)]
27-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
27+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> dest)
2828
{
2929
ref byte sBase = ref MemoryMarshal.GetReference(source);
3030
ref byte dBase = ref MemoryMarshal.GetReference(dest);
3131

32-
Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
32+
SimdUtils.Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
3333

3434
for (nuint i = 0, j = 0; i < (uint)dest.Length; i += 3, j += 4)
3535
{
@@ -44,10 +44,10 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
4444
{
4545
[MethodImpl(InliningOptions.ShortMethod)]
4646
public void ShuffleReduce(ref ReadOnlySpan<byte> source, ref Span<byte> dest)
47-
=> HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, Shuffle.MMShuffle3210);
47+
=> HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, SimdUtils.Shuffle.MMShuffle3210);
4848

4949
[MethodImpl(InliningOptions.ShortMethod)]
50-
public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
50+
public void Shuffle(ReadOnlySpan<byte> source, Span<byte> dest)
5151
{
5252
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
5353
ref Byte3 dBase = ref Unsafe.As<byte, Byte3>(ref MemoryMarshal.GetReference(dest));

0 commit comments

Comments
 (0)