Windows UI Scale Affects Render Target Sizes In Fullscreen

There seems to be some conflation between UI scale and render target sizing.

/Script/Engine.UserInterfaceSettings - bAllowHighDPIInGameMode is off by default. The category of this setting implies a relation to UI but having it off prevents Unreal from calling SetProcessDpiAware(). Which makes the GetSystemMetrics() calls in FDisplayMetrics::RebuildDisplayMetrics() return incorrect monitor sizes. Those sizes go on to inform render target size.

Window’s intention is for “DPI Unaware” applications to output at a smaller resolution and then stretch it up to the full size. But this results in really strange behavior for games. Ideally, the game would output at the monitor’s native resolution and do any scaling internally. Instead, Unreal’s default behavior when Window’s UI scaling is active is to render to an intermediate resolution and then have Windows bi-linearly scale everything up. Which degrades quality quite a bit. This is extra problematic, since by default Windows seems to recommend 150% scaling on 4k monitors regardless of physical size.

For us, the solution is to have bAllowHighDPIInGameMode set to true and simply move the InitHighDPI() call above PreloadResolutionSettings() in PreInitPreStartupScreen(). But it begs some questions about the default behavior of not calling SetProcessDpiAware() on Windows. Is this intended?

Steps to Reproduce

  1. Set Windows UI Scaling to 150% in Display Settings
  2. Play game in fullscreen
  3. Observe blurriness of the game
  4. Take a PIX capture and observe render target sizes are smaller than they should be

Hello there,

Just to clarify, are you specifically asking if InitHighDPI should occur after the preload as the intended flow or if the defaults should be the way they are?

On the former front, it’s not immediately clear that this is intended. This doesn’t affect Windowed Fullscreen, but it does affect Windowed. I hadn’t noticed when using GameUserSettings in the past that sizes above 2560x1440 are rejected by Windowed on restart due to it exceeding the non-scaled window size. From that perspective, even if intended, it means that resolutions like 3200x1800w will always reset to 1920x1080 on restart.

As an aside, stat unit in 5.6 should show the render resolution beside the render scale.

Best regards,

Chris

Sorry for the delay. To clarify, I’m curious if bAllowHighDPIInGameMode being off by default is intended. When it’s off SetProcessDpiAware() is not called and so calls to GetSystemMetrics() will report incorrect sizes. So, for instance, with a 4k monitor and windows scaling set to 150%. It will output at 2560x1440 instead of the native 3840x2160. I haven’t found much of a reason to not call SetProcessDpiAware(). Which is why I found it odd that it was hooked up to a setting and the setting defaulted to off.

I’m curious if bAllowHighDPIInGameMode being off by default is intended.

We do recommend enabling High DPI awareness and have an internal request to change the default for Windows to bAllowHighDPIInGameMode=True, but it hasn’t been prioritized yet.

Some history…

When the bAllowHighDPIInGameModewas originally added, it was to combat performance loss on Macs with High DPI screens. However, when the setting was added it was always set to True for Fortnite because it gives the user a resolution settings menu so they can fix any performance issue High DPI on a Mac may have introduced.

The reason many of our samples/templates don’t enable it by default is likely they were not aware of the potential issue with DPI scaling. Lyra specifically sets bAllowHighDPIInGameMode=False in CL#19209926 with the comment: “Lyra - Adding software widget cursor”. The default from the engine was copied and the main goal at the time was to keep the correct UI scaling, not to define fullscreen window resolution behavior.

No worries.

I’ve filed a bug report for the placement of the InitHighDPI call as it appears that Windowed applications do not correctly restore their resolution settings as a result. From experience, this can complicate handling user-defined resolutions in GameUserSettings. It does also appear that Windowed Fullscreen ends up with a secondary viewport set to 1440p instead of 2160p without DPI awareness.

Lyra setting the value to false in DefaultEngine.ini explicitly leads me to believe this may be intentional, but I cannot find any rationale for that. I’ll hand this to somebody that can give a more concrete explanation once I’ve got the bug report tracking link to you.

Best regards,

Chris

Awesome, thank you so much!

You are very welcome.

Please find the tracking link live at Unreal Engine Issues and Bug Tracker (UE\-308070\).

I’ll hand this case off to somebody who can shed some insight into why AllowHighDPIInGameMode is off by default.

Best regards,

Chris