/// <inheritdoc /> internal override void ToVector4(ReadOnlySpan <Rgba32> sourceColors, Span <Vector4> destinationVectors, int count) { Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); Guard.MustBeSizedAtLeast(destinationVectors, count, nameof(destinationVectors)); sourceColors = sourceColors.Slice(0, count); destinationVectors = destinationVectors.Slice(0, count); SimdUtils.BulkConvertByteToNormalizedFloat( MemoryMarshal.Cast <Rgba32, byte>(sourceColors), MemoryMarshal.Cast <Vector4, float>(destinationVectors)); }
/// <inheritdoc /> internal override void ToVector4( Configuration configuration, ReadOnlySpan <Rgba32> sourcePixels, Span <Vector4> destVectors) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); destVectors = destVectors.Slice(0, sourcePixels.Length); SimdUtils.BulkConvertByteToNormalizedFloat( MemoryMarshal.Cast <Rgba32, byte>(sourcePixels), MemoryMarshal.Cast <Vector4, float>(destVectors)); }
internal static void ToVector4 <TPixel>( Configuration configuration, PixelOperations <TPixel> pixelOperations, ReadOnlySpan <TPixel> sourcePixels, Span <Vector4> destVectors, PixelConversionModifiers modifiers) where TPixel : struct, IPixel <TPixel> { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); int count = sourcePixels.Length; // Not worth for small buffers: if (count < Vector4ConversionThreshold) { Default.UnsafeToVector4(sourcePixels, destVectors, modifiers); return; } // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation: int countWithoutLastItem = count - 1; ReadOnlySpan <TPixel> reducedSource = sourcePixels.Slice(0, countWithoutLastItem); Span <Rgba32> lastQuarterOfDestBuffer = MemoryMarshal.Cast <Vector4, Rgba32>(destVectors).Slice((3 * count) + 1, countWithoutLastItem); pixelOperations.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer); // 'destVectors' and 'lastQuarterOfDestBuffer' are overlapping buffers, // but we are always reading/writing at different positions: SimdUtils.BulkConvertByteToNormalizedFloat( MemoryMarshal.Cast <Rgba32, byte>(lastQuarterOfDestBuffer), MemoryMarshal.Cast <Vector4, float>(destVectors.Slice(0, countWithoutLastItem))); destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); // TODO: Investigate optimized 1-pass approach! ApplyForwardConversionModifiers(destVectors, modifiers); }
public void BulkConvertByteToNormalizedFloat(int count) { TestImpl_BulkConvertByteToNormalizedFloat( count, (s, d) => SimdUtils.BulkConvertByteToNormalizedFloat(s.Span, d.Span)); }