use crate::error::ShaderReflectError; use crate::reflect::semantics::{ SemanticMap, TextureImage, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics, }; use rustc_hash::FxHashMap; use std::str::FromStr; pub mod cross; pub mod semantics; #[cfg(feature = "unstable-rust-pipeline")] mod naga; #[cfg(feature = "unstable-rust-pipeline")] mod rspirv; pub trait ReflectShader { fn reflect( &mut self, pass_number: usize, semantics: &ReflectSemantics, ) -> Result; } pub trait TextureSemanticMap { fn get_texture_semantic(&self, name: &str) -> Option>; } pub trait VariableSemanticMap { fn get_variable_semantic(&self, name: &str) -> Option>; } impl VariableSemanticMap for FxHashMap { fn get_variable_semantic(&self, name: &str) -> Option> { match self.get(name) { // existing uniforms in the semantic map have priority None => match name { "MVP" => Some(SemanticMap { semantics: VariableSemantics::MVP, index: (), }), "OutputSize" => Some(SemanticMap { semantics: VariableSemantics::Output, index: (), }), "FinalViewportSize" => Some(SemanticMap { semantics: VariableSemantics::FinalViewport, index: (), }), "FrameCount" => Some(SemanticMap { semantics: VariableSemantics::FrameCount, index: (), }), "FrameDirection" => Some(SemanticMap { semantics: VariableSemantics::FrameDirection, index: (), }), _ => None, }, Some(UniformSemantic::Variable(variable)) => Some(*variable), Some(UniformSemantic::Texture(_)) => None, } } } impl TextureSemanticMap for FxHashMap { fn get_texture_semantic(&self, name: &str) -> Option> { match self.get(name) { None => { if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS .iter() .find(|f| name.starts_with(f.size_uniform_name())) { if semantics.is_array() { let index = &name[semantics.size_uniform_name().len()..]; let Ok(index) = usize::from_str(index) else { return None; }; return Some(SemanticMap { semantics: *semantics, index, }); } else if name == semantics.size_uniform_name() { return Some(SemanticMap { semantics: *semantics, index: 0, }); } } None } Some(UniformSemantic::Variable(_)) => None, Some(UniformSemantic::Texture(texture)) => Some(*texture), } } } impl TextureSemanticMap for FxHashMap> { fn get_texture_semantic(&self, name: &str) -> Option> { match self.get(name) { None => { if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS .iter() .find(|f| name.starts_with(f.texture_name())) { if semantics.is_array() { let index = &name[semantics.texture_name().len()..]; let Ok(index) = usize::from_str(index) else {return None}; return Some(SemanticMap { semantics: *semantics, index, }); } else if name == semantics.texture_name() { return Some(SemanticMap { semantics: *semantics, index: 0, }); } } None } Some(texture) => Some(*texture), } } } #[derive(Debug, Clone)] pub enum UniformSemantic { Variable(SemanticMap), Texture(SemanticMap), } #[derive(Debug, Clone)] pub struct ReflectSemantics { pub uniform_semantics: FxHashMap, pub non_uniform_semantics: FxHashMap>, } #[derive(Debug, Default)] pub struct ReflectMeta { pub parameter_meta: FxHashMap, pub variable_meta: FxHashMap, pub texture_meta: FxHashMap, TextureImage>, pub texture_size_meta: FxHashMap, TextureSizeMeta>, } pub use semantics::ShaderReflection;