Browse Source

Use dedicated property

pull/2793/head
James Jackson-South 2 years ago
parent
commit
4728b97d85
  1. 150
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
  2. 3
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs

150
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs

@ -23,6 +23,9 @@ internal readonly unsafe struct ResizeKernel
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ResizeKernel"/> struct. /// Initializes a new instance of the <see cref="ResizeKernel"/> struct.
/// </summary> /// </summary>
/// <param name="startIndex">The starting index for the destination row.</param>
/// <param name="bufferPtr">The pointer to the buffer with the convolution factors.</param>
/// <param name="length">The length of the kernel.</param>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
internal ResizeKernel(int startIndex, float* bufferPtr, int length) internal ResizeKernel(int startIndex, float* bufferPtr, int length)
{ {
@ -31,6 +34,15 @@ internal readonly unsafe struct ResizeKernel
this.Length = length; this.Length = length;
} }
/// <summary>
/// Gets a value indicating whether vectorization is supported.
/// </summary>
public static bool SupportsVectorization
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Vector256.IsHardwareAccelerated;
}
/// <summary> /// <summary>
/// Gets the start index for the destination row. /// Gets the start index for the destination row.
/// </summary> /// </summary>
@ -80,96 +92,99 @@ internal readonly unsafe struct ResizeKernel
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ConvolveCore(ref Vector4 rowStartRef) public Vector4 ConvolveCore(ref Vector4 rowStartRef)
{ {
if (Vector512.IsHardwareAccelerated) if (SupportsVectorization)
{ {
float* bufferStart = this.bufferPtr; if (Vector512.IsHardwareAccelerated)
ref Vector4 rowEndRef = ref Unsafe.Add(ref rowStartRef, this.Length & ~7);
Vector512<float> result512_0 = Vector512<float>.Zero;
Vector512<float> result512_1 = Vector512<float>.Zero;
while (Unsafe.IsAddressLessThan(ref rowStartRef, ref rowEndRef))
{ {
Vector512<float> pixels512_0 = Unsafe.As<Vector4, Vector512<float>>(ref rowStartRef); float* bufferStart = this.bufferPtr;
Vector512<float> pixels512_1 = Unsafe.As<Vector4, Vector512<float>>(ref Unsafe.Add(ref rowStartRef, (nuint)4)); ref Vector4 rowEndRef = ref Unsafe.Add(ref rowStartRef, this.Length & ~7);
Vector512<float> result512_0 = Vector512<float>.Zero;
Vector512<float> result512_1 = Vector512<float>.Zero;
result512_0 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart), pixels512_0, result512_0); while (Unsafe.IsAddressLessThan(ref rowStartRef, ref rowEndRef))
result512_1 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart + 16), pixels512_1, result512_1); {
Vector512<float> pixels512_0 = Unsafe.As<Vector4, Vector512<float>>(ref rowStartRef);
Vector512<float> pixels512_1 = Unsafe.As<Vector4, Vector512<float>>(ref Unsafe.Add(ref rowStartRef, (nuint)4));
bufferStart += 32; result512_0 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart), pixels512_0, result512_0);
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)8); result512_1 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart + 16), pixels512_1, result512_1);
}
result512_0 += result512_1; bufferStart += 32;
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)8);
}
if ((this.Length & 7) >= 4) result512_0 += result512_1;
{
Vector512<float> pixels512_0 = Unsafe.As<Vector4, Vector512<float>>(ref rowStartRef);
result512_0 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart), pixels512_0, result512_0);
bufferStart += 16; if ((this.Length & 7) >= 4)
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)4); {
} Vector512<float> pixels512_0 = Unsafe.As<Vector4, Vector512<float>>(ref rowStartRef);
result512_0 = Vector512Utilities.MultiplyAddEstimate(Vector512.Load(bufferStart), pixels512_0, result512_0);
Vector256<float> result256 = result512_0.GetLower() + result512_0.GetUpper(); bufferStart += 16;
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)4);
}
if ((this.Length & 3) >= 2) Vector256<float> result256 = result512_0.GetLower() + result512_0.GetUpper();
{
Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef);
result256 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256);
bufferStart += 8; if ((this.Length & 3) >= 2)
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)2); {
} Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef);
result256 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256);
Vector128<float> result128 = result256.GetLower() + result256.GetUpper(); bufferStart += 8;
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)2);
}
if ((this.Length & 1) != 0) Vector128<float> result128 = result256.GetLower() + result256.GetUpper();
{
Vector128<float> pixels128 = Unsafe.As<Vector4, Vector128<float>>(ref rowStartRef);
result128 = Vector128Utilities.MultiplyAddEstimate(Vector128.Load(bufferStart), pixels128, result128);
}
return *(Vector4*)&result128; if ((this.Length & 1) != 0)
} {
else if (Vector256.IsHardwareAccelerated) Vector128<float> pixels128 = Unsafe.As<Vector4, Vector128<float>>(ref rowStartRef);
{ result128 = Vector128Utilities.MultiplyAddEstimate(Vector128.Load(bufferStart), pixels128, result128);
float* bufferStart = this.bufferPtr; }
ref Vector4 rowEndRef = ref Unsafe.Add(ref rowStartRef, this.Length & ~3);
Vector256<float> result256_0 = Vector256<float>.Zero;
Vector256<float> result256_1 = Vector256<float>.Zero;
while (Unsafe.IsAddressLessThan(ref rowStartRef, ref rowEndRef)) return *(Vector4*)&result128;
}
else
{ {
Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef); float* bufferStart = this.bufferPtr;
Vector256<float> pixels256_1 = Unsafe.As<Vector4, Vector256<float>>(ref Unsafe.Add(ref rowStartRef, (nuint)2)); ref Vector4 rowEndRef = ref Unsafe.Add(ref rowStartRef, this.Length & ~3);
Vector256<float> result256_0 = Vector256<float>.Zero;
Vector256<float> result256_1 = Vector256<float>.Zero;
result256_0 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256_0); while (Unsafe.IsAddressLessThan(ref rowStartRef, ref rowEndRef))
result256_1 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart + 8), pixels256_1, result256_1); {
Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef);
Vector256<float> pixels256_1 = Unsafe.As<Vector4, Vector256<float>>(ref Unsafe.Add(ref rowStartRef, (nuint)2));
bufferStart += 16; result256_0 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256_0);
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)4); result256_1 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart + 8), pixels256_1, result256_1);
}
result256_0 += result256_1; bufferStart += 16;
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)4);
}
if ((this.Length & 3) >= 2) result256_0 += result256_1;
{
Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef);
result256_0 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256_0);
bufferStart += 8; if ((this.Length & 3) >= 2)
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)2); {
} Vector256<float> pixels256_0 = Unsafe.As<Vector4, Vector256<float>>(ref rowStartRef);
result256_0 = Vector256Utilities.MultiplyAddEstimate(Vector256.Load(bufferStart), pixels256_0, result256_0);
Vector128<float> result128 = result256_0.GetLower() + result256_0.GetUpper(); bufferStart += 8;
rowStartRef = ref Unsafe.Add(ref rowStartRef, (nuint)2);
}
if ((this.Length & 1) != 0) Vector128<float> result128 = result256_0.GetLower() + result256_0.GetUpper();
{
Vector128<float> pixels128 = Unsafe.As<Vector4, Vector128<float>>(ref rowStartRef); if ((this.Length & 1) != 0)
result128 = Vector128Utilities.MultiplyAddEstimate(Vector128.Load(bufferStart), pixels128, result128); {
} Vector128<float> pixels128 = Unsafe.As<Vector4, Vector128<float>>(ref rowStartRef);
result128 = Vector128Utilities.MultiplyAddEstimate(Vector128.Load(bufferStart), pixels128, result128);
}
return *(Vector4*)&result128; return *(Vector4*)&result128;
}
} }
else else
{ {
@ -195,6 +210,7 @@ internal readonly unsafe struct ResizeKernel
/// Copy the contents of <see cref="ResizeKernel"/> altering <see cref="StartIndex"/> /// Copy the contents of <see cref="ResizeKernel"/> altering <see cref="StartIndex"/>
/// to the value <paramref name="left"/>. /// to the value <paramref name="left"/>.
/// </summary> /// </summary>
/// <param name="left">The new value for <see cref="StartIndex"/>.</param>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
internal ResizeKernel AlterLeftValue(int left) internal ResizeKernel AlterLeftValue(int left)
=> new(left, this.bufferPtr, this.Length); => new(left, this.bufferPtr, this.Length);

3
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.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.Runtime.Intrinsics;
using System.Text; using System.Text;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.ImageSharp.Processing.Processors.Transforms;
@ -142,7 +141,7 @@ public partial class ResizeKernelMapTests
Span<float> actualValues; Span<float> actualValues;
ApproximateFloatComparer comparer; ApproximateFloatComparer comparer;
if (Vector256.IsHardwareAccelerated) if (ResizeKernel.SupportsVectorization)
{ {
comparer = new ApproximateFloatComparer(1e-4f); comparer = new ApproximateFloatComparer(1e-4f);

Loading…
Cancel
Save