Пример #1
0
        /// <inheritdoc/>
        public override void GetData(Span <T> span, int offset, int count)
        {
            if (IsPaddingPresent)
            {
                // Create the temporary array
                byte[] temporaryArray = ArrayPool <byte> .Shared.Rent(count *PaddedElementSizeInBytes);

                Span <byte> temporarySpan = temporaryArray.AsSpan(0, count * PaddedElementSizeInBytes);

                // Copy the padded data to the temporary array
                Map(0);
                MemoryHelper.Copy(MappedResource, offset * PaddedElementSizeInBytes, temporarySpan, 0, count * PaddedElementSizeInBytes);
                Unmap(0);

                ref byte tin  = ref temporarySpan.GetPinnableReference();
                ref T    tout = ref span.GetPinnableReference();
 private void EnsureCpacity(int n)
 {
     if (n >= _capacity)
     {
         int  newCapacity = _capacity * 2;
         int *newEntries  = (int *)HeapAllocator.New(newCapacity * sizeof(int));
         MemoryHelper.Copy((byte *)_entries, (byte *)newEntries, _capacity * sizeof(int));
         HeapAllocator.Free((byte *)_entries);
         for (int i = _capacity; i < newCapacity; i++)
         {
             newEntries[i] = i + _idOffset;
         }
         _entries  = newEntries;
         _capacity = newCapacity;
     }
 }
Пример #3
0
    /// <summary>
    /// Reads the contents of the specified range from an input <see cref="ReadBackBuffer{T}"/> instance and writes them to the current the current <see cref="StructuredBuffer{T}"/> instance.
    /// </summary>
    /// <param name="source">The input <see cref="UploadBuffer{T}"/> instance to read data from.</param>
    /// <param name="sourceOffset">The starting offset within <paramref name="source"/> to read data from.</param>
    /// <param name="destinationOffset">The offset to start reading writing data to.</param>
    /// <param name="count">The number of items to read.</param>
    internal unsafe void CopyFrom(UploadBuffer <T> source, int sourceOffset, int destinationOffset, int count)
    {
        GraphicsDevice.ThrowIfDisposed();

        ThrowIfDisposed();

        source.ThrowIfDeviceMismatch(GraphicsDevice);
        source.ThrowIfDisposed();

        Guard.IsBetweenOrEqualTo(count, 0, Length);
        Guard.IsBetweenOrEqualTo(count, 0, source.Length);
        Guard.IsInRange(sourceOffset, 0, source.Length);
        Guard.IsLessThanOrEqualTo(sourceOffset + count, source.Length, nameof(sourceOffset));
        Guard.IsInRange(destinationOffset, 0, Length);
        Guard.IsLessThanOrEqualTo(destinationOffset + count, Length, nameof(destinationOffset));

        if (GraphicsDevice.IsCacheCoherentUMA)
        {
            using ID3D12ResourceMap resource = D3D12Resource->Map();

            MemoryHelper.Copy <T>(
                source: source.MappedData,
                destination: resource.Pointer,
                sourceElementOffset: (uint)sourceOffset,
                destinationElementOffset: (uint)destinationOffset,
                sourceElementPitchInBytes: (uint)sizeof(T),
                destinationElementPitchInBytes: (uint)sizeof(T),
                count: (uint)count);
        }
        else
        {
            ulong byteSourceOffset = (uint)sourceOffset * (uint)sizeof(T);
            ulong byteOffset       = (uint)destinationOffset * (uint)sizeof(T);
            ulong byteLength       = (uint)count * (uint)sizeof(T);

            using CommandList copyCommandList = new(GraphicsDevice, D3D12_COMMAND_LIST_TYPE_COPY);

            copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(D3D12Resource, byteOffset, source.D3D12Resource, byteSourceOffset, byteLength);
            copyCommandList.ExecuteAndWaitForCompletion();
        }
    }
        /// <inheritdoc/>
        public override unsafe void CopyFrom(Buffer <T> source)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            source.ThrowIfDeviceMismatch(GraphicsDevice);
            source.ThrowIfDisposed();

            Guard.IsLessThanOrEqualTo(source.Length, Length, nameof(Length));

            if (source is ConstantBuffer <T> buffer)
            {
                using ID3D12ResourceMap sourceMap      = buffer.D3D12Resource->Map();
                using ID3D12ResourceMap destinationMap = D3D12Resource->Map();

                if (IsPaddingPresent)
                {
                    MemoryHelper.Copy <T>(
                        sourceMap.Pointer,
                        destinationMap.Pointer,
                        0,
                        (uint)source.Length,
                        (uint)GetPaddedSize(),
                        isPaddingInSourceToo: true);
                }
                else
                {
                    MemoryHelper.Copy(
                        sourceMap.Pointer,
                        0,
                        (uint)source.Length,
                        (uint)sizeof(T),
                        destinationMap.Pointer);
                }
            }
            else
            {
                CopyFromWithCpuBuffer(source);
            }
        }
Пример #5
0
        public static string GetString(this byte[] value)
        {
            if (value == null)
            {
                return(null);
            }

            int length = value.Length;

            char[] buf = new char[length / MemoryHelper.CharSizeInBytes];

            unsafe
            {
                fixed(byte *src = value)
                fixed(char *dst = buf)
                {
                    MemoryHelper.Copy(dst, src, length);
                }
            }

            return(new string(buf));
        }
Пример #6
0
        public static char[] GetChars(this string value)
        {
            if (value == null)
            {
                return(null);
            }

            int length = value.Length;

            char[] buf = new char[length];

            unsafe
            {
                fixed(char *src = value)
                fixed(char *dst = buf)
                {
                    MemoryHelper.Copy(dst, src, length * MemoryHelper.CharSizeInBytes);
                }
            }

            return(buf);
        }
Пример #7
0
        public static byte[] GetBytes(this char[] value)
        {
            if (value == null)
            {
                return(null);
            }

            int length = value.Length;

            byte[] buf = new byte[length * MemoryHelper.CharSizeInBytes];

            unsafe
            {
                fixed(char *src = value)
                fixed(byte *dst = buf)
                {
                    MemoryHelper.Copy(dst, src, buf.Length);
                }
            }

            return(buf);
        }
        /// <summary>
        /// Reads the contents of the specified range from the current <see cref="StructuredBuffer{T}"/> instance and writes them into a target <see cref="ReadBackBuffer{T}"/> instance.
        /// </summary>
        /// <param name="destination">The target <see cref="ReadBackBuffer{T}"/> instance to write data to.</param>
        /// <param name="destinationOffset">The starting offset within <paramref name="destination"/> to write data to.</param>
        /// <param name="length">The number of items to read.</param>
        /// <param name="offset">The offset to start reading data from.</param>
        internal unsafe void CopyTo(ReadBackBuffer <T> destination, int destinationOffset, int length, int offset)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            destination.ThrowIfDeviceMismatch(GraphicsDevice);
            destination.ThrowIfDisposed();

            Guard.IsInRange(offset, 0, Length, nameof(offset));
            Guard.IsLessThanOrEqualTo(offset + length, Length, nameof(length));
            Guard.IsInRange(destinationOffset, 0, destination.Length, nameof(destinationOffset));
            Guard.IsLessThanOrEqualTo(destinationOffset + length, destination.Length, nameof(length));

            if (GraphicsDevice.IsCacheCoherentUMA)
            {
                using ID3D12ResourceMap resource = D3D12Resource->Map();

                MemoryHelper.Copy(
                    resource.Pointer,
                    (uint)offset,
                    (uint)length,
                    (uint)sizeof(T),
                    destination.MappedData + destinationOffset);
            }
            else
            {
                ulong
                    byteDestinationOffset = (uint)destinationOffset * (uint)sizeof(T),
                    byteOffset            = (uint)offset * (uint)sizeof(T),
                    byteLength            = (uint)length * (uint)sizeof(T);

                using CommandList copyCommandList = new(GraphicsDevice, D3D12_COMMAND_LIST_TYPE_COPY);

                copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(destination.D3D12Resource, byteDestinationOffset, D3D12Resource, byteOffset, byteLength);
                copyCommandList.ExecuteAndWaitForCompletion();
            }
        }
        /// <summary>
        /// Reads the contents of the specified range from an input <see cref="ReadBackBuffer{T}"/> instance and writes them to the current the current <see cref="StructuredBuffer{T}"/> instance.
        /// </summary>
        /// <param name="source">The input <see cref="UploadBuffer{T}"/> instance to read data from.</param>
        /// <param name="sourceOffset">The starting offset within <paramref name="source"/> to read data from.</param>
        /// <param name="length">The number of items to read.</param>
        /// <param name="offset">The offset to start reading writing data to.</param>
        internal unsafe void CopyFrom(UploadBuffer <T> source, int sourceOffset, int length, int offset)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            source.ThrowIfDeviceMismatch(GraphicsDevice);
            source.ThrowIfDisposed();

            Guard.IsInRange(offset, 0, Length, nameof(offset));
            Guard.IsLessThanOrEqualTo(offset + length, Length, nameof(length));
            Guard.IsInRange(sourceOffset, 0, source.Length, nameof(sourceOffset));
            Guard.IsLessThanOrEqualTo(sourceOffset + length, source.Length, nameof(length));

            if (GraphicsDevice.IsCacheCoherentUMA)
            {
                using ID3D12ResourceMap resource = D3D12Resource->Map();

                MemoryHelper.Copy(
                    source.MappedData,
                    (uint)sourceOffset,
                    (uint)length,
                    (uint)sizeof(T),
                    (T *)resource.Pointer + offset);
            }
            else
            {
                ulong
                    byteSourceOffset = (uint)sourceOffset * (uint)sizeof(T),
                    byteOffset       = (uint)offset * (uint)sizeof(T),
                    byteLength       = (uint)length * (uint)sizeof(T);

                using CommandList copyCommandList = new(GraphicsDevice, D3D12_COMMAND_LIST_TYPE_COPY);

                copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(D3D12Resource, byteOffset, source.D3D12Resource, byteSourceOffset, byteLength);
                copyCommandList.ExecuteAndWaitForCompletion();
            }
        }
Пример #10
0
        protected void SetArray(int index, byte *source, int lenght)
        {
            if (index >= _descriptor.VariablePartCount)
            {
                throw new Exception("Index is out of variable parts records.");
            }
            InBlockArrayRecord *arrayRecords = ArrayRecords;
            int delta = lenght - arrayRecords[index].Lenght;

            if (delta != 0)
            {
                if (ChangeRangeLenght(arrayRecords[index].Offset, arrayRecords[index].Lenght, lenght))
                {
                    arrayRecords = ArrayRecords;
                }
            }
            arrayRecords[index].Lenght = lenght;
            MemoryHelper.Copy(source, GetArray(index).Address, lenght);
            for (int i = index + 1; i < _descriptor.VariablePartCount; i++)
            {
                arrayRecords[i].Offset += delta;
            }
        }
Пример #11
0
    /// <inheritdoc/>
    internal override unsafe void CopyTo(ref T destination, int offset, int length)
    {
        GraphicsDevice.ThrowIfDisposed();

        ThrowIfDisposed();

        Guard.IsBetweenOrEqualTo(length, 0, Length);
        Guard.IsInRange(offset, 0, Length);
        Guard.IsLessThanOrEqualTo(offset + length, Length, nameof(offset));

        using ID3D12ResourceMap resource = D3D12Resource->Map();

        fixed(void *destinationPointer = &destination)
        {
            MemoryHelper.Copy <T>(
                source: resource.Pointer,
                destination: destinationPointer,
                sourceElementOffset: (uint)offset,
                destinationElementOffset: 0,
                sourceElementPitchInBytes: (uint)GetPaddedSize(),
                destinationElementPitchInBytes: (uint)sizeof(T),
                count: (uint)length);
        }
    }
Пример #12
0
        /// <summary>
        /// Writes the contents of a given memory area to a specified area of the current <see cref="Texture2D{T}"/> instance.
        /// </summary>
        /// <param name="source">The input memory area to read data from.</param>
        /// <param name="size">The size of the memory area to read data from.</param>
        /// <param name="x">The horizontal offset in the destination texture.</param>
        /// <param name="y">The vertical offset in the destination texture.</param>
        /// <param name="width">The width of the memory area to write to.</param>
        /// <param name="height">The height of the memory area to write to.</param>
        internal void CopyFrom(ref T source, int size, int x, int y, int width, int height)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            Guard.IsInRange(x, 0, Width, nameof(x));
            Guard.IsInRange(y, 0, Height, nameof(y));
            Guard.IsBetweenOrEqualTo(width, 1, Width, nameof(width));
            Guard.IsBetweenOrEqualTo(height, 1, Height, nameof(height));
            Guard.IsLessThanOrEqualTo(x + width, Width, nameof(x));
            Guard.IsLessThanOrEqualTo(y + height, Height, nameof(y));
            Guard.IsGreaterThanOrEqualTo(size, (nint)width * height, nameof(size));

            GraphicsDevice.D3D12Device->GetCopyableFootprint(
                DXGIFormatHelper.GetForType <T>(),
                (uint)width,
                (uint)height,
                out D3D12_PLACED_SUBRESOURCE_FOOTPRINT d3D12PlacedSubresourceFootprintSource,
                out ulong rowSizeInBytes,
                out ulong totalSizeInBytes);

            using UniquePtr <D3D12MA_Allocation> allocation = default;
            using ComPtr <ID3D12Resource> d3D12Resource     = default;

            if (GraphicsDevice.IsCacheCoherentUMA)
            {
                *&d3D12Resource = GraphicsDevice.D3D12Device->CreateCommittedResource(ResourceType.Upload, AllocationMode.Default, totalSizeInBytes, true);
            }
            else
            {
                *&allocation    = GraphicsDevice.Allocator->CreateResource(ResourceType.Upload, AllocationMode.Default, totalSizeInBytes);
                *&d3D12Resource = new ComPtr <ID3D12Resource>(allocation.Get()->GetResource());
            }

            using (ID3D12ResourceMap resource = d3D12Resource.Get()->Map())
                fixed(void *sourcePointer = &source)
                {
                    MemoryHelper.Copy(
                        sourcePointer,
                        resource.Pointer,
                        (uint)height,
                        rowSizeInBytes,
                        d3D12PlacedSubresourceFootprintSource.Footprint.RowPitch);
                }

            using CommandList copyCommandList = new(GraphicsDevice, this.d3D12CommandListType);

            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->ResourceBarrier(D3D12Resource, this.d3D12ResourceState, D3D12_RESOURCE_STATE_COPY_DEST);
            }

            copyCommandList.D3D12GraphicsCommandList->CopyTextureRegion(
                d3D12ResourceDestination: D3D12Resource,
                destinationX: (uint)x,
                destinationY: (uint)y,
                destinationZ: 0,
                d3D12ResourceSource: d3D12Resource.Get(),
                &d3D12PlacedSubresourceFootprintSource,
                sourceX: 0,
                sourceY: 0,
                sourceZ: 0,
                (uint)width,
                (uint)height,
                depth: 1);

            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->ResourceBarrier(D3D12Resource, D3D12_RESOURCE_STATE_COPY_DEST, this.d3D12ResourceState);
            }

            copyCommandList.ExecuteAndWaitForCompletion();
        }
Пример #13
0
    /// <summary>
    /// Reads the contents of the specified range from the current <see cref="Texture2D{T}"/> instance and writes them into a target memory area.
    /// </summary>
    /// <param name="destination">The target memory area to write data to.</param>
    /// <param name="size">The size of the target memory area to write data to.</param>
    /// <param name="sourceOffsetX">The horizontal offset in the source texture.</param>
    /// <param name="sourceOffsetY">The vertical offset in the source texture.</param>
    /// <param name="width">The width of the memory area to copy.</param>
    /// <param name="height">The height of the memory area to copy.</param>
    internal void CopyTo(ref T destination, int size, int sourceOffsetX, int sourceOffsetY, int width, int height)
    {
        GraphicsDevice.ThrowIfDisposed();

        ThrowIfDisposed();

        Guard.IsInRange(sourceOffsetX, 0, Width, nameof(sourceOffsetX));
        Guard.IsInRange(sourceOffsetY, 0, Height, nameof(sourceOffsetY));
        Guard.IsBetweenOrEqualTo(width, 1, Width, nameof(width));
        Guard.IsBetweenOrEqualTo(height, 1, Height, nameof(height));
        Guard.IsLessThanOrEqualTo(sourceOffsetX + width, Width, nameof(sourceOffsetX));
        Guard.IsLessThanOrEqualTo(sourceOffsetY + height, Height, nameof(sourceOffsetY));
        Guard.IsGreaterThanOrEqualTo(size, (nint)width * height, nameof(size));

        GraphicsDevice.D3D12Device->GetCopyableFootprint(
            DXGIFormatHelper.GetForType <T>(),
            (uint)width,
            (uint)height,
            out D3D12_PLACED_SUBRESOURCE_FOOTPRINT d3D12PlacedSubresourceFootprintDestination,
            out ulong rowSizeInBytes,
            out ulong totalSizeInBytes);

#if NET6_0_OR_GREATER
        using ComPtr <D3D12MA_Allocation> allocation = GraphicsDevice.Allocator->CreateResource(
                  GraphicsDevice.Pool,
                  ResourceType.ReadBack,
                  AllocationMode.Default,
                  totalSizeInBytes);

        using ComPtr <ID3D12Resource> d3D12Resource = new(allocation.Get()->GetResource());
#else
        using ComPtr <ID3D12Resource> d3D12Resource = GraphicsDevice.D3D12Device->CreateCommittedResource(
                  ResourceType.ReadBack,
                  totalSizeInBytes,
                  GraphicsDevice.IsCacheCoherentUMA);
#endif

        using (CommandList copyCommandList = new(GraphicsDevice, this.d3D12CommandListType))
        {
            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->TransitionBarrier(D3D12Resource, this.d3D12ResourceState, D3D12_RESOURCE_STATE_COPY_SOURCE);
            }

            copyCommandList.D3D12GraphicsCommandList->CopyTextureRegion(
                d3D12ResourceDestination: d3D12Resource.Get(),
                &d3D12PlacedSubresourceFootprintDestination,
                destinationX: 0,
                destinationY: 0,
                destinationZ: 0,
                d3D12ResourceSource: D3D12Resource,
                sourceX: (uint)sourceOffsetX,
                sourceY: (uint)sourceOffsetY,
                sourceZ: 0,
                (uint)width,
                (uint)height,
                depth: 1);

            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->TransitionBarrier(D3D12Resource, D3D12_RESOURCE_STATE_COPY_SOURCE, this.d3D12ResourceState);
            }

            copyCommandList.ExecuteAndWaitForCompletion();
        }

        using ID3D12ResourceMap resource = d3D12Resource.Get()->Map();

        fixed(void *destinationPointer = &destination)
        {
            MemoryHelper.Copy(
                resource.Pointer,
                (uint)height,
                rowSizeInBytes,
                d3D12PlacedSubresourceFootprintDestination.Footprint.RowPitch,
                destinationPointer);
        }
    }
Пример #14
0
    /// <inheritdoc/>
    internal override unsafe void CopyTo(ref T destination, int sourceOffset, int count)
    {
        GraphicsDevice.ThrowIfDisposed();

        ThrowIfDisposed();

        Guard.IsBetweenOrEqualTo(count, 0, Length);
        Guard.IsInRange(sourceOffset, 0, Length);
        Guard.IsLessThanOrEqualTo(sourceOffset + count, Length, nameof(sourceOffset));

        if (GraphicsDevice.IsCacheCoherentUMA)
        {
            using ID3D12ResourceMap resource = D3D12Resource->Map();

            fixed(void *destinationPointer = &destination)
            {
                MemoryHelper.Copy <T>(
                    source: resource.Pointer,
                    destination: destinationPointer,
                    sourceElementOffset: (uint)sourceOffset,
                    destinationElementOffset: 0,
                    sourceElementPitchInBytes: (uint)sizeof(T),
                    destinationElementPitchInBytes: (uint)sizeof(T),
                    count: (uint)count);
            }
        }
        else
        {
            nint byteOffset = (nint)sourceOffset * sizeof(T);
            nint byteLength = count * sizeof(T);

#if NET6_0_OR_GREATER
            using ComPtr <D3D12MA_Allocation> allocation = GraphicsDevice.Allocator->CreateResource(null, ResourceType.ReadBack, AllocationMode.Default, (ulong)byteLength);
#else
            using ComPtr <ID3D12Resource> d3D12Resource = GraphicsDevice.D3D12Device->CreateCommittedResource(
                      ResourceType.ReadBack,
                      (ulong)byteLength,
                      GraphicsDevice.IsCacheCoherentUMA);
#endif

            using (CommandList copyCommandList = new(GraphicsDevice, D3D12_COMMAND_LIST_TYPE_COPY))
            {
#if NET6_0_OR_GREATER
                copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(allocation.Get()->GetResource(), 0, D3D12Resource, (ulong)byteOffset, (ulong)byteLength);
#else
                copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(d3D12Resource.Get(), 0, D3D12Resource, (ulong)byteOffset, (ulong)byteLength);
#endif
                copyCommandList.ExecuteAndWaitForCompletion();
            }

#if NET6_0_OR_GREATER
            using ID3D12ResourceMap resource = allocation.Get()->GetResource()->Map();
#else
            using ID3D12ResourceMap resource = d3D12Resource.Get()->Map();
#endif

            fixed(void *destinationPointer = &destination)
            {
                MemoryHelper.Copy <T>(
                    source: resource.Pointer,
                    destination: destinationPointer,
                    sourceElementOffset: 0,
                    destinationElementOffset: 0,
                    sourceElementPitchInBytes: (uint)sizeof(T),
                    destinationElementPitchInBytes: (uint)sizeof(T),
                    count: (uint)count);
            }
        }
    }
Пример #15
0
        private bool ParseMeshData(Assimp.Scene scene)
        {
            if (!scene.HasMeshes)
            {
                return(false);
            }

            Assimp.Mesh[] meshes = scene.Meshes;
            if (meshes.Length == 0)
            {
                return(false);
            }

            m_meshData    = new MeshData[meshes.Length];
            m_meshMatInfo = new MeshMaterialInfo[meshes.Length];

            for (int i = 0; i < meshes.Length; i++)
            {
                Assimp.Mesh      mesh = meshes[i];
                MeshData         md   = new MeshData();
                MeshMaterialInfo info = new MeshMaterialInfo();

                if (mesh.HasVertices)
                {
                    Assimp.Vector3D[]    assimpPos = mesh.Vertices;
                    DataBuffer <Vector3> positions = new DataBuffer <Vector3>(assimpPos.Length);
                    MemoryHelper.Copy(assimpPos, positions.Buffer, Vector3.SizeInBytes * assimpPos.Length);
                    md.Positions = positions;
                }

                if (mesh.HasNormals)
                {
                    Assimp.Vector3D[]    assimpNorms = mesh.Normals;
                    DataBuffer <Vector3> normals     = new DataBuffer <Vector3>(assimpNorms.Length);
                    MemoryHelper.Copy(assimpNorms, normals.Buffer, Vector3.SizeInBytes * assimpNorms.Length);
                    md.Normals      = normals;
                    info.HasNormals = true;
                }

                if (mesh.HasTangentBasis)
                {
                    Assimp.Vector3D[]    assimpTangs   = mesh.Tangents;
                    Assimp.Vector3D[]    assimpBitangs = mesh.BiTangents;
                    DataBuffer <Vector3> tangents      = new DataBuffer <Vector3>(assimpTangs.Length);
                    DataBuffer <Vector3> bitangents    = new DataBuffer <Vector3>(assimpBitangs.Length);
                    MemoryHelper.Copy(assimpTangs, tangents.Buffer, Vector3.SizeInBytes * assimpTangs.Length);
                    MemoryHelper.Copy(assimpBitangs, bitangents.Buffer, Vector3.SizeInBytes * assimpBitangs.Length);
                    md.Tangents          = tangents;
                    md.Binormals         = bitangents;
                    info.HasTangentBasis = true;
                }

                if (mesh.HasVertexColors(0))
                {
                    Assimp.Color4D[] assimpColors = mesh.GetVertexColors(0);
                    md.Colors            = new DataBuffer <Color>(ConvertColors(assimpColors));
                    info.HasVertexColors = true;
                }

                if (mesh.HasTextureCoords(0))
                {
                    Assimp.Vector3D[] assimpUV = mesh.GetTextureCoords(0);
                    md.TextureCoordinates = new DataBuffer <Vector2>(ConvertVectors(assimpUV));
                    info.HasTexCoords     = true;
                }

                md.Indices = new DataBuffer <int>(mesh.GetIntIndices());
                md.Reconstruct();
                m_meshMatInfo[i] = info;
                m_meshData[i]    = md;
            }

            ParseMaterials(scene);
            return(true);
        }