imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Minecraft example not working

Open niklasbuesing opened this issue 6 years ago • 102 comments

Hi!

I'm trying to use imgui in a Minecraft mod i'm making, so i started with the example in the wiki:

public class TestScreen extends Screen {

    private static ImGui imgui = ImGui.INSTANCE;

    private static ImplGL3 implGl3;
    private static ImplGlfw implGlfw;

    static {
        GlfwWindow window = GlfwWindow.from(MinecraftClient.getInstance().window.getHandle());
        window.makeContextCurrent();
        new Context();
        implGlfw = new ImplGlfw(window, false, null);
        implGl3 = new ImplGL3();
    }

    public TestScreen () {
        super(new TextComponent("Test Screen"));
    }

    @Override
    public void render(int x, int y, float partialTicks) {

        implGl3.newFrame(); // JVM crashes here
        implGlfw.newFrame();
        imgui.newFrame();

        imgui.text("Hello Minecraft!");

        implGl3.renderDrawData(imgui.getDrawData());

    }
}

Upon showing the screen however, the jvm crashes:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006b2e0e20, pid=2940, tid=0x00000000000059f0
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [nvoglv64.dll+0xc20e20]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

hs_err_pid2940.log

I'm not sure why this happens, i'm using exactly the same code as in the wiki.

Any help would be appreciated!

niklasbuesing avatar Jun 14 '19 09:06 niklasbuesing

I'll forward you to this guy (https://github.com/kotlin-graphics/imgui/issues/96), who did the same

elect86 avatar Jun 14 '19 10:06 elect86

What does your build.gradle look like? You're crashing in native code, so I presume you're importing the wrong version(s) of LWJGL or the like. (Reference the answer in #96 if you need an example of what you need to add to your dependencies)

zeroeightysix avatar Jun 14 '19 20:06 zeroeightysix

I'm just using the default Fabric build.gradle, plus

repositories {
    ...
    maven { url = "https://jitpack.io" }
}

dependencies {
    ...
    
    ext{
        imguiVersion = "-SNAPSHOT"
    }
    ["gl", "glfw", "core"].each {
        implementation("com.github.kotlin-graphics.imgui:imgui-$it:$imguiVersion") {
            exclude group: "org.lwjgl"
        }
    }
}

I also tried the specific commit you used (fc9aad3de1), with the same result.

Dependencies seem okay

image

niklasbuesing avatar Jun 14 '19 22:06 niklasbuesing

I tried it with several older fabric versions down to 1.14 trying to match your configuration, however it still crashes.

Anyways, i don't know what i've done, but now it crashes "gracefully": (ImGui#getDrawData() just returns null)

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method imgui.impl.ImplGL3.renderDrawData, parameter drawData
	at imgui.impl.ImplGL3.renderDrawData(ImplGL3.kt)
	at de.niklasb.client.TestScreen.render(TestScreen.java:42)
	at net.minecraft.client.gui.screen.SplashScreen.render(SplashScreen.java:56)
	at net.minecraft.client.render.GameRenderer.render(GameRenderer.java:534)
	at net.minecraft.client.MinecraftClient.render(MinecraftClient.java:896)
	at net.minecraft.client.MinecraftClient.start(MinecraftClient.java:386)
	at net.minecraft.client.main.Main.main(Main.java:126)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at net.fabricmc.loader.game.MinecraftGameProvider.launch(MinecraftGameProvider.java:170)
	at net.fabricmc.loader.launch.knot.Knot.init(Knot.java:129)
	at net.fabricmc.loader.launch.knot.KnotClient.main(KnotClient.java:26)

It's probably the same root cause, but i guess thats easier to debug.

I've made a minimal demo, maybe you can take a look at how it differs from your project. It just shows the test screen immediately after minecraft initiliazed and then, at least for me, crashes.

fabric-example-mod.zip

niklasbuesing avatar Jun 14 '19 23:06 niklasbuesing

Do you get any rendering at all? The code crashing inside the OpenGL natives leads me to believe that something is happening with the GL context in Minecraft that causes us to not have a proper GL context. This might be because you register your screen in the onInit method, at which point the window may not be properly initialized, causing us to clear all context when window.setContextCurrent() is called. I would try to add a key toggle that will only open it when you hit that key, which will delay initialization and make sure we grab the right window.

Sylvyrfysh avatar Jun 15 '19 02:06 Sylvyrfysh

Tried that, but it unfortunately still crashes.

x

Sometimes because getDrawData() returns null (https://github.com/kotlin-graphics/imgui/issues/99#issuecomment-502314096), sometimes the jvm crashes (https://github.com/kotlin-graphics/imgui/issues/99#issue-456159881)

I've also tried calling ImGui#render before calling ImplGL3#renderDrawData, not sure if that's still required, just saw it in the tests, but that also didn't help.

niklasbuesing avatar Jun 15 '19 03:06 niklasbuesing

Give me the output of this, please?

TestScreen.kt

public class TestScreen extends Screen {

    private static ImGui imgui = ImGui.INSTANCE;

    private static ImplGL3 implGl3;
    private static ImplGlfw implGlfw;

    static {
        test();
        GlfwWindow window = GlfwWindow.from(MinecraftClient.getInstance().window.getHandle());
        window.makeContextCurrent();
        new Context();
        implGlfw = new ImplGlfw(window, false, null);
        implGl3 = new ImplGL3();
    }

    public static void test() {
        ImguiKt.setIMGUI_ENABLE_TEST_ENGINE(true);
        ImguiKt.setImGuiTestEngineHook_PreNewFrame(() -> {
            TestScreen.onNewFrame();
            return null;
        });
        ImguiKt.setImGuiTestEngineHook_PostNewFrame(() -> {
            TestScreen.onPostNewFrame();
            return null;
        });
        ImguiKt.setImGuiTestEngineHook_ItemAdd((rect, integer) -> {
            System.out.printf("Item added at %f %f sz %f %f\n", rect.getBl().getX(), rect.getBr().getY(), rect.getWidth(), rect.getHeight());
            return null;
        });
        ImguiKt.setImGuiTestEngineHook_ItemInfo((id, string, itm1) -> {
            System.out.printf("Item added id %d str %s int %d\n", id, string, itm1);
            return null;
        });
    }

    private static void onNewFrame() {
        System.out.println("Pre-NewFrame");
    }
    private static void onPostNewFrame() {
        System.out.println("Post-NewFrame");
    }

    public TestScreen () {
        super(new TextComponent("Test Screen"));
    }

    @Override
    public void render(int x, int y, float partialTicks) {

        implGl3.newFrame();
        implGlfw.newFrame();
        imgui.newFrame();

        imgui.text("Hello Minecraft!");
        
        imgui.render();

        implGl3.renderDrawData(imgui.getDrawData());

    }
}

Sylvyrfysh avatar Jun 15 '19 04:06 Sylvyrfysh

Sure

[06:19:59] [main/INFO]: [STDOUT]: Pre-NewFrame
Item added at 60.000000 73.000000 sz 13.000000 13.000000
Item added at 60.000000 79.000000 sz 400.000000 19.000000
[06:19:59] [main/INFO]: [STDOUT]: Post-NewFrame
[06:19:59] [main/INFO]: [STDOUT]: in (1.0, 1.0) (3.4028235E38, 3.4028235E38)
[LWJGL] [06:19:59] [main/INFO]: [STDERR]: Loading library: Imm32
[LWJGL] [06:19:59] [main/INFO]: [STDERR]: 	Imm32.dll not found in org.lwjgl.librarypath=C:\Users\User\AppData\Local\Temp\lwjglUser\3.2.1-build-12
[LWJGL] [06:19:59] [main/INFO]: [STDERR]: 	Loaded from system paths: C:\WINDOWS\System32\IMM32.DLL
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000561328, pid=19924, tid=0x0000000000005dcc
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  0x0000000000561328
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\User\IdeaProjects\client\run\hs_err_pid19924.log
Compiled method (nm)   40450 6337     n 0       org.lwjgl.system.JNI::callPP (native)
 total in heap  [0x00000000047ae3d0,0x00000000047ae750] = 896
 relocation     [0x00000000047ae4f0,0x00000000047ae538] = 72
 main code      [0x00000000047ae540,0x00000000047ae748] = 520
 oops           [0x00000000047ae748,0x00000000047ae750] = 8
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

hs_err_pid19924.log

niklasbuesing avatar Jun 15 '19 04:06 niklasbuesing

Change the static block to this:

        test();
        GlfwWindow window = GlfwWindow.from(MinecraftClient.getInstance().window.getHandle());
        System.out.printf("GLFWWindow %d\n", MinecraftClient.getInstance().window.getHandle());
        window.makeContextCurrent();
        new Context();
        implGlfw = new ImplGlfw(window, false, null);
        implGl3 = new ImplGL3();

and does the GLFWWindow say it is 0?

My line of thinking on this issue is that all crashes we've seen here have a common root cause of a bad window. When we set the context as current on a dead/bad/non-existent window, we lose all GL functions, leading to a crash in uploading the font texture. It would also crash in the IME setposition.

Your null crash avoids this behavior by crashing before on window-specific code is called (besides font upload- the one hole with this theory), but this might be some GL client/server sync we're seeing that would generally only appear second frame or something.

If not, i'll try to get my modding environment working and see if it will work. Thank you for sticking with us through this!

Sylvyrfysh avatar Jun 15 '19 05:06 Sylvyrfysh

Window seems fine

GLFWWindow 569093408

Also not sure if relevant, but sometimes i have to run it a few times because it crashes before anything is printed with the original exception in my first comment

niklasbuesing avatar Jun 15 '19 05:06 niklasbuesing

Even with the key toggle?

Sylvyrfysh avatar Jun 15 '19 05:06 Sylvyrfysh

Yep

niklasbuesing avatar Jun 15 '19 05:06 niklasbuesing

I've made a minimal demo, maybe you can take a look at how it differs from your project. It just shows the test screen immediately after minecraft initiliazed and then, at least for me, crashes.

fabric-example-mod.zip

How do you start that? I see no main

elect86 avatar Jun 15 '19 09:06 elect86

First you have to run ./gradlew genSources, then depending on whether you use eclipse or intellij either ./gradlew eclipse or ./gradlew idea to generate the correct run configuration.

For other editors you can use those settings as reference:

image

Might help: https://fabricmc.net/wiki/tutorial:setup

niklasbuesing avatar Jun 15 '19 09:06 niklasbuesing

weird

C:\Users\elect.gradle\caches\fabric-loom\minecraft-1.14.2-mapped-7.jar: The process cannot access the file because it is being used by another process.

elect86 avatar Jun 15 '19 10:06 elect86

I got it working with the zip you provided and a few changes:

I changed MinecraftClientMixin to MixinKeyboard and changed the mixin to this:

@Mixin(Keyboard.class)
public abstract class MixinKeyboard {

    @Inject(method = "onKey", at = @At(value = "HEAD"))
    public void onKey(long handle, int keycode, int scancode, int i3, int i4, CallbackInfo info) {
        if (MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().currentScreen == null) {
            MinecraftClient.getInstance().openScreen(new TestScreen());
        }
    }

}

This way we can invoke imgui in-game by pressing a key (when we're sure everything of opengl/glfw etc has already been handled by minecraft)

And simply added imgui.render(); to your render method in TestScreen:

...
imgui.text("Hello Minecraft!");

imgui.render();

implGl3.renderDrawData(imgui.getDrawData());
...

I never ran into a JVM crash though. I'm on linux, so our natives are different. Can you try the changes above and see if it works?

zeroeightysix avatar Jun 15 '19 11:06 zeroeightysix

Nope, still crashes :/

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000677a0e20, pid=6760, tid=0x000000000000396c
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [nvoglv64.dll+0xc20e20]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\User\Desktop\fabric-example-mod\run\hs_err_pid6760.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

hs_err_pid6760.log

niklasbuesing avatar Jun 15 '19 17:06 niklasbuesing

~Solved the NPE, it was because there was a missing imgui.render(); before implGl3.renderDrawData(imgui.getDrawData());~ zeroeightysix already got that

Now I get the jvm crash though.. in the ime, at val himc: HIMC = HIMC(imm.getContext(hwnd))

elect86 avatar Jun 15 '19 18:06 elect86

So this appears to be a Windows specific issue, where the Imm Libraries cause a crash. I'll start playing around with e=that, just was finally able to get everything set up. @elect86 do you know if only one Imm context can be had per window, and possibly minecraft already has it?

Sylvyrfysh avatar Jun 15 '19 23:06 Sylvyrfysh

@elect86 I messes up the pulls on which branches but was planning to merge anyways. If you don't want the commit Cleanups/Javaifications, feel free to revert.

@niklasbuesing Using commit ccbbf105d1, set ImguiKt.MINECRAFT_BEHAVIORS = true before you create the GLFWWindow and this should resolve the problem. I was able to get the Demo Window up and showing. Let me know if this fixes it on your side as well.

The drawbacks to this method is that currently Imgui on minecraft will not receive IME events, so we'll have to see if we can reflect out the HWND MC has.

Sylvyrfysh avatar Jun 16 '19 00:06 Sylvyrfysh

Yep, works fine now! 👍

Thanks to everyone involved for their efforts. 😃

niklasbuesing avatar Jun 16 '19 02:06 niklasbuesing

It's totally fine, let's merge it.. Nice workaround @Sylvyrfysh

Btw, I double checked ImmGetContext address is exaclty the same, only hwnd varies, but it looks somehow valid also on the small fabric sample.. I wonder what it is..

We might create an issue over there (https://github.com/FabricMC) to watch this issue in the long term and see if we find the culprit, I'm afraid this may have to do with something else under the hood.. (@niklasbuesing which repo would you suggest in their organization in this matter?)

elect86 avatar Jun 16 '19 07:06 elect86

Can someone post a zip of their simple example? i keep getting the glTexture2D crashes when trying to actually fix this

Sylvyrfysh avatar Jun 21 '19 01:06 Sylvyrfysh

Example is not compiling for me on Java 8, glm seems to be compiled for Java 11...

/home/runner/work/examplemod/examplemod/src/main/java/io/github/examplemod/Imgui.java:3: error: cannot access Vec2
import glm_.vec2.Vec2;
                ^

> Task :compileJava FAILED
  bad class file: /home/runner/.gradle/caches/modules-2/files-2.1/com.github.kotlin-graphics.glm/glm/6048c31425ae6110258e4b42165f1e636f8b5603/be825795adf887a045ee19eb08db0eeff47b02fb/glm-6048c31425ae6110258e4b42165f1e636f8b5603.jar(glm_/vec2/Vec2.class)

    class file has wrong version 55.0, should be 52.0
    Please remove or make sure it appears in the correct subdirectory of the classpath.

If there is any way I could get around this, I would appreciate it greatly.

Edit: removed import as it was unused, ImGUI now says its' classpath is for Java 11.

  bad class file: /home/runner/.gradle/caches/modules-2/files-2.1/com.github.kotlin-graphics.imgui/imgui-core/-SNAPSHOT/d872d341aa28c6ddf10430d6f22bd75911763ca2/imgui-core--SNAPSHOT.jar(imgui/ImGui.class)
    class file has wrong version 55.0, should be 52.0
    Please remove or make sure it appears in the correct subdirectory of the classpath.

AlexApps99 avatar Sep 20 '19 01:09 AlexApps99

It's probably worth asking, is this library compatible with Java 8, and compatible with Linux? The README seems to advertise that but I'm not sure if it's still the case...

AlexApps99 avatar Sep 20 '19 01:09 AlexApps99

Reading the build files seems to suggest this is a Java 11 library, how would I compile this for Java 8?

AlexApps99 avatar Sep 20 '19 02:09 AlexApps99

Change the value on the line here to 8. Don't know if that will compile though

Sylvyrfysh avatar Sep 20 '19 02:09 Sylvyrfysh

Will keep you posted if it doesn't work, thanks

AlexApps99 avatar Sep 20 '19 02:09 AlexApps99

I don't think it'll work in my case as JitPack hosts this library compiled for Java 11 too. The entire library would need to be recompiled for Java 8, dependencies included

AlexApps99 avatar Sep 20 '19 02:09 AlexApps99

How does everybody else manage to compile the mod, seeing as Minecraft uses Java 8?

AlexApps99 avatar Sep 20 '19 04:09 AlexApps99