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

Use safe window handles and wgpu::Instance::create_surface #13172

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ids1024
Copy link

@ids1024 ids1024 commented May 2, 2024

Objective

I noticed that #12978 introduces a reference counted wrapper around windows, but still uses RawWindowHandle and RawDisplayHandle, with wgpu::Instance::create_surface_unsafe. This can be changed easily enough to use wgpu::Instance::create_surface, and not use the raw handles anywhere.

Solution

Instead of containing an Arc<dyn _> along with raw handles, RawHandleWrapper now contains just an Arc<dyn _>, and ThreadLockedRawWindowHandleWrapper implements HasWindowHandle/HasDisplayHandle by calling those those methods on the trait object.

bevy_render uses wgpu::Instance::create_surface with the ThreadLockedRawWindowHandleWrapper. So this increments the reference count, but guarantees the window will outlive the wgpu::Instance.

Apparently we can just cast a Arc<W> to an Arc<dyn Trait>, so that makes WindowWrapper a little simpler too.

Testing

I'm not that familiar with Bevy, but examples seem to work, and this shouldn't break anything.

Migration Guide

RawHandleWrapper no longer has window_handle and display_handle fields. Instead, the get_handle() method has to be used.

Copy link
Contributor

github-actions bot commented May 2, 2024

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

@JMS55 JMS55 requested a review from james7132 May 2, 2024 02:45
@BD103 BD103 added A-Windowing Platform-agnostic interface layer to run your app in C-Code-Quality A section of code that is hard to understand or change labels May 2, 2024
Copy link
Member

@BD103 BD103 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for stopping by, we appreciate it! :)

This change looks promising, though I'm less familiar with the windowing code. Do you think it will hurt performance?

crates/bevy_render/src/view/window/mod.rs Outdated Show resolved Hide resolved
Comment on lines +51 to 55
impl fmt::Debug for RawHandleWrapper {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("RawHandleWrapper").finish_non_exhaustive()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be automatically derived by #[derive(Debug)], or does it complain that dyn WindowTrait does not implement Debug?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's needed since dyn WindowTrait doesn't implement Debug. (The standard library has an implementation for dyn Any.) It seems simplest to just implement Debug for RawHandleWrapper.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good!

I noticed that bevyengine#12978 introduces
a reference counted wrapper around windows, but still uses
`RawWindowHandle` and `RawDisplayHandle`, with
`wgpu::Instance::create_surface_unsafe`. This can be changed easily
enough to use `wgpu::Instance::create_surface`, and not use the raw
handles anywhere.

Apparently we can just cast a `Arc<W>` to an `Arc<dyn Trait>`, so that
makes `WindowWrapper` a little simpler too.
@ids1024
Copy link
Author

ids1024 commented May 3, 2024

Do you think it will hurt performance?

This should have no non-trivial impact on performance. It will just add a reference count to the Arc and store a copy in the wgpu::Instance to ensure the window isn't destroyed before the Instance.

Otherwise things should be basically unchanged.

@Elabajaba Elabajaba self-requested a review May 3, 2024 01:53
Copy link
Member

@BD103 BD103 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@Friz64
Copy link
Contributor

Friz64 commented May 3, 2024

Taking it a step further, I like it!

Sadly though, this conflicts with the workaround to #13208 I suggested (implemented in #13221).

@alice-i-cecile
Copy link
Member

Does this resolve #13208? If so, we should merge this instead of #13221.

@alice-i-cecile alice-i-cecile added X-Contentious There are nontrivial implications that should be thought through D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Testing Testing must be done before this is safe to merge labels May 4, 2024
@mockersf
Copy link
Member

mockersf commented May 4, 2024

no it doesn't

@ids1024
Copy link
Author

ids1024 commented May 4, 2024

Hopefully a better solution can be found for that behavior on macOS. But if merging that workaround is the best for now, I guess the changes here can be merged later when that is fixed.

Come to think of it, I think WindowWrapper is unneeded now, with the Arc upcasting. RawHandleWrapper::new could just take an Arc<W>, and the Arc<W> could be used anywhere else WindowWrapper is used.

Another thing that seems a bit odd is that WindowWrapper::new requires Send + Sync, while the ThreadLockedRawWindowHandleWrapper stuff seems to be meant to deal with windows that aren't thread safe?

Wgpu in comparison has pub trait WindowHandle: HasWindowHandle + HasDisplayHandle + WasmNotSendSync {}, where WasmNotSendSync is Send + Sync except on Wasm.

@alice-i-cecile alice-i-cecile added S-Blocked This cannot move forward until something else changes and removed S-Needs-Testing Testing must be done before this is safe to merge labels May 4, 2024
@Friz64
Copy link
Contributor

Friz64 commented May 4, 2024

Come to think of it, I think WindowWrapper is unneeded now, with the Arc upcasting. RawHandleWrapper::new could just take an Arc<W>, and the Arc<W> could be used anywhere else WindowWrapper is used.

Another thing that seems a bit odd is that WindowWrapper::new requires Send + Sync, while the ThreadLockedRawWindowHandleWrapper stuff seems to be meant to deal with windows that aren't thread safe?

Yeah, these are just remnants from my PR at this point. I think this PR should address this.

@JMS55 JMS55 added this to the 0.14 milestone May 7, 2024
@Friz64
Copy link
Contributor

Friz64 commented May 12, 2024

Sadly though, this conflicts with the workaround to #13208 I suggested (implemented in #13221).

Now, because we didn't go through with my quick & dirty workaround (and instead went with #13236), I think this PR is unblocked.

@alice-i-cecile alice-i-cecile removed the S-Blocked This cannot move forward until something else changes label May 12, 2024
@mockersf
Copy link
Member

this crashes on android:

05-12 19:24:03.414 E/log event( 1386): Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events.log.target = "winit::platform_impl::platform"; log.module_path = "winit::platform_impl::platform"; log.file = "/home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.29.15/src/platform_impl/android/mod.rs"; log.line = 987;
05-12 19:24:03.414 I/RustStdoutStderr( 1386): thread 'Compute Task Pool (0)' panicked at crates/bevy_render/src/view/window/mod.rs:465:22:
05-12 19:24:03.414 I/RustStdoutStderr( 1386): Failed to create wgpu surface: CreateSurfaceError { inner: RawHandle(Unavailable) }
05-12 19:24:03.414 I/RustStdoutStderr( 1386): note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
05-12 19:24:03.415 I/RustStdoutStderr( 1386): Encountered a panic in system `bevy_render::view::window::create_surfaces`!

@ids1024
Copy link
Author

ids1024 commented May 14, 2024

Hm, so when RawHandleWrapper::new is run, AsWindowHandle works (it's between resumed and suspended?), but when create_surfaces is run, its suspended? I guess?

Not sure why that would be the case, but I'm not that familiar with how this works on Android.

@alice-i-cecile alice-i-cecile removed this from the 0.14 milestone May 16, 2024
@alice-i-cecile alice-i-cecile added D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes and removed D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Windowing Platform-agnostic interface layer to run your app in C-Code-Quality A section of code that is hard to understand or change D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants