|
|
|
@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp |
|
|
|
0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15 |
|
|
|
}; |
|
|
|
|
|
|
|
public static ReadOnlySpan<byte> PermuteMaskShiftAlpha8x32 => |
|
|
|
public static ReadOnlySpan<byte> PermuteMaskShiftAlpha8x32 => |
|
|
|
new byte[] |
|
|
|
{ |
|
|
|
0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, |
|
|
|
@ -877,6 +877,65 @@ namespace SixLabors.ImageSharp |
|
|
|
blueChannel = blueChannel.Slice(slice); |
|
|
|
destination = destination.Slice(slice); |
|
|
|
} |
|
|
|
|
|
|
|
internal static void PackFromRgbPlanesAvx2Reduce( |
|
|
|
ref ReadOnlySpan<byte> redChannel, |
|
|
|
ref ReadOnlySpan<byte> greenChannel, |
|
|
|
ref ReadOnlySpan<byte> blueChannel, |
|
|
|
ref Span<Rgba32> destination) |
|
|
|
{ |
|
|
|
ref Vector256<byte> rBase = ref Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(redChannel)); |
|
|
|
ref Vector256<byte> gBase = ref Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(greenChannel)); |
|
|
|
ref Vector256<byte> bBase = ref Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(blueChannel)); |
|
|
|
ref Vector256<byte> dBase = ref Unsafe.As<Rgba32, Vector256<byte>>(ref MemoryMarshal.GetReference(destination)); |
|
|
|
|
|
|
|
int count = redChannel.Length / Vector256<byte>.Count; |
|
|
|
|
|
|
|
ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); |
|
|
|
Vector256<uint> control1 = Unsafe.As<byte, Vector256<uint>>(ref control1Bytes); |
|
|
|
|
|
|
|
ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); |
|
|
|
Vector256<uint> control2 = Unsafe.As<byte, Vector256<uint>>(ref control2Bytes); |
|
|
|
|
|
|
|
Vector256<byte> a = Vector256.Create((byte)255); |
|
|
|
|
|
|
|
Vector256<byte> shuffleAlpha = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); |
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) |
|
|
|
{ |
|
|
|
Vector256<byte> r0 = Unsafe.Add(ref rBase, i); |
|
|
|
Vector256<byte> g0 = Unsafe.Add(ref gBase, i); |
|
|
|
Vector256<byte> b0 = Unsafe.Add(ref bBase, i); |
|
|
|
|
|
|
|
r0 = Avx2.PermuteVar8x32(r0.AsUInt32(), control1).AsByte(); |
|
|
|
g0 = Avx2.PermuteVar8x32(g0.AsUInt32(), control1).AsByte(); |
|
|
|
b0 = Avx2.PermuteVar8x32(b0.AsUInt32(), control1).AsByte(); |
|
|
|
|
|
|
|
Vector256<byte> rg = Avx2.UnpackLow(r0, g0); |
|
|
|
Vector256<byte> b1 = Avx2.UnpackLow(b0, a); |
|
|
|
|
|
|
|
Vector256<byte> rgb1 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); |
|
|
|
Vector256<byte> rgb2 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); |
|
|
|
|
|
|
|
rg = Avx2.UnpackHigh(r0, g0); |
|
|
|
b1 = Avx2.UnpackHigh(b0, a); |
|
|
|
|
|
|
|
Vector256<byte> rgb3 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); |
|
|
|
Vector256<byte> rgb4 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); |
|
|
|
|
|
|
|
ref Vector256<byte> d0 = ref Unsafe.Add(ref dBase, i * 4); |
|
|
|
d0 = rgb1; |
|
|
|
Unsafe.Add(ref d0, 1) = rgb2; |
|
|
|
Unsafe.Add(ref d0, 2) = rgb3; |
|
|
|
Unsafe.Add(ref d0, 3) = rgb4; |
|
|
|
} |
|
|
|
|
|
|
|
int slice = count * Vector256<byte>.Count; |
|
|
|
redChannel = redChannel.Slice(slice); |
|
|
|
greenChannel = greenChannel.Slice(slice); |
|
|
|
blueChannel = blueChannel.Slice(slice); |
|
|
|
destination = destination.Slice(slice); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|