using System; using System.Numerics; using RGB.NET.Core; namespace RGB.NET.Presets.Textures.Sampler; /// /// Represents a sampled that averages multiple float-data entries. /// public sealed class AverageFloatSampler : ISampler { #region Methods /// public unsafe void Sample(in SamplerInfo info, in Span pixelData) { int count = info.Width * info.Height; if (count == 0) return; int dataLength = pixelData.Length; Span sums = stackalloc float[dataLength]; int elementsPerVector = Vector.Count / dataLength; int valuesPerVector = elementsPerVector * dataLength; if (Vector.IsHardwareAccelerated && (info.Height > 1) && (info.Width >= valuesPerVector) && (dataLength <= Vector.Count)) { int chunks = info.Width / elementsPerVector; Vector sum = Vector.Zero; for (int y = 0; y < info.Height; y++) { ReadOnlySpan data = info[y]; fixed (float* colorPtr = data) { float* current = colorPtr; for (int i = 0; i < chunks; i++) { sum = Vector.Add(sum, *(Vector*)current); current += valuesPerVector; } } int missingElements = data.Length - (chunks * valuesPerVector); int offset = chunks * valuesPerVector; for (int i = 0; i < missingElements; i += dataLength) for (int j = 0; j < sums.Length; j++) sums[j] += data[offset + i + j]; } for (int i = 0; i < valuesPerVector; i += dataLength) for (int j = 0; j < sums.Length; j++) sums[j] += sum[i + j]; } else { for (int y = 0; y < info.Height; y++) { ReadOnlySpan data = info[y]; for (int i = 0; i < data.Length; i += dataLength) for (int j = 0; j < sums.Length; j++) sums[j] += data[i + j]; } } for (int i = 0; i < pixelData.Length; i++) pixelData[i] = sums[i] / count; } #endregion }