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

Update sampler along with texture on wgpu backend #5122

Merged
merged 3 commits into from
Sep 19, 2024

Conversation

valadaptive
Copy link
Contributor

This unifies the code paths in update_texture somewhat, so that the texture sampler and bind group are always replaced.

Not sure whether removing and reinserting the texture from and into the textures map, or creating a new bind group, has much of a performance impact. An alternative, as described in #5121, would be to split the functionality for updating a texture's data from updating its options, so that we don't have to unconditionally update the bind group (or do something like store the options to check if they're changed).

@valadaptive valadaptive requested a review from Wumpf as a code owner September 18, 2024 00:53
@emilk emilk added this to the Next Major Release milestone Sep 18, 2024
@Wumpf Wumpf added bug Something is broken egui-wgpu labels Sep 18, 2024
Copy link
Collaborator

@Wumpf Wumpf 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 finding and fixing this!

Not sure whether removing and reinserting the texture from and into the textures map, or creating a new bind group, has much of a performance impact.

I'm not worried about removing and inserting the texture as this is a fairly fast operation. But re-creating the bind-group every time is indeed a bit worrisome to me since this is an extra resource that has to be taken care of by wgpu and the driver. (On the web this even needs to wait garbage collection if the old one isn't explicitly destroyed).

I figure solving this shouldn't be too hard: We just store something like this on the hashmap

struct Texture {
    /// The texture may be None if the `TextureId` is just a handle to a user-provided sampler.
    texture: Option<wgpu::Texture>,
    
    /// Bindgroup for the texture + sampler.
    bind_group: wgpu::BindGroup,
    
    /// Options describing the sampler used in the bind group.
    options: epaint::textures::TextureOptions,
}

and recreate/fetch sampler & recreate bindgroup only if the options have a mismatch.

Oh and while you're on it: let's call destroy if we discard a bind_group.
It doesn't make a difference on native, but right now wgpu doesn't call that for you on object death when being on WebGPU. This is relevant because all WebGPU objects live in Javascript land and thus get only destroyed once the garbage collector runs over them.
Same on free_texture for the texture and bindgroup. (calling destroy invalidates every wgpu object that uses the resource at that point and hasn't submitted its operations yet, but free_texture is &mut and render is &self, so we should be good!)

@emilk emilk removed this from the Next Major Release milestone Sep 18, 2024
@valadaptive valadaptive requested a review from Wumpf September 18, 2024 10:37
@valadaptive
Copy link
Contributor Author

I've updated the code to store the TextureOptions along with the other texture info, and only update the bind group if they differ. I've kept the remove/reinsert from the map, since the borrow checker makes us choose between duplicating the code for creating a bind group or moving the data out of the map.

Oh and while you're on it: let's call destroy if we discard a bind_group. It doesn't make a difference on native, but right now wgpu doesn't call that for you on object death when being on WebGPU. This is relevant because all WebGPU objects live in Javascript land and thus get only destroyed once the garbage collector runs over them. Same on free_texture for the texture and bindgroup. (calling destroy invalidates every wgpu object that uses the resource at that point and hasn't submitted its operations yet, but free_texture is &mut and render is &self, so we should be good!)

I've also made it so that free_texture destroy()s the texture. As far as I can tell, BindGroup doesn't have a destroy method?

Copy link
Collaborator

@Wumpf Wumpf left a comment

Choose a reason for hiding this comment

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

oh, interesting! Wasn't aware that BindGroup has no destroy.
Small nit on doc string otherwise good to go imho. Thanks for taking care of everything!

crates/egui-wgpu/src/renderer.rs Outdated Show resolved Hide resolved
@valadaptive valadaptive requested a review from Wumpf September 19, 2024 00:55
@Wumpf Wumpf merged commit bb9e874 into emilk:master Sep 19, 2024
21 checks passed
hacknus pushed a commit to hacknus/egui that referenced this pull request Oct 30, 2024
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* Closes emilk#5121
* [x] I have followed the instructions in the PR template

This unifies the code paths in `update_texture` somewhat, so that the
texture sampler and bind group are always replaced.

Not sure whether removing and reinserting the texture from and into the
`textures` map, or creating a new bind group, has much of a performance
impact. An alternative, as described in emilk#5121, would be to split the
functionality for updating a texture's data from updating its options,
so that we don't have to unconditionally update the bind group (or do
something like store the options to check if they're changed).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken egui-wgpu
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Partial texture updates will update the sampler in egui_glow but not egui_wgpu
3 participants