/// <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();
            }
        }
Пример #2
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);
        }
    }
Пример #3
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();
        }
Пример #4
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);
        }
    }
Пример #5
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);
            }
        }
    }