High dpi issue on Windows with VST3 plugins

We’re seeing this issue as well in REAPER 5.92, VST3 only (VST2 works fine). Ableton Live is ok on the same test machine.

VST3 Scaling in Bitwig3/Windows works too…

I cluttered juce_VST3_Wrapper.cpp with Logger calls and tried to get of the bottom of this.
Each and every DAW has a very particular flavor of “when calling what” during plugin setup, it’s far from consistent.

Interesting observations: Bitwig and FL Studio call setContentScaleFactor with the display scale factor, Cubase10, Wavelab and Reaper do not (always appears to be 1).

For Cubase 10 and Fruityloops, there is a “hack” in the VST3 wrapper: The factor given to setContentScaleFactor is being overridden by peer->getPlatformScaleFactor().
I added Reaper and Wavelab there, just out of curiosity. For Reaper 6, the same trick appears to work as well. For Wavelab, it doesn’t (just leads to more overall scaling).

I still have the feeling that the whole process of setting up the different scalings (host window, screen scale, component scale, etc) should be tackled on a more fundamental level. Even if I’d find a hack/workaround that works for Wavelab too, that would only mean that on my system the hosts I have available work. But it doesn’t feel right.

JUCE devs, would you mind chiming in here?

BTW: Cleanest plugin init call trace I’ve seen was with Bitwig, worst one with Cubase 10.
BTW2: going purely from the comment in the VST3 SDK, it’s not really clear whether setContentScaleFactor should be called for handing over OS/DPI related scale factors to a plugin, or whether a plugin should handle OS/DPI scale internally, and setContentScaleFactor should be used for applying “additional scale”. This might explain why hosts behave differently in that regard…

If anyone is interested, I’m attaching my call traces/log output. Process was always “start host, load plugin, open plugin editor, close plugin editor, close host”.

VST3_JUCE_LOG_20200114T115211.193 0100_Wavelab_Wrongscale.txt (5.6 KB)
VST3_JUCE_LOG_20200114T115409.498 0100_Bitwig_Correct.txt (6.4 KB)
VST3_JUCE_LOG_20200114T115605.919 0100_Cubase10_Correct.txt (14.0 KB)
VST3_JUCE_LOG_20200114T115823.872 0100_Reaper6_wrongscale.txt (7.9 KB)
VST3_JUCE_LOG_20200114T121133.020 0100_FlStudio20_Correct.txt (6.7 KB)

1 Like

I had a report of this exact problem as well. Confirmed that VST scales the UI and window size correctly while VST3 scales the UI but not the window size. Exactly as in @jcomusic’s earlier post. Tested using Reaper 6.02 and 6.03.

Switching JUCE_WIN_PER_MONITOR_DPI_AWARE to Disabled stops anything from scaling (so is potentially very small) but at least means none of the interface is outside of the window.

So you are saying that Reaper always calls setContentScaleFactor() with 1, regardless of what is set in its HiDPI mode setting that I mentioned in my previous posts?

It sounds very strange, I’d expect that setting to play a part in that, unfortunately I don’t have time at the moment to check that myself

Reaper has not yet implemented the setContentScaleFactor().

I’ve added a feature request over at their forum Support Steinberg / Presonus VST / VST3 HiDPI extensions, but it seems it has gone under the radar.
If some of you +1 this it might get Justin’s attention :wink:


This looks to have been fixed in the newest dev version of Reaper according to a post in the Reaper FR forum!

Hey guys! Still diving deep into the bottom of the JUCE vst3 wrapper and win32 windowing systems. It’s beginning to get clearer.

  • First, as I already mentioned, it is not clear that setContentScaleFactor is supposed to hand through the windows dpi scale factor. The VST3 SDK is vague in that regard, but it’s interesting to see that most recent Cubase and Wavelab report a factor of 1. If Steinberg has it correct, this scale factor from the VST3 callback should be applied in addition to the operating system dpi scale factor.
  • Problems with the observed plugin window truncation arise whenever the editor scale factor being determined in the VST3 wrapper is different from the operating system scale factor.
  • The operating system scale factor is determined elsewhere, outside of the VST3 wrapper.
  • You can retrieve the operating system scale factor from ComponentPeer, which represents the actual OS window which contains the plugin.
  • There is even additional code for additional scaling of the content component in ComponentPeer, if their sizes don’t match.

Following those observations, the host window should always be resized to:
PluginEditorWindowSize (logical units) * combinedContentScaleFactor

With combinedContentScaleFactor being the OS scale factor, which can change if you move the window from one screen to another (not testing this yet!).
If my assumptions about VST3::setContentScaleFactor are correct, this has to be handled completely differently.

I will now try to rewrite portions of the VST3 wrapper in a way that disregards setContentScaleFactor entirely and always uses the OS scale factor to scale the host window. Just to see what happens.

Sorry, I read the comment in the VST3 SDK again: the VST3 setContentScaleFactor callback is indeed meant to communicate system changes as well, but allows for applying different scale. This fully explains why we need workarounds.

In any case, truncation must not happen, host window size must always be set to editorComponentSize * whateverScaleFactor is being used for rendering.

This indeed appears to work with all the hosts I have here for testing!

What I did:

  • setContentScaleFactor(…): Always get scale factor from component peer (if available), disregard what is given in the callback, because we can’t rely on it. This is code that was already in place for Cubase 10 and FL studio, but now I’m always doing it.
  • resizeHostWindow(…): Removed workarounds for also setting component size (setBounds(…)) for Wavelab and Live on windows. Now it simply (and only) does what I suggested, setting owner.plugFrame to pluginEditorSize * scaleFactor.

I will now investigate how this behaves with a multi monitor setup involving different scale factors. Also, I obviously can’t exclude that this might cause issues with other host/os combinations.

Turns out, this doesn’t solve the issues with multi monitor settings / different dpi per screen. It’s very much broken, with or without my fix attempts (in Cubase 10 and Wavelab).

Now trying a completely different approach, disabling per monitor dpi in project settings and doing it all myself (getting a device context, figuring out display scale factor, checking for peer size / component size mismatches, etc).

The idea is manually forcing the right scale with juce::desktop::getInstance().setGlobalScaleFactor(…). Applying the scale works, but sadly using this method, the plugin host window will not be resized correctly.

I’m running out of ideas (aside from spending days or weeks rewriting half of JUCE). Is there really noone here who managed to somehow fix the vst3/high dpi issues for a plugin?


Did you use the default constrainer (getConstrainer()) or did you set yours in the plugin editor? It looks like the host want’s to scale the plugin itself and i noticed that this only happens when the constrainer is set or if you are using the default constrainer.

I will also have a closer look at the issue. I also received some user reports regarding this.

1 Like

Hey, I sadly had to leave the issue alone for the time being and take care of more pressing matters. Also, my Wavelab trial ran out :frowning:

I still think it boils down to some hosts telling the VST3 to scale with the windows screen scale factors, others (like Wavelab and Cubase) just give it a scale factor of 1.0 no matter what. Cubase works because there is a workaround in place, wavelab doesn’t.

For investigation, just use a barebones Projucer template plugin project and use a windows 10 system with a screen scale factor of 125% (bonus task: add a second screen with a different scale factor). setContentScaleFactor and resizeHostWindow are the interesting places to look at.

I haven’t tested yet if anything changed/improved with JUCE 5.4.7 over 5.4.5.

Please let us know if you can figure something out :slight_smile:

It even doesn’t work if JUCE Plugin Host is the host! Please see:

I don’t use open gl. I wasn’t able to reproduce this on windows with my parallels windows VM and 150% scaling. I think it happens only under some special conditions i don’t know yet.

Last time I checked the issue didn’t occur when using the JUCE plugin host. Probably something else in your case?

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.