/// <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(); } }
/// <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); } }
/// <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(); }
/// <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); } }
/// <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); } } }