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},
|
parse::{Parse, ParseStream},
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
token::Comma,
|
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");
|
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_ALL: Symbol = Symbol("all");
|
||||||
const VISIBILITY_NONE: Symbol = Symbol("none");
|
const VISIBILITY_NONE: Symbol = Symbol("none");
|
||||||
|
|
||||||
fn get_visibility_flag_value(meta: Meta) -> Result<ShaderStageVisibility> {
|
fn get_visibility_flag_value(meta_list: &MetaList) -> Result<ShaderStageVisibility> {
|
||||||
let mut visibility = VisibilityFlags::vertex_fragment();
|
let mut flags = Vec::new();
|
||||||
|
|
||||||
use syn::Meta::Path;
|
meta_list.parse_nested_meta(|meta| {
|
||||||
match meta {
|
flags.push(meta.path);
|
||||||
// Parse `#[visibility(all)]`.
|
Ok(())
|
||||||
Path(path) if path == VISIBILITY_ALL => {
|
})?;
|
||||||
return Ok(ShaderStageVisibility::All)
|
|
||||||
|
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`."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
// Parse `#[visibility(none)]`.
|
|
||||||
Path(path) if path == VISIBILITY_NONE => {
|
if flags.len() == 1 {
|
||||||
return Ok(ShaderStageVisibility::None)
|
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(vertex, ...)]`.
|
}
|
||||||
Path(path) if path == VISIBILITY_VERTEX => {
|
}
|
||||||
|
|
||||||
|
let mut visibility = VisibilityFlags::default();
|
||||||
|
|
||||||
|
for flag in flags {
|
||||||
|
if flag == VISIBILITY_VERTEX {
|
||||||
visibility.vertex = true;
|
visibility.vertex = true;
|
||||||
}
|
} else if flag == VISIBILITY_FRAGMENT {
|
||||||
// Parse `#[visibility(fragment, ...)]`.
|
|
||||||
Path(path) if path == VISIBILITY_FRAGMENT => {
|
|
||||||
visibility.fragment = true;
|
visibility.fragment = true;
|
||||||
}
|
} else if flag == VISIBILITY_COMPUTE {
|
||||||
// Parse `#[visibility(compute, ...)]`.
|
|
||||||
Path(path) if path == VISIBILITY_COMPUTE => {
|
|
||||||
visibility.compute = true;
|
visibility.compute = true;
|
||||||
}
|
} else {
|
||||||
Path(path) => return Err(Error::new_spanned(
|
return Err(Error::new_spanned(
|
||||||
path,
|
flag,
|
||||||
"Not a valid visibility flag. Must be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
|
"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))
|
Ok(ShaderStageVisibility::Flags(visibility))
|
||||||
@ -794,7 +801,7 @@ fn get_texture_attrs(metas: Vec<Meta>) -> Result<TextureAttrs> {
|
|||||||
}
|
}
|
||||||
// Parse #[texture(0, visibility(...))].
|
// Parse #[texture(0, visibility(...))].
|
||||||
List(m) if m.path == VISIBILITY => {
|
List(m) if m.path == VISIBILITY => {
|
||||||
visibility = get_visibility_flag_value(Meta::Path(m.path))?;
|
visibility = get_visibility_flag_value(&m)?;
|
||||||
}
|
}
|
||||||
NameValue(m) => {
|
NameValue(m) => {
|
||||||
return Err(Error::new_spanned(
|
return Err(Error::new_spanned(
|
||||||
@ -910,7 +917,7 @@ fn get_sampler_attrs(metas: Vec<Meta>) -> Result<SamplerAttrs> {
|
|||||||
}
|
}
|
||||||
// Parse #[sampler(0, visibility(...))].
|
// Parse #[sampler(0, visibility(...))].
|
||||||
List(m) if m.path == VISIBILITY => {
|
List(m) if m.path == VISIBILITY => {
|
||||||
visibility = get_visibility_flag_value(Meta::Path(m.path))?;
|
visibility = get_visibility_flag_value(&m)?;
|
||||||
}
|
}
|
||||||
NameValue(m) => {
|
NameValue(m) => {
|
||||||
return Err(Error::new_spanned(
|
return Err(Error::new_spanned(
|
||||||
@ -966,7 +973,7 @@ fn get_storage_binding_attr(metas: Vec<Meta>) -> Result<StorageAttrs> {
|
|||||||
match meta {
|
match meta {
|
||||||
// Parse #[storage(0, visibility(...))].
|
// Parse #[storage(0, visibility(...))].
|
||||||
List(m) if m.path == 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 => {
|
Path(path) if path == READ_ONLY => {
|
||||||
read_only = true;
|
read_only = true;
|
||||||
|
|||||||
@ -334,3 +334,35 @@ where
|
|||||||
self.into()
|
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