-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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 headless renderer #3155
Comments
The new renderer does have a clear separation between "render code" and "app code", but the types are still exported from the new bevy_render crate (Mesh) and the new bevy_pbr crate (StandardMaterial). I think it makes sense logically to keep it that way. I do agree that we should support headless mode, but I think it would probably look more like this:
|
Sounds like a great idea! The same approach is used in Godot. I understand that the 0.6 release is already huge, but it there any chance to see headless render mode in 0.6? |
I think wgpu already supports "null" mode in that it still compiles / runs if you dont have any supported devices + backends available. So the biggest missing piece is just ensuring the right things are disabled / nothing panics in headless mode. This seems like a pretty small chunk of work. I can't promise that it will happen in time, but we might be able to make it work! |
A relevant message I just left on discord in response to @Shatur:
Yeah now seems like as good a time as any! I think we should start by using "runtime configuration", such as alternative plugins (or maybe configuration of RenderPlugin). I don't have a strong opinion on the UX yet, so feel free to experiment and present your thoughts.
I know that wgpu will fail to initialize a device when there are no backends available:
So step one will either be: A) ensuring we don't panic when there is no device available (and headless mode is enabled) Using (A) would probably require compiling wgpu with backends disabled (which may or may not be possible right now). (B) would avoid the failure in the first place and feels cleaner to me than (A). Both (A) and (B) would require gracefully handling the fact that the RenderDevice and RenderQueue resources dont exist at all. This would mainly mean that we don't run the render app schedule when headless mode is enabled. However we do currently support the ability for normal app code to access the RenderDevice as a resource (although we don't currently use it for anything). If we go with (A) or (B), that type of code would panic when we don't insert the RenderDevice. Theres also a future where asset loaders directly produce gpu assets in a separate thread instead of going through the Render App schedule. The only way to support these scenarios properly is with a "null wgpu backend" that does nothing, but still results in successful creation of a RenderDevice. I don't think wgpu has an actual "null backend" yet, but I'm hoping they're open to it. Imo we should start with (B) as it is easy and should generally work. |
Here is the summary of messages that I wrote in the discord. I decided to try researching the suggested step
After that I had a window with no render. Then I commented out window creation - it worked. RendererMaybe make it a compile option because
WindowWith a window, things are more complicated. If we just disable the
@cart Which of the following options would you like more? Do you have any alternative implementation suggestions? |
Glad you got the initial "headless mode" implemented! RendererI do think that we need to separate the tasks of "logical headless mode that doesn't set up the renderer when enabled" and "completely removing wgpu from the tree". The first two solutions you suggest for the renderer don't solve the "remove wgpu from the tree" problem because users still code to wgpu symbols in those scenarios. The problem here is that wgpu is a part of our public API. If we want to disable the dependency entirely at compile time, we need user code to either:
Neither (1) or (2) are actually options in my opinion. In (1) we'd just be re-inventing the wgpu api. We've already agreed that wgpu is our user-facing gpu api and I'm not reverting that decision. (2) involves foisting too much responsibility on Bevy users to manually draw hard compile-time lines between render logic and app logic. Unity / Godot / Unreal / etc don't force users to do this. We can't either. So what can we do? Did we design ourselves into a hole? Nope! We can actually accomplish (1), we just need to shift our perspective a bit. The goal of removing To solve the other "logical headless mode that doesn't set up the renderer when enabled" problem, we can either: A. Keep user / engine code as it is and implement a "null backend" in wgpu that doesn't fail when used like a gpu api. This would likely still incur some overhead as we'd still be running the renderer, it just wouldn't do anything. We probably don't want that in most headless scenarios. I think we should scope this issue to solving (B). Your idea to return Option when users call WindowWe can't really decouple the game loop from Fortunately we've already abstracted out "app runners". You can already just disable the optional bevy_winit dependency and define a custom app runner: https://github.com/bevyengine/bevy/blob/main/examples/app/custom_loop.rs. Custom runners can just choose to ignore window creation events, so this should satisfy "headless" needs already. |
Thank you a lot for your input! The suggested design is so elegant, I like it. Will start working on it. |
@cart There is an issue with removing dependencies. Bevy depends on |
@cart It looks like here we have the same issue as with renderer. bevy/pipelined/bevy_pbr2/src/light.rs Line 314 in 172f4d6
bevy/pipelined/bevy_core_pipeline/src/main_pass_3d.rs Lines 50 to 53 in 172f4d6
Should we apply the same approach as for |
Yeah I think its worth asking about. But for now I wouldn't consider it a priority, so I wouldn't push too hard 😄
Yup sounds good to me!
Hmm yeah this is interesting. I think it probably makes sense to handle this "inline" for now by not assuming cameras correlate to windows. Ultimately this feels like it will intersect with the "RenderTargets" work I have planned, which will treat windows as "just another render target type" and further decouple cameras from windows. Theres a lot to cover there that I don't have the time to unpack at the moment, so for now I think getting rid of the unwraps makes the most sense. |
@cart thanks for the input!
Which one would you think is better? |
Good news, it was just two unwraps :) I'll send a PR once you merge #3312. |
# Objective This PR fixes a crash when winit is enabled when there is a camera in the world. Part of #3155 ## Solution In this PR, I removed two unwraps and added an example for regression testing.
Opened #3321. Will try to implement dummy backend for wgpu: gfx-rs/wgpu#2291 and then use this backend in Bevy if |
I've discussed this in more detail with the wgpu developers in Matrix and there doesn't seem to be a nice solution for it. So maybe we should implement only "logical headless" mode to run Bevy on servers without GPU and close the issue. @cart so what do you think? Maybe you have a better suggestion? |
This sounds like a nice path forward. We can close this issue once that PR is merged, and reopen this issue if the solution isn't enough or if things get easier on |
@alice-i-cecile, @cart just got another idea about the design. Instead of enable "headless mode" via resource we could split bevy/crates/bevy_render/src/lib.rs Line 107 in 22c665f
Into |
Hmm. The plugin splitting is more elegant in some ways. However, it may be a bit harder to discover, and I don't believe we can (currently) enable / disable plugins at runtime 🤔 That said, I think this is a natural split, and I suspect that this will effectively always be a choice made at app start. The ability to add/remove systems at runtime is a feature we eventually need, and with a properly structured approach to plugin management I think we should be able to get the same effect for plugins. Overall, mild preference towards the plugin splitting approach. |
This is a reasonable design, but I think I prefer just adding a configuration field to the existing |
Was this addressed ? I'm trying to run the |
It does not seem to be, as a window appears to be required for the "headless" server, that uses RenderPlugin. And RenderPlugin is required for Mesh, Shader, etc. So the original issue is not addressed in my opinion. Currently, I am working around it by manually injecting the MeshPlugin/etc (and getting some missing labels warnings), but it would be nice to have a genuinely headless server that supports some of the functionality provided by the RenderPlugin |
You can run without a window, there is an example in this repo. |
I must be completely missing the correct way of doing it. There are 3 examples that I found:
What I need is basically headless server with some of the default plugins (or rather minimal plugins + manually added plugins) required for physics (e.g. mesh, gltf) and no window. Could you point me in the right direction please? |
It looks like |
Would be nice to have it working out of the box though. I guess would also be useful to not require WindowPlugin in RenderPlugin, especially when there are no backends to render to. This way it should be fine to use MinimalPlugins + RenderPlugin instead of working around it or writing a custom runner. |
Sure, there was a talk about this decoupling. I believe it will happen in the future. Maybe after #5589 |
Is this now possible? |
To those that may come across this issue: You don't need to make your own schedule runner, bevy already has one build in that is used in the TL;DR Just add this to your app builder to get a true headless bevy app that supports physics: ...
App:new()
.insert_resource(ScheduleRunnerSettings::run_loop(Duration::from_secs_f64(1.0/60.0)))
.add_plugins(DefaultPlugins.build().disable::<WinitPlugin>())
.add_plugin(ScheduleRunnerPlugin)
... I'm currently using this in Bevy version 0.10.0 |
any update on this? @2-3-5-41 have a repo / a more detailed example? |
Here's a working example ( bevy v0.12.1 ) for anyone else who needs a headless renderer - https://github.com/mosure/bevy_gaussian_splatting/blob/main/examples/headless.rs |
Thanks for your awesome example, I tried to create a really minimalistic version of it, unfortunately I had some issues on OSX.
gave me this unexpected error
my dependencies of my Cargo are
|
@richardanaya hey, i also use macOS. Think I've seen a similar error. Did you run both release and dev? |
yep, seems like it happens in release. interesting you use macos :/ not sure what the difference is. |
i can try running it locally if you put up a simple repo based on the code you posted above. |
@richardanaya the error is coming from wgpu version 0.17.2, the supported version is 0.17.1 |
@cs50victor sorry about the late reply, here is a repo with my just minimal code :) https://github.com/richardanaya/headless What's strange is I appear to be using 0.17.1, i'm not sure why it's not working. |
@richardanaya what's odd is that your repo works but I'm getting a similar error running the headless frame capture in a different project i'm working on. Investigating this issue. It might not be the wgpu crate. |
@cs50victor interesting :) We both seem to be using a metal adapter, but i'm on Apple M1 2024-01-21T17:25:57.039614Z INFO bevy_render::renderer: AdapterInfo { name: "Apple M1", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal } maybe something in wgpu is really m1/m2 specific? |
yh. maybe. came across this issue - denoland/deno#10098 but a fix already got merged in v14 |
I wonder if there is some sneaky intersystem dependency that's not being respected, or rather, maybe it succeeds in certain scheduling of the systems? |
@richardanaya think I just found the culprit. PR : richardanaya/headless#1 Hey @DGriffin91 know if your frame capture tool is compatible with Bevy's
Divided different parts of my previous post into crates here - https://github.com/cs50victor/new_media |
@cs50victor that worked for me! Thank you. Updated my repo. |
multithreaded support for anyone looking for something similar in future - cs50victor/newmedia#10 |
What problem does this solve or what need does it fill?
When creating multiplayer, often the logic of the game is executed on the headless server. But registration of renderer types such as
Asset<Meshes>
is now tied to the renderer. Therefore, to use exactly the same logic on the server, I have to add compile-time checks:This looks ugly and very inconvenient to use.
What solution would you like?
It would be great to have a headless renderer.
The text was updated successfully, but these errors were encountered: