diff --git a/src/ImageSharp/Common/Memory/BufferSpan.cs b/src/ImageSharp/Common/Memory/BufferSpan.cs
index c51c110be4..f8a5453a8d 100644
--- a/src/ImageSharp/Common/Memory/BufferSpan.cs
+++ b/src/ImageSharp/Common/Memory/BufferSpan.cs
@@ -6,6 +6,7 @@
namespace ImageSharp
{
using System;
+ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -14,6 +15,19 @@ namespace ImageSharp
///
internal static class BufferSpan
{
+ ///
+ /// Fetches a from the beginning of the span.
+ ///
+ /// The value type
+ /// The span to fetch the vector from
+ /// A reference to the beginning of the span
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref Vector FetchVector(this BufferSpan span)
+ where T : struct
+ {
+ return ref Unsafe.As>(ref span.DangerousGetPinnableReference());
+ }
+
///
/// Copy 'count' number of elements of the same type from 'source' to 'dest'
///
diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
index 9745d01338..372ac23922 100644
--- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
+++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
@@ -61,38 +61,33 @@ namespace ImageSharp
int unpackedRawCount = count * 4;
- ref uint src = ref Unsafe.As(ref sourceColors.DangerousGetPinnableReference());
+ ref uint bSource = ref Unsafe.As(ref sourceColors.DangerousGetPinnableReference());
+ ref UnpackedRGBA bDestUnpacked = ref Unsafe.As(ref destVectors.DangerousGetPinnableReference());
+ ref Vector bDestUint = ref Unsafe.As>(ref bDestUnpacked);
+ ref Vector bDestFloat = ref Unsafe.As>(ref bDestUnpacked);
- using (Buffer tempBuf = new Buffer(
- unpackedRawCount + Vector.Count))
+ for (int i = 0; i < count; i++)
{
- uint[] temp = tempBuf.Array;
- float[] fTemp = Unsafe.As(temp);
-
- ref UnpackedRGBA tempBase = ref Unsafe.As(ref tempBuf[0]);
+ uint sVal = Unsafe.Add(ref bSource, i);
+ ref UnpackedRGBA dst = ref Unsafe.Add(ref bDestUnpacked, i);
- for (int i = 0; i < count; i++)
- {
- uint sVal = Unsafe.Add(ref src, i);
- ref UnpackedRGBA dst = ref Unsafe.Add(ref tempBase, i);
+ // This call is the bottleneck now:
+ dst.Load(sVal);
+ }
- // This call is the bottleneck now:
- dst.Load(sVal);
- }
+ int n = unpackedRawCount / vecSize;
- for (int i = 0; i < unpackedRawCount; i += vecSize)
- {
- Vector vi = new Vector(temp, i);
+ for (int i = 0; i < n; i++)
+ {
+ Vector vi = Unsafe.Add(ref bDestUint, i);
- vi &= mask;
- vi |= magicInt;
+ vi &= mask;
+ vi |= magicInt;
- Vector vf = Vector.AsVectorSingle(vi);
- vf = (vf - magicFloat) * bVec;
- vf.CopyTo(fTemp, i);
- }
+ Vector vf = Vector.AsVectorSingle(vi);
+ vf = (vf - magicFloat) * bVec;
- BufferSpan.Copy(tempBuf.Span.AsBytes(), destVectors.AsBytes(), unpackedRawCount * sizeof(uint));
+ Unsafe.Add(ref bDestFloat, i) = vf;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
index efec90c996..d363769d01 100644
--- a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
+++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
@@ -57,7 +57,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
}
- public class PackFromXyzw_Color : PackFromXyzw
+ public class PackFromXyzw_Rgba32 : PackFromXyzw
{
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs
index e2c1ac7265..cd17975584 100644
--- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs
+++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs
@@ -57,7 +57,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
}
- public class ToVector4_Color : ToVector4
+ public class ToVector4_Rgba32 : ToVector4
{
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
index 88dac21cdf..663f85fb7c 100644
--- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
+++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
@@ -55,7 +55,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
}
- public class ToXyz_Color : ToXyz
+ public class ToXyz_Rgba32 : ToXyz
{
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
index 11545d3d95..7ac6211131 100644
--- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
+++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
@@ -59,11 +59,11 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
}
- public class ToXyzw_Color : ToXyzw
+ public class ToXyzw_Rgba32 : ToXyzw
{
}
- public class ToXyzw_Argb : ToXyzw
+ public class ToXyzw_Argb32 : ToXyzw
{
}
}
diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs
index 93f4095e96..e6d1a2fd01 100644
--- a/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs
+++ b/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs
@@ -86,5 +86,23 @@ namespace ImageSharp.Benchmarks.General.Vectorization
a = a * v;
}
}
+
+ [Benchmark]
+ public void FetchWithBufferSpanUtility()
+ {
+ Vector v = new Vector(this.testValue);
+
+ BufferSpan span = new BufferSpan(this.data);
+
+ ref Vector start = ref span.FetchVector();
+
+ int n = this.InputSize / Vector.Count;
+
+ for (int i = 0; i < n; i++)
+ {
+ ref Vector a = ref Unsafe.Add(ref start, i);
+ a = a * v;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs b/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs
index 3d03927536..4deeb40e85 100644
--- a/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs
+++ b/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs
@@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Colors
public class PixelOperationsTests
{
- public class Color32 : BulkPixelOperationsTests
+ public class Color32 : PixelOperationsTests
{
public Color32(ITestOutputHelper output)
: base(output)
@@ -20,7 +20,7 @@ namespace ImageSharp.Tests.Colors
}
// For 4.6 test runner MemberData does not work without redeclaring the public field in the derived test class:
- //public static new TheoryData ArraySizesData => new TheoryData { 7, 16, 1111 };
+ public static new TheoryData ArraySizesData => new TheoryData { 7, 16, 1111 };
[Fact]
public void IsSpecialImplementation()
@@ -60,7 +60,7 @@ namespace ImageSharp.Tests.Colors
}
}
- public class Argb : BulkPixelOperationsTests
+ public class Argb : PixelOperationsTests
{
// For 4.6 test runner MemberData does not work without redeclaring the public field in the derived test class:
public Argb(ITestOutputHelper output)
@@ -68,7 +68,7 @@ namespace ImageSharp.Tests.Colors
{
}
- //public static new TheoryData ArraySizesData => new TheoryData { 7, 16, 1111 };
+ public static new TheoryData ArraySizesData => new TheoryData { 7, 16, 1111 };
}
[Theory]
@@ -80,10 +80,10 @@ namespace ImageSharp.Tests.Colors
}
}
- public abstract class BulkPixelOperationsTests : MeasureFixture
+ public abstract class PixelOperationsTests : MeasureFixture
where TPixel : struct, IPixel
{
- protected BulkPixelOperationsTests(ITestOutputHelper output)
+ protected PixelOperationsTests(ITestOutputHelper output)
: base(output)
{
}
diff --git a/tests/ImageSharp.Tests/Common/BufferSpanTests.cs b/tests/ImageSharp.Tests/Common/BufferSpanTests.cs
index 3bc59df64a..e5fcbf9ffd 100644
--- a/tests/ImageSharp.Tests/Common/BufferSpanTests.cs
+++ b/tests/ImageSharp.Tests/Common/BufferSpanTests.cs
@@ -4,6 +4,7 @@
namespace ImageSharp.Tests.Common
{
using System;
+ using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.PixelFormats;
@@ -25,6 +26,21 @@ namespace ImageSharp.Tests.Common
}
}
+ [Fact]
+ public void FetchVector()
+ {
+ float[] stuff = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ BufferSpan span = new BufferSpan(stuff);
+
+ ref Vector v = ref span.FetchVector();
+
+ Assert.Equal(0, v[0]);
+ Assert.Equal(1, v[1]);
+ Assert.Equal(2, v[2]);
+ Assert.Equal(3, v[3]);
+ }
+
[Fact]
public void AsBytes()
{