1use {
2 std::{
3 fmt::Write,
4 fmt,
5 collections::{BTreeMap, BTreeSet}
6 },
7 crate::{
8 makepad_live_compiler::*,
9 makepad_live_id::*,
10 shader_ast::*,
11 generate::*,
12 shader_registry::ShaderRegistry,
13 }
14};
15
16pub struct MetalGeneratedShader{
17 pub mtlsl: String,
18 pub fields_as_uniform_blocks:BTreeMap<Ident, Vec<(usize, Ident) >>
19}
20
21pub fn generate_shader(draw_shader_def: &DrawShaderDef, const_table:&DrawShaderConstTable, shader_registry: &ShaderRegistry) -> MetalGeneratedShader {
22 let mut string = String::new();
23 let fields_as_uniform_blocks = draw_shader_def.fields_as_uniform_blocks();
24 DrawShaderGenerator {
25 draw_shader_def,
26 shader_registry,
27 const_table,
28 string: &mut string,
29 fields_as_uniform_blocks: &fields_as_uniform_blocks,
30 backend_writer: &MetalBackendWriter {shader_registry, draw_shader_def, const_table}
31 }
32 .generate_shader();
33 MetalGeneratedShader{
34 mtlsl:string,
35 fields_as_uniform_blocks
36 }
37}
38
39struct DrawShaderGenerator<'a> {
40 draw_shader_def: &'a DrawShaderDef,
41 shader_registry: &'a ShaderRegistry,
42 string: &'a mut String,
43 fields_as_uniform_blocks: &'a BTreeMap<Ident, Vec<(usize, Ident) >>,
44 backend_writer: &'a dyn BackendWriter,
45 const_table: &'a DrawShaderConstTable
46}
47
48impl<'a> DrawShaderGenerator<'a> {
49 fn generate_shader(&mut self) {
50 writeln!(self.string, "#include <metal_stdlib>").unwrap();
51 writeln!(self.string, "using namespace metal;").unwrap();
52
53 let mut all_constructor_fns = BTreeSet::new();
54
55 for fn_iter in self.draw_shader_def.all_fns.borrow().iter() {
56 let fn_def = self.shader_registry.all_fns.get(fn_iter).unwrap();
57 all_constructor_fns.extend(fn_def.constructor_fn_deps.borrow().as_ref().unwrap().iter().cloned());
58 }
59
60 for fn_iter in self.draw_shader_def.all_fns.borrow().iter() {
61 let fn_def = self.shader_registry.all_fns.get(fn_iter).unwrap();
62 if fn_def.builtin_deps.borrow().as_ref().unwrap().contains(&Ident(live_id!(sample2d))) {
63 writeln!(self.string, "float4 sample2d(texture2d<float> tex, float2 pos){{return tex.sample(sampler(mag_filter::nearest,min_filter::nearest),pos);}}").unwrap();
64 break;
65 }
66 if fn_def.builtin_deps.borrow().as_ref().unwrap().contains(&Ident(live_id!(sample2d_rt))) {
67 writeln!(self.string, "float4 sample2d_rt(texture2d<float> tex, float2 pos){{return tex.sample(sampler(mag_filter::nearest,min_filter::nearest),pos);}}").unwrap();
68 break;
69 }
70 };
71
72 self.generate_struct_defs();
73 self.generate_uniform_structs();
75 self.generate_texture_struct();
76 self.generate_geometry_struct();
77 self.generate_instance_struct();
78 self.generate_varying_struct();
79
80 for (ty_lit, ref param_tys) in all_constructor_fns{
84 generate_cons_fn(self.backend_writer, self.string, ty_lit, ¶m_tys);
85 }
86
87 let all_fns = self.draw_shader_def.all_fns.borrow();
88 for fn_iter in all_fns.iter().rev() {
89 let const_table_offset = self.const_table.offsets.get(fn_iter).cloned();
90 let fn_def = self.shader_registry.all_fns.get(fn_iter).unwrap();
91 if fn_def.has_closure_args() {
92 for call_iter in all_fns.iter().rev() {
93 let call_def = self.shader_registry.all_fns.get(call_iter).unwrap();
95 if call_def.callees.borrow().as_ref().unwrap().contains(&fn_iter) {
96 FnDefWithClosureArgsGenerator::generate_fn_def_with_all_closures(
97 &mut self.string,
98 self.shader_registry,
99 fn_def,
100 call_def,
101 self.backend_writer,
102 const_table_offset
103 );
104 }
105 }
106 continue
107 }
108 FnDefGenerator {
109 fn_def,
110 const_table_offset,
111 shader_registry: self.shader_registry,
112 backend_writer: self.backend_writer,
113 string: self.string,
114 }
115 .generate_fn_def()
116 }
117 self.generate_vertex_main();
118 self.generate_pixel_main();
119 }
120
121 fn generate_struct_defs(&mut self) {
122 for struct_ptr in self.draw_shader_def.all_structs.borrow().iter().rev() {
124 let struct_def = self.shader_registry.structs.get(struct_ptr).unwrap();
125 write!(self.string, "struct {} {{", struct_ptr).unwrap();
126 if !struct_def.fields.is_empty() {
127 writeln!(self.string).unwrap();
128 for field in &struct_def.fields {
129 write!(self.string, " ").unwrap();
130 self.write_var_decl(&DisplayStructField(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
131 writeln!(self.string, ";").unwrap();
132 }
133 }
134 writeln!(self.string, "}};").unwrap();
135 }
136 }
137
138 fn generate_uniform_structs(&mut self,) {
139 writeln!(self.string, "struct LiveUniforms {{").unwrap();
140 for (value_node_ptr, ty) in self.draw_shader_def.all_live_refs.borrow().iter() {
141 write!(self.string, " ").unwrap();
144 self.write_ty_lit(ty.maybe_ty_lit().unwrap());
145 write!(self.string, " ").unwrap();
146 write!(self.string, "{}", value_node_ptr).unwrap();
147 writeln!(self.string, ";").unwrap();
148 }
149 writeln!(self.string, "}};").unwrap();
150
151 for (ident, vec) in self.fields_as_uniform_blocks {
152 writeln!(self.string, "struct Uniforms_{} {{", ident).unwrap();
153 for (index, _item) in vec {
154 let field = &self.draw_shader_def.fields[*index];
155 write!(self.string, " ").unwrap();
156 self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
157 writeln!(self.string, ";").unwrap();
158 }
159 writeln!(self.string, "}};").unwrap();
160 }
161 }
162
163 fn generate_texture_struct(&mut self) {
164 let mut index = 0;
165 writeln!(self.string, "struct Textures {{").unwrap();
166 for field in &self.draw_shader_def.fields {
167 match field.kind {
168 DrawShaderFieldKind::Texture {..} => {
169 assert_eq!(*field.ty_expr.ty.borrow().as_ref().unwrap(), Ty::Texture2D);
170 write!(self.string, " texture2d<float> ").unwrap();
171 write!(self.string, "{}", &DisplayDsIdent(field.ident)).unwrap();
172 write!(self.string, " [[texture({})]];", index).unwrap();
173 index += 1;
174 }
175 _ => {}
176 }
177 }
178 writeln!(self.string, "}};").unwrap();
179 }
180
181 fn generate_geometry_struct(&mut self) {
182 writeln!(self.string, "struct Geometries {{").unwrap();
183 for field in &self.draw_shader_def.fields {
184 match field.kind {
185 DrawShaderFieldKind::Geometry {..} => {
186 write!(self.string, " ").unwrap();
187 self.write_var_decl_packed(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
188 writeln!(self.string, ";").unwrap();
189 }
190 _ => ()
191 }
192 }
193 writeln!(self.string, "}};").unwrap();
194 }
195
196 fn generate_instance_struct(&mut self) {
197 let mut padding = 0;
198 writeln!(self.string, "struct Instances {{").unwrap();
199 for field in &self.draw_shader_def.fields {
200 match field.kind {
201 DrawShaderFieldKind::Instance {..} => {
202 match field.ty_expr.ty.borrow().as_ref().unwrap() {
203 Ty::Float | Ty::Vec2 | Ty::Vec3 | Ty::Vec4 => {
204 write!(self.string, " ").unwrap();
205 if field.ident == Ident(LiveId(0)){
206 self.write_var_decl_packed(&DisplayPadding(padding), field.ty_expr.ty.borrow().as_ref().unwrap(),);
207 padding += 1;
208 }
209 else{
210 self.write_var_decl_packed(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
211 }
212 writeln!(self.string, ";").unwrap();
213 },
217 Ty::Mat4 => {
218 for i in 0..4 {
219 write!(self.string, " ").unwrap();
220 self.write_var_decl_packed(&DisplayDsIdent(field.ident), &Ty::Vec4);
221 writeln!(self.string, " {};", i).unwrap();
222 }
223 },
224 Ty::Mat3 => {
225 for i in 0..3 {
226 write!(self.string, " ").unwrap();
227 self.write_var_decl_packed(&DisplayDsIdent(field.ident), &Ty::Vec3);
228 writeln!(self.string, " {};", i).unwrap();
229 }
230 },
231 Ty::Mat2 => {
232 write!(self.string, " ").unwrap();
233 self.write_var_decl_packed(&DisplayDsIdent(field.ident), &Ty::Vec4);
234 writeln!(self.string, ";").unwrap();
235 },
236 Ty::Enum(v) =>{
237 write!(self.string, " ").unwrap();
238 self.write_var_decl_packed(&DisplayDsIdent(field.ident), &Ty::Enum(*v));
239 writeln!(self.string, ";").unwrap();
240 }
241 _ => panic!("unsupported type in generate_instance_struct")
242 }
243 }
244 _ => ()
254 }
255 }
256 writeln!(self.string, "}};").unwrap();
257 }
258
259 fn generate_varying_struct(&mut self) {
260 writeln!(self.string, "struct Varyings {{").unwrap();
261 writeln!(self.string, " float4 position [[position]];").unwrap();
262 for field in &self.draw_shader_def.fields {
263 match &field.kind {
264 DrawShaderFieldKind::Geometry {is_used_in_pixel_shader, ..} if is_used_in_pixel_shader.get() => {
265 write!(self.string, " ").unwrap();
266 self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
267 writeln!(self.string, ";").unwrap();
268 }
269 DrawShaderFieldKind::Instance {is_used_in_pixel_shader, ..} if is_used_in_pixel_shader.get() => {
270 match field.ty_expr.ty.borrow().as_ref().unwrap() {
271 Ty::Float | Ty::Vec2 | Ty::Vec3 | Ty::Vec4 => {
272 write!(self.string, " ").unwrap();
273 self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
274 writeln!(self.string, ";").unwrap();
275 },
276 Ty::Mat4 => {
277 for i in 0..4 {
278 write!(self.string, " ").unwrap();
279 self.write_ty_lit(TyLit::Vec4);
280 writeln!(self.string, " {}{};", &DisplayDsIdent(field.ident), i).unwrap();
281 }
282 },
283 Ty::Mat3 => {
284 for i in 0..3 {
285 write!(self.string, " ").unwrap();
286 self.write_ty_lit(TyLit::Vec3);
287 writeln!(self.string, " {}{};", &DisplayDsIdent(field.ident), i).unwrap();
288 }
289 },
290 Ty::Mat2 => {
291 write!(self.string, " ").unwrap();
292 self.write_ty_lit(TyLit::Vec4);
293 writeln!(self.string, " {};", &DisplayDsIdent(field.ident)).unwrap();
294 },
295 Ty::Enum(v) =>{
296 write!(self.string, " ").unwrap();
297 self.write_var_decl_packed(&DisplayDsIdent(field.ident), &Ty::Enum(*v));
298 writeln!(self.string, ";").unwrap();
299 }
300 _ => panic!("unsupported type in generate_varying_struct")
301 }
302 }
303 DrawShaderFieldKind::Varying {..} => {
304 write!(self.string, " ").unwrap();
305 self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
306 writeln!(self.string, ";").unwrap();
307 }
308 _ => {}
309 }
310 }
311 writeln!(self.string, "}};").unwrap();
312 }
313
314 fn generate_fn_def(&mut self, fn_def: &FnDef, const_table_offset: Option<usize>) {
315 FnDefGenerator {
316 fn_def,
317 shader_registry: self.shader_registry,
318 const_table_offset,
319 backend_writer: self.backend_writer,
320 string: self.string,
321 }
322 .generate_fn_def()
323 }
324
325 fn generate_vertex_main(&mut self) {
326
327 write!(self.string, "vertex Varyings vertex_main(").unwrap();
328 writeln!(self.string, "Textures textures").unwrap();
329 writeln!(self.string, ", const device Geometries *in_geometries [[buffer(0)]]").unwrap();
330 writeln!(self.string, ", const device Instances *in_instances [[buffer(1)]]").unwrap();
331 writeln!(self.string, ", constant LiveUniforms &live_uniforms [[buffer(2)]]").unwrap();
332 writeln!(self.string, ", constant const float *const_table [[buffer(3)]]").unwrap();
333 let mut buffer_id = 4;
334 for (field, _set) in self.fields_as_uniform_blocks {
335 writeln!(self.string, ", constant Uniforms_{0} &uniforms_{0} [[buffer({1})]]", field, buffer_id).unwrap();
336 buffer_id += 1;
337 }
338 writeln!(self.string, ", uint vtx_id [[vertex_id]]").unwrap();
339 writeln!(self.string, ", uint inst_id [[instance_id]]").unwrap();
340 writeln!(self.string, ") {{").unwrap();
341 writeln!(
342 self.string,
343 " Geometries geometries = in_geometries[vtx_id];"
344 ).unwrap();
345 writeln!(
346 self.string,
347 " Instances instances = in_instances[inst_id];"
348 ).unwrap();
349 writeln!(self.string, " Varyings varyings;").unwrap();
350
351 for decl in &self.draw_shader_def.fields {
352 match &decl.kind {
353 DrawShaderFieldKind::Geometry {is_used_in_pixel_shader, ..} if is_used_in_pixel_shader.get() => {
354 writeln!(self.string, " varyings.{0} = geometries.{0};", DisplayDsIdent(decl.ident)).unwrap();
355 }
356 DrawShaderFieldKind::Instance {is_used_in_pixel_shader, ..} if is_used_in_pixel_shader.get() => {
357 match decl.ty_expr.ty.borrow().as_ref().unwrap() {
358 Ty::Mat4 => {
359 for i in 0..4 {
360 writeln!(self.string, " varyings.{0}{1} = instances.{0}{1};", DisplayDsIdent(decl.ident), i).unwrap();
361 }
362 }
363 Ty::Mat3 => {
364 for i in 0..3 {
365 writeln!(self.string, " varyings.{0}{1} = instances.{0}{1};", DisplayDsIdent(decl.ident), i).unwrap();
366 }
367 }
368 _ => {
369 writeln!(self.string, " varyings.{0} = instances.{0};", DisplayDsIdent(decl.ident)).unwrap();
370 }
371 }
372 }
373 _ => {}
374 }
375 }
376
377 let vertex_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(vertex))).unwrap();
378 write!(self.string, " varyings.position = {}", DisplayFnName(vertex_def.fn_ptr, vertex_def.ident)).unwrap();
379
380 write!(self.string, "(").unwrap();
381 self.backend_writer.write_call_expr_hidden_args(self.string, vertex_def.hidden_args.borrow().as_ref().unwrap(), "");
382
383 writeln!(self.string, ");").unwrap();
384
385 writeln!(self.string, " return varyings;").unwrap();
386 writeln!(self.string, "}}").unwrap();
387 }
388
389 fn generate_pixel_main(&mut self) {
390
391 write!(self.string, "fragment float4 fragment_main(").unwrap();
392 writeln!(self.string, "Varyings varyings[[stage_in]]").unwrap();
393 writeln!(self.string, ", Textures textures").unwrap();
394 writeln!(self.string, ", constant LiveUniforms &live_uniforms [[buffer(2)]]").unwrap();
395 writeln!(self.string, ", constant const float *const_table [[buffer(3)]]").unwrap();
396 let mut buffer_id = 4;
397 for (field, _set) in self.fields_as_uniform_blocks {
398 writeln!(self.string, ", constant Uniforms_{0} &uniforms_{0} [[buffer({1})]]", field, buffer_id).unwrap();
399 buffer_id += 1;
400 }
401
402 writeln!(self.string, ") {{").unwrap();
403
404 write!(self.string, " return ").unwrap();
405
406 let pixel_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(pixel))).unwrap();
407 write!(self.string, " {}", DisplayFnName(pixel_def.fn_ptr, pixel_def.ident)).unwrap();
408
409 write!(self.string, "(").unwrap();
410 self.backend_writer.write_call_expr_hidden_args(self.string, pixel_def.hidden_args.borrow().as_ref().unwrap(), "");
411
412 writeln!(self.string, ");").unwrap();
413
414 writeln!(self.string, "}}").unwrap();
415 }
416
417 fn generate_expr(&mut self, expr: &Expr) {
418 ExprGenerator {
419 fn_def: None,
420 shader_registry: self.shader_registry,
421 closure_site_info: None,
422 const_table_offset: None,
424 backend_writer: self.backend_writer,
425 string: self.string,
426 }
427 .generate_expr(expr)
428 }
429
430 fn write_var_decl_packed(&mut self, ident: &dyn fmt::Display, ty: &Ty) {
431 self.backend_writer.write_var_decl(&mut self.string, "", false, true, ident, ty);
432 }
433
434 fn write_var_decl(&mut self, ident: &dyn fmt::Display, ty: &Ty) {
435 self.backend_writer.write_var_decl(&mut self.string, "", false, false, ident, ty);
436 }
437
438 fn write_ty_lit(&mut self, ty_lit: TyLit) {
439 self.backend_writer.write_ty_lit(&mut self.string, ty_lit);
440 }
441
442}
443
444struct MetalBackendWriter<'a> {
445 pub shader_registry: &'a ShaderRegistry,
446 pub draw_shader_def: &'a DrawShaderDef,
447 pub const_table: &'a DrawShaderConstTable,
448}
449
450impl<'a> BackendWriter for MetalBackendWriter<'a> {
451
452 fn get_struct_cons_type(&self) -> StructConsType {
453 StructConsType::Brace
454 }
455
456
457 fn needs_mul_fn_for_matrix_multiplication(&self) -> bool {
458 false
459 }
460
461 fn needs_unpack_for_matrix_multiplication(&self) -> bool {
462 true
463 }
464
465 fn enum_is_float(&self)->bool{
466 false
467 }
468
469 fn const_table_is_vec4(&self) -> bool {
470 false
471 }
472
473
474 fn use_cons_fn(&self, what: &str) -> bool {
475 match what {
476 "consfn_mat3_mat4" => true,
477 "consfn_mat2_mat4" => true,
478 "consfn_mat2_mat3" => true,
479 _ => false
480 }
481 }
482
483 fn write_var_decl(
484 &self,
485 string: &mut String,
486 sep: &'static str,
487 is_inout: bool,
488 is_packed: bool,
489 ident: &dyn fmt::Display,
490 ty: &Ty,
491 ) -> bool {
492 let ref_prefix = if is_inout {
493 "&"
494 } else {
495 ""
496 };
497
498 fn prefix(string: &mut String, sep: &'static str, is_inout: bool) {
499 write!(string, "{}", sep).unwrap();
500 if is_inout {
501 write!(string, "thread ").unwrap();
502 }
503 }
504
505 let packed_prefix = if is_packed {"packed_"} else {""};
506 match *ty {
507 Ty::Void => {
508 write!(string, "{}void {}", sep, ident).unwrap();
509 }
510 Ty::Bool => {
511 prefix(string, sep, is_inout);
512 self.write_ty_lit(string, TyLit::Bool);
513 write!(string, " {}{}", ref_prefix, ident).unwrap();
514 }
515 Ty::Int => {
516 prefix(string, sep, is_inout);
517 self.write_ty_lit(string, TyLit::Int);
518 write!(string, " {}{}", ref_prefix, ident).unwrap();
519 }
520 Ty::Float => {
521 prefix(string, sep, is_inout);
522 self.write_ty_lit(string, TyLit::Float);
523 write!(string, " {}{}", ref_prefix, ident).unwrap();
524 }
525 Ty::Bvec2 => {
526 prefix(string, sep, is_inout);
527 self.write_ty_lit(string, TyLit::Bvec2);
528 write!(string, " {}{}", ref_prefix, ident).unwrap();
529 }
530 Ty::Bvec3 => {
531 prefix(string, sep, is_inout);
532 write!(string, "{}", packed_prefix).unwrap();
533 self.write_ty_lit(string, TyLit::Bvec3);
534 write!(string, " {}{}", ref_prefix, ident).unwrap();
535 }
536 Ty::Bvec4 => {
537 prefix(string, sep, is_inout);
538 write!(string, "{}", packed_prefix).unwrap();
539 self.write_ty_lit(string, TyLit::Bvec4);
540 write!(string, " {}{}", ref_prefix, ident).unwrap();
541 }
542 Ty::Ivec2 => {
543 prefix(string, sep, is_inout);
544 write!(string, "{}", packed_prefix).unwrap();
545 self.write_ty_lit(string, TyLit::Ivec2);
546 write!(string, " {}{}", ref_prefix, ident).unwrap();
547 }
548 Ty::Ivec3 => {
549 write!(string, "{}", packed_prefix).unwrap();
550 self.write_ty_lit(string, TyLit::Ivec3);
551 write!(string, " {}{}", ref_prefix, ident).unwrap();
552 }
553 Ty::Ivec4 => {
554 prefix(string, sep, is_inout);
555 write!(string, "{}", packed_prefix).unwrap();
556 self.write_ty_lit(string, TyLit::Ivec4);
557 write!(string, " {}{}", ref_prefix, ident).unwrap();
558 }
559 Ty::Vec2 => {
560 prefix(string, sep, is_inout);
561 write!(string, "{}", packed_prefix).unwrap();
562 self.write_ty_lit(string, TyLit::Vec2);
563 write!(string, " {}{}", ref_prefix, ident).unwrap();
564 }
565 Ty::Vec3 => {
566 prefix(string, sep, is_inout);
567 write!(string, "{}", packed_prefix).unwrap();
568 self.write_ty_lit(string, TyLit::Vec3);
569 write!(string, " {}{}", ref_prefix, ident).unwrap();
570 }
571 Ty::Vec4 => {
572 prefix(string, sep, is_inout);
573 write!(string, "{}", packed_prefix).unwrap();
574 self.write_ty_lit(string, TyLit::Vec4);
575 write!(string, " {}{}", ref_prefix, ident).unwrap();
576 }
577 Ty::Mat2 => {
578 prefix(string, sep, is_inout);
579 write!(string, "{}", packed_prefix).unwrap();
580 self.write_ty_lit(string, TyLit::Mat2);
581 write!(string, " {}{}", ref_prefix, ident).unwrap();
582 }
583 Ty::Mat3 => {
584 prefix(string, sep, is_inout);
585 write!(string, "{}", packed_prefix).unwrap();
586 self.write_ty_lit(string, TyLit::Mat3);
587 write!(string, " {}{}", ref_prefix, ident).unwrap();
588 }
589 Ty::Mat4 => {
590 prefix(string, sep, is_inout);
591 self.write_ty_lit(string, TyLit::Mat4);
592 write!(string, " {}{}", ref_prefix, ident).unwrap();
593 }
594 Ty::Texture2D => panic!(), Ty::Array {ref elem_ty, len} => {
596 self.write_var_decl(string, sep, is_inout, is_packed, ident, elem_ty);
597 write!(string, "[{}]", len).unwrap();
598 }
599 Ty::Struct(struct_node_ptr) => {
600 prefix(string, sep, is_inout);
601 write!(string, "{} {} {}", struct_node_ptr, ref_prefix, ident).unwrap();
602 }
603 Ty::Enum(_) => {
604 prefix(string, sep, is_inout);
605 write!(string, "uint32_t {} {}", ref_prefix, ident).unwrap();
606 }
607 Ty::DrawShader(_) => {
608 return false
609 }
610 Ty::ClosureDef {..} => {
611 return false
612 }
613 Ty::ClosureDecl => {
614 return false
615 }
616 }
617 true
618 }
619
620 fn write_call_expr_hidden_args(&self, string: &mut String, hidden_args: &BTreeSet<HiddenArgKind >, sep: &str) {
621 let mut sep = sep;
622 if self.const_table.table.len()>0 {
623 write!(string, "{}", sep).unwrap();
624 sep = ", ";
625 write!(string, "const_table").unwrap();
626 }
627
628 for hidden_arg in hidden_args {
629 write!(string, "{}", sep).unwrap();
630 match hidden_arg {
631 HiddenArgKind::Geometries => {
632 write!(string, "geometries").unwrap();
633 }
634 HiddenArgKind::Instances => {
635 write!(string, "instances").unwrap();
636 }
637 HiddenArgKind::Varyings => {
638 write!(string, "varyings").unwrap();
639 }
640 HiddenArgKind::Textures => {
641 write!(string, "textures").unwrap();
642 }
643 HiddenArgKind::Uniform(ident) => {
644 write!(string, "uniforms_{}", ident).unwrap();
645 }
646 HiddenArgKind::LiveUniforms => {
647 write!(string, "live_uniforms").unwrap();
648 }
649 }
650 sep = ", ";
651 }
652 }
653
654 fn write_fn_def_hidden_params(&self, string: &mut String, hidden_args: &BTreeSet<HiddenArgKind >, sep: &str) {
655 let mut sep = sep;
656 if self.const_table.table.len()>0 {
657 write!(string, "{}", sep).unwrap();
658 sep = ", ";
659 write!(string, "constant const float *const_table").unwrap();
660 }
661
662 for hidden_arg in hidden_args {
663 write!(string, "{}", sep).unwrap();
664 match hidden_arg {
665 HiddenArgKind::Geometries => {
666 write!(string, "thread Geometries &geometries").unwrap();
667 }
668 HiddenArgKind::Instances => {
669 write!(string, "thread Instances &instances").unwrap();
670 }
671 HiddenArgKind::Varyings => {
672 write!(string, "thread Varyings &varyings").unwrap();
673 }
674 HiddenArgKind::Textures => {
675 write!(string, "Textures textures").unwrap();
676 }
677 HiddenArgKind::Uniform(ident) => {
678 write!(string, "constant Uniforms_{0} &uniforms_{0}", ident).unwrap();
679 }
680 HiddenArgKind::LiveUniforms => {
681 write!(string, "constant LiveUniforms &live_uniforms").unwrap();
682 }
683 }
684 sep = ", ";
685 }
686 }
687
688 fn generate_live_value_prefix(&self, string: &mut String) {
689 write!(string, "live_uniforms.").unwrap();
690 }
691
692 fn generate_draw_shader_field_expr(&self, string: &mut String, field_ident: Ident, ty: &Ty) {
693 let field_def = self.draw_shader_def.find_field(field_ident).unwrap();
694
695 match &field_def.kind {
696 DrawShaderFieldKind::Geometry {is_used_in_pixel_shader, ..} => {
697 if is_used_in_pixel_shader.get() {
698 write!(string, "varyings.").unwrap()
699 }
700 else {
701 write!(string, "geometries.").unwrap()
702 }
703 }
704 DrawShaderFieldKind::Instance {is_used_in_pixel_shader, ..} => {
705 let prefix = if is_used_in_pixel_shader.get() {
706 "varyings"
707 }
708 else {
709 "instances"
710 };
711
712 match ty {
713 Ty::Mat4 => {
714 write!(string, "float4x4(").unwrap();
715 for i in 0..4 {
716 for j in 0..4 {
717 if i != 0 || j != 0 {
718 write!(string, ",").unwrap();
719 }
720 write!(string, "{}.", prefix).unwrap();
721 write!(string, "{}{}", DisplayDsIdent(field_ident), j).unwrap();
722 match i {
723 0 => write!(string, ".x").unwrap(),
724 1 => write!(string, ".y").unwrap(),
725 2 => write!(string, ".z").unwrap(),
726 _ => write!(string, ".w").unwrap()
727 }
728 }
729 }
730 write!(string, ")").unwrap();
731 return
732 },
733 Ty::Mat3 => {
734 write!(string, "float3x3(").unwrap();
735 for i in 0..3 {
736 for j in 0..3 {
737 if i != 0 || j != 0 {
738 write!(string, ",").unwrap();
739 }
740 write!(string, "{}.", prefix).unwrap();
741 write!(string, "{}{}", DisplayDsIdent(field_ident), j).unwrap();
742 match i {
743 0 => write!(string, ".x").unwrap(),
744 1 => write!(string, ".y").unwrap(),
745 _ => write!(string, ".z").unwrap(),
746 }
747 }
748 }
749 write!(string, ")").unwrap();
750 return
751 },
752 Ty::Mat2 => {
753 write!(string, "float2x2({0}.{1}.x, {0}.{1}.y, {0}.{1}.z, {0}.{1}.w)", prefix, DisplayDsIdent(field_ident)).unwrap();
754 return
755 },
756 _ => {
757 write!(string, "{}.",prefix).unwrap();
758 }
759 }
760 }
761 DrawShaderFieldKind::Varying {..} => {
762 write!(string, "varyings.").unwrap()
763 }
764 DrawShaderFieldKind::Texture {..} => {
765 write!(string, "textures.").unwrap()
766 }
767 DrawShaderFieldKind::Uniform {block_ident, ..} => {
768 write!(string, "uniforms_{}.", block_ident).unwrap()
769 }
770 }
771 write!(string, "{}", &DisplayDsIdent(field_ident)).unwrap();
772 }
773
774 fn write_ty_lit(&self, string: &mut String, ty_lit: TyLit) {
775 write!(
776 string,
777 "{}",
778 match ty_lit {
779 TyLit::Bool => "bool",
780 TyLit::Int => "int",
781 TyLit::Float => "float",
782 TyLit::Bvec2 => "bool2",
783 TyLit::Bvec3 => "bool3",
784 TyLit::Bvec4 => "bool4",
785 TyLit::Ivec2 => "int2",
786 TyLit::Ivec3 => "int3",
787 TyLit::Ivec4 => "int4",
788 TyLit::Vec2 => "float2",
789 TyLit::Vec3 => "float3",
790 TyLit::Vec4 => "float4",
791 TyLit::Mat2 => "float2x2",
792 TyLit::Mat3 => "float3x3",
793 TyLit::Mat4 => "float4x4",
794 TyLit::Texture2D => panic!(), }
796 )
797 .unwrap();
798 }
799
800 fn write_builtin_call_ident(&self, string: &mut String, ident: Ident, arg_exprs: &[Expr]) {
801 match ident {
802 Ident(live_id!(atan)) => {
803 if arg_exprs.len() == 2 {
804 write!(string, "atan2").unwrap();
805 }
806 else {
807 write!(string, "atan").unwrap();
808 }
809 }
810 Ident(live_id!(mod)) => {
811 write!(string, "fmod").unwrap();
812 }
813 Ident(live_id!(dFdx)) => {
814 write!(string, "dfdx").unwrap();
815 }
816 Ident(live_id!(dFdy)) => {
817 write!(string, "dfdy").unwrap();
818 }
819 _ => {
820 write!(string, "{}", ident).unwrap()
821 }
822 }
823 }
824}