[shaders] Don't apply force_rw_storage to fine The force_rw_storage feature is a hack that enables a renderer to bind suballocations from the same buffer object to both readonly and read-write bindings inside a pipeline layout. The AA variants of the fine stage don't compile with this feature enabled, since the read-write PTCL buffer results in a uniformity analysis failure. Address this by excluding the `fine` stage from the force_rw_storage feature to preserve the shader's correctness. Since all storage bindings in `fine` are readonly, there is no restriction against binding suballocations to any of the fine pipeline variants in the first place.
diff --git a/crates/shaders/Cargo.toml b/crates/shaders/Cargo.toml index e6f8c73..5cf538e 100644 --- a/crates/shaders/Cargo.toml +++ b/crates/shaders/Cargo.toml
@@ -13,7 +13,11 @@ # to have the `read_write` access mode. For WGSL shaders, this affects the bind group # layout of all pipelines and changes the usage scope of storage buffers. For MSL shaders, # this removes the `const` qualifier from entry-point parameters in the `device` address -# space. +# space. This allows bindings with mixed access modes to be backed by suballocations from +# the same the buffer object. +# +# This feature doesn't apply to the fine stage where all storage bindings are readonly and +# the same access mode restrictions do not apply. # # Enabling this feature may have a performance impact and is not recommended. force_rw_storage = []
diff --git a/crates/shaders/src/compile/mod.rs b/crates/shaders/src/compile/mod.rs index fca4a50..a756884 100644 --- a/crates/shaders/src/compile/mod.rs +++ b/crates/shaders/src/compile/mod.rs
@@ -162,18 +162,25 @@ if let Some(name) = file_name.to_str() { let suffix = ".wgsl"; if let Some(shader_name) = name.strip_suffix(suffix) { + let mut options = preprocess::Options::default(); + if cfg!(feature = "force_rw_storage") { + // All bindings in the `fine` stage are readonly which means that a usage + // scope warning can never occur. Plus, the bindings must be declared as + // readonly to prevent a failed compilation due to uniformity analysis. + options.force_rw_storage = !name.starts_with("fine"); + } let contents = fs::read_to_string(shader_dir.join(&file_name)) .expect("Could read shader {shader_name} contents"); if let Some(permutations) = permutation_map.get(shader_name) { for permutation in permutations { let mut defines = defines.clone(); defines.extend(permutation.defines.iter().cloned()); - let source = preprocess::preprocess(&contents, &defines, &imports); + let source = preprocess::preprocess(&contents, &options, &defines, &imports); let shader_info = Self::new(source.clone(), "main").unwrap(); info.insert(permutation.name.clone(), shader_info); } } else { - let source = preprocess::preprocess(&contents, &defines, &imports); + let source = preprocess::preprocess(&contents, &options, &defines, &imports); let shader_info = Self::new(source.clone(), "main").unwrap(); info.insert(shader_name.to_string(), shader_info); }
diff --git a/crates/shaders/src/compile/preprocess.rs b/crates/shaders/src/compile/preprocess.rs index b3c6003..4ff6664 100644 --- a/crates/shaders/src/compile/preprocess.rs +++ b/crates/shaders/src/compile/preprocess.rs
@@ -37,8 +37,14 @@ else_passed: bool, } +#[derive(Default)] +pub struct Options { + pub force_rw_storage: bool, +} + pub fn preprocess( input: &str, + options: &Options, defines: &HashSet<String>, imports: &HashMap<String, String>, ) -> String { @@ -147,7 +153,7 @@ // However, in practise there will only ever be at most 2 stack items, so // it's reasonable to just recompute it every time if stack.iter().all(|item| item.active) { - output.push_str(&preprocess(import, defines, imports)); + output.push_str(&preprocess(import, options, defines, imports)); } } else { eprintln!("Unknown import `{import_name}` (line {line_number})"); @@ -167,7 +173,7 @@ output.push_str("const"); output.push_str(&line[3..]); } else if let Some(idx) = line.find("var<storage>") { - if cfg!(feature = "force_rw_storage") { + if options.force_rw_storage { let mut line = line.to_string(); line.replace_range(idx..(idx + 12), "var<storage, read_write>"); output.push_str(&line);