add uniform field attribute
This commit is contained in:
		
							parent
							
								
									c1bac8869e
								
							
						
					
					
						commit
						4a12d16307
					
				| @ -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] | ||||
| @ -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<bool>, | ||||
|     #[darling(default)] | ||||
|     pub shader_def: Option<String>, | ||||
| } | ||||
| 
 | ||||
| #[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::<Vec<(&Field, Option<UniformAttributeArgs>)>>(); | ||||
| 
 | ||||
|     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::<Vec<&Field>>(); | ||||
| 
 | ||||
|     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::<Vec<String>>(); | ||||
| 
 | ||||
|     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::<Vec<String>>(); | ||||
|     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,)* | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     }) | ||||
| } | ||||
|  | ||||
| @ -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.
 | ||||
|     ///
 | ||||
|  | ||||
| @ -305,6 +305,7 @@ impl WgpuRenderer { | ||||
|     } | ||||
| 
 | ||||
|     // TODO: remove me
 | ||||
|     #[allow(dead_code)] | ||||
|     fn setup_dynamic_entity_shader_uniforms( | ||||
|         &mut self, | ||||
|         world: &World, | ||||
|  | ||||
| @ -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<Vec<u8>>; | ||||
|     fn get_shader_defs(&self) -> Vec<&'static str>; | ||||
|     // TODO: support zero-copy uniforms
 | ||||
|     // fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
 | ||||
| } | ||||
|  | ||||
| @ -40,4 +40,8 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld { | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_shader_defs(&self) -> std::vec::Vec<&'static str> { | ||||
|         Vec::new() | ||||
|     } | ||||
| } | ||||
| @ -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,
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson