Browse Source

Skip some safety readonly struct copies

af/octree-no-pixelmap
Sergio Pedri 6 years ago
parent
commit
a77a0b2527
  1. 3
      src/ImageSharp/Advanced/IRowIntervalAction.cs
  2. 3
      src/ImageSharp/Advanced/IRowIntervalAction{TBuffer}.cs
  3. 4
      src/ImageSharp/Advanced/ParallelRowIterator.cs
  4. 10
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  5. 12
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
  6. 7
      src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
  7. 2
      src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
  8. 6
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs

3
src/ImageSharp/Advanced/IRowIntervalAction.cs

@ -95,7 +95,8 @@ namespace SixLabors.ImageSharp.Advanced
int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY); int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
var rows = new RowInterval(yMin, yMax); var rows = new RowInterval(yMin, yMax);
this.action.Invoke(in rows); // Skip the safety copy when invoking a potentially impure method on a readonly field
Unsafe.AsRef(this.action).Invoke(in rows);
} }
} }
} }

3
src/ImageSharp/Advanced/IRowIntervalAction{TBuffer}.cs

@ -92,7 +92,8 @@ namespace SixLabors.ImageSharp.Advanced
var rows = new RowInterval(yMin, yMax); var rows = new RowInterval(yMin, yMax);
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.info.MaxX); using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.info.MaxX);
this.action.Invoke(in rows, buffer.Memory);
Unsafe.AsRef(this.action).Invoke(in rows, buffer.Memory);
} }
} }
} }

4
src/ImageSharp/Advanced/ParallelRowIterator.cs

@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Advanced
if (numOfSteps == 1) if (numOfSteps == 1)
{ {
var rows = new RowInterval(top, bottom); var rows = new RowInterval(top, bottom);
body.Invoke(in rows); Unsafe.AsRef(body).Invoke(in rows);
return; return;
} }
@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Advanced
var rows = new RowInterval(top, bottom); var rows = new RowInterval(top, bottom);
using (IMemoryOwner<TBuffer> buffer = allocator.Allocate<TBuffer>(width)) using (IMemoryOwner<TBuffer> buffer = allocator.Allocate<TBuffer>(width))
{ {
body.Invoke(rows, buffer.Memory); Unsafe.AsRef(body).Invoke(rows, buffer.Memory);
} }
return; return;

10
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -554,8 +554,14 @@ namespace SixLabors.ImageSharp.Formats.Png
return; return;
} }
// Grab the palette and write it to the stream. /* Grab the palette and write it to the stream.
ReadOnlySpan<TPixel> palette = quantized.Palette.Span; * Here the palette is reinterpreted as a mutable Memory<TPixel> value,
* which is possible because the two memory types have the same layout.
* This is done so that the Span<TPixel> we're working on is mutable,
* so that we can skip the safety copies done by the compiler when we
* invoke the IPixel.ToRgba32 method below, which is not marked as readonly. */
ReadOnlyMemory<TPixel> paletteMemory = quantized.Palette;
Span<TPixel> palette = Unsafe.As<ReadOnlyMemory<TPixel>, Memory<TPixel>>(ref paletteMemory).Span;
int paletteLength = Math.Min(palette.Length, 256); int paletteLength = Math.Min(palette.Length, 256);
int colorTableLength = paletteLength * 3; int colorTableLength = paletteLength * 3;
bool anyAlpha = false; bool anyAlpha = false;

12
src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs

@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc /> /// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / Max; public readonly Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / Max;
/// <inheritdoc /> /// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
@ -343,7 +343,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary> /// </summary>
/// <returns>The <see cref="Rgba32"/>.</returns> /// <returns>The <see cref="Rgba32"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() public readonly Rgba32 ToRgba32()
{ {
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary> /// </summary>
/// <returns>The <see cref="Bgra32"/>.</returns> /// <returns>The <see cref="Bgra32"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Bgra32 ToBgra32() public readonly Bgra32 ToBgra32()
{ {
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
@ -371,7 +371,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary> /// </summary>
/// <returns>The <see cref="Argb32"/>.</returns> /// <returns>The <see cref="Argb32"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Argb32 ToArgb32() public readonly Argb32 ToArgb32()
{ {
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
@ -385,7 +385,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary> /// </summary>
/// <returns>The <see cref="Rgb24"/>.</returns> /// <returns>The <see cref="Rgb24"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Rgb24 ToRgb24() public readonly Rgb24 ToRgb24()
{ {
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
@ -398,7 +398,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary> /// </summary>
/// <returns>The <see cref="Bgr24"/>.</returns> /// <returns>The <see cref="Bgr24"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Bgr24 ToBgr24() public readonly Bgr24 ToBgr24()
{ {
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);

7
src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -66,7 +66,8 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
MemoryMarshal.Cast<Rgba32, byte>(lastQuarterOfDestBuffer), MemoryMarshal.Cast<Rgba32, byte>(lastQuarterOfDestBuffer),
MemoryMarshal.Cast<Vector4, float>(destVectors.Slice(0, countWithoutLastItem))); MemoryMarshal.Cast<Vector4, float>(destVectors.Slice(0, countWithoutLastItem)));
destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); // Reinterpret as a mutable reference to skip the safety copy of the readonly value
destVectors[countWithoutLastItem] = Unsafe.AsRef(sourcePixels[countWithoutLastItem]).ToVector4();
// TODO: Investigate optimized 1-pass approach! // TODO: Investigate optimized 1-pass approach!
ApplyForwardConversionModifiers(destVectors, modifiers); ApplyForwardConversionModifiers(destVectors, modifiers);
@ -126,4 +127,4 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
} }
} }
} }
} }

2
src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs

@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan, this.modifiers); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan, this.modifiers);
// Run the user defined pixel shader to the current row of pixels // Run the user defined pixel shader to the current row of pixels
this.rowProcessor.Invoke(vectorSpan, new Point(this.startX, y)); Unsafe.AsRef(this.rowProcessor).Invoke(vectorSpan, new Point(this.startX, y));
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers);
} }

6
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
this.pinHandle.Dispose(); Unsafe.AsRef(this.pinHandle).Dispose();
this.data.Dispose(); this.data.Dispose();
} }
@ -248,4 +248,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return new ResizeKernel(left, rowPtr, length); return new ResizeKernel(left, rowPtr, length);
} }
} }
} }

Loading…
Cancel
Save