Main Menu

Recent posts

#11
Hello everyone.

I have an indie game on Steam (Area Zero), and it is written using the LWJGL. It is in early release, so I am actively collecting feedback from players. One player was recently updated to the latest patch via Steam. When they attempted to launch the new patch, the game crashed almost immediately. I created a debug build which included logging prints during initialization and sent it to the player (not through Steam). The logging ends as soon as a call is made to org.lwjgl.vulkan.VkInstance.VkInstance. According to the logs, vkCreateInstance returns a status code of VK_SUCCESS and the pointer buffer populated by vkCreateInstance appears to have a valid address (not null).

It seems strange that this player was running the game on a previous patch without issue and that I cannot recall any code changes that would affect the Vulkan instance creation. I decided to send this player a build of the last known working patch, but this time with debug logging included. Now it appears that the previous working patch crashes in the same way as the latest patch (at or during org.lwjgl.vulkan.VkInstance.VkInstance). So, the previous patch went from working to not and appears to be failing in the same way as the latest patch.

I am using Launch4j to create an executable that bundles jdk-23. Has anyone seen this issue or something similar? I am open to suggestions for additional debugging and willing to share any code that can clarify the issue. Thanks for reading and I hope you can help.
#12
Vulkan / Re: Crash in jemalloc after te...
Last post by codex - August 01, 2025, 01:05:32
That makes sense. I'm creating the callback data struct for existing memory, not allocating memory for the struct. Getting rid of the try-with-resources fixed the exception and fixed the native crash. I also managed to patch all of the memory leaks that were reported (several of which had to do with unclosed callbacks).

Thank you so much for your help! :D
#13
Vulkan / Re: Crash in jemalloc after te...
Last post by spasi - July 31, 2025, 07:30:16
Yes, the pCallbackData struct is allocated and managed by the Vulkan implementation. By wrapping it in try-with-resources, it is getting freed from your side, then freed again from the driver side. A double-free is a serious bug that usually leads to crashes. The client-side free might crash as well, if the allocator used is different.

The callbacks themselves allocate native resources in LWJGL, which typically need to be released. Not releasing them on application exit is not necessarily problematic, however it's good practice to free them to reduce the debug allocator output, so that legit bugs are more visible.
#14
Vulkan / Re: Crash in jemalloc after te...
Last post by codex - July 31, 2025, 00:43:59
Thanks, that helps immensely. The leaks seem to be caused by various (if not all) callbacks I'm using, although I'm not sure why that is causing leakages. Here is one such leak:

[LWJGL] 56 bytes leaked, thread 21 (LwjglVulkanContext), address: 0x76982563FEE0
    at org.lwjgl.system.Callback.create(Callback.java:163)
    at org.lwjgl.system.Callback.<init>(Callback.java:113)
    at org.lwjgl.glfw.GLFWWindowSizeCallback.<init>(GLFWWindowSizeCallback.java:55)
    at com.jme3.system.vulkan.LwjglVulkanContext$3.<init>(LwjglVulkanContext.java:129)
    at com.jme3.system.vulkan.LwjglVulkanContext.glfwInitialize(LwjglVulkanContext.java:129)
    at com.jme3.system.vulkan.LwjglVulkanContext.engineInitialize(LwjglVulkanContext.java:85)
    at com.jme3.system.vulkan.LwjglVulkanContext.run(LwjglVulkanContext.java:63)
    at java.base/java.lang.Thread.run(Thread.java:1575)

The exception refers to this glfw call during initialization:

glfwSetWindowSizeCallback(window, sizeCallback = new GLFWWindowSizeCallback() {
    @Override
    public void invoke(final long window, final int width, final int height) {
        updateSizes();
    }
});

Why would this be leaking?

Edit: Oops, just realized this is probably the root of the problem, and not necessary the leaks...

Exception in thread "LwjglVulkanContext" java.lang.IllegalStateException: The memory address specified is not being tracked: 0x75F193FFDC50
	at org.lwjgl.system.MemoryManage$DebugAllocator.untrackAbort(MemoryManage.java:327)
	at org.lwjgl.system.MemoryManage$DebugAllocator.untrack(MemoryManage.java:319)
	at org.lwjgl.system.MemoryManage$DebugAllocator.free(MemoryManage.java:240)
	at org.lwjgl.system.MemoryUtil.nmemFree(MemoryUtil.java:338)
	at org.lwjgl.system.Struct.free(Struct.java:65)
	at org.lwjgl.system.NativeResource.close(NativeResource.java:20)
	at com.jme3.vulkan.VulkanLogger.invoke(VulkanLogger.java:52)
	at org.lwjgl.vulkan.VkDebugUtilsMessengerCallbackEXTI.callback(VkDebugUtilsMessengerCallbackEXTI.java:58)
	at org.lwjgl.system.JNI.callPPPI(Native Method)
	at org.lwjgl.vulkan.VK10.nvkEnumeratePhysicalDevices(VK10.java:3046)
	at org.lwjgl.vulkan.VK10.vkEnumeratePhysicalDevices(VK10.java:3100)
	at com.jme3.vulkan.PhysicalDevice.lambda$getSuitableDevice$4(PhysicalDevice.java:140)
	at com.jme3.renderer.vulkan.VulkanUtils.enumerateBuffer(VulkanUtils.java:49)
	at com.jme3.vulkan.PhysicalDevice.getSuitableDevice(PhysicalDevice.java:139)
	at jme3test.vulkan.VulkanHelperTest.simpleInitApp(VulkanHelperTest.java:117)
	at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:240)
	at com.jme3.system.vulkan.LwjglVulkanContext.engineInitialize(LwjglVulkanContext.java:88)
	at com.jme3.system.vulkan.LwjglVulkanContext.run(LwjglVulkanContext.java:63)
	at java.base/java.lang.Thread.run(Thread.java:1575)

It refers to this in the application:

@Override
public int invoke(int messageSeverity, int messageTypes, long pCallbackData, long pUserData) {
    try (VkDebugUtilsMessengerCallbackDataEXT data = VkDebugUtilsMessengerCallbackDataEXT.create(pCallbackData)) {
        Level lvl = getLoggingLevel(messageSeverity);
        if (exceptionThreshold != null && lvl.intValue() >= exceptionThreshold.intValue()) {
            throw new RuntimeException(lvl.getName() + ": " + data.pMessageString());
        } else {
            System.err.println(lvl.getName() + "  " + data.pMessageString());
        }
    } // exception occurs here
    return VK_FALSE;
}
#15
Vulkan / Re: Crash in jemalloc after te...
Last post by spasi - July 30, 2025, 21:48:37
Hey codex,

Try setting -Dorg.lwjgl.util.DebugAllocator=true. It should report any unreleased memory allocations on process exit. If it crashes before that, you could try manually calling the MemoryUtil.memReport methods to print any active allocations before quitting the application.
#16
Vulkan / Crash in jemalloc after termin...
Last post by codex - July 30, 2025, 21:01:03
I'm experiencing a crash in libjemalloc.so using Lwjgl 3.3.6. It appears to be occurring after my Vulkan application has already terminated, which leads me to believe it's a cleanup issue in jemalloc.

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f114c25933a, pid=93473, tid=93497
#
# JRE version: Java(TM) SE Runtime Environment (23.0.2+7) (build 23.0.2+7-58)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.0.2+7-58, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C  [libjemalloc.so+0x5933a]
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/codex/java/prj/jmonkeyengine/core.93473)
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

The trouble is, I have no idea what I could be doing that would cause a crash such as this. I'm not getting any errors or warnings from Vulkan or anywhere else apart from this crash, and I haven't gotten any leads from looking at the error file either (it doesn't include a stacktrace like other error files I've dealt with).

Does anyone know what mistakes I should look for in debugging this?
#17
Good idea. PM sent
#18
Area Zero is coming to Steam July 15! Add it to your wish list to be notified when it is available: https://store.steampowered.com/app/3796060/Area_Zero/
#19
OpenGL / PBO makes the texture plain wh...
Last post by Silent hallucination - June 23, 2025, 07:16:57
Hello there.
I wanted to play a video using a quad-stretched texture and for the test I made a simple class that gets a ByteBuffer with the first frame of the video and creates a texture from it. However, when I tried to do the same with PBO (which will allow me to update the texture faster in the future), only a solid white rectangle was displayed.
Here is my texture class now:
public class VidTexture {
    int w, h, textureId, pbo;
    VidTexture(int w, int h, ByteBuffer buf) {
        this.w = w;
        this.h = h;
        buf.flip();

        pbo = glGenBuffers();
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
        glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*3L, GL_STREAM_DRAW);
        ByteBuffer bb = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
        bb.put(buf);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

        textureId = glGenTextures();

        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

        glBindTexture(GL_TEXTURE_2D, textureId);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w,
                h, 0, GL_BGR, GL_UNSIGNED_BYTE, 0);
        glGenerateMipmap(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, -1);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

        buf.clear();
    }
    //Here is cleanUp and bind functions
}
Can anyone help me, please?
#20
Bug Reports / RFE / Tab key not working with ctrl ...
Last post by MGVizor - June 05, 2025, 12:44:19
The implementation of listener looks something like this:

private static final class GlfwKeyListener implements GLFWKeyCallbackI {
    private int key;

    @Override
    public void invoke(long window, int key, int scancode, int action, int mods) {
        KeyClass.key = key;
        //schedule to set key to 0 on next frame
    }
}

Then I log the inputs with something like this:

private void logUsedKeys() {
    int key = KeyClass.key;
    if (key != 0) {
        LOGGER.info("Key {}", key);
    }
}

However, when the ctrl is down it prints any pressed key, but tab.

Using macOS if it is important. In other apps everything works fine(e.g. switching tabs in browser/intellij idea)
lwjgl version: 3.3.1