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