bevy/crates/bevy_render/macros/src/lib.rs
HugoPeters1024 8afb3ceb89
add storage_texture option to as_bind_group macro (#9943)
# Objective

- Add the ability to describe storage texture bindings when deriving
`AsBindGroup`.
- This is especially valuable for the compute story of bevy which
deserves some extra love imo.

## Solution

- This add the ability to annotate struct fields with a
`#[storage_texture(0)]` annotation.
- Instead of adding specific option parsing for all the image formats
and access modes, I simply accept a token stream and defer checking to
see if the option is valid to the compiler. This still results in useful
and friendly errors and is free to maintain and always compatible with
wgpu changes.

---

## Changelog

- The `#[storage_texture(..)]` annotation is now accepted for fields of
`Handle<Image>` in structs that derive `AsBindGroup`.
- The game_of_life compute shader example has been updated to use
`AsBindGroup` together with `[storage_texture(..)]` to obtain the
`BindGroupLayout`.

## Migration Guide
2024-01-21 18:47:13 +00:00

61 lines
2.0 KiB
Rust

mod as_bind_group;
mod extract_component;
mod extract_resource;
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
pub(crate) fn bevy_render_path() -> syn::Path {
BevyManifest::default()
.maybe_get_path("bevy_render")
// NOTE: If the derivation is within bevy_render, then we need to return 'crate'
.unwrap_or_else(|| BevyManifest::parse_str("crate"))
}
#[proc_macro_derive(ExtractResource)]
pub fn derive_extract_resource(input: TokenStream) -> TokenStream {
extract_resource::derive_extract_resource(input)
}
/// Implements `ExtractComponent` trait for a component.
/// The component must implement [`Clone`].
/// The component will be extracted into the render world via cloning.
/// Note that this only enables extraction of the component, it does not execute the extraction.
/// See `ExtractComponentPlugin` to actually perform the extraction.
///
/// If you only want to extract a component conditionally, you may use the `extract_component_filter` attribute.
///
/// # Example
///
/// ```no_compile
/// use bevy_ecs::component::Component;
/// use bevy_render_macros::ExtractComponent;
///
/// #[derive(Component, Clone, ExtractComponent)]
/// #[extract_component_filter(With<Camera>)]
/// pub struct Foo {
/// pub should_foo: bool,
/// }
///
/// // Without a filter (unconditional).
/// #[derive(Component, Clone, ExtractComponent)]
/// pub struct Bar {
/// pub should_bar: bool,
/// }
/// ```
#[proc_macro_derive(ExtractComponent, attributes(extract_component_filter))]
pub fn derive_extract_component(input: TokenStream) -> TokenStream {
extract_component::derive_extract_component(input)
}
#[proc_macro_derive(
AsBindGroup,
attributes(uniform, storage_texture, texture, sampler, bind_group_data, storage)
)]
pub fn derive_as_bind_group(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
as_bind_group::derive_as_bind_group(input).unwrap_or_else(|err| err.to_compile_error().into())
}