public static void ReadbackTexture2D(GPUResource readbackBuffer, PixelBuffer srcBuffer) { var desc = readbackBuffer.Resource.Description; var footprints = new PlacedSubResourceFootprint[1]; Globals.Device.GetCopyableFootprints(ref desc, 0, 1, 0, footprints, new int[1], new long[1], out var totalBytes); var context = Begin("Copy texture to memory"); context.TransitionResource(srcBuffer, ResourceStates.CopySource, true); context._CommandList.CopyTextureRegion(new TextureCopyLocation(readbackBuffer.Resource, footprints[0]), 0, 0, 0, new TextureCopyLocation(srcBuffer.Resource, 0), null); context.Finish(true); }
public static long UpdateSubResources(GraphicsCommandList cmdList, Resource destResource, Resource intermediateResource, long intermediateOffset, int firstSubresource, int numSubresource, SubResourceInformation[] datas) { long memToAlloc = (Utilities.SizeOf <PlacedSubResourceFootprint>() + sizeof(uint) + sizeof(UInt64)) * numSubresource; var layouts = new PlacedSubResourceFootprint[numSubresource]; var numRows = new int[numSubresource]; var rowSizesInBytes = new long[numSubresource]; destResource.GetDevice(Utilities.GetGuidFromType(typeof(Device)), out var ptr); long result = 0; using (var device = new Device(ptr)) { var desc = destResource.Description; device.GetCopyableFootprints(ref desc, firstSubresource, numSubresource, intermediateOffset, layouts, numRows, rowSizesInBytes, out var requiredSize); result = UpdateSubResources(cmdList, destResource, intermediateResource, firstSubresource, numSubresource, requiredSize, layouts, rowSizesInBytes, datas); } return(result); }
private void InitializeFromImpl(DataBox[] dataBoxes = null) { bool hasInitData = dataBoxes != null && dataBoxes.Length > 0; if (ParentTexture != null) { ParentResource = ParentTexture; NativeDeviceChild = ParentTexture.NativeDeviceChild; } if (NativeDeviceChild == null) { ClearValue?clearValue = GetClearValue(); ResourceDescription nativeDescription; switch (Dimension) { case TextureDimension.Texture1D: nativeDescription = ConvertToNativeDescription1D(); break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: nativeDescription = ConvertToNativeDescription2D(); break; case TextureDimension.Texture3D: nativeDescription = ConvertToNativeDescription3D(); break; default: throw new ArgumentOutOfRangeException(); } var initialResourceState = ResourceStates.GenericRead; var heapType = HeapType.Default; var currentResourceState = initialResourceState; if (Usage == GraphicsResourceUsage.Staging) { heapType = HeapType.Readback; NativeResourceState = ResourceStates.CopyDestination; int totalSize = ComputeBufferTotalSize(); nativeDescription = ResourceDescription.Buffer(totalSize); // Staging textures on DirectX 12 use buffer internally NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, NativeResourceState); if (hasInitData) { var commandList = GraphicsDevice.NativeCopyCommandList; commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null); Resource uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset, TextureSubresourceAlignment); // Copy data to the upload buffer int dataBoxIndex = 0; var uploadMemoryMipStart = uploadMemory; for (int arraySlice = 0; arraySlice < ArraySize; arraySlice++) { for (int mipLevel = 0; mipLevel < MipLevels; mipLevel++) { var databox = dataBoxes[dataBoxIndex++]; var mipHeight = CalculateMipSize(Width, mipLevel); var mipRowPitch = ComputeRowPitch(mipLevel); var uploadMemoryCurrent = uploadMemoryMipStart; var dataPointerCurrent = databox.DataPointer; for (int rowIndex = 0; rowIndex < mipHeight; rowIndex++) { Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, mipRowPitch); uploadMemoryCurrent += mipRowPitch; dataPointerCurrent += databox.RowPitch; } uploadMemoryMipStart += ComputeSubresourceSize(mipLevel); } } // Copy from upload heap to actual resource commandList.CopyBufferRegion(NativeResource, 0, uploadResource, uploadOffset, totalSize); commandList.Close(); StagingFenceValue = 0; GraphicsDevice.WaitCopyQueue(); } return; } if (hasInitData) { currentResourceState = ResourceStates.CopyDestination; } // TODO D3D12 move that to a global allocator in bigger committed resources NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, currentResourceState, clearValue); GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes); if (hasInitData) { // Trigger copy var commandList = GraphicsDevice.NativeCopyCommandList; commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null); long textureCopySize; var placedSubresources = new PlacedSubResourceFootprint[dataBoxes.Length]; var rowCounts = new int[dataBoxes.Length]; var rowSizeInBytes = new long[dataBoxes.Length]; GraphicsDevice.NativeDevice.GetCopyableFootprints(ref nativeDescription, 0, dataBoxes.Length, 0, placedSubresources, rowCounts, rowSizeInBytes, out textureCopySize); SharpDX.Direct3D12.Resource uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer((int)textureCopySize, out uploadResource, out uploadOffset, TextureSubresourceAlignment); for (int i = 0; i < dataBoxes.Length; ++i) { var databox = dataBoxes[i]; var dataPointer = databox.DataPointer; var rowCount = rowCounts[i]; var sliceCount = placedSubresources[i].Footprint.Depth; var rowSize = (int)rowSizeInBytes[i]; var destRowPitch = placedSubresources[i].Footprint.RowPitch; // Memcpy data for (int z = 0; z < sliceCount; ++z) { var uploadMemoryCurrent = uploadMemory + (int)placedSubresources[i].Offset + z * destRowPitch * rowCount; var dataPointerCurrent = dataPointer + z * databox.SlicePitch; for (int y = 0; y < rowCount; ++y) { Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, rowSize); uploadMemoryCurrent += destRowPitch; dataPointerCurrent += databox.RowPitch; } } // Adjust upload offset (circular dependency between GetCopyableFootprints and AllocateUploadBuffer) placedSubresources[i].Offset += uploadOffset; commandList.CopyTextureRegion(new TextureCopyLocation(NativeResource, i), 0, 0, 0, new TextureCopyLocation(uploadResource, placedSubresources[i]), null); } commandList.ResourceBarrierTransition(NativeResource, ResourceStates.CopyDestination, initialResourceState); commandList.Close(); GraphicsDevice.WaitCopyQueue(); } NativeResourceState = initialResourceState; } NativeShaderResourceView = GetShaderResourceView(ViewType, ArraySlice, MipLevel); NativeRenderTargetView = GetRenderTargetView(ViewType, ArraySlice, MipLevel); NativeDepthStencilView = GetDepthStencilView(out HasStencil); NativeUnorderedAccessView = GetUnorderedAccessView(ViewType, ArraySlice, MipLevel); }
public TextureCopyLocation(SharpDX.Direct3D12.Resource resource, PlacedSubResourceFootprint placedFootprint) : this() { Type = TextureCopyType.PlacedFootprint; PResource = resource != null ? resource.NativePointer : IntPtr.Zero; PlacedFootprint = placedFootprint; }
private void InitializeFromImpl(DataBox[] dataBoxes = null) { if (ParentTexture != null) { ParentResource = ParentTexture; NativeDeviceChild = ParentTexture.NativeDeviceChild; } if (NativeDeviceChild == null) { ResourceDescription nativeDescription; switch (Dimension) { case TextureDimension.Texture1D: nativeDescription = ConvertToNativeDescription1D(); break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: nativeDescription = ConvertToNativeDescription2D(); break; case TextureDimension.Texture3D: nativeDescription = ConvertToNativeDescription3D(); break; default: throw new ArgumentOutOfRangeException(); } var initialResourceState = ResourceStates.GenericRead; var heapType = HeapType.Default; var currentResourceState = initialResourceState; if (Usage == GraphicsResourceUsage.Staging) { if (dataBoxes != null) { throw new NotImplementedException(); } heapType = HeapType.Readback; initialResourceState = ResourceStates.CopyDestination; currentResourceState = ResourceStates.CopyDestination; nativeDescription = ResourceDescription.Buffer(ComputeBufferTotalSize()); // TODO: Alloc in readback heap as a buffer //return; } if (dataBoxes != null && dataBoxes.Length > 0) { currentResourceState = ResourceStates.CopyDestination; } // TODO D3D12 move that to a global allocator in bigger committed resources NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, currentResourceState); GraphicsDevice.TextureMemory += (Depth * DepthStride) / (float)0x100000; if (dataBoxes != null && dataBoxes.Length > 0) { if (Usage == GraphicsResourceUsage.Staging) { throw new NotImplementedException("D3D12: Staging textures can't be created with initial data"); } // Trigger copy var commandList = GraphicsDevice.NativeCopyCommandList; commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null); long textureCopySize; var placedSubresources = new PlacedSubResourceFootprint[dataBoxes.Length]; var rowCounts = new int[dataBoxes.Length]; var rowSizeInBytes = new long[dataBoxes.Length]; GraphicsDevice.NativeDevice.GetCopyableFootprints(ref nativeDescription, 0, dataBoxes.Length, 0, placedSubresources, rowCounts, rowSizeInBytes, out textureCopySize); SharpDX.Direct3D12.Resource uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer((int)textureCopySize, out uploadResource, out uploadOffset, TextureSubresourceAlignment); for (int i = 0; i < dataBoxes.Length; ++i) { var databox = dataBoxes[i]; var dataPointer = databox.DataPointer; var rowCount = rowCounts[i]; var sliceCount = placedSubresources[i].Footprint.Depth; var rowSize = (int)rowSizeInBytes[i]; var destRowPitch = placedSubresources[i].Footprint.RowPitch; // Memcpy data for (int z = 0; z < sliceCount; ++z) { var uploadMemoryCurrent = uploadMemory + (int)placedSubresources[i].Offset + z * destRowPitch * rowCount; var dataPointerCurrent = dataPointer + z * databox.SlicePitch; for (int y = 0; y < rowCount; ++y) { Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, rowSize); uploadMemoryCurrent += destRowPitch; dataPointerCurrent += databox.RowPitch; } } // Adjust upload offset (circular dependency between GetCopyableFootprints and AllocateUploadBuffer) placedSubresources[i].Offset += uploadOffset; commandList.CopyTextureRegion(new TextureCopyLocation(NativeResource, i), 0, 0, 0, new TextureCopyLocation(uploadResource, placedSubresources[i]), null); } commandList.ResourceBarrierTransition(NativeResource, ResourceStates.CopyDestination, initialResourceState); commandList.Close(); GraphicsDevice.WaitCopyQueue(); } NativeResourceState = initialResourceState; } NativeShaderResourceView = GetShaderResourceView(ViewType, ArraySlice, MipLevel); NativeRenderTargetView = GetRenderTargetView(ViewType, ArraySlice, MipLevel); NativeDepthStencilView = GetDepthStencilView(out HasStencil); }
internal void Upload <T>(Resource destinationResource, ResourceUploadData <T>[] sourceSubresourceData) where T : struct { if (!_inBeginEndBlock) { throw new InvalidOperationException(); } var destinationResourceDescription = destinationResource.Description; var numSubresources = sourceSubresourceData.Length; var resourceLayouts = new PlacedSubResourceFootprint[numSubresources]; var resourceNumRows = new int[numSubresources]; var resourceRowSizesInBytes = new long[numSubresources]; _device.GetCopyableFootprints( ref destinationResourceDescription, 0, numSubresources, 0, resourceLayouts, resourceNumRows, resourceRowSizesInBytes, out var uploadSize); // Create intermediate GPU upload buffer. var uploadResource = _device.CreateCommittedResource( new HeapProperties(HeapType.Upload), HeapFlags.None, ResourceDescription.Buffer(uploadSize), ResourceStates.GenericRead); var sizeOfT = Marshal.SizeOf <T>(); var dataPtr = uploadResource.Map(0); for (var i = 0; i < numSubresources; i++) { var subresourceData = sourceSubresourceData[i]; var resourceLayout = resourceLayouts[i]; var numRows = resourceNumRows[i]; var resourceRowSizeInBytes = resourceRowSizesInBytes[i]; for (var y = 0; y < numRows; y++) { Utilities.Write( dataPtr + (int)resourceLayout.Offset + (resourceLayout.Footprint.RowPitch * y), subresourceData.Data, (subresourceData.BytesPerRow / sizeOfT) * y, (int)(resourceRowSizeInBytes / sizeOfT)); } } uploadResource.Unmap(0); if (destinationResourceDescription.Dimension == ResourceDimension.Buffer) { _commandList.CopyBufferRegion( destinationResource, 0, uploadResource, resourceLayouts[0].Offset, resourceLayouts[0].Footprint.Width); } else { for (var i = 0; i < numSubresources; i++) { _commandList.CopyTextureRegion( new TextureCopyLocation(destinationResource, i), 0, 0, 0, new TextureCopyLocation(uploadResource, resourceLayouts[i]), null); } } _trackedResources.Add(uploadResource); }
public TextureCopyLocation(SharpDX.Direct3D12.Resource resource, PlacedSubResourceFootprint placedFootprint) : this() { Type = TextureCopyType.PlacedFootprint; PResource = resource != null ? resource.NativePointer : IntPtr.Zero; PlacedFootprint = placedFootprint; }
private void InitializeFromImpl(DataBox[] dataBoxes = null) { if (ParentTexture != null) { ParentResource = ParentTexture; NativeDeviceChild = ParentTexture.NativeDeviceChild; } if (NativeDeviceChild == null) { ResourceDescription nativeDescription; switch (Dimension) { case TextureDimension.Texture1D: nativeDescription = ConvertToNativeDescription1D(); break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: nativeDescription = ConvertToNativeDescription2D(); break; case TextureDimension.Texture3D: nativeDescription = ConvertToNativeDescription3D(); break; default: throw new ArgumentOutOfRangeException(); } var initialResourceState = ResourceStates.GenericRead; var heapType = HeapType.Default; var currentResourceState = initialResourceState; if (Usage == GraphicsResourceUsage.Staging) { if (dataBoxes != null) throw new NotImplementedException(); heapType = HeapType.Readback; initialResourceState = ResourceStates.CopyDestination; currentResourceState = ResourceStates.CopyDestination; nativeDescription = ResourceDescription.Buffer(ComputeBufferTotalSize()); // TODO: Alloc in readback heap as a buffer //return; } if (dataBoxes != null && dataBoxes.Length > 0) currentResourceState = ResourceStates.CopyDestination; // TODO D3D12 move that to a global allocator in bigger committed resources NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, currentResourceState); GraphicsDevice.TextureMemory += (Depth*DepthStride) / (float)0x100000; if (dataBoxes != null && dataBoxes.Length > 0) { if (Usage == GraphicsResourceUsage.Staging) throw new NotImplementedException("D3D12: Staging textures can't be created with initial data"); // Trigger copy var commandList = GraphicsDevice.NativeCopyCommandList; commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null); long textureCopySize; var placedSubresources = new PlacedSubResourceFootprint[dataBoxes.Length]; var rowCounts = new int[dataBoxes.Length]; var rowSizeInBytes = new long[dataBoxes.Length]; GraphicsDevice.NativeDevice.GetCopyableFootprints(ref nativeDescription, 0, dataBoxes.Length, 0, placedSubresources, rowCounts, rowSizeInBytes, out textureCopySize); SharpDX.Direct3D12.Resource uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer((int)textureCopySize, out uploadResource, out uploadOffset, TextureSubresourceAlignment); for (int i = 0; i < dataBoxes.Length; ++i) { var databox = dataBoxes[i]; var dataPointer = databox.DataPointer; var rowCount = rowCounts[i]; var sliceCount = placedSubresources[i].Footprint.Depth; var rowSize = (int)rowSizeInBytes[i]; var destRowPitch = placedSubresources[i].Footprint.RowPitch; // Memcpy data for (int z = 0; z < sliceCount; ++z) { var uploadMemoryCurrent = uploadMemory + (int)placedSubresources[i].Offset + z * destRowPitch * rowCount; var dataPointerCurrent = dataPointer + z * databox.SlicePitch; for (int y = 0; y < rowCount; ++y) { Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, rowSize); uploadMemoryCurrent += destRowPitch; dataPointerCurrent += databox.RowPitch; } } // Adjust upload offset (circular dependency between GetCopyableFootprints and AllocateUploadBuffer) placedSubresources[i].Offset += uploadOffset; commandList.CopyTextureRegion(new TextureCopyLocation(NativeResource, i), 0, 0, 0, new TextureCopyLocation(uploadResource, placedSubresources[i]), null); } commandList.ResourceBarrierTransition(NativeResource, ResourceStates.CopyDestination, initialResourceState); commandList.Close(); GraphicsDevice.WaitCopyQueue(); } NativeResourceState = initialResourceState; } NativeShaderResourceView = GetShaderResourceView(ViewType, ArraySlice, MipLevel); NativeRenderTargetView = GetRenderTargetView(ViewType, ArraySlice, MipLevel); NativeDepthStencilView = GetDepthStencilView(out HasStencil); }