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