Esempio n. 1
0
        /// <summary>
        /// Convert 'source.Length' <see cref="float"/> values normalized into [0..1] from 'source' into 'dest' buffer of <see cref="byte"/> values.
        /// The values gonna be scaled up into [0-255] and rounded.
        /// Based on:
        /// <see>
        ///     <cref>http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions</cref>
        /// </see>
        /// </summary>
        internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan <float> source, Span <byte> dest)
        {
            GuardAvx2(nameof(BulkConvertNormalizedFloatToByte));

            DebugGuard.IsTrue((source.Length % Vector <float> .Count) == 0, nameof(source), "source.Length should be divisable by Vector<float>.Count!");

            if (source.Length == 0)
            {
                return;
            }

            ref Vector <float> srcBase  = ref Unsafe.As <float, Vector <float> >(ref source.DangerousGetPinnableReference());
Esempio n. 2
0
        internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan <float> source, Span <byte> dest)
        {
            DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

#if SUPPORTS_EXTENDED_INTRINSICS
            ExtendedIntrinsics.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest);
#else
            BasicIntrinsics256.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest);
#endif
            FallbackIntrinsics128.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest);

            // Deal with the remainder:
            if (source.Length > 0)
            {
                ConvertNormalizedFloatToByteRemainder(source, dest);
            }
        }
Esempio n. 3
0
        internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan <byte> source, Span <float> dest)
        {
            DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

#if NETCOREAPP2_1
            ExtendedIntrinsics.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest);
#else
            BasicIntrinsics256.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest);
#endif
            FallbackIntrinsics128.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest);

            // Deal with the remainder:
            if (source.Length > 0)
            {
                ConverByteToNormalizedFloatRemainder(source, dest);
            }
        }
Esempio n. 4
0
        internal static void ByteToNormalizedFloat(ReadOnlySpan <byte> source, Span <float> dest)
        {
            DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

#if SUPPORTS_EXTENDED_INTRINSICS
            ExtendedIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest);
#else
            BasicIntrinsics256.ByteToNormalizedFloatReduce(ref source, ref dest);
#endif

            // Also deals with the remainder from previous conversions:
            FallbackIntrinsics128.ByteToNormalizedFloatReduce(ref source, ref dest);

            // Deal with the remainder:
            if (source.Length > 0)
            {
                ConvertByteToNormalizedFloatRemainder(source, dest);
            }
        }
            internal static void BulkConvertNormalizedFloatToByteClampOverflowsReduce(
                ref ReadOnlySpan <float> source,
                ref Span <byte> dest)
            {
                DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

                int remainder     = ImageMaths.Modulo4(source.Length);
                int adjustedCount = source.Length - remainder;

                if (adjustedCount > 0)
                {
                    BulkConvertNormalizedFloatToByteClampOverflows(
                        source.Slice(0, adjustedCount),
                        dest.Slice(0, adjustedCount));

                    source = source.Slice(adjustedCount);
                    dest   = dest.Slice(adjustedCount);
                }
            }
            internal static void NormalizedFloatToByteSaturateReduce(
                ref ReadOnlySpan <float> source,
                ref Span <byte> dest)
            {
                DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

                int remainder     = Numerics.Modulo4(source.Length);
                int adjustedCount = source.Length - remainder;

                if (adjustedCount > 0)
                {
                    NormalizedFloatToByteSaturate(
                        source.Slice(0, adjustedCount),
                        dest.Slice(0, adjustedCount));

                    source = source.Slice(adjustedCount);
                    dest   = dest.Slice(adjustedCount);
                }
            }
Esempio n. 7
0
            /// <summary>
            /// SIMD optimized bulk implementation of <see cref="IPixel.PackFromVector4(Vector4)"/>
            /// that works only with `count` divisible by <see cref="Vector{UInt32}.Count"/>.
            /// </summary>
            /// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
            /// <param name="destVectors">The <see cref="Span{T}"/> to the dstination vectors.</param>
            /// <param name="count">The number of pixels to convert.</param>
            /// <remarks>
            /// Implementation adapted from:
            /// <see>
            ///     <cref>http://stackoverflow.com/a/5362789</cref>
            /// </see>
            /// TODO: We can replace this implementation in the future using new Vector API-s:
            /// <see>
            ///     <cref>https://github.com/dotnet/corefx/issues/15957</cref>
            /// </see>
            /// </remarks>
            internal static void ToVector4SimdAligned(Span <Rgba32> sourceColors, Span <Vector4> destVectors, int count)
            {
                if (!Vector.IsHardwareAccelerated)
                {
                    throw new InvalidOperationException(
                              "Rgba32.PixelOperations.ToVector4SimdAligned() should not be called when Vector.IsHardwareAccelerated == false!");
                }

                DebugGuard.IsTrue(
                    count % Vector <uint> .Count == 0,
                    nameof(count),
                    "Argument 'count' should divisible by Vector<uint>.Count!");

                var bVec       = new Vector <float>(256.0f / 255.0f);
                var magicFloat = new Vector <float>(32768.0f);
                var magicInt   = new Vector <uint>(1191182336); // reinterpreded value of 32768.0f
                var mask       = new Vector <uint>(255);

                int unpackedRawCount = count * 4;

                ref uint           sourceBase         = ref Unsafe.As <Rgba32, uint>(ref sourceColors.DangerousGetPinnableReference());
            internal static void BulkConvertByteToNormalizedFloatReduce(
                ref ReadOnlySpan <byte> source,
                ref Span <float> dest)
            {
                DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");

                if (!IsAvailable)
                {
                    return;
                }

                int remainder     = ImageMaths.ModuloP2(source.Length, Vector <byte> .Count);
                int adjustedCount = source.Length - remainder;

                if (adjustedCount > 0)
                {
                    BulkConvertByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount));

                    source = source.Slice(adjustedCount);
                    dest   = dest.Slice(adjustedCount);
                }
            }
Esempio n. 9
0
        internal static void PackFromRgbPlanes(
            Configuration configuration,
            ReadOnlySpan <byte> redChannel,
            ReadOnlySpan <byte> greenChannel,
            ReadOnlySpan <byte> blueChannel,
            Span <Rgba32> destination)
        {
            DebugGuard.IsTrue(greenChannel.Length == redChannel.Length, nameof(greenChannel), "Channels must be of same size!");
            DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!");
            DebugGuard.IsTrue(destination.Length > redChannel.Length, nameof(destination), "'destination' span should not be shorter than the source channels!");

#if SUPPORTS_RUNTIME_INTRINSICS
            if (Avx2.IsSupported)
            {
                HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
            }
            else
#endif
            {
                PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
            }

            PackFromRgbPlanesRemainder(redChannel, greenChannel, blueChannel, destination);
        }