public DX11RWStructuredBuffer(int elementcount, int stride, IntPtr uav, IntPtr srv)
 {
     this.ElementCount = elementcount;
     this.Stride       = stride;
     this.UAV          = UnorderedAccessView.FromPointer(uav);
     //this.UAV.Dispose();
     this.SRV = ShaderResourceView.FromPointer(srv);
     //this.SRV.Dispose();
 }
Пример #2
0
        public static void RenderDrawData(ImDrawDataPtr drawData)
        {
            // Avoid rendering when minimized
            if (drawData.DisplaySize.X <= 0 || drawData.DisplaySize.Y <= 0)
            {
                return;
            }

            if (!drawData.Valid || drawData.CmdListsCount == 0)
            {
                return;
            }

            //drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);

            // Create and grow vertex/index buffers if needed
            if (_vertexBuffer == null || _vertexBufferSize < drawData.TotalVtxCount)
            {
                _vertexBuffer?.Dispose();
                _vertexBufferSize = drawData.TotalVtxCount + 5000;

                _vertexBuffer = new Buffer(_device, new BufferDescription
                {
                    Usage          = ResourceUsage.Dynamic,
                    SizeInBytes    = Unsafe.SizeOf <ImDrawVert>() * _vertexBufferSize,
                    BindFlags      = BindFlags.VertexBuffer,
                    CpuAccessFlags = CpuAccessFlags.Write,
                    OptionFlags    = ResourceOptionFlags.None
                });
            }

            if (_indexBuffer == null || _indexBufferSize < drawData.TotalIdxCount)
            {
                _indexBuffer?.Dispose();
                _indexBufferSize = drawData.TotalIdxCount + 10000;

                _indexBuffer = new Buffer(_device, new BufferDescription
                {
                    Usage          = ResourceUsage.Dynamic,
                    SizeInBytes    = sizeof(ushort) * _indexBufferSize, // ImGui.NET doesn't provide an ImDrawIdx, but their sample uses ushort
                    BindFlags      = BindFlags.IndexBuffer,
                    CpuAccessFlags = CpuAccessFlags.Write
                });
            }

            // Upload vertex/index data into a single contiguous GPU buffer
            int vertexOffset = 0, indexOffset = 0;
            var vertexData = _deviceContext.MapSubresource(_vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None).DataPointer;
            var indexData  = _deviceContext.MapSubresource(_indexBuffer, 0, MapMode.WriteDiscard, MapFlags.None).DataPointer;

            for (int n = 0; n < drawData.CmdListsCount; n++)
            {
                var cmdList = drawData.CmdListsRange[n];
                unsafe
                {
                    System.Buffer.MemoryCopy(cmdList.VtxBuffer.Data.ToPointer(),
                                             (ImDrawVert *)vertexData + vertexOffset,
                                             Unsafe.SizeOf <ImDrawVert>() * _vertexBufferSize,
                                             Unsafe.SizeOf <ImDrawVert>() * cmdList.VtxBuffer.Size);

                    System.Buffer.MemoryCopy(cmdList.IdxBuffer.Data.ToPointer(),
                                             (ushort *)indexData + indexOffset,
                                             sizeof(ushort) * _indexBufferSize,
                                             sizeof(ushort) * cmdList.IdxBuffer.Size);

                    vertexOffset += cmdList.VtxBuffer.Size;
                    indexOffset  += cmdList.IdxBuffer.Size;
                }
            }
            _deviceContext.UnmapSubresource(_vertexBuffer, 0);
            _deviceContext.UnmapSubresource(_indexBuffer, 0);

            // Setup orthographic projection matrix into our constant buffer
            // Our visible imgui space lies from drawData.DisplayPos (top left) to drawData.DisplayPos+drawData.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
            var L   = drawData.DisplayPos.X;
            var R   = drawData.DisplayPos.X + drawData.DisplaySize.X;
            var T   = drawData.DisplayPos.Y;
            var B   = drawData.DisplayPos.Y + drawData.DisplaySize.Y;
            var mvp = new float[]
            {
                2f / (R - L), 0, 0, 0,
                0, 2f / (T - B), 0, 0,
                0, 0, 0.5f, 0,
                (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1f
            };

            var constantBuffer = _deviceContext.MapSubresource(_vertexConstantBuffer, 0, MapMode.WriteDiscard, MapFlags.None).DataPointer;

            unsafe
            {
                fixed(void *mvpPtr = mvp)
                {
                    System.Buffer.MemoryCopy(mvpPtr, constantBuffer.ToPointer(), 16 * sizeof(float), 16 * sizeof(float));
                }
            }
            _deviceContext.UnmapSubresource(_vertexConstantBuffer, 0);

            // Backup DX state that will be modified to restore it afterwards
            // note that this does nothing if _backupState is false
            var oldState = BackupState();

            // Setup desired DX state
            SetupRenderState(drawData);

            // Render command lists
            // (Because we merged all buffers into a single one, we maintain our own offset into them)
            vertexOffset = 0;
            indexOffset  = 0;
            var clipOff = drawData.DisplayPos;

            for (int n = 0; n < drawData.CmdListsCount; n++)
            {
                var cmdList = drawData.CmdListsRange[n];
                for (int cmd = 0; cmd < cmdList.CmdBuffer.Size; cmd++)
                {
                    var pcmd = cmdList.CmdBuffer[cmd];
                    if (pcmd.UserCallback != IntPtr.Zero)
                    {
                        // TODO
                        throw new NotImplementedException();
                    }
                    else
                    {
                        // Apply scissor/clipping rectangle
                        _deviceContext.Rasterizer.SetScissorRectangle((int)(pcmd.ClipRect.X - clipOff.X), (int)(pcmd.ClipRect.Y - clipOff.Y), (int)(pcmd.ClipRect.Z - clipOff.X), (int)(pcmd.ClipRect.W - clipOff.Y));

                        // Bind texture, Draw
                        // Not sure why this bind is done in the loops instead of once per frame, but leaving to match the source for now
                        var textureSrv = ShaderResourceView.FromPointer <ShaderResourceView>(pcmd.TextureId);
                        _deviceContext.PixelShader.SetShaderResource(0, textureSrv);
                        _deviceContext.DrawIndexed((int)pcmd.ElemCount, (int)(pcmd.IdxOffset + indexOffset), (int)(pcmd.VtxOffset + vertexOffset));
                    }
                }

                indexOffset  += cmdList.IdxBuffer.Size;
                vertexOffset += cmdList.VtxBuffer.Size;
            }

            // Restore modified DX state
            RestoreState(oldState);
        }