internal static void FromVector4 <TPixel>( Configuration configuration, PixelOperations <TPixel> pixelOperations, ReadOnlySpan <Vector4> sourceVectors, Span <TPixel> destPixels, bool scaled) where TPixel : struct, IPixel <TPixel> { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); int count = sourceVectors.Length; // Not worth for small buffers: if (count < Vector4ConversionThreshold) { FromVector4Fallback(sourceVectors, destPixels, scaled); 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)) { Span <Rgba32> tempSpan = tempBuffer.Memory.Span; SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast <Vector4, float>(sourceVectors), MemoryMarshal.Cast <Rgba32, byte>(tempSpan)); pixelOperations.FromRgba32(configuration, tempSpan, destPixels); } }
/// <inheritdoc /> internal override void PackFromVector4(ReadOnlySpan <Vector4> sourceVectors, Span <Rgba32> destinationColors, int count) { GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count); sourceVectors = sourceVectors.Slice(0, count); destinationColors = destinationColors.Slice(0, count); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast <Vector4, float>(sourceVectors), MemoryMarshal.Cast <Rgba32, byte>(destinationColors)); }
/// <inheritdoc /> internal override void FromVector4( Configuration configuration, ReadOnlySpan <Vector4> sourceVectors, Span <Rgba32> destPixels) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); destPixels = destPixels.Slice(0, sourceVectors.Length); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast <Vector4, float>(sourceVectors), MemoryMarshal.Cast <Rgba32, byte>(destPixels)); }
/// <inheritdoc /> internal override void FromVector4Destructive( Configuration configuration, Span <Vector4> sourceVectors, Span <Rgba32> destPixels, PixelConversionModifiers modifiers) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); destPixels = destPixels.Slice(0, sourceVectors.Length); Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast <Vector4, float>(sourceVectors), MemoryMarshal.Cast <Rgba32, byte>(destPixels)); }
public void BulkConvertNormalizedFloatToByteClampOverflows(int count) { TestImpl_BulkConvertNormalizedFloatToByteClampOverflows(count, (s, d) => SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(s.Span, d.Span)); // For small values, let's stress test the implementation a bit: if (count > 0 && count < 10) { for (int i = 0; i < 20; i++) { TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( count, (s, d) => SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(s.Span, d.Span), i + 42); } } }
public void BulkConvertNormalizedFloatToByteClampOverflows(int seed, int count) { if (this.SkipOnNonAvx2()) { return; } float[] orig = new Random(seed).GenerateRandomRoundedFloatArray(count, -50, 444); float[] normalized = orig.Select(f => f / 255f).ToArray(); byte[] dest = new byte[count]; SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(normalized, dest); byte[] expected = orig.Select(f => (byte)Clamp255(f)).ToArray(); Assert.Equal(expected, dest); }
internal static void FromVector4 <TPixel>( Configuration configuration, PixelOperations <TPixel> pixelOperations, Span <Vector4> sourceVectors, Span <TPixel> destPixels, PixelConversionModifiers modifiers) where TPixel : unmanaged, IPixel <TPixel> { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); int count = sourceVectors.Length; // Not worth for small buffers: if (count < Vector4ConversionThreshold) { Default.UnsafeFromVector4(sourceVectors, destPixels, modifiers); return; } // TODO: Investigate optimized 1-pass approach! ApplyBackwardConversionModifiers(sourceVectors, modifiers); // 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)) { Span <Rgba32> tempSpan = tempBuffer.Memory.Span; SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast <Vector4, float>(sourceVectors), MemoryMarshal.Cast <Rgba32, byte>(tempSpan)); pixelOperations.FromRgba32(configuration, tempSpan, destPixels); } }