Make AsBindGroup unsized (#6937)

# Objective

`AsBindGroup` can't be used as a trait object because of the constraint `Sized` and because of the associated function.

This is a problem for [`bevy_atmosphere`](https://github.com/JonahPlusPlus/bevy_atmosphere) because it needs to use a trait that depends on `AsBindGroup` as a trait object, for switching out different shaders at runtime. The current solution it employs is reimplementing the trait and derive macro into that trait, instead of constraining to `AsBindGroup`.

## Solution

Remove the `Sized` constraint from `AsBindGroup` and add the constraint `where Self: Sized` to the associated function `bind_group_layout`. Also change `PreparedBindGroup<T: AsBindGroup>` to `PreparedBindGroup<T>` and use it as `PreparedBindGroup<Self::Data>` instead of `PreparedBindGroup<Self>`.

This weakens the constraints, but increases the flexibility of `AsBindGroup`.
I'm not entirely sure why the `Sized` constraint was there, because it worked fine without it (maybe @cart wasn't aware of use cases for `AsBindGroup` as a trait object or this was just leftover from legacy code?).

---

## Changelog

- `AsBindGroup` can be used as a trait object.
This commit is contained in:
Jonah Henriksson 2022-12-16 01:40:15 +00:00
parent ec0478d100
commit 38d567d2c5
3 changed files with 9 additions and 7 deletions

View File

@ -371,7 +371,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
render_device: &#render_path::renderer::RenderDevice, render_device: &#render_path::renderer::RenderDevice,
images: &#render_path::render_asset::RenderAssets<#render_path::texture::Image>, images: &#render_path::render_asset::RenderAssets<#render_path::texture::Image>,
fallback_image: &#render_path::texture::FallbackImage, fallback_image: &#render_path::texture::FallbackImage,
) -> Result<#render_path::render_resource::PreparedBindGroup<Self>, #render_path::render_resource::AsBindGroupError> { ) -> Result<#render_path::render_resource::PreparedBindGroup<Self::Data>, #render_path::render_resource::AsBindGroupError> {
let bindings = vec![#(#binding_impls,)*]; let bindings = vec![#(#binding_impls,)*];
let bind_group = { let bind_group = {

View File

@ -253,7 +253,7 @@ impl Deref for BindGroup {
/// } /// }
/// } /// }
/// ``` /// ```
pub trait AsBindGroup: Sized { pub trait AsBindGroup {
/// Data that will be stored alongside the "prepared" bind group. /// Data that will be stored alongside the "prepared" bind group.
type Data: Send + Sync; type Data: Send + Sync;
@ -264,10 +264,12 @@ pub trait AsBindGroup: Sized {
render_device: &RenderDevice, render_device: &RenderDevice,
images: &RenderAssets<Image>, images: &RenderAssets<Image>,
fallback_image: &FallbackImage, fallback_image: &FallbackImage,
) -> Result<PreparedBindGroup<Self>, AsBindGroupError>; ) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError>;
/// Creates the bind group layout matching all bind groups returned by [`AsBindGroup::as_bind_group`] /// Creates the bind group layout matching all bind groups returned by [`AsBindGroup::as_bind_group`]
fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout; fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout
where
Self: Sized;
} }
/// An error that occurs during [`AsBindGroup::as_bind_group`] calls. /// An error that occurs during [`AsBindGroup::as_bind_group`] calls.
@ -277,10 +279,10 @@ pub enum AsBindGroupError {
} }
/// A prepared bind group returned as a result of [`AsBindGroup::as_bind_group`]. /// A prepared bind group returned as a result of [`AsBindGroup::as_bind_group`].
pub struct PreparedBindGroup<T: AsBindGroup> { pub struct PreparedBindGroup<T> {
pub bindings: Vec<OwnedBindingResource>, pub bindings: Vec<OwnedBindingResource>,
pub bind_group: BindGroup, pub bind_group: BindGroup,
pub data: T::Data, pub data: T,
} }
/// An owned binding resource of any type (ex: a [`Buffer`], [`TextureView`], etc). /// An owned binding resource of any type (ex: a [`Buffer`], [`TextureView`], etc).

View File

@ -227,7 +227,7 @@ impl AsBindGroup for CubemapMaterial {
render_device: &RenderDevice, render_device: &RenderDevice,
images: &RenderAssets<Image>, images: &RenderAssets<Image>,
_fallback_image: &FallbackImage, _fallback_image: &FallbackImage,
) -> Result<PreparedBindGroup<Self>, AsBindGroupError> { ) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError> {
let base_color_texture = self let base_color_texture = self
.base_color_texture .base_color_texture
.as_ref() .as_ref()