imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Backends: D3D12: Use FramebufferScale

Open WSSDude opened this issue 1 year ago • 10 comments

Use FramebufferScale similar to how OpenGL backend does.

Fixes issue when DisplaySize is bigger than real framebuffer due to eg. fullscreen window when specified, provided that user or window backend sets it up correctly.

WSSDude avatar Feb 19 '25 13:02 WSSDude

I hope to tackle those soon in a batch, but I would like to ask: can you clarify which setup are you using where window size is != framebuffer size on window?

ocornut avatar Feb 19 '25 14:02 ocornut

Exclusive fullscreen causes this for example - you can have resolution set to 1920x1080 but on 4k display, client size is getting reported as 3840x2160, messing the cursor positions at minimum, unsure if it breaks anything else on top.

Another one I found which may cause this is DPI scaling in specific instances, not always. Sometimes when changing DPI, Windows seems to report weird resolution for the window (eg. when I swap from 200% -> 100%, client rect reports as having 0.5% of size for some reason, causing mismatch again).

This seemed to help in both cases.

WSSDude avatar Feb 19 '25 14:02 WSSDude

But, this would only be useful if someone was setting FramebufferScale, where and how are you setting it? Win32 backend doesn't set it and use ClientRect size to set io.DisplaySize. So this change is assuming something else which you have not described.

ocornut avatar Feb 19 '25 15:02 ocornut

Oh right I understand now what you mean. Like pseudocode of sorts is basically this

// init stuff
ImGui_ImplWin32_NewFrame();
ImGui::GetIO().DisplayFramebufferScale = ImVec2(framebufferWidth / io.DisplaySize.x, framebufferHeight / io.DisplaySize.y);
ImGui::NewFrame();
// do rest of ImGui things

I set it manually before each NewFrame basically, following one issue I found here which mentioned this for Android setup with OpenGL, tried it, realised it doesn't work still and looking at the code of the respective backends, figured out that it is unused. Tried to plug it in in similar manner and it started to work.

Not ideal and yeah, definitely not able to get it just from Win32 backend (unsure how I could do that at least, maybe there is some message I could try to catch?), but other backends do set it, like GLFW or SDL from what I saw so I suppose it should work fine there?

Manual setup before new ImGui frame though seems to work just fine for this when it is not available, it just need to actually do something in that case.

WSSDude avatar Feb 19 '25 15:02 WSSDude

#6064 This is where I found the io.DisplayFramebufferScale specifically this comment https://github.com/ocornut/imgui/issues/6064#issuecomment-1426981755

But yeah, didn't work, looked at backends, effectively copied it, started to work.

WSSDude avatar Feb 19 '25 15:02 WSSDude

Actually I see now that the person which made the issue was also using the same combination of backends as me (Win32+D3D12). Maybe worth noting.

WSSDude avatar Feb 19 '25 15:02 WSSDude

I hope to tackle those soon in a batch

In any case, if you would rather do it in batch, no hard feelings I suppose, but would be really useful as this is currently practically only real reason we have to include the backend in our project, so we can do this tiny change to the backend.

Otherwise, we would be able to just have it included from XMake package directly am pretty sure, trying to remove last 2 hacks which I believe are not needed upon further inspection if I utilize DrawLists more properly. Need to set different shader and font which I am pretty sure should be doable via custom draw commands and callbacks, but maybe am wrong, will see soon I suppose 😁

WSSDude avatar Feb 19 '25 15:02 WSSDude

I'll have to try exclusive fullscreen to dig further, but since I assumed this field would never be set to != 1.0f on Windows it is probably harmless to merge this.

ocornut avatar Feb 19 '25 16:02 ocornut

Like one potential issue I see with this is inside imgui.cpp in InitViewportDrawData function

draw_data->FramebufferScale = io.DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis?

I am a bit uncertain how this would behave on multi-monitor setup when windows are detached. Can't really test that properly.

I would assume it may cause some issues there.

WSSDude avatar Feb 19 '25 16:02 WSSDude

But on the other hand, unless someone explicitly sets it up it shouldn't affect anything. And would guess same issue may happen with other backends unless it is somehow handled there per-viewport basis.

WSSDude avatar Feb 19 '25 16:02 WSSDude

Exclusive fullscreen causes this for example - you can have resolution set to 1920x1080 but on 4k display, client size is getting reported as 3840x2160, messing the cursor positions at minimum, unsure if it breaks anything else on top.

Could you provide repro code for this, in the form of a patch over your DX12 sample?

ocornut avatar May 05 '25 13:05 ocornut

I have merged this as ba513ba804c87635f7bcb3a054a463598a0a332d and added DX10 and DX11. I can't really understand how/why you are using this, but it's been useful to experiment and reason about Windows equivalent of macOS style scaling.

ocornut avatar May 07 '25 17:05 ocornut