H-uru / Plasma

Cyan Worlds's Plasma game engine
http://h-uru.github.io/Plasma/
GNU General Public License v3.0
205 stars 81 forks source link

Display Modes for New Renderers #1502

Open colincornaby opened 1 year ago

colincornaby commented 1 year ago

I'm going to write this issue with a Mac slant - but I don't think this is a Mac specific issue. This is attempting to take #1244 and back it up into an issue so we can talk it through without going into the code.

Background

Direct3D 9 requires that full screen rendering be done in one of the display's supported modes. For Metal and OpenGL - there is no such requirement. Frames can be rendered in any resolution.

There are a few rough edges with the current approach:

For the Mac specifically:

Possible approach

1244 proposes adding a render scale slider - like most modern games have. The render scale could be maintained between different displays. And because Metal and OpenGL don't actually have to follow the display modes on the current system - it's ok if the output resolution is completely made up by Plasma.

There are a few other features that could be added after a render scale:

What other games do

Hoikas commented 1 year ago

Direct3D 9 requires that full screen rendering be done in one of the display's supported modes

While this is strictly speaking true, H'uru no longer uses exclusive fullscreen in this way. Fullscreen gameplay is now accomplished by creating a borderless window and changing the resolution of the display. We are, at this point, using the list of D3D9 resolutions as a convenience.

colincornaby commented 1 year ago

Direct3D 9 requires that full screen rendering be done in one of the display's supported modes

While this is strictly speaking true, H'uru no longer uses exclusive fullscreen in this way. Fullscreen gameplay is now accomplished by creating a borderless window and changing the resolution of the display. We are, at this point, using the list of D3D9 resolutions as a convenience.

Ahhh, thanks. I see that line in the DX renderer. https://github.com/H-uru/Plasma/blob/e78036173d1fbe2a9e1bab3cba8d2d0bee0a1650/Sources/Plasma/FeatureLib/pfDXPipeline/plDXPipeline.cpp#L2066

I'll update the text of the issue.

Hoikas commented 1 year ago

Plasma doesn't adjust properly when moving between a HiDPI and standard DPI display in windowed mode - because the required display mode has changed.

I don't think this is true - #1269 was supposed to fix this with the DPI stuff.

colincornaby commented 1 year ago

Plasma doesn't adjust properly when moving between a HiDPI and standard DPI display in windowed mode - because the required display mode has changed.

I don't think this is true - #1269 was supposed to fix this with the DPI stuff.

I'm not sure there has been standard behavior defined here. (I need to look at what Windows is doing.)

When a Window moves from a low DPI display to a HiDPI display, the framebuffer resolution is going to double. Games treat this as a new resolution. So either Plasma locks the resolution to exactly what is in the settings (in which case the window size gets halved as the window moves displays which is kind of weird.) Or the active resolution is doubled, which requires a write to options and may not match the available display modes on the display.

The other weird thing is that moving displays means the display modes should change. The new display has a different set of available modes. Plasma ignores this. But it means internally its rules about how to manage resolutions don't match up with what the window is doing. So technically the current display mode in windowed mode may not even be available on the other display.

This sort of weirdness is why it would be nice to decouple Plasma from the available display modes. The contract it's trying to make with the display modes is awkward to enforce.

Hoikas commented 1 year ago

While we don't write back to the options, when the DPI changes (eg moving to a display with a different DPI), we do reset the pipeline with the new display's information per https://github.com/H-uru/Plasma/pull/1269/commits/9c05355073caa02c188c26757840063f93abab8d. If we're using a sufficiently recent version of Windows 10 (from either 2017 or 2018), then game window will remain the same size when swapping monitors.

colincornaby commented 1 year ago

While we don't write back to the options, when the DPI changes (eg moving to a display with a different DPI), we do reset the pipeline with the new display's information per 9c05355. If we're using a sufficiently recent version of Windows 10 (from either 2017 or 2018), then game window will remain the same size when swapping monitors.

Lemme go connect my low DPI portable display to my Windows machine, but immediate thought on why this could be an issue:

Even in windowed mode - Plasma's output is supposed to match one of the display's available video modes. So maintaining the same window size isn't in alignment with that rule. If the new display doesn't have a display mode that matches the desired window size, things will get misaligned.

That said - I think there are several bugs that are also stacking here. I'm not sure Windows is querying anything but the main display for display modes (which is wrong, if my main display is a 4k display and my secondary display is a 1080p display, it's going to offer display modes my secondary display can't do.) I also don't think on Windows anything is being written back to options when the window moves displays, so Plasma may never realize things have become inconsistent. But that means the resolution won't be remembered the next run.

colincornaby commented 1 year ago

Ok - Checked out Windows. There are some issues - but there might be a reason the Mac is stumbling more than Windows is.

On macOS - I can move a full screen window to any display. So I can tell my Mac to move my Plasma window from a 4k display to a 1080p display - even if it's in full screen mode. I can also do it manually by un-fullscreening it, and then re-fullscreening it on the new display. But there are ways to move it even without leaving full screen.

This is not how Windows Plasma works. Windows Plasma will not let you go full screen on any display but the primary display. Windows also will only query display modes from the primary display. Even if I move the window to another display - I can't select the display modes from the new display. So if I move from a 4k display to a 1080p display in windowed mode - I still only see the 4k display modes.

So - macOS needs a way to move full screen from one display to another and have the display modes adjust correctly. I don't think Plasma is capable of that today.

I'll add that in general it seems like multiple displays in Windows is broken in Plasma. Weird things began to happen. I started the debug copy which defaults to windowed. But when I set a resolution of 800x600, hit apply, and then went full screen and hit apply - It resized my primary display's output resolution to 800x600. As in the display mode was changed and Windows was in 800x600. It also was drawing entirely on my main display, but I was also seeing half out the game output on my secondary display. My secondary display's output resolution was also resized to 800x600.

So - very much not convinced display modes are working properly under Windows right now. I don't think the current code will scale to macOS. I'm open to what approach we use exactly to scale to macOS - but the current code isn't working.