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