public CommandList BuildCommandList(GraphicsDevice graphicsDevice, Framebuffer framebuffer)
        {
            Veldrid.CommandList _commandList = null;
            try
            {
                _commandList = graphicsDevice.ResourceFactory.CreateCommandList();
                if (_commandList == null)
                {
                    return(null);
                }

                _commandList.Begin();

                _commandList.SetFramebuffer(framebuffer);
                _commandList.SetFullViewports();

                _commandList.ClearColorTarget(0, RgbaFloat.DarkRed);

                _commandList.End();

                Veldrid.CommandList vret = _commandList;
                _commandList = null;

                return(vret);
            }
            finally
            {
                _commandList?.Dispose();
            }
        }
        static void render(SwapChainPanel swapChainPanel)
        {
            ICommandListFactory commandListFactory = GetCommandListFactory(swapChainPanel);

            if (commandListFactory == null)
            {
                return;
            }

            RenderData _renderData = RenderData.Find(swapChainPanel, false);

            if (_renderData == null)
            {
                return;
            }

            Debug.WriteLine($"{nameof(SwapChainPanelPainter)}.{nameof(render)} _renderData={_renderData}");

            GraphicsDevice _graphicsDevice = _renderData.graphicsDevice;

            if (_graphicsDevice == null)
            {
                return;
            }

            Veldrid.Swapchain _swapchain = _renderData.swapchain;
            if (_swapchain == null)
            {
                return;
            }

            Framebuffer _framebuffer = _renderData.framebuffer;

            if (_framebuffer == null)
            {
                return;
            }

            {
                Veldrid.CommandList _commandList = null;
                try
                {
                    _commandList = commandListFactory.BuildCommandList(_graphicsDevice, _framebuffer);
                    if (_commandList == null)
                    {
                        return;
                    }

                    _graphicsDevice.SubmitCommands(_commandList);
                    _graphicsDevice.SwapBuffers(_swapchain);
                }
                catch (Exception E)
                {
                }
                finally
                {
                    _commandList?.Dispose();
                }
            }
        }
示例#3
0
        public Veldrid.CommandList BuildStandardCommandList()
        {
            if (CommandList == null)
            {
                CommandList = Renderer.VeldridFactory.CreateCommandList();
            }

            CommandList.Begin();
            CommandList.SetFramebuffer(Renderer.GraphicsDevice.SwapchainFramebuffer);

            if (ClearColor.HasValue)
            {
                float[] Floats = ClearColor.Value.GetFloats();
                CommandList.ClearColorTarget(0, new RgbaFloat(Floats[0], Floats[1], Floats[2], Floats[3]));
            }

            if (VertexBuffer != null)
            {
                if (!VertexBuffer.Bound)
                {
                    VertexBuffer.Bind();
                }
                VeldridCamera vCam = Camera as VeldridCamera;
                vCam.Update();

                UpdateModelBuffer();

                VeldridTexture texture = Texture as VeldridTexture;

                CommandList.SetVertexBuffer(0, (VertexBuffer as VeldridVertexBuffer).VertexBuffer);
                CommandList.SetIndexBuffer((VertexBuffer as VeldridVertexBuffer).IndexBuffer, IndexFormat.UInt16);
                if (texture != null)
                {
                    CommandList.SetPipeline((Material as VeldridMaterial).TexturedPipeline);
                }
                else
                {
                    CommandList.SetPipeline((Material as VeldridMaterial).UntexturedPipeline);
                }
                CommandList.SetGraphicsResourceSet(0, vCam.ProjectionViewResourceSet);
                CommandList.SetGraphicsResourceSet(1, ModelResourceSet);

                if (texture != null)
                {
                    CommandList.SetGraphicsResourceSet(2, texture.GetTextureResourceSet());
                }

                CommandList.DrawIndexed((uint)NumIndicies, 1, (uint)StartIndex, 0, 0);
            }

            CommandList.End();

            return(CommandList);
        }
示例#4
0
        public void initialize()
        {
            Veldrid.StartupUtilities.VeldridStartup.CreateWindowAndGraphicsDevice(
                new Veldrid.StartupUtilities.WindowCreateInfo(48, 48, 1280, 720, Veldrid.WindowState.Normal, "Example"),
                new Veldrid.GraphicsDeviceOptions(true, null, true), out window, out gd);

            window.Resized += () =>
            {
                gd.MainSwapchain.Resize((uint)window.Width, (uint)window.Height);
                controller.WindowResized(window.Width, window.Height);
            };

            cl         = gd.ResourceFactory.CreateCommandList();
            controller = new Veldrid.ImGuiRenderer(gd, gd.MainSwapchain.Framebuffer.OutputDescription, window.Width, window.Height);
        }
示例#5
0
        private void PostImageLoad()
        {
            uint tx = (uint)Size.X;
            uint ty = (uint)Size.Y;

            Texture = Renderer.VeldridFactory.CreateTexture(new Veldrid.TextureDescription(
                                                                tx, ty, 1,
                                                                1, 1,
                                                                Veldrid.PixelFormat.R8_G8_B8_A8_UNorm, Veldrid.TextureUsage.Sampled, Veldrid.TextureType.Texture2D));

            Veldrid.Texture StagingTexture = Renderer.VeldridFactory.CreateTexture(new Veldrid.TextureDescription(
                                                                                       tx, ty, 1,
                                                                                       1, 1,
                                                                                       Veldrid.PixelFormat.R8_G8_B8_A8_UNorm, Veldrid.TextureUsage.Staging, Veldrid.TextureType.Texture2D));

            Span <Rgba32> Pixels;

            InternalTexture.TryGetSinglePixelSpan(out Pixels);

            Span <byte> Bytes = MemoryMarshal.AsBytes(Pixels);


            //TODO: Fix this copy (Bytes.ToArray()) and use the memory directly.  UpdateTexture takes an intptr so get that
            Renderer.GraphicsDevice.UpdateTexture(StagingTexture, Bytes.ToArray(),
                                                  0, 0, 0,
                                                  tx, ty, 1,
                                                  0, 0);

            using (Veldrid.CommandList cl = Renderer.VeldridFactory.CreateCommandList())
            {
                cl.Begin();
                cl.CopyTexture(StagingTexture, Texture);
                cl.End();
                Renderer.GraphicsDevice.SubmitCommands(cl);
                Renderer.GraphicsDevice.WaitForIdle();
            }
        }
        unsafe public CommandList BuildCommandList(GraphicsDevice graphicsDevice, Framebuffer framebuffer)
        {
            ResourceFactory factory       = graphicsDevice.ResourceFactory;
            Shader          _vsShader     = null;
            Shader          _psShader     = null;
            DeviceBuffer    _vertexBuffer = null;
            Pipeline        _pipeline     = null;

            Veldrid.CommandList _commandList = null;
            try
            {
                #region --- try

                #region --- shaders
                {
                    string _vsname = null;
                    string _psname = null;

                    switch (graphicsDevice.BackendType)
                    {
                    case GraphicsBackend.Direct3D11:
                        _vsname = "Test_Colored2DVertices.vs";
                        _psname = "Test_Colored2DVertices.ps";
                        break;

                    case GraphicsBackend.Metal:
                        _vsname = "Test_Colored2DVertices_vs.msl";
                        _psname = "Test_Colored2DVertices_ps.msl";
                        break;

                    case GraphicsBackend.Vulkan:
                        _vsname = "Test_Colored2DVertices_vs.spv";
                        _psname = "Test_Colored2DVertices_ps.spv";
                        break;

                    case GraphicsBackend.OpenGL:
                        _vsname = "Test_Colored2DVertices_vs.glsl";
                        _psname = "Test_Colored2DVertices_ps.glsl";
                        break;

                    case GraphicsBackend.OpenGLES:
                        _vsname = "Test_Colored2DVertices_vs_es.glsl";
                        _psname = "Test_Colored2DVertices_ps_es.glsl";
                        break;
                    }

                    string _vs = loadResourceString(Assembly.GetExecutingAssembly(), _vsname);
                    if (string.IsNullOrEmpty(_vs))
                    {
                        return(null);
                    }
                    string _ps = loadResourceString(Assembly.GetExecutingAssembly(), _psname);
                    if (string.IsNullOrEmpty(_ps))
                    {
                        return(null);
                    }

                    ShaderDescription vertexShaderDesc = new ShaderDescription(
                        ShaderStages.Vertex,
                        Encoding.UTF8.GetBytes(_vs),
                        "_VertexShader");
                    ShaderDescription fragmentShaderDesc = new ShaderDescription(
                        ShaderStages.Fragment,
                        Encoding.UTF8.GetBytes(_ps),
                        "_PixelShader");

                    _vsShader = factory.CreateShader(vertexShaderDesc);
                    _psShader = factory.CreateShader(fragmentShaderDesc);
                }
                #endregion

                VertexLayoutDescription _vertexLayout = new VertexLayoutDescription();
                int _vertexCount;

                #region --- _vertexBuffer + _vertexLayout
                {
                    int    _count = 10;
                    byte[] _data  = Build_2DColoredQuads_16SNorm_8UNorm(_count, _count, out _vertexCount);
                    //
                    Veldrid.BufferDescription vbDescription = new Veldrid.BufferDescription(
                        (uint)_data.Length,
                        BufferUsage.VertexBuffer);
                    _vertexBuffer = factory.CreateBuffer(vbDescription);

                    fixed(byte *_pdata = _data)
                    {
                        graphicsDevice.UpdateBuffer(_vertexBuffer, bufferOffsetInBytes: 0, (IntPtr)_pdata, (uint)_data.Length);
                    }

                    _vertexLayout = new VertexLayoutDescription(
                        new VertexElementDescription("Position",
                                                     VertexElementSemantic.Position,
                                                     VertexElementFormat.Short2_Norm,
                                                     offset: 0),
                        new VertexElementDescription("Color",
                                                     VertexElementSemantic.Color,
                                                     VertexElementFormat.Byte4_Norm,
                                                     offset: 2 * sizeof(short)));
                }
                #endregion

                #region --- pipeline
                {
                    GraphicsPipelineDescription _pipelineDescription = new GraphicsPipelineDescription();

                    _pipelineDescription.BlendState = Veldrid.BlendStateDescription.SingleOverrideBlend;

                    _pipelineDescription.DepthStencilState = new Veldrid.DepthStencilStateDescription(
                        depthTestEnabled: false,
                        depthWriteEnabled: false,
                        comparisonKind: ComparisonKind.LessEqual);

                    _pipelineDescription.RasterizerState = new Veldrid.RasterizerStateDescription(
                        cullMode: FaceCullMode.None,
                        fillMode: PolygonFillMode.Solid,
                        frontFace: FrontFace.Clockwise,
                        depthClipEnabled: true, // Android ?
                        scissorTestEnabled: false);

                    _pipelineDescription.PrimitiveTopology = Veldrid.PrimitiveTopology.TriangleList;
                    _pipelineDescription.ResourceLayouts   = System.Array.Empty <ResourceLayout>();

                    _pipelineDescription.ShaderSet = new ShaderSetDescription(
                        vertexLayouts: new VertexLayoutDescription[] { _vertexLayout },
                        shaders: new Shader[] { _vsShader, _psShader });

                    _pipelineDescription.Outputs = framebuffer.OutputDescription; // _offscreenFB.OutputDescription;

                    _pipeline = factory.CreateGraphicsPipeline(_pipelineDescription);
                }
                #endregion

                #region --- commandList
                {
                    _commandList = factory.CreateCommandList();

                    // Begin() must be called before commands can be issued.
                    _commandList.Begin();

                    _commandList.SetPipeline(_pipeline);

                    // We want to render directly to the output window.
                    _commandList.SetFramebuffer(framebuffer);

                    _commandList.SetFullViewports();
                    _commandList.ClearColorTarget(0, RgbaFloat.DarkRed);

                    // Set all relevant state to draw our quad.
                    _commandList.SetVertexBuffer(0, _vertexBuffer);

                    _commandList.Draw(vertexCount: (uint)_vertexCount);

                    // End() must be called before commands can be submitted for execution.
                    _commandList.End();
                }
                #endregion

                CommandList vret = _commandList;
                _commandList = null;

                return(vret);

                #endregion
            }
            catch (Exception e)
            {
                return(null);
            }
            finally
            {
                _vsShader?.Dispose();
                _psShader?.Dispose();
                _vertexBuffer?.Dispose();
                _pipeline?.Dispose();
                _commandList?.Dispose();
            }
        }
示例#7
0
 public void DrawTo(Veldrid.CommandList cmd, _IndexedVertexBuffer vb)
 {
     vb.DrawIndexed(cmd, Offset, Count * 3);
 }
示例#8
0
        static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            D3D11Image d3D11Image = d as D3D11Image;

            if (d3D11Image == null)
            {
                return;
            }

            d3D11Image.OnRender = null;

            ICommandListFactory commandListFactory = e.NewValue as ICommandListFactory;

            if (commandListFactory == null)
            {
                return;
            }

            RenderData _renderData = RenderData.Find(d3D11Image, true);

            if (_renderData == null)
            {
                return;
            }

            GraphicsDevice _graphicsDevice = _renderData.graphicsDevice;

            if (_graphicsDevice == null)
            {
                return;
            }

            SharpDX.Direct3D11.Device _device = _renderData.device;
            if (_device == null)
            {
                return;
            }

            d3D11Image.OnRender = (IntPtr surface, bool isNewSurface) =>
            {
                #region --- OnRender
                Framebuffer _framebuffer = _renderData.FrameBuffer(surface, isNewSurface);
                if (_framebuffer == null)
                {
                    return;
                }

                Veldrid.CommandList commandList = null;
                try
                {
                    commandList = commandListFactory.BuildCommandList(_graphicsDevice, _framebuffer);
                    if (commandList == null)
                    {
                        return;
                    }
                    _graphicsDevice.SubmitCommands(commandList);
                }
                finally
                {
                    commandList?.Dispose();
                }

                _device.ImmediateContext.Flush();
                #endregion
            };
        }
        static void Main(string[] args)
        {
            //AppDomain.CurrentDomain.ProcessExit+= (s,e)=>{}

            var path = Path.GetTempFileName();

            System.IO.File.WriteAllText(path, testVGAOutputProgram);
            var assemblerInst   = new assembler.Assembler(path);
            var assembledResult = assemblerInst.ConvertToBinary();
            var binaryProgram   = assembledResult.Select(x => Convert.ToInt32(x, 16));

            //lets convert our final assembled program back to assembly instructions so we can view it.
            //dissasembly)
            var assembler2 = new assembler.Assembler(path);

            expandedCode = assembler2.ExpandMacros().ToArray();


            simulatorInstance = new simulator.eightChipsSimulator(16, (int)Math.Pow(2, 16));
            simulatorInstance.setUserCode(binaryProgram.ToArray());

            //TODO use cancellation token here.
            simulationThread = Task.Run(() =>
            {
                simulatorInstance.ProgramCounter = (int)assembler.Assembler.MemoryMap[assembler.Assembler.MemoryMapKeys.user_code].AbsoluteStart;
                simulatorInstance.runSimulation();
            });


            // Create window, GraphicsDevice, and all resources necessary for the demo.
            VeldridStartup.CreateWindowAndGraphicsDevice(
                new WindowCreateInfo(50, 50, 1280, 720, WindowState.Normal, "8 chips simulator 2"),
                new GraphicsDeviceOptions(true, null, true),
                out mainWindow,
                out gd);

            mainWindow.Resized += () =>
            {
                gd.MainSwapchain.Resize((uint)mainWindow.Width, (uint)mainWindow.Height);
                controller.WindowResized(mainWindow.Width, mainWindow.Height);
            };
            commandList = gd.ResourceFactory.CreateCommandList();
            controller  = new Veldrid.ImGuiRenderer(gd, gd.MainSwapchain.Framebuffer.OutputDescription, mainWindow.Width, mainWindow.Height);

            var data = simulatorInstance.mainMemory.Select(x => convertShortFormatToFullColor(Convert.ToInt32(x).ToBinary())).ToArray();

            //try creating an texture and binding it to an image which imgui will draw...
            //we'll need to modify this image every frame potentially...

            var texture = gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(width, height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled));

            CPUframeBufferTextureId = controller.GetOrCreateImGuiBinding(gd.ResourceFactory, texture);
            gd.UpdateTexture(texture, data, 0, 0, 0, width, height, 1, 0, 0);
            textureMap.Add(CPUframeBufferTextureId, texture);

            /*
             *          var state = new object();
             *          var timer = new System.Threading.Timer((o) =>
             *          {
             *              int[] newdata = simulatorInstance.mainMemory.Select(x => convertShortFormatToFullColor(x)).ToArray();
             *              var currenttexture = textureMap[CPUframeBufferTextureId];
             *              gd.UpdateTexture(currenttexture, newdata, 0, 0, 0, 256, 256, 1, 0, 0);
             *          }, state, 1000, 150);
             *
             */
            // Main application loop
            while (mainWindow.Exists)
            {
                InputSnapshot snapshot = mainWindow.PumpEvents();
                if (!mainWindow.Exists)
                {
                    break;
                }
                controller.Update(1f / 60f, snapshot); // Feed the input events to our ImGui controller, which passes them through to ImGui.

                SubmitUI();

                commandList.Begin();
                commandList.SetFramebuffer(gd.MainSwapchain.Framebuffer);
                commandList.ClearColorTarget(0, new RgbaFloat(.1f, .1f, .1f, .2f));
                controller.Render(gd, commandList);
                commandList.End();
                gd.SubmitCommands(commandList);
                gd.SwapBuffers(gd.MainSwapchain);
            }

            // Clean up Veldrid resources
            gd.WaitForIdle();
            controller.Dispose();
            commandList.Dispose();
            gd.Dispose();
        }
示例#10
0
        private unsafe void RenderImDrawData(DrawData *draw_data, GraphicsDevice gd, CommandList cl)
        {
            uint vertexOffsetInVertices = 0;
            uint indexOffsetInElements  = 0;

            if (draw_data->CmdListsCount == 0)
            {
                return;
            }

            uint totalVBSize = (uint)(draw_data->TotalVtxCount * sizeof(DrawVert));

            if (totalVBSize > _vertexBuffer.SizeInBytes)
            {
                _vertexBuffer.Dispose();
                _vertexBuffer = gd.ResourceFactory.CreateVertexBuffer(new BufferDescription((ulong)(totalVBSize * 1.5f), true));
            }

            uint totalIBSize = (uint)(draw_data->TotalIdxCount * sizeof(ushort));

            if (totalIBSize > _indexBuffer.SizeInBytes)
            {
                _indexBuffer.Dispose();
                _indexBuffer = gd.ResourceFactory.CreateIndexBuffer(new IndexBufferDescription((ulong)(totalIBSize * 1.5f), IndexFormat.UInt16, true));
            }

            for (int i = 0; i < draw_data->CmdListsCount; i++)
            {
                NativeDrawList *cmd_list = draw_data->CmdLists[i];

                cl.UpdateBuffer(
                    _vertexBuffer,
                    (uint)(vertexOffsetInVertices * sizeof(DrawVert)),
                    new IntPtr(cmd_list->VtxBuffer.Data),
                    (uint)(cmd_list->VtxBuffer.Size * sizeof(DrawVert)));
                cl.UpdateBuffer(
                    _indexBuffer,
                    (uint)(indexOffsetInElements * sizeof(ushort)),
                    new IntPtr(cmd_list->IdxBuffer.Data),
                    (uint)(cmd_list->IdxBuffer.Size * sizeof(ushort)));

                vertexOffsetInVertices += (uint)cmd_list->VtxBuffer.Size;
                indexOffsetInElements  += (uint)cmd_list->IdxBuffer.Size;
            }

            // Setup orthographic projection matrix into our constant buffer
            {
                var io = ImGui.GetIO();

                Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter(
                    0f,
                    io.DisplaySize.X,
                    io.DisplaySize.Y,
                    0.0f,
                    -1.0f,
                    1.0f);

                cl.UpdateBuffer(_projMatrixBuffer, 0, ref mvp);
            }

            cl.SetVertexBuffer(0, _vertexBuffer);
            cl.SetIndexBuffer(_indexBuffer);
            cl.SetPipeline(_pipeline);
            cl.SetResourceSet(0, _resourceSet);

            ImGui.ScaleClipRects(draw_data, ImGui.GetIO().DisplayFramebufferScale);

            // Render command lists
            int vtx_offset = 0;
            int idx_offset = 0;

            for (int n = 0; n < draw_data->CmdListsCount; n++)
            {
                NativeDrawList *cmd_list = draw_data->CmdLists[n];
                for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
                {
                    DrawCmd *pcmd = &(((DrawCmd *)cmd_list->CmdBuffer.Data)[cmd_i]);
                    if (pcmd->UserCallback != IntPtr.Zero)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        if (pcmd->TextureId != IntPtr.Zero)
                        {
                            if (pcmd->TextureId != new IntPtr(_fontAtlasID))
                            {
                                throw new NotImplementedException();
                            }
                        }

                        cl.SetScissorRect(
                            0,
                            (uint)pcmd->ClipRect.X,
                            (uint)pcmd->ClipRect.Y,
                            (uint)pcmd->ClipRect.Z,
                            (uint)pcmd->ClipRect.W);

                        cl.Draw(pcmd->ElemCount, 1, (uint)idx_offset, vtx_offset, 0);
                    }

                    idx_offset += (int)pcmd->ElemCount;
                }
                vtx_offset += cmd_list->VtxBuffer.Size;
            }
        }
示例#11
0
 /// <summary>
 /// Renders the ImGui draw list data.
 /// </summary>
 public unsafe void Render(GraphicsDevice gd, CommandList cl)
 {
     ImGui.Render();
     RenderImDrawData(ImGui.GetDrawData(), gd, cl);
 }
示例#12
0
        private unsafe void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl)
        {
            uint vertexOffsetInVertices = 0;
            uint indexOffsetInElements  = 0;

            if (draw_data.CmdListsCount == 0)
            {
                return;
            }

            uint totalVBSize = (uint)(draw_data.TotalVtxCount * sizeof(ImDrawVert));

            if (totalVBSize > _vertexBuffer.SizeInBytes)
            {
                gd.DisposeWhenIdle(_vertexBuffer);
                _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
            }

            uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort));

            if (totalIBSize > _indexBuffer.SizeInBytes)
            {
                gd.DisposeWhenIdle(_indexBuffer);
                _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
            }

            for (int i = 0; i < draw_data.CmdListsCount; i++)
            {
                ImDrawListPtr cmd_list = draw_data.CmdListsRange[i];

                cl.UpdateBuffer(
                    _vertexBuffer,
                    vertexOffsetInVertices * (uint)sizeof(ImDrawVert),
                    cmd_list.VtxBuffer.Data,
                    (uint)(cmd_list.VtxBuffer.Size * sizeof(ImDrawVert)));

                cl.UpdateBuffer(
                    _indexBuffer,
                    indexOffsetInElements * sizeof(ushort),
                    cmd_list.IdxBuffer.Data,
                    (uint)(cmd_list.IdxBuffer.Size * sizeof(ushort)));

                vertexOffsetInVertices += (uint)cmd_list.VtxBuffer.Size;
                indexOffsetInElements  += (uint)cmd_list.IdxBuffer.Size;
            }

            // Setup orthographic projection matrix into our constant buffer
            {
                var io = ImGui.GetIO();

                Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter(
                    0f,
                    io.DisplaySize.X,
                    io.DisplaySize.Y,
                    0.0f,
                    -1.0f,
                    1.0f);

                _gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp);
            }

            cl.SetVertexBuffer(0, _vertexBuffer);
            cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
            cl.SetPipeline(_pipeline);
            cl.SetGraphicsResourceSet(0, _mainResourceSet);

            draw_data.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);

            // Render command lists
            int vtx_offset = 0;
            int idx_offset = 0;

            for (int n = 0; n < draw_data.CmdListsCount; n++)
            {
                ImDrawListPtr cmd_list = draw_data.CmdListsRange[n];
                for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
                {
                    ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i];
                    if (pcmd.UserCallback != IntPtr.Zero)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        if (pcmd.TextureId != IntPtr.Zero)
                        {
                            if (pcmd.TextureId == _fontAtlasID)
                            {
                                cl.SetGraphicsResourceSet(1, _fontTextureResourceSet);
                            }
                            else
                            {
                                cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd.TextureId));
                            }
                        }

                        cl.SetScissorRect(
                            0,
                            (uint)pcmd.ClipRect.X,
                            (uint)pcmd.ClipRect.Y,
                            (uint)(pcmd.ClipRect.Z - pcmd.ClipRect.X),
                            (uint)(pcmd.ClipRect.W - pcmd.ClipRect.Y));

                        cl.DrawIndexed(pcmd.ElemCount, 1, (uint)idx_offset, vtx_offset, 0);
                    }

                    idx_offset += (int)pcmd.ElemCount;
                }
                vtx_offset += cmd_list.VtxBuffer.Size;
            }
        }