Browse Source

avoid allocation in RunRgba32CompatibleToVector4Conversion

af/merge-core
Anton Firszov 8 years ago
parent
commit
62da375f63
  1. 24
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

24
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

@ -171,6 +171,8 @@ namespace SixLabors.ImageSharp.PixelFormats
} }
} }
// TODO: The Vector4 helpers should be moved to a utility class.
/// <summary> /// <summary>
/// Provides an efficient default implementation for <see cref="ToVector4"/> and <see cref="ToScaledVector4"/> /// Provides an efficient default implementation for <see cref="ToVector4"/> and <see cref="ToScaledVector4"/>
/// which is applicable for <see cref="Rgba32"/>-compatible pixel types where <see cref="IPixel.ToVector4"/> /// which is applicable for <see cref="Rgba32"/>-compatible pixel types where <see cref="IPixel.ToVector4"/>
@ -195,15 +197,19 @@ namespace SixLabors.ImageSharp.PixelFormats
return; return;
} }
using (IMemoryOwner<Rgba32> tempBuffer = configuration.MemoryAllocator.Allocate<Rgba32>(count)) // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation:
{ int countWithoutLastItem = count - 1;
Span<Rgba32> tempSpan = tempBuffer.Memory.Span; ReadOnlySpan<TPixel> reducedSource = sourcePixels.Slice(0, countWithoutLastItem);
this.ToRgba32(configuration, sourcePixels, tempSpan); Span<Rgba32> lastQuarterOfDestBuffer = MemoryMarshal.Cast<Vector4, Rgba32>(destVectors).Slice((3 * count) + 1, countWithoutLastItem);
this.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer);
SimdUtils.BulkConvertByteToNormalizedFloat( // 'destVectors' and 'lastQuarterOfDestBuffer' are ovelapping buffers,
MemoryMarshal.Cast<Rgba32, byte>(tempSpan), // but we are always reading/writing at different positions:
MemoryMarshal.Cast<Vector4, float>(destVectors)); SimdUtils.BulkConvertByteToNormalizedFloat(
} MemoryMarshal.Cast<Rgba32, byte>(lastQuarterOfDestBuffer),
MemoryMarshal.Cast<Vector4, float>(destVectors.Slice(0, countWithoutLastItem)));
destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4();
} }
/// <summary> /// <summary>
@ -230,6 +236,8 @@ namespace SixLabors.ImageSharp.PixelFormats
return; return;
} }
// For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion,
// so let's allocate a temporary buffer as usually:
using (IMemoryOwner<Rgba32> tempBuffer = configuration.MemoryAllocator.Allocate<Rgba32>(count)) using (IMemoryOwner<Rgba32> tempBuffer = configuration.MemoryAllocator.Allocate<Rgba32>(count))
{ {
Span<Rgba32> tempSpan = tempBuffer.Memory.Span; Span<Rgba32> tempSpan = tempBuffer.Memory.Span;

Loading…
Cancel
Save