Browse Source

gfoidl fixes

pull/1761/head
Dmitry Pentin 5 years ago
parent
commit
6b3f0f7bd9
  1. 10
      src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs
  3. 4
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  4. 9
      src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs
  5. 4
      src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs
  6. 14
      src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs
  7. 16
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs

10
src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs

@ -172,7 +172,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
public static Block8x8 Load(Span<short> data) public static Block8x8 Load(Span<short> data)
{ {
Block8x8 result = default; Unsafe.SkipInit(out Block8x8 result);
result.LoadFrom(data); result.LoadFrom(data);
return result; return result;
} }
@ -204,7 +204,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
{ {
ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this); ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this);
ref byte destRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<short, byte>(destination)); ref byte destRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<short, byte>(destination));
Unsafe.CopyBlock(ref destRef, ref selfRef, Size * sizeof(short)); Unsafe.CopyBlockUnaligned(ref destRef, ref selfRef, Size * sizeof(short));
} }
/// <summary> /// <summary>
@ -287,7 +287,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// Index of the last non-zero element. Returns -1 if all elements are equal to zero. /// Index of the last non-zero element. Returns -1 if all elements are equal to zero.
/// </returns> /// </returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public int GetLastNonZeroIndex() public nint GetLastNonZeroIndex()
{ {
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported) if (Avx2.IsSupported)
@ -298,7 +298,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ref Vector256<short> mcuStride = ref Unsafe.As<Block8x8, Vector256<short>>(ref this); ref Vector256<short> mcuStride = ref Unsafe.As<Block8x8, Vector256<short>>(ref this);
for (int i = 3; i >= 0; i--) for (nint i = 3; i >= 0; i--)
{ {
int areEqual = Avx2.MoveMask(Avx2.CompareEqual(Unsafe.Add(ref mcuStride, i), zero16).AsByte()); int areEqual = Avx2.MoveMask(Avx2.CompareEqual(Unsafe.Add(ref mcuStride, i), zero16).AsByte());
@ -325,7 +325,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
else else
#endif #endif
{ {
int index = Size - 1; nint index = Size - 1;
ref short elemRef = ref Unsafe.As<Block8x8, short>(ref this); ref short elemRef = ref Unsafe.As<Block8x8, short>(ref this);
while (index >= 0 && Unsafe.Add(ref elemRef, index) == 0) while (index >= 0 && Unsafe.Add(ref elemRef, index) == 0)

6
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ref Vector256<short> destRef = ref dest.V01; ref Vector256<short> destRef = ref dest.V01;
for (int i = 0; i < 8; i += 2) for (nint i = 0; i < 8; i += 2)
{ {
Vector256<int> row0 = Avx.ConvertToVector256Int32(Avx.Multiply(Unsafe.Add(ref aBase, i + 0), Unsafe.Add(ref bBase, i + 0))); Vector256<int> row0 = Avx.ConvertToVector256Int32(Avx.Multiply(Unsafe.Add(ref aBase, i + 0), Unsafe.Add(ref bBase, i + 0)));
Vector256<int> row1 = Avx.ConvertToVector256Int32(Avx.Multiply(Unsafe.Add(ref aBase, i + 1), Unsafe.Add(ref bBase, i + 1))); Vector256<int> row1 = Avx.ConvertToVector256Int32(Avx.Multiply(Unsafe.Add(ref aBase, i + 1), Unsafe.Add(ref bBase, i + 1)));
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
Vector256<short> row = Avx2.PackSignedSaturate(row0, row1); Vector256<short> row = Avx2.PackSignedSaturate(row0, row1);
row = Avx2.PermuteVar8x32(row.AsInt32(), MultiplyIntoInt16ShuffleMask).AsInt16(); row = Avx2.PermuteVar8x32(row.AsInt32(), MultiplyIntoInt16ShuffleMask).AsInt16();
Unsafe.Add(ref destRef, i / 2) = row; Unsafe.Add(ref destRef, (IntPtr)((uint)i / 2)) = row;
} }
} }
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
Vector128<int> right = Sse2.ConvertToVector128Int32(Sse.Multiply(Unsafe.Add(ref aBase, i + 1), Unsafe.Add(ref bBase, i + 1))); Vector128<int> right = Sse2.ConvertToVector128Int32(Sse.Multiply(Unsafe.Add(ref aBase, i + 1), Unsafe.Add(ref bBase, i + 1)));
Vector128<short> row = Sse2.PackSignedSaturate(left, right); Vector128<short> row = Sse2.PackSignedSaturate(left, right);
Unsafe.Add(ref destBase, i / 2) = row; Unsafe.Add(ref destBase, (IntPtr)((uint)i / 2)) = row;
} }
} }

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

@ -414,12 +414,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
if (Avx2.IsSupported) if (Avx2.IsSupported)
{ {
MultiplyIntoInt16_Avx2(ref block, ref qt, ref dest); MultiplyIntoInt16_Avx2(ref block, ref qt, ref dest);
ZigZag.ApplyZigZagOrderingAvx(ref dest); ZigZag.ApplyZigZagOrderingAvx2(ref dest);
} }
else if (Ssse3.IsSupported) else if (Ssse3.IsSupported)
{ {
MultiplyIntoInt16_Sse2(ref block, ref qt, ref dest); MultiplyIntoInt16_Sse2(ref block, ref qt, ref dest);
ZigZag.ApplyZigZagOrderingSse(ref dest); ZigZag.ApplyZigZagOrderingSsse3(ref dest);
} }
else else
#endif #endif

9
src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
private bool IsFlushNeeded private bool IsFlushNeeded
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.emitWriteIndex < this.emitBuffer.Length / 2; get => this.emitWriteIndex < (uint)this.emitBuffer.Length / 2;
} }
/// <summary> /// <summary>
@ -408,15 +408,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
// Emit the AC components. // Emit the AC components.
int[] acHuffTable = this.huffmanTables[(2 * (int)index) + 1].Values; int[] acHuffTable = this.huffmanTables[(2 * (int)index) + 1].Values;
int lastValuableIndex = spectralBlock.GetLastNonZeroIndex(); nint lastValuableIndex = spectralBlock.GetLastNonZeroIndex();
int runLength = 0; int runLength = 0;
for (int zig = 1; zig <= lastValuableIndex; zig++) ref short blockRef = ref Unsafe.As<Block8x8, short>(ref spectralBlock);
for (nint zig = 1; zig <= lastValuableIndex; zig++)
{ {
const int zeroRun1 = 1 << 4; const int zeroRun1 = 1 << 4;
const int zeroRun16 = 16 << 4; const int zeroRun16 = 16 << 4;
int ac = spectralBlock[zig]; int ac = Unsafe.Add(ref blockRef, zig);
if (ac == 0) if (ac == 0)
{ {
runLength += zeroRun1; runLength += zeroRun1;

4
src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs

@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// Values are also scaled by 8 so DCT code won't do unnecessary division. /// Values are also scaled by 8 so DCT code won't do unnecessary division.
/// </para> /// </para>
/// </remarks> /// </remarks>
public static ReadOnlySpan<float> DctReciprocalAdjustmentCoefficients => new float[] public static readonly float[] DctReciprocalAdjustmentCoefficients = new float[]
{ {
0.125f, 0.09011998f, 0.09567086f, 0.10630376f, 0.125f, 0.15909483f, 0.23096988f, 0.45306373f, 0.125f, 0.09011998f, 0.09567086f, 0.10630376f, 0.125f, 0.15909483f, 0.23096988f, 0.45306373f,
0.09011998f, 0.064972885f, 0.068974845f, 0.07664074f, 0.09011998f, 0.11470097f, 0.16652f, 0.32664075f, 0.09011998f, 0.064972885f, 0.068974845f, 0.07664074f, 0.09011998f, 0.11470097f, 0.16652f, 0.32664075f,
@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
public static void TransformFDCT(ref Block8x8F block) public static void TransformFDCT(ref Block8x8F block)
{ {
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported || Sse.IsSupported) if (Sse.IsSupported)
{ {
ForwardTransformSimd(ref block); ForwardTransformSimd(ref block);
} }

14
src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
#pragma warning restore SA1309 #pragma warning restore SA1309
/// <summary> /// <summary>
/// Gets shuffle vectors for <see cref="ApplyZigZagOrderingSse"/> /// Gets shuffle vectors for <see cref="ApplyZigZagOrderingSsse3"/>
/// zig zag implementation. /// zig zag implementation.
/// </summary> /// </summary>
private static ReadOnlySpan<byte> SseShuffleMasks => new byte[] private static ReadOnlySpan<byte> SseShuffleMasks => new byte[]
@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}; };
/// <summary> /// <summary>
/// Gets shuffle vectors for <see cref="ApplyZigZagOrderingAvx"/> /// Gets shuffle vectors for <see cref="ApplyZigZagOrderingAvx2"/>
/// zig zag implementation. /// zig zag implementation.
/// </summary> /// </summary>
private static ReadOnlySpan<byte> AvxShuffleMasks => new byte[] private static ReadOnlySpan<byte> AvxShuffleMasks => new byte[]
@ -126,11 +126,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary> /// <summary>
/// Applies zig zag ordering for given 8x8 matrix using SSE cpu intrinsics. /// Applies zig zag ordering for given 8x8 matrix using SSE cpu intrinsics.
/// </summary> /// </summary>
/// <remarks>
/// Requires Ssse3 support.
/// </remarks>
/// <param name="block">Input matrix.</param> /// <param name="block">Input matrix.</param>
public static unsafe void ApplyZigZagOrderingSse(ref Block8x8 block) public static unsafe void ApplyZigZagOrderingSsse3(ref Block8x8 block)
{ {
DebugGuard.IsTrue(Ssse3.IsSupported, "Ssse3 support is required to run this operation!"); DebugGuard.IsTrue(Ssse3.IsSupported, "Ssse3 support is required to run this operation!");
@ -227,11 +224,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary> /// <summary>
/// Applies zig zag ordering for given 8x8 matrix using AVX cpu intrinsics. /// Applies zig zag ordering for given 8x8 matrix using AVX cpu intrinsics.
/// </summary> /// </summary>
/// <remarks>
/// Requires Avx2 support.
/// </remarks>
/// <param name="block">Input matrix.</param> /// <param name="block">Input matrix.</param>
public static unsafe void ApplyZigZagOrderingAvx(ref Block8x8 block) public static unsafe void ApplyZigZagOrderingAvx2(ref Block8x8 block)
{ {
DebugGuard.IsTrue(Avx2.IsSupported, "Avx2 support is required to run this operation!"); DebugGuard.IsTrue(Avx2.IsSupported, "Avx2 support is required to run this operation!");

16
tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs

@ -130,9 +130,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
Block8x8 data = default; Block8x8 data = default;
int expected = -1; nint expected = -1;
int actual = data.GetLastNonZeroIndex(); nint actual = data.GetLastNonZeroIndex();
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
@ -153,9 +153,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
data[i] = 10; data[i] = 10;
} }
int expected = Block8x8.Size - 1; nint expected = Block8x8.Size - 1;
int actual = data.GetLastNonZeroIndex(); nint actual = data.GetLastNonZeroIndex();
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
@ -182,9 +182,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int setIndex = rng.Next(1, Block8x8.Size); int setIndex = rng.Next(1, Block8x8.Size);
data[setIndex] = (short)rng.Next(-2000, 2000); data[setIndex] = (short)rng.Next(-2000, 2000);
int expected = setIndex; nint expected = setIndex;
int actual = data.GetLastNonZeroIndex(); nint actual = data.GetLastNonZeroIndex();
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int expected = lastIndex; int expected = lastIndex;
int actual = data.GetLastNonZeroIndex(); nint actual = data.GetLastNonZeroIndex();
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
@ -265,7 +265,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int expected = secondChunkEnd; int expected = secondChunkEnd;
int actual = data.GetLastNonZeroIndex(); nint actual = data.GetLastNonZeroIndex();
Assert.True(expected == actual, $"Expected: {expected}\nActual: {actual}\nInput matrix: {data}"); Assert.True(expected == actual, $"Expected: {expected}\nActual: {actual}\nInput matrix: {data}");
} }

Loading…
Cancel
Save