Пример #1
0
        internal IntPtr AllocateUploadBuffer(int size, out SharpDX.Direct3D12.Resource resource, out int offset, int alignment = 0)
        {
            // TODO D3D12 thread safety, should we simply use locks?

            // Align
            if (alignment > 0)
            {
                nativeUploadBufferOffset = (nativeUploadBufferOffset + alignment - 1) / alignment * alignment;
            }

            if (nativeUploadBuffer == null || nativeUploadBufferOffset + size > nativeUploadBuffer.Description.Width)
            {
                if (nativeUploadBuffer != null)
                {
                    nativeUploadBuffer.Unmap(0);
                    TemporaryResources.Enqueue(new KeyValuePair <long, object>(NextFenceValue, nativeUploadBuffer));
                }

                // Allocate new buffer
                // TODO D3D12 recycle old ones (using fences to know when GPU is done with them)
                // TODO D3D12 ResourceStates.CopySource not working?
                var bufferSize = Math.Max(4 * 1024 * 1024, size);
                nativeUploadBuffer       = NativeDevice.CreateCommittedResource(new HeapProperties(HeapType.Upload), HeapFlags.None, ResourceDescription.Buffer(bufferSize), ResourceStates.GenericRead);
                nativeUploadBufferStart  = nativeUploadBuffer.Map(0, new SharpDX.Direct3D12.Range());
                nativeUploadBufferOffset = 0;
            }

            // Bump allocate
            resource = nativeUploadBuffer;
            offset   = nativeUploadBufferOffset;
            nativeUploadBufferOffset += size;
            return(nativeUploadBufferStart + offset);
        }
        private void DoComputeWork()
        {
            // Reuse the memory associated with command recording.
            // We can only reset when the associated command lists have finished execution on the GPU.
            DirectCmdListAlloc.Reset();

            // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
            // Reusing the command list reuses memory.
            CommandList.Reset(DirectCmdListAlloc, _psos["vecAdd"]);

            CommandList.SetComputeRootSignature(_rootSignature);

            CommandList.SetComputeRootShaderResourceView(0, _inputBufferA.GPUVirtualAddress);
            CommandList.SetComputeRootShaderResourceView(1, _inputBufferB.GPUVirtualAddress);
            CommandList.SetComputeRootUnorderedAccessView(2, _outputBuffer.GPUVirtualAddress);

            CommandList.Dispatch(1, 1, 1);

            // Schedule to copy the data to the default buffer to the readback buffer.
            CommandList.ResourceBarrierTransition(_outputBuffer, ResourceStates.Common, ResourceStates.CopySource);

            CommandList.CopyResource(_readBackBuffer, _outputBuffer);

            CommandList.ResourceBarrierTransition(_outputBuffer, ResourceStates.CopySource, ResourceStates.Common);

            // Done recording commands.
            CommandList.Close();

            // Add the command list to the queue for execution.
            CommandQueue.ExecuteCommandList(CommandList);

            // Wait for the work to finish.
            FlushCommandQueue();

            // Map the data so we can read it on CPU.
            var    mappedData = new Data[NumDataElements];
            IntPtr ptr        = _readBackBuffer.Map(0);

            Utilities.Read(ptr, mappedData, 0, NumDataElements);

            using (var fstream = File.OpenWrite("results.txt"))
            {
                using (var strWriter = new StreamWriter(fstream))
                {
                    foreach (Data data in mappedData)
                    {
                        strWriter.WriteLine($"({data.V1.X}, {data.V1.Y}, {data.V1.Z}, {data.V2.X}, {data.V2.Y})");
                    }
                }
            }

            _readBackBuffer.Unmap(0);
        }
Пример #3
0
        private void PlatformCreateShaders()
        {
            var inputElementDescs = new[]
            {
                new InputElement("POSITION", 0, Format.R32G32_Float, 0, 0),
                new InputElement("COLOR", 0, Format.B8G8R8A8_UNorm, 8, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 8 + 4, 0)
            };

            var psoDesc = new GraphicsPipelineStateDescription()
            {
                InputLayout        = new InputLayoutDescription(inputElementDescs),
                RootSignature      = graphicsHost.RootSignature,
                VertexShader       = DXHelper.CompileShader(vertexShaderSource, "main", "vs_5_0"),
                PixelShader        = DXHelper.CompileShader(pixelShaderSource, "main", "ps_5_0"),
                RasterizerState    = RasterizerStateDescription.Default(),
                BlendState         = BlendStateDescription.Default(),
                DepthStencilFormat = SharpDX.DXGI.Format.D32_Float,
                DepthStencilState  = new DepthStencilStateDescription()
                {
                    IsDepthEnabled = false, IsStencilEnabled = false
                },
                SampleMask            = int.MaxValue,
                PrimitiveTopologyType = PrimitiveTopologyType.Triangle,
                RenderTargetCount     = 1,
                Flags             = PipelineStateFlags.None,
                SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
                StreamOutput      = new StreamOutputDescription()
            };

            psoDesc.RenderTargetFormats[0] = SharpDX.DXGI.Format.R8G8B8A8_UNorm;

            pipelineState = graphicsHost.Device.CreateGraphicsPipelineState(psoDesc);

            // TODO: Move buffer
            var constantBufferDesc = ResourceDescription.Buffer(1024 * 64);

            constantBuffer      = graphicsHost.Device.CreateCommittedResource(new HeapProperties(HeapType.Upload), HeapFlags.None, constantBufferDesc, ResourceStates.GenericRead);
            constantBuffer.Name = "[SpriteRenderer] Constant Buffer";

            var cbvDesc = new ConstantBufferViewDescription()
            {
                BufferLocation = constantBuffer.GPUVirtualAddress,
                SizeInBytes    = (SharpDX.Utilities.SizeOf <ConstantBuffer>() + 255) & ~255,
            };

            graphicsHost.Device.CreateConstantBufferView(cbvDesc, graphicsHost.CBVHeap.CPUDescriptorHandleForHeapStart);

            mappedConstantBuffer = constantBuffer.Map(0);
            SharpDX.Utilities.Write(mappedConstantBuffer, ref constantBufferData);
        }
Пример #4
0
        protected override unsafe void Draw(Vertex2D *pVertex, int vertexCount, DXTexture texture, bool isTransparent)
        {
            // TODO: texture, isTransparent

            commandList.SetGraphicsRootDescriptorTable(1, graphicsHost.SRVHeap.GPUDescriptorHandleForHeapStart);

            // Update the vertex buffer
            IntPtr dataBegin = vertexBuffer.Map(0);

            SharpDX.Utilities.CopyMemory(dataBegin, new IntPtr(pVertex), vertexCount * Vertex2D.SizeInBytes);
            vertexBuffer.Unmap(0);

            // Record the commands.
            commandList.SetVertexBuffer(0, vertexBufferView);
            // commandList.SetIndexBuffer(quadIndexBuffer.indexBufferView);

            // Call draw.
            commandList.DrawIndexedInstanced(vertexCount / 4 * 6, 1, 0, 0, 0);
        }
        public static Resource CreateDefaultBuffer <T>(
            Device device,
            GraphicsCommandList cmdList,
            T[] initData,
            long byteSize,
            out Resource uploadBuffer) where T : struct
        {
            // Create the actual default buffer resource.
            Resource defaultBuffer = device.CreateCommittedResource(
                new HeapProperties(HeapType.Default),
                HeapFlags.None,
                ResourceDescription.Buffer(byteSize),
                ResourceStates.Common);

            // In order to copy CPU memory data into our default buffer, we need to create
            // an intermediate upload heap.
            uploadBuffer = device.CreateCommittedResource(
                new HeapProperties(HeapType.Upload),
                HeapFlags.None,
                ResourceDescription.Buffer(byteSize),
                ResourceStates.GenericRead);

            // Copy the data to the upload buffer.
            IntPtr ptr = uploadBuffer.Map(0);

            Utilities.Write(ptr, initData, 0, initData.Length);
            uploadBuffer.Unmap(0);

            // Schedule to copy the data to the default buffer resource.
            cmdList.ResourceBarrierTransition(defaultBuffer, ResourceStates.Common, ResourceStates.CopyDestination);
            cmdList.CopyResource(defaultBuffer, uploadBuffer);
            cmdList.ResourceBarrierTransition(defaultBuffer, ResourceStates.CopyDestination, ResourceStates.GenericRead);

            // Note: uploadBuffer has to be kept alive after the above function calls because
            // the command list has not been executed yet that performs the actual copy.
            // The caller can Release the uploadBuffer after it knows the copy has been executed.

            return(defaultBuffer);
        }
Пример #6
0
        /// <summary>
        /// Setup resources for rendering
        /// </summary>
        void LoadAssets()
        {
            // Create the main command list
            commandList = Collect(device.CreateCommandList(CommandListType.Direct, commandListAllocator, pipelineState));

            // Create the descriptor heap for the render target view
            descriptorHeapRT = Collect(device.CreateDescriptorHeap(new DescriptorHeapDescription()
            {
                Type            = DescriptorHeapType.RenderTargetView,
                DescriptorCount = 1
            }));
#if USE_DEPTH
            descriptorHeapDS = Collect(device.CreateDescriptorHeap(new DescriptorHeapDescription()
            {
                Type            = DescriptorHeapType.DepthStencilView,
                DescriptorCount = 1
            }));
#endif
#if USE_TEXTURE
            descriptorHeapCB = Collect(device.CreateDescriptorHeap(new DescriptorHeapDescription()
            {
                Type            = DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView,
                DescriptorCount = 2,
                Flags           = DescriptorHeapFlags.ShaderVisible,
            }));
            descriptorHeapS = Collect(device.CreateDescriptorHeap(new DescriptorHeapDescription()
            {
                Type            = DescriptorHeapType.Sampler,
                DescriptorCount = 1,
                Flags           = DescriptorHeapFlags.ShaderVisible,
            }));
            descriptorsHeaps[0] = descriptorHeapCB;
            descriptorsHeaps[1] = descriptorHeapS;
#else
            descriptorHeapCB = Collect(device.CreateDescriptorHeap(new DescriptorHeapDescription()
            {
                Type            = DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView,
                DescriptorCount = 1,
                Flags           = DescriptorHeapFlags.ShaderVisible,
            }));
            descriptorsHeaps[0] = descriptorHeapCB;
#endif
#if true // root signature in code
            var rsparams = new RootParameter[]
            {
                new RootParameter(ShaderVisibility.Vertex, new RootDescriptor(), RootParameterType.ConstantBufferView),
                new RootParameter(ShaderVisibility.Vertex,
                                  new DescriptorRange
                {
                    RangeType          = DescriptorRangeType.ConstantBufferView,
                    BaseShaderRegister = 1,
                    DescriptorCount    = 1,
                }),
#if USE_TEXTURE
                new RootParameter(ShaderVisibility.Pixel,
                                  new DescriptorRange
                {
                    RangeType          = DescriptorRangeType.ShaderResourceView,
                    BaseShaderRegister = 0,
                    DescriptorCount    = 1,
                }),
                new RootParameter(ShaderVisibility.Pixel,
                                  new DescriptorRange
                {
                    RangeType          = DescriptorRangeType.Sampler,
                    BaseShaderRegister = 0,
                    DescriptorCount    = 1,
                }),
#endif
            };
            var rs = new RootSignatureDescription(RootSignatureFlags.AllowInputAssemblerInputLayout, rsparams);
            rootSignature = Collect(device.CreateRootSignature(rs.Serialize()));
#else
            var rootSignatureByteCode = Utilities.ReadStream(assembly.GetManifestResourceStream("Shaders.Cube" + shaderNameSuffix + ".rs"));
            using (var bufferRootSignature = DataBuffer.Create(rootSignatureByteCode))
                rootSignature = Collect(device.CreateRootSignature(bufferRootSignature));
#endif
            byte[] vertexShaderByteCode = GetResourceBytes("Cube" + shaderNameSuffix + ".vso");
            byte[] pixelShaderByteCode  = GetResourceBytes("Cube" + shaderNameSuffix + ".pso");

            var layout = new InputLayoutDescription(new InputElement[]
            {
                new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
                new InputElement("NORMAL", 0, Format.R32G32B32_Float, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0),
#if USE_INSTANCES
                new InputElement("OFFSET", 0, Format.R32G32B32_Float, 0, 1, InputClassification.PerInstanceData, 1),
#endif
            });

            #region pipeline state
            var psd = new GraphicsPipelineStateDescription
            {
                InputLayout           = layout,
                VertexShader          = vertexShaderByteCode,
                PixelShader           = pixelShaderByteCode,
                RootSignature         = rootSignature,
                DepthStencilState     = DepthStencilStateDescription.Default(),
                DepthStencilFormat    = Format.Unknown,
                BlendState            = BlendStateDescription.Default(),
                RasterizerState       = RasterizerStateDescription.Default(),
                SampleDescription     = new SampleDescription(1, 0),
                RenderTargetCount     = 1,
                PrimitiveTopologyType = PrimitiveTopologyType.Triangle,
                SampleMask            = -1,
                StreamOutput          = new StreamOutputDescription()
            };
            psd.RenderTargetFormats[0] = Format.R8G8B8A8_UNorm;
#if USE_DEPTH
            psd.DepthStencilFormat = Format.D32_Float;
#else
            psd.DepthStencilState.IsDepthEnabled = false;
#endif
            //psd.RasterizerState.CullMode = CullMode.None;
            pipelineState = Collect(device.CreateGraphicsPipelineState(psd));
            #endregion pipeline state

            #region vertices
            var vertices = new[]
            {
                -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                       // Front
                -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

                -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // BACK
                -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // BACK
                1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

                -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // Top
                -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // Top
                -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

                -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                       // Bottom
                -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                       // Bottom
                1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

                -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                       // Left
                -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                       // Left
                -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

                1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // Right
                1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,                        // Right
                1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
            };
            #endregion vertices
            #region vertex buffer
            // Instantiate Vertex buiffer from vertex data
            int sizeOfFloat = sizeof(float);
            int sizeInBytes = vertices.Length * sizeOfFloat;
            vertexBuffer = Collect(device.CreateCommittedResource(
                                       new HeapProperties(HeapType.Upload),
                                       HeapFlags.None,
                                       new ResourceDescription(ResourceDimension.Buffer, 0, sizeInBytes, 1, 1, 1, Format.Unknown, 1, 0, TextureLayout.RowMajor, ResourceFlags.None),
                                       ResourceStates.GenericRead));
            vertexBufferView = new[]
            {
                new VertexBufferView
                {
                    BufferLocation = vertexBuffer.GPUVirtualAddress,
                    SizeInBytes    = sizeInBytes,
                    StrideInBytes  = sizeOfFloat * 8,
                }
            };
            var ptr = vertexBuffer.Map(0);
            Utilities.Write(ptr, vertices, 0, vertices.Length);
            vertexBuffer.Unmap(0);
            #endregion vertex buffer
            #region instances
#if USE_INSTANCES
            int instanceSizeInBytes = sizeOfFloat * instances.Length;
            instancesBuffer = Collect(device.CreateCommittedResource(
                                          new HeapProperties(HeapType.Upload),
                                          HeapFlags.None,
                                          new ResourceDescription(ResourceDimension.Buffer, 0, instanceSizeInBytes, 1, 1, 1, Format.Unknown, 1, 0, TextureLayout.RowMajor, ResourceFlags.None),
                                          ResourceStates.GenericRead));
            instancesBufferView = new[]
            {
                new VertexBufferView
                {
                    BufferLocation = instancesBuffer.GPUVirtualAddress,
                    SizeInBytes    = instanceSizeInBytes,
                    StrideInBytes  = sizeOfFloat * 3,
                }
            };
            ptr = instancesBuffer.Map(0);
            Utilities.Write(ptr, instances, 0, instances.Length);
            instancesBuffer.Unmap(0);
#endif
            #endregion instances

            #region indices
#if USE_INDICES
            var indexData = new[]
            {
                0, 1, 2, 3, 4,
                5, 6, 7, 8, 9, 10,
                11, 12, 13, 14, 15, 16,
                17, 18, 19, 20, 21, 22,
                23, 24, 25, 26, 27, 28,
                29, 30, 31, 32, 33
            };
            sizeInBytes = indexData.Length * sizeof(int);
            indexBuffer = Collect(device.CreateCommittedResource(
                                      new HeapProperties(HeapType.Upload),
                                      HeapFlags.None,
                                      new ResourceDescription(ResourceDimension.Buffer, 0, sizeInBytes, 1, 1, 1, Format.Unknown, 1, 0, TextureLayout.RowMajor, ResourceFlags.None),
                                      ResourceStates.GenericRead));
            ptr = indexBuffer.Map(0);
            Utilities.Write(ptr, indexData, 0, indexData.Length);
            indexBuffer.Unmap(0);
            indexBufferView = new IndexBufferView
            {
                BufferLocation = indexBuffer.GPUVirtualAddress,
                SizeInBytes    = sizeInBytes,
                Format         = Format.R32_UInt
            };
#endif
            #endregion indices

            #region transform
            transWorld = Collect(device.CreateCommittedResource(
                                     new HeapProperties(HeapType.Upload),
                                     HeapFlags.None,
                                     new ResourceDescription(ResourceDimension.Buffer, 0, 16 * sizeOfMatrix, 1, 1, 1, Format.Unknown, 1, 0, TextureLayout.RowMajor, ResourceFlags.None),
                                     ResourceStates.GenericRead));
            transWorldPtr = transWorld.Map(0);
            transViewProj = Collect(device.CreateCommittedResource(
                                        new HeapProperties(HeapType.Upload),
                                        HeapFlags.None,
                                        new ResourceDescription(ResourceDimension.Buffer, 0, sizeOfMatrix, 1, 1, 1, Format.Unknown, 1, 0, TextureLayout.RowMajor, ResourceFlags.None),
                                        ResourceStates.GenericRead));
            device.CreateConstantBufferView(new ConstantBufferViewDescription
            {
                BufferLocation = transViewProj.GPUVirtualAddress,
                SizeInBytes    = sizeOfMatrix,
            }, descriptorHeapCB.CPUDescriptorHandleForHeapStart);

            var view = Matrix.LookAtLH(new Vector3(5, 5, -5), Vector3.Zero, Vector3.UnitY);
            var proj = Matrix.PerspectiveFovLH(MathUtil.Pi / 4, (float)width / height, 0.1f, 100);
            var vpT  = view * proj;
            vpT.Transpose();
            ptr = transViewProj.Map(0);
            Utilities.Write(ptr, ref vpT);
            transViewProj.Unmap(0);
            #endregion transform

#if USE_TEXTURE
            #region texture
            Resource buf;
            using (var tl = new TextureLoader("GeneticaMortarlessBlocks.jpg"))
            {
                int w = tl.Width, h = tl.Height;
                var descrs = new[]
                {
                    new ResourceDescription(ResourceDimension.Texture2D,
                                            0, w, h, 1, 1,
                                            Format.B8G8R8A8_UNorm, 1, 0,
                                            TextureLayout.Unknown,
                                            ResourceFlags.None),
                };
                texture = Collect(device.CreateCommittedResource(
                                      new HeapProperties(HeapType.Default),
                                      HeapFlags.None,
                                      descrs[0],
                                      ResourceStates.CopyDestination)
                                  );
                var resAllocInfo = device.GetResourceAllocationInfo(1, 1, descrs);
                buf = device.CreateCommittedResource(
                    new HeapProperties(HeapType.Upload),
                    HeapFlags.None,
                    new ResourceDescription(
                        ResourceDimension.Buffer,
                        0,
                        resAllocInfo.SizeInBytes,
                        1, 1, 1,
                        Format.Unknown,
                        1, 0,
                        TextureLayout.RowMajor,
                        ResourceFlags.None),
                    ResourceStates.GenericRead);

                var ptrBuf   = buf.Map(0);
                int rowPitch = tl.CopyImageData(ptrBuf);
                buf.Unmap(0);

                var src = new TextureCopyLocation(buf,
                                                  new PlacedSubResourceFootprint
                {
                    Offset    = 0,
                    Footprint = new SubResourceFootprint
                    {
                        Format   = Format.B8G8R8A8_UNorm_SRgb,
                        Width    = w,
                        Height   = h,
                        Depth    = 1,
                        RowPitch = rowPitch
                    }
                }
                                                  );
                var dst = new TextureCopyLocation(texture, 0);
                // record copy
                commandList.CopyTextureRegion(dst, 0, 0, 0, src, null);

                commandList.ResourceBarrierTransition(texture, ResourceStates.CopyDestination, ResourceStates.GenericRead);
            }
            descrOffsetCB = device.GetDescriptorHandleIncrementSize(DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView);
            device.CreateShaderResourceView(texture, null, descriptorHeapCB.CPUDescriptorHandleForHeapStart + descrOffsetCB);
            #endregion texture

            #region sampler
            device.CreateSampler(new SamplerStateDescription
            {
                AddressU = TextureAddressMode.Wrap,
                AddressV = TextureAddressMode.Wrap,
                AddressW = TextureAddressMode.Wrap,
                Filter   = Filter.MaximumMinMagMipLinear,
            }, descriptorHeapS.CPUDescriptorHandleForHeapStart);
            #endregion sampler
#endif
            // Get the backbuffer and creates the render target view
            renderTarget = Collect(swapChain.GetBackBuffer <Resource>(0));
            device.CreateRenderTargetView(renderTarget, null, descriptorHeapRT.CPUDescriptorHandleForHeapStart);

#if USE_DEPTH
            depthBuffer = Collect(device.CreateCommittedResource(
                                      new HeapProperties(HeapType.Default),
                                      HeapFlags.None,
                                      new ResourceDescription(ResourceDimension.Texture2D, 0, width, height, 1, 1, Format.D32_Float, 1, 0, TextureLayout.Unknown, ResourceFlags.AllowDepthStencil),
                                      ResourceStates.Present,
                                      new ClearValue
            {
                Format       = Format.D32_Float,
                DepthStencil = new DepthStencilValue
                {
                    Depth   = 1,
                    Stencil = 0,
                }
            }));
            device.CreateDepthStencilView(depthBuffer, null, descriptorHeapDS.CPUDescriptorHandleForHeapStart);
#endif

            // Create the viewport
            viewPort = new ViewportF(0, 0, width, height);

            // Create the scissor
            scissorRectangle = new Rectangle(0, 0, width, height);

            // Create a fence to wait for next frame
            fence        = Collect(device.CreateFence(0, FenceFlags.None));
            currentFence = 1;

            // Close command list
            commandList.Close();
            commandQueue.ExecuteCommandList(commandList);

            // Create an event handle use for VTBL
            CreateWaitEvent();

            // Wait the command list to complete
            WaitForPrevFrame();
#if USE_TEXTURE
            buf.Dispose();
#endif
        }
Пример #7
0
        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);
        }