High-DPI scaling bug with NVIDIA drivers and OpenGL on Windows 10

When a thread opts into to handling per-monitor DPI awareness by calling Win10’s SetThreadDpiAwarenessContext() with any value other than “unaware”, and uses OpenGL, its window contents is scaled in correctly - specifically a corner of the viewport is being scaled up using nearest filtering, looking terrible, and, of course, discarding a portion of the rendered frame.

Example, loading screen of Splody with 125% Scale: https://bit.ly/2YVYe9y
Expected (on non-NVIDIA or with workaround or no High-DPI scaling): https://bit.ly/2TizCm5

This does not happen on Intel, AMD, or software OpenGL drivers (in all of those cases, you get a nice, high-DPI app).

This appears to happen consistently back on all driver versions (checked as far back as the 399.x drivers, oldest I could download from the NVIDIA site to test with).

This appears to affect various models - between my tests and user reports, I’ve seen it on a GTX 660, 1080 Ti and RTX 2070.

This does not happen if the DPI_AWARENESS_CONTEXT value is set via the newer SetProcessDpiAwarenessContext(), however that function was only recently introduced and is not available on all Windows 10 systems. Where available, we are now using this function instead to work around this issue.

This does not happen if DPI awareness is enabled via the Windows 8.1 SetProcessDpiAwareness(), however that method behaves incorrectly and inconsistently when a user has different DPIs set on each monitor, or if the user has changed their DPI since they last logged in/out.

This also does not happen if I inject code into all nvoglv32.dll threads to call SetThreadDpiAwarenessContext() from there - presumably something in nvoglv32.dll is querying for a DPI value and getting the thread’s value instead of the window in question’s value (e.g. not calling GetDpiForWindow appropriately). Injecting this code is clearly not a viable solution for customers =).

This issue is mildly affecting Splody on Steam - a patch today switches it to prefer SetProcessDpiAwarenessContext(), mostly addressing the issue, however users on Win 10 build 1607 (pre-“Creator’s Update”) will still have issues. Any other program using SetThreadDpiAwarenessContext is also affected. One other developer has provided a simple reproduction case and has done a write-up of the issue and his findings here.

Please let me know if any additional information is required.

Jimb Esser
Dashing Strike LLC

1 Like

I ran into this issue as well. After many hours of debugging and learning almost everything there is about how Windows handles High DPI nowadays, I can confirm this issue. Here are my observations:

I develop Audio Plug-Ins using the JUCE framework. Some of these use OpenGL for rendering Visualizers. Rendering is consistently broken in exactly the way Jimp described in the initial post.

It turns out that some pretty important Digital Audio Workstations (DAWs) are “DPI unaware” on the process side (as displayed by Task Manager), but rely entirely on “mixed mode” DPI handling for their high dpi implementations. Specifically, this applies to Steinberg Cubase 10.5 and Ableton Live 10.

The bug doesn’t occur with Reaper, which is process-wide “per monitor dpi aware” from the start.

High DPI support in DAWs is a bit of a mixed bag and it has organically grown over the years with different workarounds being in place. For example, in case of VST3 plugins, the interface allows the host to explicitly report DPI changes to plugins.

To reproduce the issue with JUCE, you can do the following:

  1. set display scale on primary display to 125%
  2. use projucer to create a template plugin project
  3. add an OpenGL context and attach it to the editor component
  4. build vst3
  5. open in a vst3 host (I tested with Cubase 10.5 and Ableton Live 10, make sure to enable high dpi modes in both hosts)
  6. observe broken scaling (window bounds are correct though, aside from occasional issues when moving between differently scaled screens in Cubase 10.5, but that’s another topic)

Software rendering is correct.

In some rare occasions I also observed the OpenGL render scale magically fixing itself when alt-tabbing back and forth, moving the plugin window, or opening the start menu.

Workaround: When Cubase 10.5 or Ableton Live 10s executables have the “High DPI managed by application” compatibility setting enabled, the bug doesn’t occur.

It’s very likely the nvidida driver not correctly respecting thread/window dpi awareness, as described by Jimb.

I have observed the issue on different nvidia GPUs, e.g. GTX 1050 and RTX 2060.
I have not found any viable/shippable work around, so please address this issue.

I can confirm all that - we’ve tested the same (audio plugins with OpenGL running in Ableton Live) on various Windows 10 computers, and only computers with NVIDIA computers had been affected.

It’s a major bug for us.

1 Like