Fix AsBindGroup derive, texture attribute, visibility flag parsing (#8868)
# Objective - Fix the AsBindGroup texture attribute visibility flag parsing - This appears to have been caused by a syn crate update which then the visibility code got updated - Also I noticed that by default the vertex and fragment flags were on, so visibility(compute) would actually make the texture visible to vertex, fragment and compute shaders, I fixed this too ## Solution - Update flag parsing to use MetaList.parse_nested_meta function, which loads the flags into a Vec then loop through those flags - Change initial visibility flags to use VisibilityFlags::default() rather than VisibilityFlags::vertex_fragment()
This commit is contained in:
		
							parent
							
								
									c39e02cefb
								
							
						
					
					
						commit
						ee1368a032
					
				@ -6,7 +6,7 @@ use syn::{
 | 
			
		||||
    parse::{Parse, ParseStream},
 | 
			
		||||
    punctuated::Punctuated,
 | 
			
		||||
    token::Comma,
 | 
			
		||||
    Data, DataStruct, Error, Fields, LitInt, LitStr, Meta, Result,
 | 
			
		||||
    Data, DataStruct, Error, Fields, LitInt, LitStr, Meta, MetaList, Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const UNIFORM_ATTRIBUTE_NAME: Symbol = Symbol("uniform");
 | 
			
		||||
@ -636,39 +636,46 @@ const VISIBILITY_COMPUTE: Symbol = Symbol("compute");
 | 
			
		||||
const VISIBILITY_ALL: Symbol = Symbol("all");
 | 
			
		||||
const VISIBILITY_NONE: Symbol = Symbol("none");
 | 
			
		||||
 | 
			
		||||
fn get_visibility_flag_value(meta: Meta) -> Result<ShaderStageVisibility> {
 | 
			
		||||
    let mut visibility = VisibilityFlags::vertex_fragment();
 | 
			
		||||
fn get_visibility_flag_value(meta_list: &MetaList) -> Result<ShaderStageVisibility> {
 | 
			
		||||
    let mut flags = Vec::new();
 | 
			
		||||
 | 
			
		||||
    use syn::Meta::Path;
 | 
			
		||||
    match meta {
 | 
			
		||||
        // Parse `#[visibility(all)]`.
 | 
			
		||||
        Path(path) if path == VISIBILITY_ALL => {
 | 
			
		||||
            return Ok(ShaderStageVisibility::All)
 | 
			
		||||
    meta_list.parse_nested_meta(|meta| {
 | 
			
		||||
        flags.push(meta.path);
 | 
			
		||||
        Ok(())
 | 
			
		||||
    })?;
 | 
			
		||||
 | 
			
		||||
    if flags.is_empty() {
 | 
			
		||||
        return Err(Error::new_spanned(
 | 
			
		||||
            meta_list,
 | 
			
		||||
            "Invalid visibility format. Must be `visibility(flags)`, flags can be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if flags.len() == 1 {
 | 
			
		||||
        if let Some(flag) = flags.get(0) {
 | 
			
		||||
            if flag == VISIBILITY_ALL {
 | 
			
		||||
                return Ok(ShaderStageVisibility::All);
 | 
			
		||||
            } else if flag == VISIBILITY_NONE {
 | 
			
		||||
                return Ok(ShaderStageVisibility::None);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Parse `#[visibility(none)]`.
 | 
			
		||||
        Path(path) if path == VISIBILITY_NONE => {
 | 
			
		||||
            return Ok(ShaderStageVisibility::None)
 | 
			
		||||
        }
 | 
			
		||||
        // Parse `#[visibility(vertex, ...)]`.
 | 
			
		||||
        Path(path) if path == VISIBILITY_VERTEX => {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut visibility = VisibilityFlags::default();
 | 
			
		||||
 | 
			
		||||
    for flag in flags {
 | 
			
		||||
        if flag == VISIBILITY_VERTEX {
 | 
			
		||||
            visibility.vertex = true;
 | 
			
		||||
        }
 | 
			
		||||
        // Parse `#[visibility(fragment, ...)]`.
 | 
			
		||||
        Path(path) if path == VISIBILITY_FRAGMENT => {
 | 
			
		||||
        } else if flag == VISIBILITY_FRAGMENT {
 | 
			
		||||
            visibility.fragment = true;
 | 
			
		||||
        }
 | 
			
		||||
        // Parse `#[visibility(compute, ...)]`.
 | 
			
		||||
        Path(path) if path == VISIBILITY_COMPUTE => {
 | 
			
		||||
        } else if flag == VISIBILITY_COMPUTE {
 | 
			
		||||
            visibility.compute = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            return Err(Error::new_spanned(
 | 
			
		||||
                flag,
 | 
			
		||||
                "Not a valid visibility flag. Must be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        Path(path) => return Err(Error::new_spanned(
 | 
			
		||||
            path,
 | 
			
		||||
            "Not a valid visibility flag. Must be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
 | 
			
		||||
        )),
 | 
			
		||||
        _ => return Err(Error::new_spanned(
 | 
			
		||||
            meta,
 | 
			
		||||
            "Invalid visibility format: `visibility(...)`.",
 | 
			
		||||
        )),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(ShaderStageVisibility::Flags(visibility))
 | 
			
		||||
@ -794,7 +801,7 @@ fn get_texture_attrs(metas: Vec<Meta>) -> Result<TextureAttrs> {
 | 
			
		||||
            }
 | 
			
		||||
            // Parse #[texture(0, visibility(...))].
 | 
			
		||||
            List(m) if m.path == VISIBILITY => {
 | 
			
		||||
                visibility = get_visibility_flag_value(Meta::Path(m.path))?;
 | 
			
		||||
                visibility = get_visibility_flag_value(&m)?;
 | 
			
		||||
            }
 | 
			
		||||
            NameValue(m) => {
 | 
			
		||||
                return Err(Error::new_spanned(
 | 
			
		||||
@ -910,7 +917,7 @@ fn get_sampler_attrs(metas: Vec<Meta>) -> Result<SamplerAttrs> {
 | 
			
		||||
            }
 | 
			
		||||
            // Parse #[sampler(0, visibility(...))].
 | 
			
		||||
            List(m) if m.path == VISIBILITY => {
 | 
			
		||||
                visibility = get_visibility_flag_value(Meta::Path(m.path))?;
 | 
			
		||||
                visibility = get_visibility_flag_value(&m)?;
 | 
			
		||||
            }
 | 
			
		||||
            NameValue(m) => {
 | 
			
		||||
                return Err(Error::new_spanned(
 | 
			
		||||
@ -966,7 +973,7 @@ fn get_storage_binding_attr(metas: Vec<Meta>) -> Result<StorageAttrs> {
 | 
			
		||||
        match meta {
 | 
			
		||||
            // Parse #[storage(0, visibility(...))].
 | 
			
		||||
            List(m) if m.path == VISIBILITY => {
 | 
			
		||||
                visibility = get_visibility_flag_value(Meta::Path(m.path))?;
 | 
			
		||||
                visibility = get_visibility_flag_value(&m)?;
 | 
			
		||||
            }
 | 
			
		||||
            Path(path) if path == READ_ONLY => {
 | 
			
		||||
                read_only = true;
 | 
			
		||||
 | 
			
		||||
@ -334,3 +334,35 @@ where
 | 
			
		||||
        self.into()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use crate as bevy_render;
 | 
			
		||||
    use bevy_asset::Handle;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn texture_visibility() {
 | 
			
		||||
        #[derive(AsBindGroup)]
 | 
			
		||||
        pub struct TextureVisibilityTest {
 | 
			
		||||
            #[texture(0, visibility(all))]
 | 
			
		||||
            pub all: Handle<Image>,
 | 
			
		||||
            #[texture(1, visibility(none))]
 | 
			
		||||
            pub none: Handle<Image>,
 | 
			
		||||
            #[texture(2, visibility(fragment))]
 | 
			
		||||
            pub fragment: Handle<Image>,
 | 
			
		||||
            #[texture(3, visibility(vertex))]
 | 
			
		||||
            pub vertex: Handle<Image>,
 | 
			
		||||
            #[texture(4, visibility(compute))]
 | 
			
		||||
            pub compute: Handle<Image>,
 | 
			
		||||
            #[texture(5, visibility(vertex, fragment))]
 | 
			
		||||
            pub vertex_fragment: Handle<Image>,
 | 
			
		||||
            #[texture(6, visibility(vertex, compute))]
 | 
			
		||||
            pub vertex_compute: Handle<Image>,
 | 
			
		||||
            #[texture(7, visibility(fragment, compute))]
 | 
			
		||||
            pub fragment_compute: Handle<Image>,
 | 
			
		||||
            #[texture(8, visibility(vertex, fragment, compute))]
 | 
			
		||||
            pub vertex_fragment_compute: Handle<Image>,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user