makepad_shader_compiler/
generate_metal.rs

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        //let fields_as_uniform_blocks = self.draw_shader_def.fields_as_uniform_blocks();
74        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        //let vertex_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(vertex))).unwrap();
81        //let pixel_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(pixel))).unwrap();
82
83        for (ty_lit, ref param_tys) in all_constructor_fns{
84            generate_cons_fn(self.backend_writer, self.string, ty_lit, &param_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                    // any function that depends on us, will have the closures we need
94                    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        // we have all the structs already from analyse
123        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            // we have a span and an ident_path.
142            // lets fully qualify it
143            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                            //write!(self.string, "    ").unwrap();
214                            //self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
215                            //writeln!(self.string, ";").unwrap();
216                        },
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                /*                
245                DrawShaderFieldKind::Instance {..} => {
246                    write!(self.string, "    ").unwrap();
247                    self.write_var_decl_packed(
248                        &DisplayDsIdent(field.ident),
249                        field.ty_expr.ty.borrow().as_ref().unwrap(),
250                    );
251                    writeln!(self.string, ";").unwrap();
252                }*/
253                _ => ()
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            //env: self.env,
423            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!(), // TODO
595            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!(), // TODO
795            }
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}