kotlin-graphics / imgui

Bloat-free Immediate Mode Graphical User interface for JVM with minimal dependencies (rewrite of dear imgui)
MIT License
594 stars 37 forks source link

Minecraft example not working #99

Open niklasbuesing opened 5 years ago

niklasbuesing commented 5 years ago

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!

elect86 commented 5 years ago

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

zeroeightysix commented 5 years ago

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)

niklasbuesing commented 5 years ago

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 commented 5 years ago

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

Sylvyrfysh commented 5 years ago

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.

niklasbuesing commented 5 years ago

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.

Sylvyrfysh commented 5 years ago

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());

    }
}
niklasbuesing commented 5 years ago

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

Sylvyrfysh commented 5 years ago

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!

niklasbuesing commented 5 years ago

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

Sylvyrfysh commented 5 years ago

Even with the key toggle?

niklasbuesing commented 5 years ago

Yep

elect86 commented 5 years ago

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

niklasbuesing commented 5 years ago

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

elect86 commented 5 years ago

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.

zeroeightysix commented 5 years ago

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?

niklasbuesing commented 5 years ago

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

elect86 commented 5 years ago

~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))

Sylvyrfysh commented 5 years ago

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 commented 5 years ago

@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.

niklasbuesing commented 5 years ago

Yep, works fine now! 👍

Thanks to everyone involved for their efforts. 😃

elect86 commented 5 years ago

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?)

Sylvyrfysh commented 5 years ago

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

AlexApps99 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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

Sylvyrfysh commented 4 years ago

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

AlexApps99 commented 4 years ago

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

AlexApps99 commented 4 years ago

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 commented 4 years ago

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

elect86 commented 4 years ago

Yep, we moved since some time to the current LTS, that is jdk11.

If you still need legacy support, you need to have the whole libraries on jdk8. It's quite simple actually:

However, honestly I dont have the resources and the interest to do that.

So if you would like that, I can send you an invite and you can jump in and take care of that :)

AlexApps99 commented 4 years ago

Sure, I could do that.

What should the branch be named?

elect86 commented 4 years ago

as you wish, jdk8 or whatever you think is better

you shall create a branch for unsigned, kool, glm, gli, gln and uno

I sent you an invite for the organization, if this is not enough, let me know and I'll send for each repo

AlexApps99 commented 4 years ago

It seems I cannot create branches yet, I may need individual permissions for each repository.

elect86 commented 4 years ago

Done, you are good to go :)

AlexApps99 commented 4 years ago

Ok, I have made the branches and will be committing to them over the coming days to change Java versions.

Commited branches so far:

To be done branches:

None

AlexApps99 commented 4 years ago

What should I do about these lines:

    unsigned_version = 'c81c2e39fb9e10403650c1b371b8573fc745bfb4'
    kool_version = '1e564cfb7ab72523d0f748a235e21cf33d0c73bc'

from https://github.com/kotlin-graphics/glm/blob/jdk8/build.gradle#L28?

They appear in all of the other repositories too, do they need to be updated to reflect the jdk8 branch somehow?

elect86 commented 4 years ago

yep

AlexApps99 commented 4 years ago

What does the hash represent?

elect86 commented 4 years ago

it's the commit hash/id of the given dependency

AlexApps99 commented 4 years ago

I have modified every repo required on the jdk8 branch, is there any way to tell if the CI is working or if I have made a mistake?

AlexApps99 commented 4 years ago

The list of relevant repos and commits is available here.

Sylvyrfysh commented 4 years ago

https://travis-ci.org/kotlin-graphics/imgui/branches

AlexApps99 commented 4 years ago

Oh, think I know what the problem is - specified commit id without branch name Will try to amend the errors soon

elect86 commented 4 years ago

You should start from the lowest library, like kool, which has this error

AlexApps99 commented 4 years ago

Will try to do the bulk of the fixes tomorrow, hopefully it'll work

AlexApps99 commented 4 years ago

Travis CI for Imgui All dependencies have built sucessfully but there were a few errors for imgui itself.

Edit: Seems like com.sun.jdi isn't importing, will look into it Edit edit: Line 36 of build.gradle seems to be the offending line, as me researching for a solution came upon the same exact line here

elect86 commented 4 years ago

You can comment out jdi and the tools.jar in gradle without problems, it's used only for counting the allocated instances, but it's quite unstable/untested

AlexApps99 commented 4 years ago

I have removed JDI, now I am getting the following error message on Travis CI:

e: /home/travis/build/kotlin-graphics/imgui/imgui-gl/src/main/kotlin/imgui/impl/gl/ImplGL3.kt: (14, 24): Unresolved reference: GlVertexArray
e: /home/travis/build/kotlin-graphics/imgui/imgui-gl/src/main/kotlin/imgui/impl/gl/ImplGL3.kt: (42, 15): Unresolved reference: GlVertexArray
e: /home/travis/build/kotlin-graphics/imgui/imgui-gl/src/main/kotlin/imgui/impl/gl/ImplGL3.kt: (276, 15): Unresolved reference: GlVertexArray
e: /home/travis/build/kotlin-graphics/imgui/imgui-gl/src/main/kotlin/imgui/impl/gl/commonGL.kt: (4, 12): Unresolved reference: GlBufferEnum
e: /home/travis/build/kotlin-graphics/imgui/imgui-gl/src/main/kotlin/imgui/impl/gl/commonGL.kt: (148, 21): Unresolved reference: GlBufferEnum
AlexApps99 commented 4 years ago

I have looked and they are indeed undefined in gln, do I need to hotfix/revert to an older version? Is this a regression or a mistake on my part?