-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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 optional shared bind group to custom materials #5962
Conversation
Hi, First time pull-request here :). Hope the description makes sense. Happy for any feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, the PR description is well made and I like the feature, unfortunately I personally dislike some things about the implementation.
I'm not a fan of using an associated type for that. It adds complexity to all uses of Material even if most Material don't need shared data. I also don't like the need for a new branch everywhere you want to add a draw command that could potentially make use of the shared data.
I don't think this should be an alternative to adding a time/globals bind group. This is something that is useful in enough situations to justify a permanent bind group and most other engines also offer similar features. Especially if people want to have more things other than time, it would be annoying that they would now need to merge them somehow.
crates/bevy_pbr/src/material.rs
Outdated
@@ -78,6 +78,8 @@ use std::marker::PhantomData; | |||
/// // All functions on `Material` have default impls. You only need to implement the | |||
/// // functions that are relevant for your material. | |||
/// impl Material for CustomMaterial { | |||
/// type SharedGroup = (); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a lot more documentation to explain what it is and how to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment
Fully agree with you on basically all accounts.
Me neither, it is unfortunate that it forces boilerplate on all implementations. I will try an implementation of the alternate (in the description) and see how that goes.
Are you referring to the two sets of draw commands (DrawWithoutSharedGroup and DrawWithSharedGroup)? Honestly I thought these where only meant for internal use within the MaterialPlugin, but maybe I have missunderstood their full purpose.
Agreed, personally I would like both a standard set of often used globals (time, etc.) and the option to add your own. In my case some map data for my grid. |
Yes, but reading the code again, it's not as bad as I thought. It's still a bit unfortunate that it needs to separate sets of draw commands. |
Changed the implementation to use a optional (defaulted to |
I definitely appreciate the need that you put forth in the description and you clarify your approach well. A couple of things come to mind:
So, I want to peel back AsBindGroup a bit to ideally have methods that return bind group layout entries and bind group entries or something like that such that one can say ‘I want the view uniform binding in bind group 0 binding 0, and this noise texture and sampler in bind group 0 bindings 1 and 2’ etc. I don’t know what @cart thinks about this exactly. I think they’ll be on board with the flexibility as long as the ergonomics and performance are there. :) And if we take a plain data only material asset (ie no textures/samplers) as an example, I want those to be written into arrays in single buffers and the array index to be stored in a component on the render world entity, kind of like the mesh uniform dynamic offset stuff, but array indices instead of buffer offsets. I started work on all this but unfortunately I don’t currently have the time to continue. |
Alright, this is very interesting.
Ah, that makes some things a lot clearer. I knew that the best/common practice was to group the shader resources by frequency to minimize binds/rebinds, but not that the actual index mattered. That., of course, makes my proposed implementation less than ideal to say the least.
Yes, I was thinking the same thing while diggin' through the code for this implementation. For me it was simply the fact that after the
This would be fantastic. While working on this I was thinking of something similar where the material system have couple of named contexts or "buckets" for shader resources defined. E.g. GLOBAL, SHADER, MATERIAL, MESH. Where each correspond to a update frequency or basically nesting depth in the render loop. |
Objective
Add the possibility for all instances of a custom material to have a shared data set (Uniforms, Textures, Samplers, etc.) or multiple custom materials to share a common data set.
This can be used for things like:
Time
can be uploaded only once per frame and then used by multiple materials. (Even though time probably should be addressed by something like: [Merged by Bors] - add globals to mesh view bind group #5409)In my project the need arose when trying to visualize my world grid in multiple shaders.
Solution
Add a secondary generic parameter to MaterialPlugin<M, G> that specify a resource that can be turned into a shared bind group (must impl AsBindGroup). This resource can either use the
derive(AsBindGroup)
to create a group of shared static data (e.g. shared textures, samplers) or manually implemented for user managed buffers etc.Update
MaterialPlugin
to bind the SharedGroup bind group to slot 3 if present. (If no shared group is specified the code path should be identical to pre- this patch)Add a convenience plugin that will fetch a resource that impl
AsBindGroup
and prepares it for use as a shared bind group in the material plugin.Alternate Solution:
Example
Added a new example showing this feature in action. Here two materials are created that both are aware of the position and parameters of a "force field" to create different effects.
Changelog
MaterialPlugin
to support an optional user-specified shared bind group parameterSharedBindGroupPlugin
to help prepare shared bind groupsMigration Guide