From 4a12d16307c850990e78f0b5d44656cb1d43936b Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sun, 9 Feb 2020 21:41:51 -0800 Subject: [PATCH] add uniform field attribute --- bevy_derive/Cargo.toml | 1 + bevy_derive/src/lib.rs | 76 +++++++++++++++++-- bevy_legion/src/storage.rs | 2 +- .../render_graph_2/renderers/wgpu_renderer.rs | 1 + src/render/render_graph_2/uniform.rs | 1 + .../render_graph_2/uniforms/local_to_world.rs | 4 + .../uniforms/standard_material.rs | 2 + 7 files changed, 80 insertions(+), 7 deletions(-) diff --git a/bevy_derive/Cargo.toml b/bevy_derive/Cargo.toml index 2ef015a6c7..78313c11dd 100644 --- a/bevy_derive/Cargo.toml +++ b/bevy_derive/Cargo.toml @@ -13,5 +13,6 @@ proc-macro = true syn = "1.0" quote = "1.0" Inflector = { version = "0.11.4", default-features = false } +darling = "0.10.2" [dev-dependencies] \ No newline at end of file diff --git a/bevy_derive/src/lib.rs b/bevy_derive/src/lib.rs index 645d2727f7..fc212c5e98 100644 --- a/bevy_derive/src/lib.rs +++ b/bevy_derive/src/lib.rs @@ -1,9 +1,10 @@ extern crate proc_macro; +use darling::FromMeta; use inflector::Inflector; use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields}; +use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields}; #[proc_macro_derive(EntityArchetype)] pub fn derive_entity_archetype(input: TokenStream) -> TokenStream { @@ -29,10 +30,19 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream { } }) } +#[derive(FromMeta, Debug, Default)] +struct UniformAttributeArgs { + #[darling(default)] + pub ignore: Option, + #[darling(default)] + pub shader_def: Option, +} -#[proc_macro_derive(Uniforms)] +#[proc_macro_derive(Uniforms, attributes(uniform))] pub fn derive_uniforms(input: TokenStream) -> TokenStream { + const UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform"; let ast = parse_macro_input!(input as DeriveInput); + let fields = match &ast.data { Data::Struct(DataStruct { fields: Fields::Named(fields), @@ -41,19 +51,67 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream { _ => panic!("expected a struct with named fields"), }; + let uniform_fields = fields + .iter() + .map(|f| { + ( + f, + f.attrs + .iter() + .find(|a| { + a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME + }) + .map(|a| { + UniformAttributeArgs::from_meta(&a.parse_meta().unwrap()) + .unwrap_or_else(|_err| UniformAttributeArgs::default()) + }), + ) + }) + .collect::)>>(); + + let active_uniform_fields = uniform_fields + .iter() + .filter(|(_field, attrs)| { + attrs.is_none() + || match attrs.as_ref().unwrap().ignore { + Some(ignore) => !ignore, + None => true, + } + }) + .map(|(f, _attr)| *f) + .collect::>(); + + let shader_defs = uniform_fields + .iter() + .filter(|(_f, attrs)| match attrs { + Some(attrs) => attrs.shader_def.is_some(), + None => false, + }) + .map(|(f, attrs)| { + // attrs is guaranteed to be set because we checked in filter + let shader_def = attrs.as_ref().unwrap().shader_def.as_ref().unwrap(); + if shader_def.len() == 0 { + f.ident.as_ref().unwrap().to_string() + } else { + shader_def.to_string() + } + }) + .collect::>(); + let struct_name = &ast.ident; let struct_name_screaming_snake = struct_name.to_string().to_screaming_snake_case(); let info_ident = format_ident!("{}_UNIFORM_INFO", struct_name_screaming_snake); let layout_ident = format_ident!("{}_UNIFORM_LAYOUTS", struct_name_screaming_snake); - let layout_arrays = (0..fields.len()).map(|_| quote!(&[])); - let uniform_name_uniform_info = fields + let layout_arrays = (0..active_uniform_fields.len()).map(|_| quote!(&[])); + let uniform_name_uniform_info = active_uniform_fields .iter() .map(|field| format!("{}_{}", struct_name, field.ident.as_ref().unwrap())) .collect::>(); - let get_uniform_bytes_field_name = fields.iter().map(|field| &field.ident); + let get_uniform_bytes_field_name = active_uniform_fields.iter().map(|field| &field.ident); let get_uniform_bytes_uniform_name = uniform_name_uniform_info.clone(); let get_uniform_info_uniform_name = uniform_name_uniform_info.clone(); - let get_uniform_info_array_refs = (0..fields.len()).map(|i| quote!(&#info_ident[#i])); + let get_uniform_info_array_refs = + (0..active_uniform_fields.len()).map(|i| quote!(&#info_ident[#i])); TokenStream::from(quote! { const #info_ident: &[UniformInfo] = &[ @@ -92,6 +150,12 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream { _ => None, } } + + fn get_shader_defs(&self) -> Vec<&'static str> { + vec![ + #(#shader_defs,)* + ] + } } }) } diff --git a/bevy_legion/src/storage.rs b/bevy_legion/src/storage.rs index 03302042cb..ec98570425 100644 --- a/bevy_legion/src/storage.rs +++ b/bevy_legion/src/storage.rs @@ -1377,7 +1377,7 @@ pub struct ComponentResourceSet { impl ComponentResourceSet { /// Gets the version of the component slice. - pub fn version(&self) -> u64 { unsafe { (*self.version.get()) } } + pub fn version(&self) -> u64 { unsafe { *self.version.get() } } /// Gets a raw pointer to the start of the component slice. /// diff --git a/src/render/render_graph_2/renderers/wgpu_renderer.rs b/src/render/render_graph_2/renderers/wgpu_renderer.rs index 4d43b07576..230163745e 100644 --- a/src/render/render_graph_2/renderers/wgpu_renderer.rs +++ b/src/render/render_graph_2/renderers/wgpu_renderer.rs @@ -305,6 +305,7 @@ impl WgpuRenderer { } // TODO: remove me + #[allow(dead_code)] fn setup_dynamic_entity_shader_uniforms( &mut self, world: &World, diff --git a/src/render/render_graph_2/uniform.rs b/src/render/render_graph_2/uniform.rs index 8913de32bc..ba530bdd10 100644 --- a/src/render/render_graph_2/uniform.rs +++ b/src/render/render_graph_2/uniform.rs @@ -41,6 +41,7 @@ pub trait AsUniforms { fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>; fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]]; fn get_uniform_bytes(&self, name: &str) -> Option>; + fn get_shader_defs(&self) -> Vec<&'static str>; // TODO: support zero-copy uniforms // fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>; } diff --git a/src/render/render_graph_2/uniforms/local_to_world.rs b/src/render/render_graph_2/uniforms/local_to_world.rs index 1afde9e208..500681d5b0 100644 --- a/src/render/render_graph_2/uniforms/local_to_world.rs +++ b/src/render/render_graph_2/uniforms/local_to_world.rs @@ -40,4 +40,8 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld { _ => None, } } + + fn get_shader_defs(&self) -> std::vec::Vec<&'static str> { + Vec::new() + } } \ No newline at end of file diff --git a/src/render/render_graph_2/uniforms/standard_material.rs b/src/render/render_graph_2/uniforms/standard_material.rs index 106d23de91..23d911fa14 100644 --- a/src/render/render_graph_2/uniforms/standard_material.rs +++ b/src/render/render_graph_2/uniforms/standard_material.rs @@ -11,4 +11,6 @@ use bevy_derive::Uniforms; #[derive(Uniforms)] pub struct StandardMaterial { pub albedo: Vec4, + // #[uniform(ignore,shader_def="Hi")] + // pub enable_thing: bool, } \ No newline at end of file