Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a project setting to continue drawing while the window is minimized #1931

Open
abb128 opened this issue Dec 3, 2020 · 20 comments
Open

Comments

@abb128
Copy link

abb128 commented Dec 3, 2020

Describe the project you are working on

An OpenVR dashboard overlay

Describe the problem or limitation you are having in your project

I am currently passing the texture of a Viewport to SteamVR through a GDNative module in order to create a dashboard. This dashboard is accessible within SteamVR and it can be viewed even if the window is minimized on the desktop, or even if there's no window at all.

In Windows Mixed Reality, entering VR mode can minimize all of your desktop windows depending on your settings, in order to improve performance for VR.

Godot Engine currently stops rendering if the window is minimized on desktop, presumably to avoid unnecessarily rendering:

bool OS_Windows::can_draw() const {

	return !minimized;
};

( https://github.com/godotengine/godot/blob/3.2.3-stable/platform/windows/os_windows.cpp#L272 )

All of these factors combined make it so that my dashboard is useless and does not re-render unless the user manually makes sure to open the window on their desktop, so that the engine can continue rendering.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The ability to override can_draw(), or even just an option to allow rendering while minimized, would allow the dashboard to continue rendering regardless of the state of the actual window.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I'm unsure about how to actually design overriding that method (ideas would be appreciated), but one simpler solution would be to simply have a boolean project setting called display/window/energy_saving/render_while_minimized.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This is not scriptable functionality as it is part of the engine. For now, I had to build a custom version of the engine with the can_draw method above replaced with

bool OS_Windows::can_draw() const {

	return true;
};

Is there a reason why this should be core and not an add-on in the asset library?

See above

@Calinou
Copy link
Member

Calinou commented Dec 3, 2020

Another use case for this is performing offline rendering while the window is minimized.

@Calinou Calinou changed the title Ability to customize can_draw() behavior Ability to customize can_draw() behavior / Add a project setting to continue drawing while the window is minimized Dec 4, 2020
@vilhalmer
Copy link

vilhalmer commented Jul 10, 2024

Now that tray icons are on the way (godotengine/godot#80211) this would be even more useful, since for VR overlays we could hide the window away entirely.

@vilhalmer
Copy link

This is now possible using DisplayServer::register_additional_output: godotengine/godot#94412

@Calinou Calinou changed the title Ability to customize can_draw() behavior / Add a project setting to continue drawing while the window is minimized Add a project setting to continue drawing while the window is minimized Aug 1, 2024
@pochoco24
Copy link

@Calinou I am using Game Capture, but there aren't any options for capturing minimized windows.

Some Unity programs like VSeeFace keep rendering while minimized with Game Capture without any extra set up in OBS.

@pochoco24
Copy link

In vulkan_context.cpp:

if (window->width == 0 || window->height == 0) {
	free(presentModes);
	// Likely window minimized, no swapchain created.
	return ERR_SKIP;
}

I've tried to change it so it creates a swapchain for rendering in minimized windows, but now it doesn't let me un-minimize the window back:

if (window->width == 0 || window->height == 0) {
	swapchainExtent.width = 1152;
	swapchainExtent.height = 648;
	window->width = 1152;
	window->height = 648;
}

@pochoco24
Copy link

@Calinou Apart from can_any_window_draw(), there's another function in display_server_windows.cpp:

bool DisplayServerWindows::window_can_draw(WindowID p_window) const {
	_THREAD_SAFE_METHOD_

	ERR_FAIL_COND_V(!windows.has(p_window), false);
	const WindowData &wd = windows[p_window];
	return !wd.minimized;
}

After changing it to return true always, the window still doesn't update when minimized.

@Calinou
Copy link
Member

Calinou commented Aug 3, 2024

I wonder if this is something that requires #5692 to work with Vulkan.

@pochoco24
Copy link

@Calinou How so?

@Calinou
Copy link
Member

Calinou commented Aug 3, 2024

@Calinou How so?

I don't know, I'm just guessing here 🙂

@pochoco24
Copy link

@dsnopek What are your thoughts on what could be causing this? (Mentioning since you added the minimized rendering feature)

@dsnopek
Copy link

dsnopek commented Aug 5, 2024

@pochoco24 I don't know. The feature I worked on was specifically to fix a VR-related issue, which is fixed by the work I did. Like I said in previous comment (which I can't seem to find right now - this conversation is spread across a few places), I suspect there's something special that needs to be done for Windows or OBS, but I don't personally know what. Someone will need to do the research and some experimentation!

@pochoco24
Copy link

@Calinou @dsnopek From the OBS Documentation, OBS directly captures the DirectX or OpenGL of the game, and it also supports Vulkan.

Do you know what files handle Vulkan (Forward+) or OpenGL 3 (Compatibility) so I can check them out?

@Calinou
Copy link
Member

Calinou commented Aug 6, 2024

The Vulkan context is created in drivers/vulkan/rendering_context_driver_vulkan.cpp, with some Windows-specific code in platform/windows/rendering_context_driver_vulkan_windows.cpp.

The OpenGL context is created in platform/windows/gl_manager_windows_native.cpp on Windows.

@pochoco24
Copy link

@Calinou In gl_manager_windows_native.cpp, there's a function that gets called every frame, even if the window is minimized:

void GLManagerNative_Windows::swap_buffers() {
	SwapBuffers(_current_window->hDC);
}

I want to check if SwapBuffers() has something that prevents minimized rendering, but VSCode can't find any references to SwapBuffers in any file 🤔

@Calinou
Copy link
Member

Calinou commented Aug 6, 2024

SwapBuffers() is a Windows API function: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-swapbuffers

@pochoco24
Copy link

@Calinou I managed to get it working (kind of) with a bare-bones Vulkan renderer. I just removed the handling minimization snippet and ensured that the swapchain renders at window resolution.

Demo.mov

Since VSeeFace can do minimized rendering and uses DX11 with a DXGI swapchain, someone ran the demo by layering a DXGI swapchain with driver settings:

image

and they said it works just fine, but it still complains about being out-of-date. Using an actual DXGI swapchain in Godot would be the way to go, so your initial guess was right! #5692

@pochoco24
Copy link

@Calinou ITS FIXED NOW!!
It works specifically for Windows using Direct3D 12 on the new Godot 4.3 build

In the source code, go to file rendering_device_driver_d3d12.cpp and change the line 2506 from:
res = swap_chain->d3d_swap_chain->ResizeBuffers(p_desired_framebuffer_count, 0, 0, DXGI_FORMAT_UNKNOWN, creation_flags);
to:
res = swap_chain->d3d_swap_chain->ResizeBuffers(p_desired_framebuffer_count, surface->width, surface->height, DXGI_FORMAT_UNKNOWN, creation_flags);

In Godot Project Settings set the Renderer Device to d3d12 (for windows), then, make a script that registers an additional output so it keeps rendering even when there are no visible windows available:

extends Node

var object = Object.new()

func _ready() -> void:
	DisplayServer.register_additional_output(object)

# Free the object before closing the game
func _notification(what: int) -> void:
	if what == NOTIFICATION_WM_CLOSE_REQUEST:
		object.free()

Now when minimizing the window, it keeps rendering.

@MudkipWorld
Copy link

@Calinou ITS FIXED NOW!! It works specifically for Windows using Direct3D 12 on the new Godot 4.3 build

Hi, since a fix got found. Would it be possible to have this feature as a project settings toggle maybe? I personally need it too since I am working on a Vtubing software which needs stuff top stay rendering when the window is minimized. I think the feature could be useful for making other non-game based projects 👀

If this feature happen to get added, would you mind informing me?

@oakheartsoftware
Copy link

oakheartsoftware commented Oct 18, 2024

Free the object before closing the game

@pochoco24, I was able to get the rendering to continue while Godot is minimized, but I'm wondering what the importance is of freeing the registered object before closing? Doesn't closing Godot just blow it away anyways, or is there something unsafe about leaving it?

@Calinou
Copy link
Member

Calinou commented Oct 18, 2024

Doesn't closing Godot just blow it away anyways, or is there something unsafe about leaving it?

Godot will print a warning on exit if you forget to free some resources before quitting, as it's bad practice. RefCounted handles this on its own, but manually managed resources such as RIDs don't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants