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        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        //let fields_as_uniform_blocks = self.draw_shader_def.fields_as_uniform_blocks();
81        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        //let vertex_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(vertex))).unwrap();
88        //let pixel_def = self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(fragment))).unwrap();
89
90        for (ty_lit, ref param_tys) in all_constructor_fns{
91            generate_cons_fn(self.backend_writer, self.string, ty_lit, &param_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                    // any function that depends on us, will have the closures we need
101                    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        // we have all the structs already from analyse
130        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            // we have a span and an ident_path.
149            // lets fully qualify it
150            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                            //write!(self.string, "    ").unwrap();
222                            //self.write_var_decl(&DisplayDsIdent(field.ident), field.ty_expr.ty.borrow().as_ref().unwrap(),);
223                            //writeln!(self.string, ";").unwrap();
224                        },
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                /*                
253                DrawShaderFieldKind::Instance {..} => {
254                    write!(self.string, "    ").unwrap();
255                    self.write_var_decl_packed(
256                        &DisplayDsIdent(field.ident),
257                        field.ty_expr.ty.borrow().as_ref().unwrap(),
258                    );
259                    writeln!(self.string, ";").unwrap();
260                }*/
261                _ => ()
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            //env: self.env,
431            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!(), // TODO
603            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!(), // TODO
803            }
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}