High dpi issue on Windows with VST3 plugins

Has this been fixed in the meantime? I have a customer with exact same symptoms.

Hey guys! Out of curiosity I just took a look at a diff between juce_VST3_Wrapper.cpp of JUCE 5.4.7 and the preview of JUCE 6 in the repo. Apparently a lot of the high dpi handling has changed, which is a good sign. I haven tried it yet, but once JUCE 6 is officially released I’ll test it again. It looks pretty much like the resolution handling overhaul that I feared would be necessary.

PS: just a small feedback from my side, latest dev tip of JUCE 5 seems to solve the problem i have mentioned

1 Like

Bumping this instead of creating a new thread. VST3 with high dpi settings on windows is still a massive problem as of JUCE 6.0.5. While many things appear to have been fixed (thanks!), I have massive problems when using OpenGL now.

Steps to reproduce on Windows 10:

  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)

Moving the plugin window to a 100% scale screen → it’s fine. Problem occurs once there is a >100% scale.

It’s noteworthy that it appears to behave fine without opengl.

I’m very deep in debug hell right now, deep diving into juce_OpenGLContext.cpp, juce_OpenGL_win32.h, juce_win32_Windowing.cpp. I verified frame buffer sizes, cached component image size, all kinds of bounds, no luck so far, but I’ll keep digging because this is a serious problem for me right now.

I have confirmed the issue with two additional systems.
Reaper doesn’t show this behavior, interestingly.
My current guess is that it has to do with DPI awareness of the window created for the opengl context.

Have you tested with the current develop branch? There’s been some changes in this area in the last couple of days so it’s worth checking whether the issues you’re seeing are still present in the newest version of JUCE.

Thanks for the heads up, will try immediately.

Sadly I’m getting the exact same issue with the current state of develop.

This doesn’t make any sense… What JUCE does when attaching an OpenGL context looks absolutely correct. It checks the top level window (our vst3 wrapper) for dpi awareness. If it’s dpi aware (high dpi DAW):
JUCE makes sure that the main thread is dpi aware as well before creating the native window (createNativeWindow).
It also makes sure that the opengl thread gets dpi awareness (initialiseOnRenderThread).

updateWindowPosition correctly sets the physical coordinates in high dpi mode, which is also correct. But windows still decides to somehow scale the rendering, resulting in this somewhat pixelated result and cropped areas…

I’ve been stepping through this for 15 hours now, and I’m running out of ideas :wink:

I do not know what Steinberg and Ableton did there, but the Processes for Cubase 10.5 and Ableton Live 10 are considered ā€œdpi unawareā€ by Windows. It turns out, that if I force those applications to ā€œDPI scaling managed by Applicationā€ via windows compatibility settings for the executables, the DAWs still run correctly, but are now considered dpi aware. This magically makes the opengl scaling issue go away.

In conclusion it appears that for some reason, mixed mode DPI (thread setting) doesn’t work correctly for the OpenGL window, and I still don’t know why, but if a customer stumbles onto this scaling issue, the ā€œdpi compatibility settingsā€ might be a viable workaround for the moment.

bam, I think this is it:

High-DPI scaling bug with NVIDIA drivers and OpenGL on Windows 10 - Visual, Game & Mobile Development / OpenGL - NVIDIA Developer Forums

Yes we’ve run into this before, and came to the same conclusion that it is an NVIDIA driver issue. See this thread:

Unfortunately as a plug-in, we’re stuck with the DPI-awareness of the host process that we’re running in and can’t change it via SetProcessDpiAwarenessContext() as this would break the host’s scaling. We need to use SetThreadDpiAwarenessContext() to temporarily change the thread’s awareness and then set it back again. Since f6338c0f we’re doing this via the ScopedThreadDPIAwarenessSetter, but that thread implies that this won’t work on NVIDIA machines…

1 Like

Exactly. JUCE is doing everything correctly, ThreadDpiAwarenessContext is the right way to do it, according to MSDN. I also like the way you implemented it.

The sad story here is that apparently this issue has been reported to nvidia 2 years ago (see link I posted, someone took a very close look at what’s going on). I wrote a detailed response in the nvidia forum, confirming the bug and bumping the thread, but somehow I have a feeling nvidia will keep ignoring this.

Maybe you could get in contact with nvidia and ask them about this? You have more ā€œrelevanceā€ than a random small indie developer like me :wink:

By the way, good job on keeping to improve high dpi behavior in JUCE. It has improved a lot, I no longer have any dealbreaker issues demanding crazy workarounds with plugins that don’t use opengl. :+1:

1 Like

Thanks for looking into this and updating the thread. I’ll see if we can raise this but I think in the grand scheme of things JUCE is still quite small fry as far as NVIDIA are concerned.

Thanks, there have been quite a few changes recently and I’m glad to hear they are working well for you.

Unfortunately it could be that the NVIDIA bug may not be necessarily related, as we’re currently experiencing this problem with multiple of our plugins on all sorts of other graphics cards. (Or perhaps we’ve hit a very similar bug.) I’ve tried to narrow it down a bit more, perhaps it’ll be of use here, but the conditions are fairly specific to trigger.

For us, to reproduce this issue on Windows:

  • Make use of a juce::OpenGLRenderer to render the entire app.
  • Set the DPI scaling on Windows to >100% (e.g. 125%).
  • Start a specific DAW that uses specific DPI handling (e.g. Renoise 3.3.1).
  • Load the VST3 version of the app.

You’ll now see that the window is in fact scaled up but the contents are not, resulting in the typical black bars that have been reported multiple before, e.g. here: Windows Per-Monitor DPI Scaling with Juce plugins and Cantabile

What’s interesting is that if you disable the OpenGLRenderer and just use the software renderer, everything seems to scale correctly. This makes me think there’s a bug specifically in juce_OpenGLContext.cpp’s way of handling the scaling that is inconsistent with JUCE’s software renderer.

I’m aware that getScaleFactorForWindow was added there (specifically in updateViewportSize) to get the context’s HWND dpi scale. For a VST3 in Reaper, that function will return 1.25 and everything seems to work correctly.

However, in Renoise, that function will return 1.00 because of the way it handles DPI scaling. Renoise will keep the plugins unaware of DPI (so scale == 1.0) and apparently upscale the editor window instead (HiDPI and UI Scaling - Renoise User Manual). I assume there will be other DAWs that will work in a similar way.

What I find strange is that, even though you could easily blame a DAW, the JUCE software renderer does work correctly under these conditions and the OpenGL renderer seems inconsistent here.

2 Likes

Some more info that is perhaps related to this issue. At least I hope it adds more data points.

I compiled the JUCE (6.1.2) example GainPlugin on Windows and tried it in Waveform but with DPI Awareness on it doesn’t render correctly (see screenshot) if Windows DPI scaling is anything other than 100%. With DPI Awareness off it renders fine but pixelated if DPI is greater than 100%.

The GainPlugin does not use OpenGL but if I adapt it to use OpenGL then it doesn’t work with Waveform with DPI Awareness on or off.

I’ve tried this with NVIDEA and AMD cards and found no difference.