private unsafe void UpdateMonitors()
        {
            if (p_sdl_GetNumVideoDisplays == null)
            {
                p_sdl_GetNumVideoDisplays = Sdl2Native.LoadFunction <SDL_GetNumVideoDisplays_t>("SDL_GetNumVideoDisplays");
            }
            if (p_sdl_GetDisplayUsableBounds_t == null)
            {
                p_sdl_GetDisplayUsableBounds_t = Sdl2Native.LoadFunction <SDL_GetDisplayUsableBounds_t>("SDL_GetDisplayUsableBounds");
            }

            ImGuiPlatformIOPtr plIo = ImGui.GetPlatformIO();

            Marshal.FreeHGlobal(plIo.NativePtr->Monitors.Data);
            int    numMonitors = p_sdl_GetNumVideoDisplays();
            IntPtr data        = Marshal.AllocHGlobal(Unsafe.SizeOf <ImGuiPlatformMonitor>() * numMonitors);

            plIo.NativePtr->Monitors = new ImVector(numMonitors, numMonitors, data);
            for (int i = 0; i < numMonitors; i++)
            {
                Rectangle r;
                p_sdl_GetDisplayUsableBounds_t(i, &r);
                ImGuiPlatformMonitorPtr monitor = plIo.Monitors[i];
                monitor.DpiScale = 1f;
                monitor.MainPos  = new Vector2(r.X, r.Y);
                monitor.MainSize = new Vector2(r.Width, r.Height);
                monitor.WorkPos  = new Vector2(r.X, r.Y);
                monitor.WorkSize = new Vector2(r.Width, r.Height);
            }
        }
        public void SwapExtraWindows(GraphicsDevice gd)
        {
            ImGuiPlatformIOPtr platformIO = ImGui.GetPlatformIO();

            for (int i = 1; i < platformIO.Viewports.Size; i++)
            {
                ImGuiViewportPtr   vp     = platformIO.Viewports[i];
                VeldridImGuiWindow window = (VeldridImGuiWindow)GCHandle.FromIntPtr(vp.PlatformUserData).Target;
                gd.SwapBuffers(window.Swapchain);
            }
        }
        /// <summary>
        /// Sets per-frame data based on the associated window.
        /// This is called by Update(float).
        /// </summary>
        private void SetPerFrameImGuiData(float deltaSeconds)
        {
            ImGuiIOPtr io = ImGui.GetIO();

            io.DisplaySize = new Vector2(
                _windowWidth / _scaleFactor.X,
                _windowHeight / _scaleFactor.Y);
            io.DisplayFramebufferScale = _scaleFactor;
            io.DeltaTime = deltaSeconds;             // DeltaTime is in seconds.

            ImGuiPlatformIOPtr platformIo = ImGui.GetPlatformIO();

            platformIo.MainViewport.Pos  = new Vector2(_window.X, _window.Y);
            platformIo.MainViewport.Size = new Vector2(_window.Width, _window.Height);
        }
        /// <summary>
        /// Renders the ImGui draw list data.
        /// This method requires a <see cref="GraphicsDevice"/> because it may create new DeviceBuffers if the size of vertex
        /// or index data has increased beyond the capacity of the existing buffers.
        /// A <see cref="CommandList"/> is needed to submit drawing and resource update commands.
        /// </summary>
        public void Render(GraphicsDevice gd, CommandList cl)
        {
            if (_frameBegun)
            {
                _frameBegun = false;
                ImGui.Render();
                RenderImDrawData(ImGui.GetDrawData(), gd, cl);

                // Update and Render additional Platform Windows
                if ((ImGui.GetIO().ConfigFlags & ImGuiConfigFlags.ViewportsEnable) != 0)
                {
                    ImGui.UpdatePlatformWindows();
                    ImGuiPlatformIOPtr platformIO = ImGui.GetPlatformIO();
                    for (int i = 1; i < platformIO.Viewports.Size; i++)
                    {
                        ImGuiViewportPtr   vp     = platformIO.Viewports[i];
                        VeldridImGuiWindow window = (VeldridImGuiWindow)GCHandle.FromIntPtr(vp.PlatformUserData).Target;
                        cl.SetFramebuffer(window.Swapchain.Framebuffer);
                        RenderImDrawData(vp.DrawData, gd, cl);
                    }
                }
            }
        }
        /// <summary>
        /// Constructs a new ImGuiController.
        /// </summary>
        public ImGuiController(GraphicsDevice gd, Sdl2Window window, OutputDescription outputDescription, int width, int height)
        {
            _gd           = gd;
            _window       = window;
            _windowWidth  = width;
            _windowHeight = height;

            IntPtr context = ImGui.CreateContext();

            ImGui.SetCurrentContext(context);
            ImGuiIOPtr io = ImGui.GetIO();


            io.ConfigFlags |= ImGuiConfigFlags.DockingEnable;
            io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;

            ImGuiPlatformIOPtr platformIO   = ImGui.GetPlatformIO();
            ImGuiViewportPtr   mainViewport = platformIO.MainViewport;

            _mainViewportWindow         = new VeldridImGuiWindow(gd, mainViewport, _window);
            mainViewport.PlatformHandle = window.Handle;

            _createWindow       = CreateWindow;
            _destroyWindow      = DestroyWindow;
            _getWindowPos       = GetWindowPos;
            _showWindow         = ShowWindow;
            _setWindowPos       = SetWindowPos;
            _setWindowSize      = SetWindowSize;
            _getWindowSize      = GetWindowSize;
            _setWindowFocus     = SetWindowFocus;
            _getWindowFocus     = GetWindowFocus;
            _getWindowMinimized = GetWindowMinimized;
            _setWindowTitle     = SetWindowTitle;

            platformIO.Platform_CreateWindow       = Marshal.GetFunctionPointerForDelegate(_createWindow);
            platformIO.Platform_DestroyWindow      = Marshal.GetFunctionPointerForDelegate(_destroyWindow);
            platformIO.Platform_ShowWindow         = Marshal.GetFunctionPointerForDelegate(_showWindow);
            platformIO.Platform_SetWindowPos       = Marshal.GetFunctionPointerForDelegate(_setWindowPos);
            platformIO.Platform_SetWindowSize      = Marshal.GetFunctionPointerForDelegate(_setWindowSize);
            platformIO.Platform_SetWindowFocus     = Marshal.GetFunctionPointerForDelegate(_setWindowFocus);
            platformIO.Platform_GetWindowFocus     = Marshal.GetFunctionPointerForDelegate(_getWindowFocus);
            platformIO.Platform_GetWindowMinimized = Marshal.GetFunctionPointerForDelegate(_getWindowMinimized);
            platformIO.Platform_SetWindowTitle     = Marshal.GetFunctionPointerForDelegate(_setWindowTitle);
            platformIO.Platform_GetWindowPos       = Marshal.GetFunctionPointerForDelegate(_getWindowPos);
            platformIO.Platform_GetWindowSize      = Marshal.GetFunctionPointerForDelegate(_getWindowSize);

            unsafe
            {
                io.NativePtr->BackendPlatformName = (byte *)new FixedAsciiString("Veldrid.SDL2 Backend").DataPtr;
            }
            io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
            io.BackendFlags |= ImGuiBackendFlags.HasSetMousePos;
            io.BackendFlags |= ImGuiBackendFlags.PlatformHasViewports;
            io.BackendFlags |= ImGuiBackendFlags.RendererHasViewports;

            io.Fonts.AddFontDefault();

            CreateDeviceResources(gd, outputDescription);
            SetKeyMappings();

            SetPerFrameImGuiData(1f / 60f);

            UpdateMonitors();

            ImGui.NewFrame();
            _frameBegun = true;
        }