librashader_reflect/reflect/
presets.rs1use crate::back::targets::OutputTarget;
2use crate::back::{CompilerBackend, FromCompilation};
3use crate::error::{ShaderCompileError, ShaderReflectError};
4use crate::front::{ShaderInputCompiler, ShaderReflectObject};
5use crate::reflect::semantics::{
6 Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics,
7};
8use librashader_common::map::{FastHashMap, ShortString};
9use librashader_pack::PassResource;
10use librashader_preprocess::{PreprocessError, ShaderSource};
11use librashader_presets::{ShaderPreset, TextureMeta};
12
13pub type ShaderPassArtifact<T> = (PassResource, CompilerBackend<T>);
32
33impl<T: OutputTarget> CompilePresetTarget for T {}
34
35pub trait CompilePresetTarget: OutputTarget {
38 fn compile_preset_passes<'a, I, R, E>(
41 passes: impl IntoIterator<Item = PassResource>,
42 textures: impl Iterator<Item = &'a TextureMeta>,
43 ) -> Result<
44 (
45 Vec<ShaderPassArtifact<<Self as FromCompilation<I, R>>::Output>>,
46 ShaderSemantics,
47 ),
48 E,
49 >
50 where
51 I: ShaderReflectObject,
52 Self: Sized,
53 Self: FromCompilation<I, R>,
54 I::Compiler: ShaderInputCompiler<I>,
55 E: From<PreprocessError>,
56 E: From<ShaderReflectError>,
57 E: From<ShaderCompileError>,
58 {
59 compile_preset_passes::<Self, I, R, E>(passes, textures)
60 }
61}
62
63fn compile_preset_passes<'a, T, I, R, E>(
66 passes: impl IntoIterator<Item = PassResource>,
67 textures: impl Iterator<Item = &'a TextureMeta>,
68) -> Result<
69 (
70 Vec<ShaderPassArtifact<<T as FromCompilation<I, R>>::Output>>,
71 ShaderSemantics,
72 ),
73 E,
74>
75where
76 I: ShaderReflectObject,
77 T: OutputTarget,
78 T: FromCompilation<I, R>,
79 I::Compiler: ShaderInputCompiler<I>,
80 E: From<PreprocessError>,
81 E: From<ShaderReflectError>,
82 E: From<ShaderCompileError>,
83{
84 let mut uniform_semantics: FastHashMap<ShortString, UniformSemantic> = Default::default();
85 let mut texture_semantics: FastHashMap<ShortString, Semantic<TextureSemantics>> =
86 Default::default();
87
88 let artifacts = passes
89 .into_iter()
90 .map(|shader| {
91 let source = &shader.data;
92 let compiled = I::Compiler::compile(source)?;
93 let reflect = T::from_compilation(compiled)?;
94
95 for parameter in source.parameters.values() {
96 uniform_semantics.insert(
97 parameter.id.clone(),
98 UniformSemantic::Unique(Semantic {
99 semantics: UniqueSemantics::FloatParameter,
100 index: (),
101 }),
102 );
103 }
104 Ok::<_, E>((shader, reflect))
105 })
106 .collect::<Result<Vec<(PassResource, CompilerBackend<_>)>, E>>()?;
107
108 for (pass, _) in artifacts.iter() {
109 insert_pass_semantics(
110 &mut uniform_semantics,
111 &mut texture_semantics,
112 pass.meta.alias.as_ref(),
113 pass.meta.id as usize,
114 );
115 insert_pass_semantics(
116 &mut uniform_semantics,
117 &mut texture_semantics,
118 pass.data.name.as_ref(),
119 pass.meta.id as usize,
120 );
121 }
122
123 insert_lut_semantics(textures, &mut uniform_semantics, &mut texture_semantics);
124
125 let semantics = ShaderSemantics {
126 uniform_semantics,
127 texture_semantics,
128 };
129
130 Ok((artifacts, semantics))
131}
132
133fn insert_pass_semantics(
135 uniform_semantics: &mut FastHashMap<ShortString, UniformSemantic>,
136 texture_semantics: &mut FastHashMap<ShortString, Semantic<TextureSemantics>>,
137 alias: Option<&ShortString>,
138 index: usize,
139) {
140 let Some(alias) = alias else {
141 return;
142 };
143
144 if alias.trim().is_empty() {
146 return;
147 }
148
149 texture_semantics.insert(
151 alias.clone(),
152 Semantic {
153 semantics: TextureSemantics::PassOutput,
154 index,
155 },
156 );
157
158 let mut alias_size = alias.clone();
159 alias_size.push_str("Size");
160 uniform_semantics.insert(
161 alias_size,
162 UniformSemantic::Texture(Semantic {
163 semantics: TextureSemantics::PassOutput,
164 index,
165 }),
166 );
167
168 let mut alias_feedback = alias.clone();
169 alias_feedback.push_str("Feedback");
170 texture_semantics.insert(
172 alias_feedback,
173 Semantic {
174 semantics: TextureSemantics::PassFeedback,
175 index,
176 },
177 );
178
179 let mut alias_feedback_size = alias.clone();
180 alias_feedback_size.push_str("FeedbackSize");
181 uniform_semantics.insert(
182 alias_feedback_size,
183 UniformSemantic::Texture(Semantic {
184 semantics: TextureSemantics::PassFeedback,
185 index,
186 }),
187 );
188}
189
190fn insert_lut_semantics<'a>(
192 textures: impl Iterator<Item = &'a TextureMeta>,
193 uniform_semantics: &mut FastHashMap<ShortString, UniformSemantic>,
194 texture_semantics: &mut FastHashMap<ShortString, Semantic<TextureSemantics>>,
195) {
196 for (index, texture) in textures.enumerate() {
197 let mut size_semantic = texture.name.clone();
198 size_semantic.push_str("Size");
199
200 texture_semantics.insert(
201 texture.name.clone(),
202 Semantic {
203 semantics: TextureSemantics::User,
204 index,
205 },
206 );
207
208 uniform_semantics.insert(
209 size_semantic,
210 UniformSemantic::Texture(Semantic {
211 semantics: TextureSemantics::User,
212 index,
213 }),
214 );
215 }
216}
217
218impl ShaderSemantics {
219 pub fn create_pass_semantics<E>(
223 preset: &ShaderPreset,
224 index: usize,
225 ) -> Result<ShaderSemantics, E>
226 where
227 E: From<ShaderReflectError>,
228 E: From<PreprocessError>,
229 {
230 let mut uniform_semantics: FastHashMap<ShortString, UniformSemantic> = Default::default();
231 let mut texture_semantics: FastHashMap<ShortString, Semantic<TextureSemantics>> =
232 Default::default();
233
234 let config = preset
235 .passes
236 .get(index)
237 .ok_or_else(|| PreprocessError::InvalidStage)?;
238
239 let source = ShaderSource::load(&config.path, preset.features)?;
240
241 for parameter in source.parameters.values() {
242 uniform_semantics.insert(
243 parameter.id.clone(),
244 UniformSemantic::Unique(Semantic {
245 semantics: UniqueSemantics::FloatParameter,
246 index: (),
247 }),
248 );
249 }
250
251 insert_pass_semantics(
252 &mut uniform_semantics,
253 &mut texture_semantics,
254 config.meta.alias.as_ref(),
255 config.meta.id as usize,
256 );
257 insert_pass_semantics(
258 &mut uniform_semantics,
259 &mut texture_semantics,
260 source.name.as_ref(),
261 config.meta.id as usize,
262 );
263 insert_lut_semantics(
264 preset.textures.iter().map(|t| &t.meta),
265 &mut uniform_semantics,
266 &mut texture_semantics,
267 );
268
269 Ok(ShaderSemantics {
270 uniform_semantics,
271 texture_semantics,
272 })
273 }
274}