ImGuiNET / ImGui.NET

An ImGui wrapper for .NET.
MIT License
1.87k stars 304 forks source link

Getting an access violation; called code appears identical to sample #133

Open MouseProducedGames opened 5 years ago

MouseProducedGames commented 5 years ago

The first call to ImGui.NewFrame() always throws an access violation in my project. I copied over all the non-Veldrid specific parts to my code, and the exact same result occurs:

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

I was able to copy over the entire set of code and resource files from ImGui.NET.SampleProgram and that worked (once I embedded the shader resources properly). It may be that I don't have a render output setup for ImGui.Net, yet - based on my reading of the code, that should only result in no GUI being displayed, not an access violation exception?

I'm using glfw-net, glfw (don't know if it's necessary) and my own OpenGL very thin wrapper that doesn't do any processing at all - so it shouldn't be that; also all I use it for is clearing the screen, and commenting out those doesn't change a thing.

` public static void Run(AApplication application) { Glfw.Init();

        using var window = new NativeWindow(800, 600, "Hello, World!");

        if (window == null)
        {
            Glfw.Terminate();
            return;
        }

        Glfw.Init();

        BLAH = window;

        while (window.Handle == IntPtr.Zero) ;

        Glfw.MakeContextCurrent(window);
        Glfw.SwapInterval(1);

        application.Init();

        application.LoadContent();

        _frameBegun = false;
        {
            IntPtr context = ImGui.CreateContext();
            ImGui.SetCurrentContext(context);

            var io = ImGui.GetIO();
            io.Fonts.AddFontDefault();

            SetKeyMappings();

            SetPerFrameImGuiData(1f / 60f);

            ImGui.NewFrame(); // Access violation exception here.
            _frameBegun = true;
        }

        while (!Glfw.WindowShouldClose(window))
        {
            Glfw.PollEvents();

            Update(1.0F / 60.0F);

            GL4.ClearColor(0.0F, 1.0F, 1.0F, 1.0F);
            GL4.Clear(GLbitfield.COLOR_BUFFER_BIT);

            Render();

            EventDispatcher.Dispatch(application);

            application.OnUpdatePre();
            application.OnUpdate();
            foreach (var layer in application.Layers)
            {
                layer.OnUpdate();
            }
            application.OnUpdatePost();

            application.OnRenderPre();
            application.OnRender();
            foreach (var layer in application.Layers)
            {
                layer.OnRender();
            }
            application.OnRenderPost();

            Glfw.SwapBuffers(window);

            Glfw.PollEvents();
        }

        Glfw.Terminate();

        /* string envDebug = Environment.GetEnvironmentVariable("DEBUG");
        if (envDebug == "GL")
        {
            KhronosApi.Log += delegate (object sender, KhronosLogEventArgs e)
            {
                Console.WriteLine(e.ToString());
            };
            KhronosApi.LogEnabled = true;
        }

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        application.Init();
        Application.Run(new OpenGLForm(application)); */
    }

    private static void Update(float deltaSeconds)
    {
        if (_frameBegun)
        {
            ImGui.Render();
        }

        SetPerFrameImGuiData(deltaSeconds);

        _frameBegun = true;
        ImGui.NewFrame();
    }
    public static void Render()
    {
        if (_frameBegun)
        {
            _frameBegun = false;
            ImGui.Render();
        }
    }
    private static void SetPerFrameImGuiData(float deltaSeconds)
    {
        var _windowWidth = BLAH.Size.Width;
        var _windowHeight = BLAH.Size.Height;
        var _scaleFactor = new Vector2(1, 1);
        ImGuiIOPtr io = ImGui.GetIO();
        io.DisplaySize = new Vector2(
            _windowWidth / _scaleFactor.X,
            _windowHeight / _scaleFactor.Y);
        io.DisplayFramebufferScale = _scaleFactor;
        io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
    }

    private static void SetKeyMappings()
    {
        ImGuiIOPtr io = ImGui.GetIO();
        io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab;
        io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left;
        io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right;
        io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up;
        io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down;
        io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp;
        io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown;
        io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home;
        io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End;
        io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete;
        io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Backspace;
        io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter;
        io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape;
        io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A;
        io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C;
        io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V;
        io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X;
        io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y;
        io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z;
    }

`

JayPeet commented 5 years ago

Try to call the function below before you call SetKeyMappings();

private static void RecreateFontDeviceTexture() { ImGuiIOPtr io = ImGui.GetIO(); IntPtr pixels; int width, height, bytesPerPixel; io.Fonts.GetTexDataAsRGBA32(out pixels, out width, out height, out bytesPerPixel); io.Fonts.ClearTexData(); }

Normally you would then send the pixels to the Graphics library to upload as a texture to use, then set the fonts texture ID to point to it using io.Fonts.SetTexID(fontTexID);

JayPeet commented 5 years ago

Sorry for that terrible code formatting.

trvkv commented 3 years ago

private static void RecreateFontDeviceTexture() { ImGuiIOPtr io = ImGui.GetIO(); IntPtr pixels; int width, height, bytesPerPixel; io.Fonts.GetTexDataAsRGBA32(out pixels, out width, out height, out bytesPerPixel); io.Fonts.ClearTexData(); }

I was having exactly the same issue (and I'm also using the lib without any rendering backend for now) and calling this actually fixes the issue with AccessViolation. I'm using OpenTK so it was kind of tricky to find something on that. Thank you!

bryanedds commented 1 year ago

YES, I was having the exact same issue trying to get my game engine to run under NUnit, and calling GetTexDataAsRGBA32 and ClearTexData fixed it!

That said, I'm ALL on board for having better error information! It took me hours of trying then finding this issue to fix this problem 💯