Browse Source

More codegen improvements to shared methods

js/color-alpha-handling
Sergio Pedri 6 years ago
parent
commit
aab2837d28
  1. 22
      src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs
  2. 89
      src/ImageSharp/Common/Helpers/Numerics.cs
  3. 48
      src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs

22
src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -25,12 +25,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public static void Expand(Span<Vector4> vectors) public static void Expand(Span<Vector4> vectors)
{ {
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
for (int i = 0; i < vectors.Length; i++) while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd))
{ {
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); Expand(ref vectorsStart);
Expand(ref v);
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1);
} }
} }
@ -41,12 +43,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public static void Compress(Span<Vector4> vectors) public static void Compress(Span<Vector4> vectors)
{ {
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
for (int i = 0; i < vectors.Length; i++) while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd))
{ {
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); Compress(ref vectorsStart);
Compress(ref v);
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1);
} }
} }

89
src/ImageSharp/Common/Helpers/Numerics.cs

@ -41,13 +41,11 @@ namespace SixLabors.ImageSharp
/// <summary> /// <summary>
/// Determine the Least Common Multiple (LCM) of two numbers. /// Determine the Least Common Multiple (LCM) of two numbers.
/// See https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int LeastCommonMultiple(int a, int b) public static int LeastCommonMultiple(int a, int b)
{ => a / GreatestCommonDivisor(a, b) * b;
// https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
return (a / GreatestCommonDivisor(a, b)) * b;
}
/// <summary> /// <summary>
/// Calculates <paramref name="x"/> % 2 /// Calculates <paramref name="x"/> % 2
@ -290,10 +288,14 @@ namespace SixLabors.ImageSharp
if (remainder.Length > 0) if (remainder.Length > 0)
{ {
for (int i = 0; i < remainder.Length; i++) ref byte remainderStart = ref MemoryMarshal.GetReference(remainder);
ref byte remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length);
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd))
{ {
ref byte v = ref remainder[i]; remainderStart = Clamp(remainderStart, min, max);
v = Clamp(v, min, max);
remainderStart = ref Unsafe.Add(ref remainderStart, 1);
} }
} }
} }
@ -311,10 +313,14 @@ namespace SixLabors.ImageSharp
if (remainder.Length > 0) if (remainder.Length > 0)
{ {
for (int i = 0; i < remainder.Length; i++) ref uint remainderStart = ref MemoryMarshal.GetReference(remainder);
ref uint remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length);
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd))
{ {
ref uint v = ref remainder[i]; remainderStart = Clamp(remainderStart, min, max);
v = Clamp(v, min, max);
remainderStart = ref Unsafe.Add(ref remainderStart, 1);
} }
} }
} }
@ -332,10 +338,14 @@ namespace SixLabors.ImageSharp
if (remainder.Length > 0) if (remainder.Length > 0)
{ {
for (int i = 0; i < remainder.Length; i++) ref int remainderStart = ref MemoryMarshal.GetReference(remainder);
ref int remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length);
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd))
{ {
ref int v = ref remainder[i]; remainderStart = Clamp(remainderStart, min, max);
v = Clamp(v, min, max);
remainderStart = ref Unsafe.Add(ref remainderStart, 1);
} }
} }
} }
@ -353,10 +363,14 @@ namespace SixLabors.ImageSharp
if (remainder.Length > 0) if (remainder.Length > 0)
{ {
for (int i = 0; i < remainder.Length; i++) ref float remainderStart = ref MemoryMarshal.GetReference(remainder);
ref float remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length);
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd))
{ {
ref float v = ref remainder[i]; remainderStart = Clamp(remainderStart, min, max);
v = Clamp(v, min, max);
remainderStart = ref Unsafe.Add(ref remainderStart, 1);
} }
} }
} }
@ -374,10 +388,14 @@ namespace SixLabors.ImageSharp
if (remainder.Length > 0) if (remainder.Length > 0)
{ {
for (int i = 0; i < remainder.Length; i++) ref double remainderStart = ref MemoryMarshal.GetReference(remainder);
ref double remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length);
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd))
{ {
ref double v = ref remainder[i]; remainderStart = Clamp(remainderStart, min, max);
v = Clamp(v, min, max);
remainderStart = ref Unsafe.Add(ref remainderStart, 1);
} }
} }
} }
@ -472,10 +490,8 @@ namespace SixLabors.ImageSharp
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2) if (Avx2.IsSupported && vectors.Length >= 2)
{ {
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float> // Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
@ -495,12 +511,14 @@ namespace SixLabors.ImageSharp
else else
#endif #endif
{ {
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
for (int i = 0; i < vectors.Length; i++) while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd))
{ {
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); Premultiply(ref vectorsStart);
Premultiply(ref v);
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1);
} }
} }
} }
@ -515,10 +533,8 @@ namespace SixLabors.ImageSharp
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2) if (Avx2.IsSupported && vectors.Length >= 2)
{ {
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float> // Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
@ -538,12 +554,14 @@ namespace SixLabors.ImageSharp
else else
#endif #endif
{ {
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
for (int i = 0; i < vectors.Length; i++) while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd))
{ {
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); UnPremultiply(ref vectorsStart);
UnPremultiply(ref v);
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1);
} }
} }
} }
@ -633,10 +651,10 @@ namespace SixLabors.ImageSharp
vectors128Ref = y4; vectors128Ref = y4;
vectors128Ref = ref Unsafe.Add(ref vectors128Ref, 1); vectors128Ref = ref Unsafe.Add(ref vectors128Ref, 1);
} }
return;
} }
else
#endif #endif
{
ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length); ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length);
@ -684,3 +702,4 @@ namespace SixLabors.ImageSharp
} }
} }
} }
}

48
src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs

@ -88,14 +88,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
Span<TPixel> destPixels) Span<TPixel> destPixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); ref Vector4 sourceStart = ref MemoryMarshal.GetReference(sourceVectors);
ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceStart, sourceVectors.Length);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < sourceVectors.Length; i++) while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd))
{ {
ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); destRef.FromVector4(sourceStart);
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.FromVector4(sp); sourceStart = ref Unsafe.Add(ref sourceStart, 1);
destRef = ref Unsafe.Add(ref destRef, 1);
} }
} }
@ -105,14 +107,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
Span<Vector4> destVectors) Span<Vector4> destVectors)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); ref TPixel sourceStart = ref MemoryMarshal.GetReference(sourcePixels);
ref TPixel sourceEnd = ref Unsafe.Add(ref sourceStart, sourcePixels.Length);
ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors);
for (int i = 0; i < sourcePixels.Length; i++) while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd))
{ {
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); destRef = sourceStart.ToVector4();
ref Vector4 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToVector4(); sourceStart = ref Unsafe.Add(ref sourceStart, 1);
destRef = ref Unsafe.Add(ref destRef, 1);
} }
} }
@ -122,14 +126,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
Span<TPixel> destinationColors) Span<TPixel> destinationColors)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); ref Vector4 sourceStart = ref MemoryMarshal.GetReference(sourceVectors);
ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceStart, sourceVectors.Length);
ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors);
for (int i = 0; i < sourceVectors.Length; i++) while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd))
{ {
ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); destRef.FromScaledVector4(sourceStart);
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.FromScaledVector4(sp); sourceStart = ref Unsafe.Add(ref sourceStart, 1);
destRef = ref Unsafe.Add(ref destRef, 1);
} }
} }
@ -139,14 +145,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
Span<Vector4> destinationVectors) Span<Vector4> destinationVectors)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); ref TPixel sourceStart = ref MemoryMarshal.GetReference(sourceColors);
ref TPixel sourceEnd = ref Unsafe.Add(ref sourceStart, sourceColors.Length);
ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors);
for (int i = 0; i < sourceColors.Length; i++) while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd))
{ {
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); destRef = sourceStart.ToScaledVector4();
ref Vector4 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToScaledVector4(); sourceStart = ref Unsafe.Add(ref sourceStart, 1);
destRef = ref Unsafe.Add(ref destRef, 1);
} }
} }
} }

Loading…
Cancel
Save