public void BuildResources(GraphicsCommandList cmdList) { // All the textures for the wave simulation will be bound as a shader resource and // unordered access view at some point since we ping-pong the buffers. var texDesc = new ResourceDescription { Dimension = ResourceDimension.Texture2D, Alignment = 0, Width = ColumnCount, Height = RowCount, DepthOrArraySize = 1, MipLevels = 1, Format = Format.R32_Float, SampleDescription = new SampleDescription(1, 0), Layout = TextureLayout.Unknown, Flags = ResourceFlags.AllowUnorderedAccess }; _prevSol = _device.CreateCommittedResource( new HeapProperties(HeapType.Default), HeapFlags.None, texDesc, ResourceStates.Common); _currSol = _device.CreateCommittedResource( new HeapProperties(HeapType.Default), HeapFlags.None, texDesc, ResourceStates.Common); _nextSol = _device.CreateCommittedResource( new HeapProperties(HeapType.Default), HeapFlags.None, texDesc, ResourceStates.Common); // // In order to copy CPU memory data into our default buffer, we need to create // an intermediate upload heap. // int num2DSubresources = texDesc.DepthOrArraySize * texDesc.MipLevels; long uploadBufferSize; _device.GetCopyableFootprints(ref texDesc, 0, num2DSubresources, 0, null, null, null, out uploadBufferSize); _prevUploadBuffer = _device.CreateCommittedResource( new HeapProperties(HeapType.Upload), HeapFlags.None, ResourceDescription.Buffer(uploadBufferSize), ResourceStates.GenericRead); _currUploadBuffer = _device.CreateCommittedResource( new HeapProperties(HeapType.Upload), HeapFlags.None, ResourceDescription.Buffer(uploadBufferSize), ResourceStates.GenericRead); // // Schedule to copy the data to the default resource, and change states. // Note that mCurrSol is put in the GENERIC_READ state so it can be // read by a shader. // cmdList.ResourceBarrierTransition(_prevSol, ResourceStates.Common, ResourceStates.CopyDestination); cmdList.CopyResource(_prevSol, _prevUploadBuffer); cmdList.ResourceBarrierTransition(_prevSol, ResourceStates.CopyDestination, ResourceStates.UnorderedAccess); cmdList.ResourceBarrierTransition(_currSol, ResourceStates.Common, ResourceStates.CopyDestination); cmdList.CopyResource(_currSol, _currUploadBuffer); cmdList.ResourceBarrierTransition(_currSol, ResourceStates.CopyDestination, ResourceStates.GenericRead); cmdList.ResourceBarrierTransition(_nextSol, ResourceStates.Common, ResourceStates.UnorderedAccess); }
public override ImageCapture CaptureRenderTarget(RenderTarget surface) { IntPtr texNativePtr = RenderDeviceD3D11.GetTextureNativePointer(surface.Texture); SharpDX.Direct3D12.Resource texture = new SharpDX.Direct3D12.Resource(texNativePtr); SharpDX.Direct3D12.ResourceDescription texDesc = texture.Description; // Transition PIXEL_SHADER_RESOURCE -> COPY_SOURCE SharpDX.Direct3D12.ResourceBarrier barrier = new SharpDX.Direct3D12.ResourceBarrier(); barrier.Type = SharpDX.Direct3D12.ResourceBarrierType.Transition; barrier.Flags = SharpDX.Direct3D12.ResourceBarrierFlags.None; barrier.Transition = new SharpDX.Direct3D12.ResourceTransitionBarrier(texture, SharpDX.Direct3D12.ResourceStates.PixelShaderResource, SharpDX.Direct3D12.ResourceStates.CopySource) { Subresource = 0 }; _commands.ResourceBarrier(barrier); long totalBytes; long[] rowSize = { 0 }; _dev.GetCopyableFootprints(ref texDesc, 0, 1, 0, null, null, rowSize, out totalBytes); long pitch = (rowSize[0] + 255) & ~255; // Create staging texture SharpDX.Direct3D12.HeapProperties heap; heap.Type = SharpDX.Direct3D12.HeapType.Readback; heap.CPUPageProperty = SharpDX.Direct3D12.CpuPageProperty.Unknown; heap.MemoryPoolPreference = SharpDX.Direct3D12.MemoryPool.Unknown; heap.CreationNodeMask = 0; heap.VisibleNodeMask = 0; SharpDX.Direct3D12.ResourceDescription desc; desc.Dimension = SharpDX.Direct3D12.ResourceDimension.Buffer; desc.Alignment = 0; desc.Width = pitch * texDesc.Height * 4; desc.Height = 1; desc.DepthOrArraySize = 1; desc.MipLevels = 1; desc.Format = SharpDX.DXGI.Format.Unknown; desc.SampleDescription = new SampleDescription { Count = 1, Quality = 0 }; desc.Layout = SharpDX.Direct3D12.TextureLayout.RowMajor; desc.Flags = SharpDX.Direct3D12.ResourceFlags.None; SharpDX.Direct3D12.Resource stagingTex = _dev.CreateCommittedResource(heap, SharpDX.Direct3D12.HeapFlags.None, desc, SharpDX.Direct3D12.ResourceStates.CopyDestination, null); SharpDX.Direct3D12.TextureCopyLocation copySrc = new SharpDX.Direct3D12.TextureCopyLocation(texture, 0); SharpDX.Direct3D12.TextureCopyLocation copyDst = new SharpDX.Direct3D12.TextureCopyLocation(texture, new SharpDX.Direct3D12.PlacedSubResourceFootprint { Offset = 0, Footprint = new SharpDX.Direct3D12.SubResourceFootprint { Width = (int)texDesc.Width, Height = (int)texDesc.Height, Depth = 1, RowPitch = (int)pitch, Format = texDesc.Format } }); // Wait GPU completion _commands.CopyTextureRegion(copyDst, 0, 0, 0, copySrc, null); _commands.Close(); _queue.ExecuteCommandList(_commands); WaitForGpu(); // Ensure image capture object is created with the appropriate size if (_imageCapture == null || _imageCapture.Width != desc.Width || _imageCapture.Height != desc.Height) { _imageCapture = new ImageCapture((uint)desc.Width, (uint)desc.Height); } // Map and copy to image byte[] dst = _imageCapture.Pixels; IntPtr src = stagingTex.Map(0); for (int i = 0; i < desc.Height; ++i) { int dstRow = i * (int)_imageCapture.Stride; int srcRow = i * (int)pitch; for (int j = 0; j < desc.Width; j++) { // RGBA -> BGRA dst[dstRow + 4 * j + 2] = Noesis.Marshal.ReadByte(src, srcRow + 4 * j + 0); dst[dstRow + 4 * j + 1] = Noesis.Marshal.ReadByte(src, srcRow + 4 * j + 1); dst[dstRow + 4 * j + 0] = Noesis.Marshal.ReadByte(src, srcRow + 4 * j + 2); dst[dstRow + 4 * j + 3] = Noesis.Marshal.ReadByte(src, srcRow + 4 * j + 3); } } stagingTex.Unmap(0); return(_imageCapture); }