GLFW / LWJGL 3 bugs

Started by theagentd, August 26, 2015, 19:54:43

Previous topic - Next topic

theagentd

I've trying to wrap my head around GLFW to get into LWJGL 3 lately, but I've stumbled upon a few bugs, possibly driver bugs on my computer. I'm running Windows 7 with 2xGTX 770s (SLI disabled) and two 2560x1440 monitors, both connected to the main GPU.

- If you create two fullscreen windows on two different monitors, every time focus switches from one window to the other they both flicker (turn black) for half a second and then come back.

- When iconifying a fullscreen window, the original resolution isn't restored despite the documentation of GLFW saying it should be:
QuoteIf the specified window is a full screen window, the original monitor resolution is restored until the window is restored.
For example, if I iconify a 1920x1080 fullscreen window, the monitor doesn't revert to 2560x1440 as it should. Instead I see my desktop at 1920x1080 as long as the window is alive. Quitting the application restores the resolution properly.

- glfwSwapInterval() says that it can accept negative swap intervals, which means that it'll disable V-sync if the FPS drops below the refresh rate of the monitor.
advancedSwapSupported = 
				glfwExtensionSupported("WGL_EXT_swap_control_tear") == GL_TRUE ||
				glfwExtensionSupported("GLX_EXT_swap_control_tear") == GL_TRUE;

		if(advancedSwapSupported){
			glfwSwapInterval(swapInterval);
		}else{
			glfwSwapInterval(Math.abs(swapInterval));
		}

The extension(s) is supported on my computer, but when I tried it out I got a white unresponsive window that wouldn't render anything. The thread is blocked indefinitely on the first call to glfwSwapBuffers(). I am not overriding anything in the Nvidia Control Panel (everything default according to Nvidia Inspector).

- For all GLFW windows, V-sync is enabled by default. This makes no sense as the documentation for glfwCreateWindow() says:
QuoteThe swap interval is not set during window creation and the initial value may vary depending on driver settings and defaults.
I'm faaaaaiiirly sure Nvidia doesn't enabled V-sync by default. EDIT: Confirmed, LWJGL 2 does not have V-sync enabled by default.

- Forcing V-sync off through the Nvidia control panel does not work for windows. Fullscreen V-sync is properly disabled by the driver though. Only windows are still having V-sync enabled.



EDIT: Unrelated question: Is there any way to switch between fullscreen and windowed mode? LWJGL2 supported this, but GLFW does not seem to be able to do that?

spasi

Hey theagentd,

I'm currently returning from a short vacation, I'll try to reply to everything later tonight or tomorrow.

In the meantime, see this issue, for the flicker problem.

FortressBuilder

Quote from: theagentd on August 26, 2015, 19:54:43
EDIT: Unrelated question: Is there any way to switch between fullscreen and windowed mode? LWJGL2 supported this, but GLFW does not seem to be able to do that?

It seems to be coming in the next release.

abcdef

You can switch between full screen and non full screen during the window creation process (you need to create a new window for different resolutions and you will here too)

Here is what I do

if (fullScreen)
        {
            window = GLFW.glfwCreateWindow(displayData.getWidth(), displayData.getHeight(), "", GLFW.glfwGetPrimaryMonitor(), MemoryUtil.NULL);
        } else
        {
            window = GLFW.glfwCreateWindow(displayData.getWidth(), displayData.getHeight(), "", MemoryUtil.NULL, MemoryUtil.NULL);
        }

theagentd

For me it seems like every time one of the fullscreen windows lose focus they both flicker.

@abcdef
That does not help. I want to switch between fullscreen and windowed mode while the game is running without having to create a new OpenGL context.


EDIT: Disabling Aero did nothing. Still the exact same problem. As soon as one of the windows lose focus they both flicker.

EDIT2: The failure to restore the original screen resolution when the window is iconified only occurs when using glfwIconifyWindow(). If GLFW_AUTO_ICONIFY is set to GL_TRUE, the original video mode is restored when the fullscreen window loses focus. This is inconvenient as I've disabled GLFW_AUTO_ICONIFY to have multiple windows and use my own logic to iconify windows (if one window has focus, bring them all up and if none of them have focus iconify them all).

spasi

Quote from: theagentd on August 26, 2015, 19:54:43- If you create two fullscreen windows on two different monitors, every time focus switches from one window to the other they both flicker (turn black) for half a second and then come back.

EDIT: Disabling Aero did nothing. Still the exact same problem. As soon as one of the windows lose focus they both flicker.

(from the issue I linked): Afaict, this is standard Windows behavior. An undecorated window that matches the monitor resolution will go into fullscreen mode when it receives focus. The flicker you see is fullscreen mode being turned on/off when you transfer window focus. From the research I did I could not find a decent solution and it seems to affect all kinds of applications and frameworks, it is not a GLFW bug. If you need 2 windows, Windows expects them to be decorated or not cover the whole screen. If decoration is not an option, you can for example make the windows 1 pixel shorter, but then you'll have trouble with the taskbar.

Quote from: theagentd on August 26, 2015, 19:54:43- When iconifying a fullscreen window, the original resolution isn't restored despite the documentation of GLFW saying it should be:
QuoteIf the specified window is a full screen window, the original monitor resolution is restored until the window is restored.
For example, if I iconify a 1920x1080 fullscreen window, the monitor doesn't revert to 2560x1440 as it should. Instead I see my desktop at 1920x1080 as long as the window is alive. Quitting the application restores the resolution properly.

EDIT2: The failure to restore the original screen resolution when the window is iconified only occurs when using glfwIconifyWindow(). If GLFW_AUTO_ICONIFY is set to GL_TRUE, the original video mode is restored when the fullscreen window loses focus. This is inconvenient as I've disabled GLFW_AUTO_ICONIFY to have multiple windows and use my own logic to iconify windows (if one window has focus, bring them all up and if none of them have focus iconify them all).

I could verify this from the GLFW source, the resolution is restored only when GLFW_AUTO_ICONIFY is enabled. I'm not sure if this is by design or it is a bug. Try opening an issue with GLFW.

Quote from: theagentd on August 26, 2015, 19:54:43- glfwSwapInterval() says that it can accept negative swap intervals, which means that it'll disable V-sync if the FPS drops below the refresh rate of the monitor.
advancedSwapSupported = 
				glfwExtensionSupported("WGL_EXT_swap_control_tear") == GL_TRUE ||
				glfwExtensionSupported("GLX_EXT_swap_control_tear") == GL_TRUE;

		if(advancedSwapSupported){
			glfwSwapInterval(swapInterval);
		}else{
			glfwSwapInterval(Math.abs(swapInterval));
		}

The extension(s) is supported on my computer, but when I tried it out I got a white unresponsive window that wouldn't render anything. The thread is blocked indefinitely on the first call to glfwSwapBuffers(). I am not overriding anything in the Nvidia Control Panel (everything default according to Nvidia Inspector).

The infinite loop bug was fixed today. I just uploaded 3.0.0b #21, which includes the fix.

More info: GLFW does not use EXT_swap_control when desktop composition is enabled (on Windows) and the window is not fullscreen. Instead, it uses DwmFlush to synchronize with the DWM compositor. See this FAQ entry.

Quote from: theagentd on August 26, 2015, 19:54:43- For all GLFW windows, V-sync is enabled by default. This makes no sense as the documentation for glfwCreateWindow() says:
QuoteThe swap interval is not set during window creation and the initial value may vary depending on driver settings and defaults.
I'm faaaaaiiirly sure Nvidia doesn't enabled V-sync by default. EDIT: Confirmed, LWJGL 2 does not have V-sync enabled by default.

The documentation is correct and this is a driver issue. GLFW never sets the swap interval, unless the user asks for it. LWJGL 2 happens to always set the swap interval when you create the Display.

Quote from: theagentd on August 26, 2015, 19:54:43- Forcing V-sync off through the Nvidia control panel does not work for windows. Fullscreen V-sync is properly disabled by the driver though. Only windows are still having V-sync enabled.

I had ordered a GTX before my vacation and installed it earlier. Forcing v-sync off works for me. With the default driver settings, wglGetSwapIntervalEXT() returns 1.

Quote from: theagentd on August 26, 2015, 19:54:43EDIT: Unrelated question: Is there any way to switch between fullscreen and windowed mode? LWJGL2 supported this, but GLFW does not seem to be able to do that?

As FortressBuilder mentioned, this is planned for GLFW 3.2. Until then, your best option is to use context sharing so that resources survive between mode switches. The Gears demo in the LWJGL repository implements this solution.

theagentd

Thank you a lot for your thorough answer, Spasi!


The thing about fullscreen windows (= not a borderless window covering the screen, I mean a proper fullscreen window) is that they shouldn't flicker when they change focus. It probably is a Windows thing though. We'll just grab the mouse on all monitors and draw our own I guess. It's not impossible to work around.

I've opened an issue on the GLFW project on GitHub: https://github.com/glfw/glfw/issues/590.

Thanks for the swap control fix info, I'll try it out. Indeed, negative swap intervals work for full screen windows, only windowed windows deadlock.

We'll just make sure to set the V-sync mode. I'll look into the driver overriding again to see if I messed something up on my end. I was pretty sure V-sync wasn't enabled by default though. I'm surprised.

For full screen, we'll probably just add a "restart to apply settings" message for now. Context sharing really doesn't cut it for our game. We'd have to recreate hundreds of FBOs and VAOs. This kind of context sharing was really a horrible design choice for OpenGL. That being said, we really want to be able to do this in the future. It's really frustrating to lose features in a supposed upgrade.



EDIT: Again, unrelated question, but is there any way to force our game to use the Nvidia GPU instead of the Intel GPU on Optimus enabled computers? That'd solve so many problems for us.
EDIT2: I found this: http://www.glfw.org/docs/latest/compile.html#compile_options_win32. I would really really like to have GLFW_USE_OPTIMUS_HPG. Looks like it wouldn't work with GLFW as a DLL? ._.

Kai

Quote from: theagentd on August 28, 2015, 01:08:04
... is there any way to force our game to use the Nvidia GPU instead of the Intel GPU on Optimus enabled computers? That'd solve so many problems for us.
I did some thorough experimentation with native apps, and java apps on this, and the thing is: it just does not work (reliably).
My findings are here: http://forum.lwjgl.org/index.php?topic=5617.msg30013#msg30013
GLFW is not built as a DLL in LWJGL. It is linked statically into LWJGL's DLL. But yes, this would make it non-working for LWJGL applications, since LWJGL itself is a DLL. To make it really work - even if it did not, when I was building a native application with statically linked GLFW myself (see linked post) - you would have to statically link GLFW into a custom native launcher that launches Java via the JNI Invocation API.
Or, you would have to export NvOptimusEnablement=1 manually within your launcher exe file.
I tried this, but it did not work for me.

Mickelukas

Quote from: theagentd on August 28, 2015, 01:08:04For full screen, we'll probably just add a "restart to apply settings" message for now. Context sharing really doesn't cut it for our game. We'd have to recreate hundreds of FBOs and VAOs. This kind of context sharing was really a horrible design choice for OpenGL. That being said, we really want to be able to do this in the future. It's really frustrating to lose features in a supposed upgrade.

I already had the code for removing the window and building everything up again due to enabling/disabling antialiasing so it wasn't a big deal to implement it. Luckily it's coming in 3.2 (together with custom window icons it seems).

theagentd

Quote from: Kai on August 28, 2015, 07:25:15
I did some thorough experimentation with native apps, and java apps on this, and the thing is: it just does not work (reliably).
My findings are here: http://forum.lwjgl.org/index.php?topic=5617.msg30013#msg30013
GLFW is not built as a DLL in LWJGL. It is linked statically into LWJGL's DLL. But yes, this would make it non-working for LWJGL applications, since LWJGL itself is a DLL. To make it really work - even if it did not, when I was building a native application with statically linked GLFW myself (see linked post) - you would have to statically link GLFW into a custom native launcher that launches Java via the JNI Invocation API.
Or, you would have to export NvOptimusEnablement=1 manually within your launcher exe file.
I tried this, but it did not work for me.
That probably won't work, as the launcher just launches javaw.exe. For this to actually work, you'd probably need to modify jawaw.exe to have that little tag. That is really outside my comfort zone though... WGLNVGPUAffinity is supported in LWJGL3 though and looks promising. I'll see if I can make that work. EDIT: It was a dead end. WGLNVGPUAffinity can't be used until a context has been created, and it's not supported by the Intel driver.

Quote from: Mickelukas on August 28, 2015, 12:06:39
I already had the code for removing the window and building everything up again due to enabling/disabling antialiasing so it wasn't a big deal to implement it. Luckily it's coming in 3.2 (together with custom window icons it seems).
We do all anti-aliasing with FBOs, which we can easily recreate, but the problem is VAOs spread around the entire graphics engine. It'd be a huge amount of work to fix them. ._.



It looks like the fullscreen iconify video mode restore bug I posted got fixed over night! :o When will that GLFW commit end up in an LWJGL 3 build so I can verify the fix?

Kai

Quote from: theagentd on August 28, 2015, 14:26:01
That probably won't work, as the launcher just launches javaw.exe...
No, you don't understand. You would need to build your own launcher that (again) uses The JNI Invocation API. It will be a replacement for javaw.exe and java.exe, which internally does the exact same thing (that and argument parsing and displaying usage help). The actual JVM is not implemented in those exe files but in a shared library that you would load with platform specific functions (LoadLibrary under Windows), lookup the entry point to the JVM (which is a JNI Invocation API function) and then call that function to execute the JVM.
In fact, no "launcher" for Java programs uses javaw.exe. Neither launch4j nor exe4j. Also the Eclipse IDE uses its own launcher, the eclipse.exe, which also uses the JNI Invocation API and not just shell-delegates to javaw.exe.

spasi

Quote from: theagentd on August 28, 2015, 14:26:01It looks like the fullscreen iconify video mode restore bug I posted got fixed over night! :o When will that GLFW commit end up in an LWJGL 3 build so I can verify the fix?

That's why we love GLFW. :)

The commit was pushed to a new branch and LWJGL builds the master branch only. If you aren't able to build GLFW+LWJGL locally, I can provide a custom build but I won't have time for it today.

theagentd

Quote from: Kai on August 28, 2015, 14:56:15
Quote from: theagentd on August 28, 2015, 14:26:01
That probably won't work, as the launcher just launches javaw.exe...
No, you don't understand. You would need to build your own launcher that (again) uses The JNI Invocation API. It will be a replacement for javaw.exe and java.exe, which internally does the exact same thing (that and argument parsing and displaying usage help). The actual JVM is not implemented in those exe files but in a shared library that you would load with platform specific functions (LoadLibrary under Windows), lookup the entry point to the JVM (which is a JNI Invocation API function) and then call that function to execute the JVM.
In fact, no "launcher" for Java programs uses javaw.exe. Neither launch4j nor exe4j. Also the Eclipse IDE uses its own launcher, the eclipse.exe, which also uses the JNI Invocation API and not just shell-delegates to javaw.exe.
I was speaking about the launcher we have already coded, but you're wrong about Launch4j. Launch4j does launch javaw.exe as a separate process. It's one of the problems we have, as it forces people to add javaw.exe to make driver profiles etc for our game. If you know of an exe generator that launches the jar from the exe process directly that'd be extremely helpful for us.

Quote from: spasi on August 28, 2015, 15:54:49
The commit was pushed to a new branch and LWJGL builds the master branch only. If you aren't able to build GLFW+LWJGL locally, I can provide a custom build but I won't have time for it today.
Sorry, I don't have that set up... I'd really appreciate if you could make one, but I completely understand if you don't have time. Feel no pressure. >_<

Kai

Quote from: theagentd on August 28, 2015, 20:06:12
I was speaking about the launcher we have already coded, but you're wrong about Launch4j. Launch4j does launch javaw.exe as a separate process. It's one of the problems we have, as it forces people to add javaw.exe to make driver profiles etc for our game. If you know of an exe generator that launches the jar from the exe process directly that'd be extremely helpful for us.
As you know :) I created a launcher that dynamically loads the JVM shared library and exports the NvOptimusEnablement flag and IT FINALLY WORKS!
Yes, people. Using a customer launcher exe file works with Optimus without having to create application-specific profiles. :)
(at least I used 353.82 driver)

Test sources: https://github.com/httpdigest/optimustest

spasi

Custom build with the iconify fix: lwjgl.dll