makepad_shader_compiler/
generate_hlsl.rs

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