Skip to content

Commit 71e3ac1

Browse files
Merge pull request #1131 from SixLabors/sp/generic-octet
Generic Octet<T> struct
2 parents 9f59241 + ab4211f commit 71e3ac1

File tree

5 files changed

+95
-134
lines changed

5 files changed

+95
-134
lines changed

src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,17 @@ internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan<byte> source,
9494
var magicInt = new Vector<uint>(1191182336); // reinterpreted value of 32768.0f
9595
var mask = new Vector<uint>(255);
9696

97-
ref Octet.OfByte sourceBase = ref Unsafe.As<byte, Octet.OfByte>(ref MemoryMarshal.GetReference(source));
98-
ref Octet.OfUInt32 destBaseAsWideOctet = ref Unsafe.As<float, Octet.OfUInt32>(ref MemoryMarshal.GetReference(dest));
97+
ref Octet<byte> sourceBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(source));
98+
ref Octet<uint> destBaseAsWideOctet = ref Unsafe.As<float, Octet<uint>>(ref MemoryMarshal.GetReference(dest));
9999

100-
ref Vector<float> destBaseAsFloat = ref Unsafe.As<Octet.OfUInt32, Vector<float>>(ref destBaseAsWideOctet);
100+
ref Vector<float> destBaseAsFloat = ref Unsafe.As<Octet<uint>, Vector<float>>(ref destBaseAsWideOctet);
101101

102102
int n = dest.Length / 8;
103103

104104
for (int i = 0; i < n; i++)
105105
{
106-
ref Octet.OfByte s = ref Unsafe.Add(ref sourceBase, i);
107-
ref Octet.OfUInt32 d = ref Unsafe.Add(ref destBaseAsWideOctet, i);
106+
ref Octet<byte> s = ref Unsafe.Add(ref sourceBase, i);
107+
ref Octet<uint> d = ref Unsafe.Add(ref destBaseAsWideOctet, i);
108108
d.LoadFrom(ref s);
109109
}
110110

@@ -137,17 +137,17 @@ internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan
137137
}
138138

139139
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
140-
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref MemoryMarshal.GetReference(dest));
140+
ref Octet<byte> destBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(dest));
141141
int n = source.Length / 8;
142142

143143
var magick = new Vector<float>(32768.0f);
144144
var scale = new Vector<float>(255f) / new Vector<float>(256f);
145145

146146
// need to copy to a temporary struct, because
147-
// SimdUtils.Octet.OfUInt32 temp = Unsafe.As<Vector<float>, SimdUtils.Octet.OfUInt32>(ref x)
147+
// SimdUtils.Octet<uint> temp = Unsafe.As<Vector<float>, SimdUtils.Octet<uint>>(ref x)
148148
// does not work. TODO: This might be a CoreClr bug, need to ask/report
149-
var temp = default(Octet.OfUInt32);
150-
ref Vector<float> tempRef = ref Unsafe.As<Octet.OfUInt32, Vector<float>>(ref temp);
149+
var temp = default(Octet<uint>);
150+
ref Vector<float> tempRef = ref Unsafe.As<Octet<uint>, Vector<float>>(ref temp);
151151

152152
for (int i = 0; i < n; i++)
153153
{
@@ -161,7 +161,7 @@ internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan
161161
x = (x * scale) + magick;
162162
tempRef = x;
163163

164-
ref Octet.OfByte d = ref Unsafe.Add(ref destBase, i);
164+
ref Octet<byte> d = ref Unsafe.Add(ref destBase, i);
165165
d.LoadFrom(ref temp);
166166
}
167167
}
@@ -186,17 +186,17 @@ internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan<float> source
186186
}
187187

188188
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
189-
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref MemoryMarshal.GetReference(dest));
189+
ref Octet<byte> destBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(dest));
190190
int n = source.Length / 8;
191191

192192
var magick = new Vector<float>(32768.0f);
193193
var scale = new Vector<float>(255f) / new Vector<float>(256f);
194194

195195
// need to copy to a temporary struct, because
196-
// SimdUtils.Octet.OfUInt32 temp = Unsafe.As<Vector<float>, SimdUtils.Octet.OfUInt32>(ref x)
196+
// SimdUtils.Octet<uint> temp = Unsafe.As<Vector<float>, SimdUtils.Octet<uint>>(ref x)
197197
// does not work. TODO: This might be a CoreClr bug, need to ask/report
198-
var temp = default(Octet.OfUInt32);
199-
ref Vector<float> tempRef = ref Unsafe.As<Octet.OfUInt32, Vector<float>>(ref temp);
198+
var temp = default(Octet<uint>);
199+
ref Vector<float> tempRef = ref Unsafe.As<Octet<uint>, Vector<float>>(ref temp);
200200

201201
for (int i = 0; i < n; i++)
202202
{
@@ -207,7 +207,7 @@ internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan<float> source
207207
x = (x * scale) + magick;
208208
tempRef = x;
209209

210-
ref Octet.OfByte d = ref Unsafe.Add(ref destBase, i);
210+
ref Octet<byte> d = ref Unsafe.Add(ref destBase, i);
211211
d.LoadFrom(ref temp);
212212
}
213213
}

src/ImageSharp/Common/Tuples/Octet.cs

Lines changed: 0 additions & 112 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) Six Labors and contributors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
7+
namespace SixLabors.ImageSharp.Tuples
8+
{
9+
/// <summary>
10+
/// Contains 8 element value tuples of various types.
11+
/// </summary>
12+
[StructLayout(LayoutKind.Sequential)]
13+
internal struct Octet<T>
14+
where T : unmanaged
15+
{
16+
public T V0;
17+
public T V1;
18+
public T V2;
19+
public T V3;
20+
public T V4;
21+
public T V5;
22+
public T V6;
23+
public T V7;
24+
25+
/// <inheritdoc/>
26+
public override readonly string ToString()
27+
{
28+
return $"Octet<{typeof(T)}>({this.V0},{this.V1},{this.V2},{this.V3},{this.V4},{this.V5},{this.V6},{this.V7})";
29+
}
30+
}
31+
32+
/// <summary>
33+
/// Extension methods for the <see cref="Octet{T}"/> type.
34+
/// </summary>
35+
internal static class OctetExtensions
36+
{
37+
/// <summary>
38+
/// Loads the fields in a target <see cref="Octet{T}"/> of <see cref="uint"/> from one of <see cref="byte"/> type.
39+
/// </summary>
40+
/// <param name="destination">The target <see cref="Octet{T}"/> of <see cref="uint"/> instance.</param>
41+
/// <param name="source">The source <see cref="Octet{T}"/> of <see cref="byte"/> instance.</param>
42+
[MethodImpl(InliningOptions.ShortMethod)]
43+
public static void LoadFrom(ref this Octet<uint> destination, ref Octet<byte> source)
44+
{
45+
destination.V0 = source.V0;
46+
destination.V1 = source.V1;
47+
destination.V2 = source.V2;
48+
destination.V3 = source.V3;
49+
destination.V4 = source.V4;
50+
destination.V5 = source.V5;
51+
destination.V6 = source.V6;
52+
destination.V7 = source.V7;
53+
}
54+
55+
/// <summary>
56+
/// Loads the fields in a target <see cref="Octet{T}"/> of <see cref="byte"/> from one of <see cref="uint"/> type.
57+
/// </summary>
58+
/// <param name="destination">The target <see cref="Octet{T}"/> of <see cref="byte"/> instance.</param>
59+
/// <param name="source">The source <see cref="Octet{T}"/> of <see cref="uint"/> instance.</param>
60+
[MethodImpl(InliningOptions.ShortMethod)]
61+
public static void LoadFrom(ref this Octet<byte> destination, ref Octet<uint> source)
62+
{
63+
destination.V0 = (byte)source.V0;
64+
destination.V1 = (byte)source.V1;
65+
destination.V2 = (byte)source.V2;
66+
destination.V3 = (byte)source.V3;
67+
destination.V4 = (byte)source.V4;
68+
destination.V5 = (byte)source.V5;
69+
destination.V6 = (byte)source.V6;
70+
destination.V7 = (byte)source.V7;
71+
}
72+
}
73+
}

tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ public void Bitops_SingleTuple()
233233
// [Benchmark]
234234
public void Bitops_Simd()
235235
{
236-
ref Octet.OfUInt32 sBase = ref Unsafe.As<Rgba32, Octet.OfUInt32>(ref this.source[0]);
237-
ref Octet.OfUInt32 dBase = ref Unsafe.As<Bgra32, Octet.OfUInt32>(ref this.dest[0]);
236+
ref Octet<uint> sBase = ref Unsafe.As<Rgba32, Octet<uint>>(ref this.source[0]);
237+
ref Octet<uint> dBase = ref Unsafe.As<Bgra32, Octet<uint>>(ref this.dest[0]);
238238

239239
for (int i = 0; i < this.Count / 8; i++)
240240
{
@@ -257,9 +257,9 @@ private struct C
257257
#pragma warning restore SA1132 // Do not combine fields
258258

259259
[MethodImpl(MethodImplOptions.AggressiveInlining)]
260-
private static void BitopsSimdImpl(ref Octet.OfUInt32 s, ref Octet.OfUInt32 d)
260+
private static void BitopsSimdImpl(ref Octet<uint> s, ref Octet<uint> d)
261261
{
262-
Vector<uint> sVec = Unsafe.As<Octet.OfUInt32, Vector<uint>>(ref s);
262+
Vector<uint> sVec = Unsafe.As<Octet<uint>, Vector<uint>>(ref s);
263263
var aMask = new Vector<uint>(0xFF00FF00);
264264
var bMask = new Vector<uint>(0x00FF00FF);
265265

@@ -282,7 +282,7 @@ private static void BitopsSimdImpl(ref Octet.OfUInt32 s, ref Octet.OfUInt32 d)
282282
Vector<uint> cc = Unsafe.As<C, Vector<uint>>(ref c);
283283
Vector<uint> dd = aa + cc;
284284

285-
d = Unsafe.As<Vector<uint>, Octet.OfUInt32>(ref dd);
285+
d = Unsafe.As<Vector<uint>, Octet<uint>>(ref dd);
286286
}
287287

288288
// [Benchmark]

tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public void Standard()
3131
{
3232
const int N = Count / 8;
3333

34-
ref Octet.OfByte sBase = ref Unsafe.As<byte, Octet.OfByte>(ref this.source[0]);
35-
ref Octet.OfUInt32 dBase = ref Unsafe.As<uint, Octet.OfUInt32>(ref this.dest[0]);
34+
ref Octet<byte> sBase = ref Unsafe.As<byte, Octet<byte>>(ref this.source[0]);
35+
ref Octet<uint> dBase = ref Unsafe.As<uint, Octet<uint>>(ref this.dest[0]);
3636

3737
for (int i = 0; i < N; i++)
3838
{

0 commit comments

Comments
 (0)