コード例 #1
0
            /// <inheritdoc />
            internal override void ToVector4(BufferSpan <Color> sourceColors, BufferSpan <Vector4> destVectors, int count)
            {
                if (count < 256 || !Vector.IsHardwareAccelerated)
                {
                    // Doesn't worth to bother with SIMD:
                    base.ToVector4(sourceColors, destVectors, count);
                    return;
                }

                int remainder = count % Vector <uint> .Count;

                int alignedCount = count - remainder;

                if (alignedCount > 0)
                {
                    ToVector4SimdAligned(sourceColors, destVectors, alignedCount);
                }

                if (remainder > 0)
                {
                    sourceColors = sourceColors.Slice(alignedCount);
                    destVectors  = destVectors.Slice(alignedCount);
                    base.ToVector4(sourceColors, destVectors, remainder);
                }
            }
コード例 #2
0
        public static unsafe void Copy <T>(BufferSpan <T> source, BufferSpan <T> destination, int count)
            where T : struct
        {
            DebugGuard.MustBeLessThanOrEqualTo(count, source.Length, nameof(count));
            DebugGuard.MustBeLessThanOrEqualTo(count, destination.Length, nameof(count));

            ref byte srcRef  = ref Unsafe.As <T, byte>(ref source.DangerousGetPinnableReference());
コード例 #3
0
ファイル: BufferSpan.cs プロジェクト: vovgou/ImageSharp
        private static unsafe void CopyImpl <T, TDest>(BufferSpan <T> source, BufferSpan <TDest> destination, int count)
            where T : struct
            where TDest : struct
        {
            int byteCount = SizeOf <T>(count);

            if (byteCount > ByteCountThreshold)
            {
                if (Unsafe.SizeOf <T>() == sizeof(long))
                {
                    Marshal.Copy(Unsafe.As <long[]>(source.Array), source.Start, destination.PointerAtOffset, count);
                    return;
                }
                else if (Unsafe.SizeOf <T>() == sizeof(int))
                {
                    Marshal.Copy(Unsafe.As <int[]>(source.Array), source.Start, destination.PointerAtOffset, count);
                    return;
                }
                else if (Unsafe.SizeOf <T>() == sizeof(short))
                {
                    Marshal.Copy(Unsafe.As <short[]>(source.Array), source.Start, destination.PointerAtOffset, count);
                    return;
                }
                else if (Unsafe.SizeOf <T>() == sizeof(byte))
                {
                    Marshal.Copy(Unsafe.As <byte[]>(source.Array), source.Start, destination.PointerAtOffset, count);
                    return;
                }
            }

            Unsafe.CopyBlock((void *)destination.PointerAtOffset, (void *)source.PointerAtOffset, (uint)byteCount);
        }
コード例 #4
0
 private void CopyFromXyzw(PixelArea <TColor> area, int targetX, int targetY, int width, int height)
 {
     for (int y = 0; y < height; y++)
     {
         BufferSpan <byte>   source      = area.GetRowSpan(y);
         BufferSpan <TColor> destination = this.GetRowSpan(targetX, targetY + y);
         Operations.PackFromXyzwBytes(source, destination, width);
     }
 }
コード例 #5
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="BufferSpan{T}"/> to the source colors.</param>
            /// <param name="destVectors">The <see cref="BufferSpan{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 unsafe void ToVector4SimdAligned(
                BufferSpan <Color> sourceColors,
                BufferSpan <Vector4> destVectors,
                int count)
            {
                if (!Vector.IsHardwareAccelerated)
                {
                    throw new InvalidOperationException(
                              "Color.BulkOperations.ToVector4SimdAligned() should not be called when Vector.IsHardwareAccelerated == false!");
                }

                int vecSize = Vector <uint> .Count;

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

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

                int unpackedRawCount = count * 4;

                uint *src    = (uint *)sourceColors.PointerAtOffset;
                uint *srcEnd = src + count;

                using (PinnedBuffer <uint> tempBuf = new PinnedBuffer <uint>(
                           unpackedRawCount + Vector <uint> .Count))
                {
                    uint *        tPtr  = (uint *)tempBuf.Pointer;
                    uint[]        temp  = tempBuf.Array;
                    float[]       fTemp = Unsafe.As <float[]>(temp);
                    UnpackedRGBA *dst   = (UnpackedRGBA *)tPtr;

                    for (; src < srcEnd; src++, dst++)
                    {
                        // This call is the bottleneck now:
                        dst->Load(*src);
                    }

                    for (int i = 0; i < unpackedRawCount; i += vecSize)
                    {
                        Vector <uint> vi = new Vector <uint>(temp, i);

                        vi &= mask;
                        vi |= magicInt;

                        Vector <float> vf = Vector.AsVectorSingle(vi);
                        vf = (vf - magicFloat) * bVec;
                        vf.CopyTo(fTemp, i);
                    }

                    BufferSpan.Copy <uint>(tempBuf, (BufferSpan <byte>)destVectors, unpackedRawCount);
                }
            }
コード例 #6
0
 private void CopyToXyzw(PixelArea <TColor> area, int sourceX, int sourceY, int width, int height)
 {
     for (int y = 0; y < height; y++)
     {
         BufferSpan <TColor> source      = this.GetRowSpan(sourceX, sourceY + y);
         BufferSpan <byte>   destination = area.GetRowSpan(y);
         Operations.ToXyzwBytes(source, destination, width);
     }
 }
コード例 #7
0
        /// <summary>
        /// Returns a reference to specified element of the span.
        /// </summary>
        /// <param name="index">The index</param>
        /// <returns>The reference to the specified element</returns>
        public ref T this[int index]
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                DebugGuard.MustBeLessThan(index, this.Length, nameof(index));

                byte *ptr = (byte *)this.PointerAtOffset + BufferSpan.SizeOf <T>(index);
                return(ref Unsafe.AsRef <T>(ptr));
            }
        }
コード例 #8
0
        public BufferSpan <T> Slice(int start)
        {
            DebugGuard.MustBeLessThan(start, this.Length, nameof(start));

            BufferSpan <T> result = default(BufferSpan <T>);

            result.Array           = this.Array;
            result.Start           = this.Start + start;
            result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf <T>() * start);
            result.Length          = this.Length - start;
            return(result);
        }
コード例 #9
0
        /// <summary>
        /// Bulk version of <see cref="IPixel.ToZyxBytes(byte[], int)"/>.
        /// </summary>
        /// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
        /// <param name="destBytes">The <see cref="BufferSpan{T}"/> to the destination bytes.</param>
        /// <param name="count">The number of pixels to convert.</param>
        internal virtual void ToZyxBytes(BufferSpan <TColor> sourceColors, BufferSpan <byte> destBytes, int count)
        {
            byte *sp = (byte *)sourceColors;

            byte[] dest = destBytes.Array;

            for (int i = destBytes.Start; i < destBytes.Start + (count * 3); i += 3)
            {
                TColor c = Unsafe.Read <TColor>(sp);
                c.ToZyxBytes(dest, i);
                sp += ColorSize;
            }
        }
コード例 #10
0
            /// <inheritdoc />
            internal override unsafe void PackFromZyxwBytes(BufferSpan <byte> sourceBytes, BufferSpan <Color> destColors, int count)
            {
                byte *source      = (byte *)sourceBytes;
                byte *destination = (byte *)destColors;

                for (int x = 0; x < count; x++)
                {
                    Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24));

                    source      += 4;
                    destination += 4;
                }
            }
コード例 #11
0
        public void Clear(int count)
        {
            DebugGuard.MustBeLessThanOrEqualTo(count, this.Length, nameof(count));

            if (count < 256)
            {
                Unsafe.InitBlock((void *)this.PointerAtOffset, 0, BufferSpan.USizeOf <T>(count));
            }
            else
            {
                System.Array.Clear(this.Array, this.Start, count);
            }
        }
コード例 #12
0
ファイル: BufferSpan.cs プロジェクト: vovgou/ImageSharp
        public static unsafe void Copy <T>(BufferSpan <byte> source, BufferSpan <T> destination, int countInDest)
            where T : struct
        {
            int byteCount = SizeOf <T>(countInDest);

            if (byteCount > (int)ByteCountThreshold)
            {
                Marshal.Copy(source.Array, source.Start, destination.PointerAtOffset, byteCount);
            }
            else
            {
                Unsafe.CopyBlock((void *)destination.PointerAtOffset, (void *)source.PointerAtOffset, (uint)byteCount);
            }
        }
コード例 #13
0
            /// <inheritdoc />
            internal override unsafe void ToZyxBytes(BufferSpan <Color> sourceColors, BufferSpan <byte> destBytes, int count)
            {
                byte *source      = (byte *)sourceColors;
                byte *destination = (byte *)destBytes;

                for (int x = 0; x < count; x++)
                {
                    *destination = *(source + 2);
                    *(destination + 1) = *(source + 1);
                    *(destination + 2) = *(source + 0);

                    source      += 4;
                    destination += 3;
                }
            }
コード例 #14
0
        /// <summary>
        /// Bulk version of <see cref="IPixel.ToVector4()"/>.
        /// </summary>
        /// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
        /// <param name="destVectors">The <see cref="BufferSpan{T}"/> to the destination vectors.</param>
        /// <param name="count">The number of pixels to convert.</param>
        internal virtual void ToVector4(
            BufferSpan <TColor> sourceColors,
            BufferSpan <Vector4> destVectors,
            int count)
        {
            byte *   sp = (byte *)sourceColors;
            Vector4 *dp = (Vector4 *)destVectors.PointerAtOffset;

            for (int i = 0; i < count; i++)
            {
                TColor c = Unsafe.Read <TColor>(sp);
                *dp = c.ToVector4();
                sp += ColorSize;
                dp++;
            }
        }
コード例 #15
0
        /// <summary>
        /// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyz"/>.
        /// </summary>
        /// <param name="sourceBytes">The <see cref="BufferSpan{T}"/> to the source bytes.</param>
        /// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
        /// <param name="count">The number of pixels to convert.</param>
        internal virtual void PackFromXyzBytes(
            BufferSpan <byte> sourceBytes,
            BufferSpan <TColor> destColors,
            int count)
        {
            byte *sp = (byte *)sourceBytes;
            byte *dp = (byte *)destColors.PointerAtOffset;

            for (int i = 0; i < count; i++)
            {
                TColor c = default(TColor);
                c.PackFromBytes(sp[0], sp[1], sp[2], 255);
                Unsafe.Write(dp, c);
                sp += 3;
                dp += ColorSize;
            }
        }
コード例 #16
0
        /// <summary>
        /// Bulk version of <see cref="IPixel.PackFromVector4(Vector4)"/>
        /// </summary>
        /// <param name="sourceVectors">The <see cref="BufferSpan{T}"/> to the source vectors.</param>
        /// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
        /// <param name="count">The number of pixels to convert.</param>
        internal virtual void PackFromVector4(
            BufferSpan <Vector4> sourceVectors,
            BufferSpan <TColor> destColors,
            int count)
        {
            Vector4 *sp = (Vector4 *)sourceVectors.PointerAtOffset;
            byte *   dp = (byte *)destColors;

            for (int i = 0; i < count; i++)
            {
                Vector4 v = Unsafe.Read <Vector4>(sp);
                TColor  c = default(TColor);
                c.PackFromVector4(v);
                Unsafe.Write(dp, c);

                sp++;
                dp += ColorSize;
            }
        }
コード例 #17
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="BufferSpan{T}"/> to the source colors.</param>
            /// <param name="destVectors">The <see cref="BufferSpan{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(BufferSpan <Rgba32> sourceColors, BufferSpan <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!");

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

                int unpackedRawCount = count * 4;

                ref uint           sourceBase         = ref Unsafe.As <Rgba32, uint>(ref sourceColors.DangerousGetPinnableReference());
コード例 #18
0
 /// <summary>
 /// Bulk version of <see cref="IPixel.PackFromVector4(Vector4)"/>
 /// </summary>
 /// <param name="sourceVectors">The <see cref="BufferSpan{T}"/> to the source vectors.</param>
 /// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
 /// <param name="count">The number of pixels to convert.</param>
 internal virtual void PackFromVector4(BufferSpan <Vector4> sourceVectors, BufferSpan <TColor> destColors, int count)
 {
     ref Vector4 sourceRef = ref sourceVectors.DangerousGetPinnableReference();
コード例 #19
0
 /// <summary>
 /// Copies the pixels to another <see cref="PixelAccessor{TColor}"/> of the same size.
 /// </summary>
 /// <param name="target">The target pixel buffer accessor.</param>
 internal void CopyTo(PixelAccessor <TColor> target)
 {
     BufferSpan.Copy(this.pixelBuffer.Span, target.pixelBuffer.Span);
 }
コード例 #20
0
 /// <inheritdoc />
 internal override void PackFromXyzwBytes(BufferSpan <byte> sourceBytes, BufferSpan <Color> destColors, int count)
 {
     BufferSpan.Copy(sourceBytes, destColors, count);
 }
コード例 #21
0
 public static ref Vector <T> FetchVector <T>(this BufferSpan <T> span)
     where T : struct
 {
     return(ref Unsafe.As <T, Vector <T> >(ref span.DangerousGetPinnableReference()));
 }
コード例 #22
0
 /// <inheritdoc />
 internal override void ToXyzwBytes(BufferSpan <Color> sourceColors, BufferSpan <byte> destBytes, int count)
 {
     BufferSpan.Copy(sourceColors, destBytes, count);
 }
コード例 #23
0
ファイル: BufferSpan.cs プロジェクト: vovgou/ImageSharp
 public static void Copy <T>(BufferSpan <T> source, BufferSpan <byte> destination, int countInSource)
     where T : struct
 {
     CopyImpl(source, destination, countInSource);
 }
コード例 #24
0
 /// <inheritdoc />
 internal override unsafe void ToVector4(BufferSpan <ColorVector> sourceColors, BufferSpan <Vector4> destVectors, int count)
 {
     BufferSpan.Copy(sourceColors.AsBytes(), destVectors.AsBytes(), count * sizeof(Vector4));
 }