示例#1
0
        private T[] CreateAndCopyToDebugBuf <T>(D3D11Buffer buffer) where T : struct
        {
            var d3dDevice  = this.deviceResources.D3DDevice;
            var d3dContext = this.deviceResources.D3DContext;

            var desc = buffer.Description;

            desc.CpuAccessOptions = D3D11CpuAccessOptions.Read;
            desc.Usage            = D3D11Usage.Staging;
            desc.BindOptions      = D3D11BindOptions.None;
            desc.MiscOptions      = D3D11ResourceMiscOptions.None;

            //int sizeT = Marshal.SizeOf<T>();
            int sizeT      = Unsafe.SizeOf <T>();
            int dataLength = (int)desc.ByteWidth / sizeT;
            var data       = new T[dataLength];

            using (var debugbuf = d3dDevice.CreateBuffer(desc))
            {
                d3dContext.CopyResource(debugbuf, buffer);

                D3D11MappedSubResource mappedResource = d3dContext.Map(debugbuf, 0, D3D11MapCpuPermission.Read, D3D11MapOptions.None);

                try
                {
                    //for (int i = 0; i < dataLength; i++)
                    //{
                    //    data[i] = Marshal.PtrToStructure<T>(mappedResource.Data + i * sizeT);
                    //}

                    var b = new byte[desc.ByteWidth];
                    Marshal.Copy(mappedResource.Data, b, 0, b.Length);

                    IntPtr d = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
                    Marshal.Copy(b, 0, d, b.Length);
                }
                finally
                {
                    d3dContext.Unmap(debugbuf, 0);
                }
            }

            return(data);
        }
示例#2
0
        static void GPUSort()
        {
            var d3dContext = deviceResources.D3DContext;

            // Upload the data
            d3dContext.UpdateSubresource(g_pBuffer1, 0, null, data, 0, 0);

            d3dContext.ComputeShaderSetConstantBuffers(0, new[] { g_pCB });

            // Sort the data
            // First sort the rows for the levels <= to the block size
            for (uint level = 2; level <= BITONIC_BLOCK_SIZE; level *= 2)
            {
                GPUSortSetConstants(level, level, MATRIX_HEIGHT, MATRIX_WIDTH);

                // Sort the row data
                d3dContext.ComputeShaderSetUnorderedAccessViews(0, new[] { g_pBuffer1UAV }, new[] { 0U });
                d3dContext.ComputeShaderSetShader(g_pComputeShaderBitonic, null);
                d3dContext.Dispatch(NUM_ELEMENTS / BITONIC_BLOCK_SIZE, 1, 1);
            }

            // Then sort the rows and columns for the levels > than the block size
            // Transpose. Sort the Columns. Transpose. Sort the Rows.
            for (uint level = (BITONIC_BLOCK_SIZE * 2); level <= NUM_ELEMENTS; level *= 2)
            {
                GPUSortSetConstants(level / BITONIC_BLOCK_SIZE, (level & ~NUM_ELEMENTS) / BITONIC_BLOCK_SIZE, MATRIX_WIDTH, MATRIX_HEIGHT);

                // Transpose the data from buffer 1 into buffer 2
                d3dContext.ComputeShaderSetShaderResources(0, new D3D11ShaderResourceView[] { null });
                d3dContext.ComputeShaderSetUnorderedAccessViews(0, new[] { g_pBuffer2UAV }, new[] { 0U });
                d3dContext.ComputeShaderSetShaderResources(0, new[] { g_pBuffer1SRV });
                d3dContext.ComputeShaderSetShader(g_pComputeShaderTranspose, null);
                d3dContext.Dispatch(MATRIX_WIDTH / TRANSPOSE_BLOCK_SIZE, MATRIX_HEIGHT / TRANSPOSE_BLOCK_SIZE, 1);

                // Sort the transposed column data
                d3dContext.ComputeShaderSetShader(g_pComputeShaderBitonic, null);
                d3dContext.Dispatch(NUM_ELEMENTS / BITONIC_BLOCK_SIZE, 1, 1);

                GPUSortSetConstants(BITONIC_BLOCK_SIZE, level, MATRIX_HEIGHT, MATRIX_WIDTH);

                // Transpose the data from buffer 2 back into buffer 1
                d3dContext.ComputeShaderSetShaderResources(0, new D3D11ShaderResourceView[] { null });
                d3dContext.ComputeShaderSetUnorderedAccessViews(0, new[] { g_pBuffer1UAV }, new[] { 0U });
                d3dContext.ComputeShaderSetShaderResources(0, new[] { g_pBuffer2SRV });
                d3dContext.ComputeShaderSetShader(g_pComputeShaderTranspose, null);
                d3dContext.Dispatch(MATRIX_HEIGHT / TRANSPOSE_BLOCK_SIZE, MATRIX_WIDTH / TRANSPOSE_BLOCK_SIZE, 1);

                // Sort the row data
                d3dContext.ComputeShaderSetShader(g_pComputeShaderBitonic, null);
                d3dContext.Dispatch(NUM_ELEMENTS / BITONIC_BLOCK_SIZE, 1, 1);
            }

            // Download the data
            d3dContext.CopyResource(g_pReadBackBuffer, g_pBuffer1);
            D3D11MappedSubResource mappedResource = d3dContext.Map(g_pReadBackBuffer, 0, D3D11MapCpuPermission.Read, D3D11MapOptions.None);

            try
            {
                for (int i = 0; i < NUM_ELEMENTS; i++)
                {
                    results[i] = (uint)Marshal.ReadInt32(mappedResource.Data + i * sizeof(uint));
                }
            }
            finally
            {
                d3dContext.Unmap(g_pReadBackBuffer, 0);
            }
        }
示例#3
0
        public void PerEdgeTessellation(
            XMMatrix matWVP,
            ref D3D11Buffer ppTessedVerticesBuf,
            ref D3D11Buffer ppTessedIndicesBuf,
            out uint num_tessed_vertices,
            out uint num_tessed_indices)
        {
            var d3dDevice  = this.deviceResources.D3DDevice;
            var d3dContext = this.deviceResources.D3DContext;

            // Update per-edge tessellation factors
            {
                EdgeFactorConstantBuffer cbCS = default;
                cbCS.MatWVP = matWVP;
                cbCS.TessEdgeLengthScale = this.m_tess_edge_len_scale;
                cbCS.NumTriangles        = this.m_nVertices / 3;

                d3dContext.UpdateSubresource(
                    this.s_pEdgeFactorCSCB,
                    D3D11Utils.CalcSubresource(0, 0, 1),
                    null,
                    cbCS,
                    EdgeFactorConstantBuffer.Size,
                    EdgeFactorConstantBuffer.Size);

                this.RunComputeShader(
                    this.s_pEdgeFactorCS,
                    new[] { this.m_pBaseVBSRV },
                    null,
                    this.s_pEdgeFactorCSCB,
                    this.m_pEdgeFactorBufUAV,
                    (uint)Math.Ceiling(this.m_nVertices / 3 / 128.0f),
                    1U,
                    1U);
            }

            // How many vertices/indices are needed for the tessellated mesh?
            {
                uint[] cbCS = new uint[] { this.m_nVertices / 3, 0, 0, 0 };

                d3dContext.UpdateSubresource(
                    this.s_pCSCB,
                    D3D11Utils.CalcSubresource(0, 0, 1),
                    null,
                    cbCS,
                    4 * 4,
                    4 * 4);

                this.RunComputeShader(
                    this.s_pNumVerticesIndicesCSs[(int)this.PartitioningMode],
                    new[] { this.m_pEdgeFactorBufSRV },
                    this.s_pLookupTableCSCB,
                    this.s_pCSCB,
                    this.m_pScanBuf0UAV,
                    (uint)Math.Ceiling(this.m_nVertices / 3 / 128.0f),
                    1U,
                    1U);

                this.s_ScanCS.Scan(d3dContext, this.m_nVertices / 3, this.m_pScanBuf0SRV, this.m_pScanBuf0UAV, this.m_pScanBuf1SRV, this.m_pScanBuf1UAV);

                // read back the number of vertices/indices for tessellation output
                D3D11Box box = default;
                box.Left   = 4 * 2 * this.m_nVertices / 3 - 4 * 2;
                box.Right  = 4 * 2 * this.m_nVertices / 3;
                box.Top    = 0;
                box.Bottom = 1;
                box.Front  = 0;
                box.Back   = 1;

                d3dContext.CopySubresourceRegion(this.s_pCSReadBackBuf, 0, 0, 0, 0, this.m_pScanBuf0, 0, box);

                D3D11MappedSubResource mappedResource = d3dContext.Map(this.s_pCSReadBackBuf, 0, D3D11MapCpuPermission.Read, D3D11MapOptions.None);

                try
                {
                    num_tessed_vertices = (uint)Marshal.ReadInt32(mappedResource.Data + 4 * 0);
                    num_tessed_indices  = (uint)Marshal.ReadInt32(mappedResource.Data + 4 * 1);
                }
                finally
                {
                    d3dContext.Unmap(this.s_pCSReadBackBuf, 0);
                }
            }

            if (num_tessed_vertices == 0 || num_tessed_indices == 0)
            {
                return;
            }

            // Turn on this and set a breakpoint on the line beginning with "p = " and see what has been written to m_pScanBuf0
            if (DebugEnabled)
            {
#pragma warning disable IDE0059 // Assignation inutile d'une valeur
                var p = this.CreateAndCopyToDebugBuf <(uint v, uint t)>(this.m_pScanBuf0);
#pragma warning restore IDE0059 // Assignation inutile d'une valeur
            }

            // Generate buffers for scattering TriID and IndexID for both vertex data and index data,
            // also generate buffers for output tessellated vertex data and index data
            {
                if (this.m_pScatterVertexBuf == null || this.m_nCachedTessedVertices < num_tessed_vertices || this.m_nCachedTessedVertices > num_tessed_vertices * 2)
                {
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterVertexBuf);
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterVertexBufSRV);
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterVertexBufUAV);

                    D3D11Utils.DisposeAndNull(ref ppTessedVerticesBuf);
                    D3D11Utils.DisposeAndNull(ref this.m_pTessedVerticesBufUAV);
                    D3D11Utils.DisposeAndNull(ref this.m_pTessedVerticesBufSRV);

                    this.m_pScatterVertexBuf = d3dDevice.CreateBuffer(new D3D11BufferDesc
                    {
                        BindOptions         = D3D11BindOptions.ShaderResource | D3D11BindOptions.UnorderedAccess,
                        ByteWidth           = 4 * 2 * num_tessed_vertices,
                        StructureByteStride = 4 * 2,
                        MiscOptions         = D3D11ResourceMiscOptions.BufferStructured,
                        Usage = D3D11Usage.Default
                    });

                    this.m_pScatterVertexBufSRV = d3dDevice.CreateShaderResourceView(this.m_pScatterVertexBuf, new D3D11ShaderResourceViewDesc
                    {
                        ViewDimension = D3D11SrvDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferSrv
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_vertices
                        }
                    });

                    this.m_pScatterVertexBufUAV = d3dDevice.CreateUnorderedAccessView(this.m_pScatterVertexBuf, new D3D11UnorderedAccessViewDesc
                    {
                        ViewDimension = D3D11UavDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferUav
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_vertices
                        }
                    });

                    // generate the output tessellated vertices buffer
                    ppTessedVerticesBuf = d3dDevice.CreateBuffer(new D3D11BufferDesc
                    {
                        BindOptions         = D3D11BindOptions.ShaderResource | D3D11BindOptions.UnorderedAccess,
                        ByteWidth           = 4 * 3 * num_tessed_vertices,
                        StructureByteStride = 4 * 3,
                        MiscOptions         = D3D11ResourceMiscOptions.BufferStructured,
                        Usage = D3D11Usage.Default
                    });

                    this.m_pTessedVerticesBufUAV = d3dDevice.CreateUnorderedAccessView(ppTessedVerticesBuf, new D3D11UnorderedAccessViewDesc
                    {
                        ViewDimension = D3D11UavDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferUav
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_vertices
                        }
                    });

                    this.m_pTessedVerticesBufSRV = d3dDevice.CreateShaderResourceView(ppTessedVerticesBuf, new D3D11ShaderResourceViewDesc
                    {
                        ViewDimension = D3D11SrvDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferSrv
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_vertices
                        }
                    });

                    this.m_nCachedTessedVertices = num_tessed_vertices;
                }

                if (this.m_pScatterIndexBuf == null || this.m_nCachedTessedIndices < num_tessed_indices)
                {
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterIndexBuf);
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterIndexBufSRV);
                    D3D11Utils.DisposeAndNull(ref this.m_pScatterIndexBufUAV);

                    D3D11Utils.DisposeAndNull(ref ppTessedIndicesBuf);
                    D3D11Utils.DisposeAndNull(ref this.m_pTessedIndicesBufUAV);

                    this.m_pScatterIndexBuf = d3dDevice.CreateBuffer(new D3D11BufferDesc
                    {
                        BindOptions         = D3D11BindOptions.ShaderResource | D3D11BindOptions.UnorderedAccess,
                        ByteWidth           = 4 * 2 * num_tessed_indices,
                        StructureByteStride = 4 * 2,
                        MiscOptions         = D3D11ResourceMiscOptions.BufferStructured,
                        Usage = D3D11Usage.Default
                    });

                    this.m_pScatterIndexBufSRV = d3dDevice.CreateShaderResourceView(this.m_pScatterIndexBuf, new D3D11ShaderResourceViewDesc
                    {
                        ViewDimension = D3D11SrvDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferSrv
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_indices
                        }
                    });

                    this.m_pScatterIndexBufUAV = d3dDevice.CreateUnorderedAccessView(this.m_pScatterIndexBuf, new D3D11UnorderedAccessViewDesc
                    {
                        ViewDimension = D3D11UavDimension.Buffer,
                        Format        = DxgiFormat.Unknown,
                        Buffer        = new D3D11BufferUav
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_indices
                        }
                    });

                    // generate the output tessellated indices buffer
                    ppTessedIndicesBuf = d3dDevice.CreateBuffer(new D3D11BufferDesc
                    {
                        BindOptions = D3D11BindOptions.ShaderResource | D3D11BindOptions.UnorderedAccess | D3D11BindOptions.IndexBuffer,
                        ByteWidth   = 4 * num_tessed_indices,
                        MiscOptions = D3D11ResourceMiscOptions.BufferAllowRawViews,
                        Usage       = D3D11Usage.Default
                    });

                    this.m_pTessedIndicesBufUAV = d3dDevice.CreateUnorderedAccessView(ppTessedIndicesBuf, new D3D11UnorderedAccessViewDesc
                    {
                        ViewDimension = D3D11UavDimension.Buffer,
                        Format        = DxgiFormat.R32Typeless,
                        Buffer        = new D3D11BufferUav
                        {
                            FirstElement = 0,
                            NumElements  = num_tessed_indices,
                            Options      = D3D11BufferUavOptions.Raw
                        }
                    });

                    this.m_nCachedTessedIndices = num_tessed_indices;
                }
            }

            // Scatter TriID, IndexID
            {
                uint[] cbCS = new uint[] { this.m_nVertices / 3, 0, 0, 0 };
                D3D11ShaderResourceView[] aRViews = new[] { this.m_pScanBuf0SRV };

                d3dContext.UpdateSubresource(
                    this.s_pCSCB,
                    D3D11Utils.CalcSubresource(0, 0, 1),
                    null,
                    cbCS,
                    4 * 4,
                    4 * 4);

                // Scatter vertex TriID, IndexID
                this.RunComputeShader(
                    this.s_pScatterVertexTriIDIndexIDCS,
                    aRViews,
                    null,
                    this.s_pCSCB,
                    this.m_pScatterVertexBufUAV,
                    (uint)Math.Ceiling(this.m_nVertices / 3 / 128.0f),
                    1U,
                    1U);

                // Scatter index TriID, IndexID
                this.RunComputeShader(
                    this.s_pScatterIndexTriIDIndexIDCS,
                    aRViews,
                    null,
                    this.s_pCSCB,
                    this.m_pScatterIndexBufUAV,
                    (uint)Math.Ceiling(this.m_nVertices / 3 / 128.0f),
                    1U,
                    1U);
            }

            // Turn on this and set a breakpoint on the line beginning with "p = " and see what has been written to m_pScatterVertexBuf
            if (DebugEnabled)
            {
#pragma warning disable IDE0059 // Assignation inutile d'une valeur
                var p = this.CreateAndCopyToDebugBuf <(uint v, uint t)>(this.m_pScatterVertexBuf);
#pragma warning restore IDE0059 // Assignation inutile d'une valeur
            }

            // Tessellate vertex
            {
                uint[] cbCS = new uint[] { num_tessed_vertices, 0, 0, 0 };

                d3dContext.UpdateSubresource(
                    this.s_pCSCB,
                    D3D11Utils.CalcSubresource(0, 0, 1),
                    null,
                    cbCS,
                    4 * 4,
                    4 * 4);

                this.RunComputeShader(
                    this.s_pTessVerticesCSs[(int)this.PartitioningMode],
                    new[] { this.m_pScatterVertexBufSRV, this.m_pEdgeFactorBufSRV },
                    this.s_pLookupTableCSCB,
                    this.s_pCSCB,
                    this.m_pTessedVerticesBufUAV,
                    (uint)Math.Ceiling(num_tessed_vertices / 128.0f),
                    1U,
                    1U);
            }

            // Turn on this and set a breakpoint on the line beginning with "p = " and see what has been written to *ppTessedVerticesBuf
            if (DebugEnabled)
            {
#pragma warning disable IDE0059 // Assignation inutile d'une valeur
                var p = this.CreateAndCopyToDebugBuf <(uint id, float u, float v)>(ppTessedVerticesBuf);
#pragma warning restore IDE0059 // Assignation inutile d'une valeur
            }

            // Tessellate indices
            {
                uint[] cbCS = new uint[] { num_tessed_indices, 0, 0, 0 };

                d3dContext.UpdateSubresource(
                    this.s_pCSCB,
                    D3D11Utils.CalcSubresource(0, 0, 1),
                    null,
                    cbCS,
                    4 * 4,
                    4 * 4);

                this.RunComputeShader(
                    this.s_pTessIndicesCSs[(int)this.PartitioningMode],
                    new[] { this.m_pScatterIndexBufSRV, this.m_pEdgeFactorBufSRV, this.m_pScanBuf0SRV },
                    this.s_pLookupTableCSCB,
                    this.s_pCSCB,
                    this.m_pTessedIndicesBufUAV,
                    (uint)Math.Ceiling(num_tessed_indices / 128.0f),
                    1U,
                    1U);
            }

            // Turn on this and set a breakpoint on the line beginning with "p = " and see what has been written to *ppTessedIndicesBuf
            if (DebugEnabled)
            {
#pragma warning disable IDE0059 // Assignation inutile d'une valeur
                var p = this.CreateAndCopyToDebugBuf <int>(ppTessedIndicesBuf);
#pragma warning restore IDE0059 // Assignation inutile d'une valeur
            }
        }
示例#4
0
        static void Main(string[] args)
        {
            try
            {
                Console.Write("Creating device...");
                CreateComputeDevice();
                Console.WriteLine("done");

                Console.Write("Creating Compute Shader...");
                CreateComputeShader();
                Console.WriteLine("done");

                Console.Write("Creating buffers and filling them with initial data...");

                for (int i = 0; i < NUM_ELEMENTS; ++i)
                {
                    g_vBuf0[i].i = i;
                    g_vBuf0[i].f = (float)i;
#if TEST_DOUBLE
                    g_vBuf0[i].d = (double)i;
#endif

                    g_vBuf1[i].i = i;
                    g_vBuf1[i].f = (float)i;
#if TEST_DOUBLE
                    g_vBuf1[i].d = (double)i;
#endif
                }

#if USE_STRUCTURED_BUFFERS
                g_pBuf0      = CreateStructuredBuffer(deviceResources.D3DDevice, g_vBuf0);
                g_pBuf1      = CreateStructuredBuffer(deviceResources.D3DDevice, g_vBuf1);
                g_pBufResult = CreateStructuredBuffer(deviceResources.D3DDevice, new BufType[NUM_ELEMENTS]);
#else
                g_pBuf0      = CreateRawBuffer(deviceResources.D3DDevice, g_vBuf0);
                g_pBuf1      = CreateRawBuffer(deviceResources.D3DDevice, g_vBuf1);
                g_pBufResult = CreateRawBuffer(deviceResources.D3DDevice, new BufType[NUM_ELEMENTS]);
#endif

#if DEBUG
                g_pBuf0?.SetDebugName("Buffer0");
                g_pBuf1?.SetDebugName("Buffer1");
                g_pBufResult?.SetDebugName("Result");
#endif

                Console.WriteLine("done");

                Console.Write("Creating buffer views...");
                g_pBuf0SRV      = CreateBufferSRV(deviceResources.D3DDevice, g_pBuf0);
                g_pBuf1SRV      = CreateBufferSRV(deviceResources.D3DDevice, g_pBuf1);
                g_pBufResultUAV = CreateBufferUAV(deviceResources.D3DDevice, g_pBufResult);

#if DEBUG
                g_pBuf0SRV?.SetDebugName("Buffer0 SRV");
                g_pBuf1SRV?.SetDebugName("Buffer1 SRV");
                g_pBufResultUAV?.SetDebugName("Result UAV");
#endif

                Console.WriteLine("done");

                Console.Write("Running Compute Shader...");
                RunComputeShader(deviceResources.D3DContext, g_pCS, new[] { g_pBuf0SRV, g_pBuf1SRV }, g_pBufResultUAV, NUM_ELEMENTS, 1, 1);
                Console.WriteLine("done");

                // Read back the result from GPU, verify its correctness against result computed by CPU
                D3D11Buffer debugbuf = CreateAndCopyToDebugBuf(deviceResources.D3DDevice, deviceResources.D3DContext, g_pBufResult);

                try
                {
                    D3D11MappedSubResource mappedResource = deviceResources.D3DContext.Map(debugbuf, 0, D3D11MapCpuPermission.Read, D3D11MapOptions.None);

                    try
                    {
                        // Set a break point here and put down the expression "p, 1024" in your watch window to see what has been written out by our CS
                        // This is also a common trick to debug CS programs.

                        // Verify that if Compute Shader has done right
                        Console.Write("Verifying against CPU result...");
                        bool bSuccess = true;

                        for (int i = 0; i < NUM_ELEMENTS; ++i)
                        {
                            BufType p = Marshal.PtrToStructure <BufType>(mappedResource.Data + i * (int)BufType.Size);

                            if ((p.i != g_vBuf0[i].i + g_vBuf1[i].i) ||
                                (p.f != g_vBuf0[i].f + g_vBuf1[i].f)
#if TEST_DOUBLE
                                || (p.d != g_vBuf0[i].d + g_vBuf1[i].d)
#endif
                                )
                            {
                                Console.WriteLine("failure");
                                bSuccess = false;
                                break;
                            }
                        }

                        if (bSuccess)
                        {
                            Console.WriteLine("succeeded");
                        }
                    }
                    finally
                    {
                        deviceResources.D3DContext.Unmap(debugbuf, 0);
                    }
                }
                finally
                {
                    D3D11Utils.ReleaseAndNull(ref debugbuf);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                Console.Write("Cleaning up...");
                CleanupResources();
                Console.WriteLine("done");
            }

            Console.ReadKey(false);
        }