-
-
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
Bind group entries #9694
Bind group entries #9694
Conversation
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.
Alright, I went over everything it looks really good. The diffs are so nice to look at!
LGTM
render_device.create_bind_group( | ||
Some("model_only_mesh_bind_group"), | ||
&self.model_only, | ||
&[entry::model(0, model.clone())], |
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.
It makes sense to not change this in this PR but the pattern used here and the rest of the file will be easy to remove in a future PR.
Oh, I reviewed before the |
I think you can remove the |
Not sure what went wrong with the ci, I tried on my repo and it’s green. I also don’t know how to rerun it any more (rip bors) |
Yeah, build works fine on my side too. Must be a CI issue, I think only maintainers are allowed to force rerun CI. Alternatively you could push a new commit |
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.
Approving but do not merge until after #9258 is merged. I don't want to disrupt that large PR.
I've been using this in a codebase that uses impl<'a, T: ShaderType + WriteInto> IntoBinding<'a> for &'a UniformBuffer<T> {
#[inline]
fn into_binding(self) -> BindingResource<'a> {
BindingResource::Buffer(
self.buffer()
.expect("Failed to get buffer")
.as_entire_buffer_binding(),
)
}
} We could also add this so it can work with any buffer binding impl<'a> IntoBinding<'a> for BufferBinding<'a> {
#[inline]
fn into_binding(self) -> BindingResource<'a> {
BindingResource::Buffer(self)
}
} I also have used this one for impl<'a, T: ShaderType + WriteInto> IntoBinding<'a> for &'a DynamicUniformBuffer<T>
{
#[inline]
fn into_binding(self) -> BindingResource<'a> {
BindingResource::Buffer(BufferBinding {
buffer: self.buffer().expect("Failed to get buffer"),
offset: 0,
size: Some(T::min_size()),
})
}
} |
Co-authored-by: IceSentry <[email protected]>
I added your impl for
this one was already in the PR though |
Ah, right, sorry, it was in |
crates/bevy_gizmos/src/lib.rs
Outdated
bindgroup: render_device.create_bind_group( | ||
"LineGizmoUniform bindgroup", | ||
&line_gizmo_uniform_layout.layout, | ||
&[BindGroupEntry { |
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.
With the UniformBuffer/BufferBinding impl you should be able to use it here too now I think?
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.
i didn't use it anywhere there was only 1 entry, it doesn't really save any typing. i guess i could for consistency though?
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.
Right, makes sense then. I'll personally use it everywhere in my own code but I think it's fine as is.
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.
it ends up looking like &BindGroupEntries::sequential((binding,)),
which is a bit weird...
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.
Oof, yeah, nevermind then 😅
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.
there's actually quite a few single-entry bindings at zero over the codebase ... i'll try adding a BindGroupEntries::single
method.
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.
added, i think it's nice
Co-authored-by: IceSentry <[email protected]>
Here's another impl that could be useful to have impl<'a> IntoBinding<'a> for &'a CachedTexture {
#[inline]
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(&self.default_view)
}
} I needed that because I wanted to suggest an impl that unwraps for Options but I think it makes sense to do unwrapping at the callsites. |
# Objective Simplify bind group creation code. alternative to (and based on) bevyengine#9476 ## Solution - Add a `BindGroupEntries` struct that can transparently be used where `&[BindGroupEntry<'b>]` is required in BindGroupDescriptors. Allows constructing the descriptor's entries as: ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::with_indexes(( (2, &my_sampler), (3, my_uniform), )), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 2, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 3, resource: my_uniform, }, ], ); ``` or ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::sequential((&my_sampler, my_uniform)), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 0, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 1, resource: my_uniform, }, ], ); ``` the structs has no user facing macros, is tuple-type-based so stack allocated, and has no noticeable impact on compile time. - Also adds a `DynamicBindGroupEntries` struct with a similar api that uses a `Vec` under the hood and allows extending the entries. - Modifies `RenderDevice::create_bind_group` to take separate arguments `label`, `layout` and `entries` instead of a `BindGroupDescriptor` struct. The struct can't be stored due to the internal references, and with only 3 members arguably does not add enough context to justify itself. - Modify the codebase to use the new api and the `BindGroupEntries` / `DynamicBindGroupEntries` structs where appropriate (whenever the entries slice contains more than 1 member). ## Migration Guide - Calls to `RenderDevice::create_bind_group({BindGroupDescriptor { label, layout, entries })` must be amended to `RenderDevice::create_bind_group(label, layout, entries)`. - If `label`s have been specified as `"bind_group_name".into()`, they need to change to just `"bind_group_name"`. `Some("bind_group_name")` and `None` will still work, but `Some("bind_group_name")` can optionally be simplified to just `"bind_group_name"`. --------- Co-authored-by: IceSentry <[email protected]>
# Objective Simplify bind group creation code. alternative to (and based on) bevyengine#9476 ## Solution - Add a `BindGroupEntries` struct that can transparently be used where `&[BindGroupEntry<'b>]` is required in BindGroupDescriptors. Allows constructing the descriptor's entries as: ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::with_indexes(( (2, &my_sampler), (3, my_uniform), )), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 2, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 3, resource: my_uniform, }, ], ); ``` or ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::sequential((&my_sampler, my_uniform)), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 0, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 1, resource: my_uniform, }, ], ); ``` the structs has no user facing macros, is tuple-type-based so stack allocated, and has no noticeable impact on compile time. - Also adds a `DynamicBindGroupEntries` struct with a similar api that uses a `Vec` under the hood and allows extending the entries. - Modifies `RenderDevice::create_bind_group` to take separate arguments `label`, `layout` and `entries` instead of a `BindGroupDescriptor` struct. The struct can't be stored due to the internal references, and with only 3 members arguably does not add enough context to justify itself. - Modify the codebase to use the new api and the `BindGroupEntries` / `DynamicBindGroupEntries` structs where appropriate (whenever the entries slice contains more than 1 member). ## Migration Guide - Calls to `RenderDevice::create_bind_group({BindGroupDescriptor { label, layout, entries })` must be amended to `RenderDevice::create_bind_group(label, layout, entries)`. - If `label`s have been specified as `"bind_group_name".into()`, they need to change to just `"bind_group_name"`. `Some("bind_group_name")` and `None` will still work, but `Some("bind_group_name")` can optionally be simplified to just `"bind_group_name"`. --------- Co-authored-by: IceSentry <[email protected]>
# Objective - Follow up to #9694 ## Solution - Same api as #9694 but adapted for `BindGroupLayoutEntry` - Use the same `ShaderStages` visibilty for all entries by default - Add `BindingType` helper function that mirror the wgsl equivalent and that make writing layouts much simpler. Before: ```rust let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { label: Some("post_process_bind_group_layout"), entries: &[ BindGroupLayoutEntry { binding: 0, visibility: ShaderStages::FRAGMENT, ty: BindingType::Texture { sample_type: TextureSampleType::Float { filterable: true }, view_dimension: TextureViewDimension::D2, multisampled: false, }, count: None, }, BindGroupLayoutEntry { binding: 1, visibility: ShaderStages::FRAGMENT, ty: BindingType::Sampler(SamplerBindingType::Filtering), count: None, }, BindGroupLayoutEntry { binding: 2, visibility: ShaderStages::FRAGMENT, ty: BindingType::Buffer { ty: bevy::render::render_resource::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: Some(PostProcessSettings::min_size()), }, count: None, }, ], }); ``` After: ```rust let layout = render_device.create_bind_group_layout( "post_process_bind_group_layout"), &BindGroupLayoutEntries::sequential( ShaderStages::FRAGMENT, ( texture_2d_f32(), sampler(SamplerBindingType::Filtering), uniform_buffer(false, Some(PostProcessSettings::min_size())), ), ), ); ``` Here's a more extreme example in bevy_solari: JMS55@86dab7f --- ## Changelog - Added `BindGroupLayoutEntries` and all `BindingType` helper functions. ## Migration Guide `RenderDevice::create_bind_group_layout()` doesn't take a `BindGroupLayoutDescriptor` anymore. You need to provide the parameters separately ```rust // 0.12 let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { label: Some("post_process_bind_group_layout"), entries: &[ BindGroupLayoutEntry { // ... }, ], }); // 0.13 let layout = render_device.create_bind_group_layout( "post_process_bind_group_layout", &[ BindGroupLayoutEntry { // ... }, ], ); ``` ## TODO - [x] implement a `Dynamic` variant - [x] update the `RenderDevice::create_bind_group_layout()` api to match the one from `RenderDevice::creat_bind_group()` - [x] docs
# Objective Simplify bind group creation code. alternative to (and based on) bevyengine#9476 ## Solution - Add a `BindGroupEntries` struct that can transparently be used where `&[BindGroupEntry<'b>]` is required in BindGroupDescriptors. Allows constructing the descriptor's entries as: ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::with_indexes(( (2, &my_sampler), (3, my_uniform), )), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 2, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 3, resource: my_uniform, }, ], ); ``` or ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &BindGroupEntries::sequential((&my_sampler, my_uniform)), ); ``` instead of ```rust render_device.create_bind_group( "my_bind_group", &my_layout, &[ BindGroupEntry { binding: 0, resource: BindingResource::Sampler(&my_sampler), }, BindGroupEntry { binding: 1, resource: my_uniform, }, ], ); ``` the structs has no user facing macros, is tuple-type-based so stack allocated, and has no noticeable impact on compile time. - Also adds a `DynamicBindGroupEntries` struct with a similar api that uses a `Vec` under the hood and allows extending the entries. - Modifies `RenderDevice::create_bind_group` to take separate arguments `label`, `layout` and `entries` instead of a `BindGroupDescriptor` struct. The struct can't be stored due to the internal references, and with only 3 members arguably does not add enough context to justify itself. - Modify the codebase to use the new api and the `BindGroupEntries` / `DynamicBindGroupEntries` structs where appropriate (whenever the entries slice contains more than 1 member). ## Migration Guide - Calls to `RenderDevice::create_bind_group({BindGroupDescriptor { label, layout, entries })` must be amended to `RenderDevice::create_bind_group(label, layout, entries)`. - If `label`s have been specified as `"bind_group_name".into()`, they need to change to just `"bind_group_name"`. `Some("bind_group_name")` and `None` will still work, but `Some("bind_group_name")` can optionally be simplified to just `"bind_group_name"`. --------- Co-authored-by: IceSentry <[email protected]>
Objective
Simplify bind group creation code. alternative to (and based on) #9476
Solution
BindGroupEntries
struct that can transparently be used where&[BindGroupEntry<'b>]
is required in BindGroupDescriptors.Allows constructing the descriptor's entries as:
instead of
or
instead of
the structs has no user facing macros, is tuple-type-based so stack allocated, and has no noticeable impact on compile time.
DynamicBindGroupEntries
struct with a similar api that uses aVec
under the hood and allows extending the entries.RenderDevice::create_bind_group
to take separate argumentslabel
,layout
andentries
instead of aBindGroupDescriptor
struct. The struct can't be stored due to the internal references, and with only 3 members arguably does not add enough context to justify itself.BindGroupEntries
/DynamicBindGroupEntries
structs where appropriate (whenever the entries slice contains more than 1 member).Migration Guide
RenderDevice::create_bind_group({BindGroupDescriptor { label, layout, entries })
must be amended toRenderDevice::create_bind_group(label, layout, entries)
.label
s have been specified as"bind_group_name".into()
, they need to change to just"bind_group_name"
.Some("bind_group_name")
andNone
will still work, butSome("bind_group_name")
can optionally be simplified to just"bind_group_name"
.