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.

Cheers!
Jimb Esser
jimb@dashingstrike.com
Dashing Strike LLC