diff --git a/crates/bevy_render/macros/src/as_bind_group.rs b/crates/bevy_render/macros/src/as_bind_group.rs index 8af04edd688b9..acf2fed037341 100644 --- a/crates/bevy_render/macros/src/as_bind_group.rs +++ b/crates/bevy_render/macros/src/as_bind_group.rs @@ -200,6 +200,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { let StorageAttrs { visibility, read_only, + buffer, } = get_storage_binding_attr(nested_meta_items)?; let visibility = visibility.hygenic_quote("e! { #render_path::render_resource }); @@ -207,18 +208,32 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { let field_name = field.ident.as_ref().unwrap(); let field_ty = &field.ty; - binding_impls.push(quote! {{ - use #render_path::render_resource::AsBindGroupShaderType; - let mut buffer = #render_path::render_resource::encase::StorageBuffer::new(Vec::new()); - buffer.write(&self.#field_name).unwrap(); - #render_path::render_resource::OwnedBindingResource::Buffer(render_device.create_buffer_with_data( - &#render_path::render_resource::BufferInitDescriptor { - label: None, - usage: #render_path::render_resource::BufferUsages::COPY_DST | #render_path::render_resource::BufferUsages::STORAGE, - contents: buffer.as_ref(), - }, - )) - }}); + let min_binding_size = if buffer { + quote! {None} + } else { + quote! {Some(<#field_ty as #render_path::render_resource::ShaderType>::min_size())} + }; + + if buffer { + binding_impls.push(quote! { + #render_path::render_resource::OwnedBindingResource::Buffer({ + self.#field_name.clone() + }) + }); + } else { + binding_impls.push(quote! {{ + use #render_path::render_resource::AsBindGroupShaderType; + let mut buffer = #render_path::render_resource::encase::StorageBuffer::new(Vec::new()); + buffer.write(&self.#field_name).unwrap(); + #render_path::render_resource::OwnedBindingResource::Buffer(render_device.create_buffer_with_data( + &#render_path::render_resource::BufferInitDescriptor { + label: None, + usage: #render_path::render_resource::BufferUsages::COPY_DST | #render_path::render_resource::BufferUsages::STORAGE, + contents: buffer.as_ref(), + }, + )) + }}); + } binding_layouts.push(quote! { #render_path::render_resource::BindGroupLayoutEntry { @@ -227,7 +242,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { ty: #render_path::render_resource::BindingType::Buffer { ty: #render_path::render_resource::BufferBindingType::Storage { read_only: #read_only }, has_dynamic_offset: false, - min_binding_size: Some(<#field_ty as #render_path::render_resource::ShaderType>::min_size()), + min_binding_size: #min_binding_size, }, count: None, } @@ -907,13 +922,16 @@ fn get_sampler_binding_type_value(lit_str: &LitStr) -> Result) -> Result { let mut visibility = ShaderStageVisibility::vertex_fragment(); let mut read_only = false; + let mut buffer = false; for meta in metas { use syn::{Meta::List, Meta::Path, NestedMeta::Meta}; @@ -925,6 +943,9 @@ fn get_storage_binding_attr(metas: Vec) -> Result { Meta(Path(path)) if path == READ_ONLY => { read_only = true; } + Meta(Path(path)) if path == BUFFER => { + buffer = true; + } _ => { return Err(Error::new_spanned( meta, @@ -937,5 +958,6 @@ fn get_storage_binding_attr(metas: Vec) -> Result { Ok(StorageAttrs { visibility, read_only, + buffer, }) } diff --git a/crates/bevy_render/src/render_resource/bind_group.rs b/crates/bevy_render/src/render_resource/bind_group.rs index 46e30771b03bd..15d87a969f2f6 100644 --- a/crates/bevy_render/src/render_resource/bind_group.rs +++ b/crates/bevy_render/src/render_resource/bind_group.rs @@ -84,6 +84,8 @@ impl Deref for BindGroup { /// color_texture: Handle, /// #[storage(3, read_only)] /// values: Vec, +/// #[storage(4, read_only, buffer)] +/// buffer: Buffer, /// } /// ``` ///