1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 extern crate glsl;
6
7 mod hir;
8
9 use glsl::parser::Parse;
10 use glsl::syntax;
11 use glsl::syntax::{TranslationUnit, UnaryOp};
12 use hir::{Statement, SwizzleSelector, Type};
13 use std::cell::{Cell, RefCell};
14 use std::collections::{BTreeMap, HashMap};
15 use std::io::Read;
16 use std::mem;
17
18 #[derive(PartialEq, Eq)]
19 enum ShaderKind {
20 Fragment,
21 Vertex,
22 }
23
24 type UniformIndices = BTreeMap<String, (i32, hir::TypeKind, hir::StorageClass)>;
25
build_uniform_indices(indices: &mut UniformIndices, state: &hir::State)26 fn build_uniform_indices(indices: &mut UniformIndices, state: &hir::State) {
27 for u in state.used_globals.borrow().iter() {
28 let sym = state.sym(*u);
29 match &sym.decl {
30 hir::SymDecl::Global(storage, _, ty, _) => match storage {
31 hir::StorageClass::Uniform | hir::StorageClass::Sampler(..) => {
32 let next_index = indices.len() as i32 + 1;
33 indices.entry(sym.name.clone()).or_insert((
34 next_index,
35 ty.kind.clone(),
36 *storage,
37 ));
38 }
39 _ => {}
40 },
41 _ => {}
42 }
43 }
44 }
45
translate(args: &mut dyn Iterator<Item = String>) -> String46 pub fn translate(args: &mut dyn Iterator<Item = String>) -> String {
47 let _cmd_name = args.next();
48 let vertex_file = args.next().unwrap();
49
50 let vs_name = std::path::Path::new(&vertex_file)
51 .file_stem()
52 .unwrap()
53 .to_string_lossy()
54 .to_string();
55
56 let frag_file = args.next().unwrap();
57
58 let fs_name = std::path::Path::new(&frag_file)
59 .file_stem()
60 .unwrap()
61 .to_string_lossy()
62 .to_string();
63
64 let (vs_state, vs_hir, vs_is_frag) = parse_shader(vertex_file);
65 let (fs_state, fs_hir, fs_is_frag) = parse_shader(frag_file);
66
67 // we use a BTree so that iteration is stable
68 let mut uniform_indices = BTreeMap::new();
69 build_uniform_indices(&mut uniform_indices, &vs_state);
70 build_uniform_indices(&mut uniform_indices, &fs_state);
71
72 assert_eq!(fs_name, vs_name);
73
74 let mut result = translate_shader(
75 vs_name,
76 vs_state,
77 vs_hir,
78 vs_is_frag,
79 &uniform_indices,
80 );
81 result += "\n";
82 result += &translate_shader(
83 fs_name,
84 fs_state,
85 fs_hir,
86 fs_is_frag,
87 &uniform_indices,
88 );
89 result
90 }
91
parse_shader(file: String) -> (hir::State, hir::TranslationUnit, bool)92 fn parse_shader(file: String) -> (hir::State, hir::TranslationUnit, bool) {
93 let mut contents = String::new();
94 let is_frag = file.contains("frag");
95 std::fs::File::open(&file)
96 .unwrap()
97 .read_to_string(&mut contents)
98 .unwrap();
99 let r = TranslationUnit::parse(contents);
100
101 //println!("{:#?}", r);
102 let mut ast_glsl = String::new();
103 let r = r.unwrap();
104 glsl::transpiler::glsl::show_translation_unit(&mut ast_glsl, &r);
105 //let mut fast = std::fs::File::create("ast").unwrap();
106 //fast.write(ast_glsl.as_bytes());
107
108 let mut state = hir::State::new();
109 let hir = hir::ast_to_hir(&mut state, &r);
110 (state, hir, is_frag)
111 }
112
translate_shader( name: String, mut state: hir::State, hir: hir::TranslationUnit, is_frag: bool, uniform_indices: &UniformIndices, ) -> String113 fn translate_shader(
114 name: String,
115 mut state: hir::State,
116 hir: hir::TranslationUnit,
117 is_frag: bool,
118 uniform_indices: &UniformIndices,
119 ) -> String {
120 //println!("{:#?}", state);
121
122 hir::infer_run_class(&mut state, &hir);
123
124 let mut uniforms = Vec::new();
125 let mut inputs = Vec::new();
126 let mut outputs = Vec::new();
127
128 for i in &hir {
129 match i {
130 hir::ExternalDeclaration::Declaration(hir::Declaration::InitDeclaratorList(ref d)) => {
131 match &state.sym(d.head.name).decl {
132 hir::SymDecl::Global(storage, ..)
133 if state.used_globals.borrow().contains(&d.head.name) =>
134 {
135 match storage {
136 hir::StorageClass::Uniform | hir::StorageClass::Sampler(..) => {
137 uniforms.push(d.head.name);
138 }
139 hir::StorageClass::In => {
140 inputs.push(d.head.name);
141 }
142 hir::StorageClass::Out | hir::StorageClass::FragColor(_) => {
143 outputs.push(d.head.name);
144 }
145 _ => {}
146 }
147 }
148 _ => {}
149 }
150 }
151 _ => {}
152 }
153 }
154
155 //println!("{:#?}", hir);
156
157 let mut state = OutputState {
158 hir: state,
159 output: String::new(),
160 buffer: RefCell::new(String::new()),
161 indent: 0,
162 should_indent: false,
163 output_cxx: false,
164 mask: None,
165 cond_index: 0,
166 return_type: None,
167 return_declared: false,
168 return_vector: false,
169 is_scalar: Cell::new(false),
170 is_lval: Cell::new(false),
171 name: name.clone(),
172 kind: if is_frag {
173 ShaderKind::Fragment
174 } else {
175 ShaderKind::Vertex
176 },
177 functions: HashMap::new(),
178 deps: RefCell::new(Vec::new()),
179 vector_mask: 0,
180 uses_discard: false,
181 used_fragcoord: Cell::new(0),
182 use_perspective: false,
183 used_globals: RefCell::new(Vec::new()),
184 texel_fetches: RefCell::new(Vec::new()),
185 };
186
187 show_translation_unit(&mut state, &hir);
188 let _output_glsl = state.finish_output();
189
190 state.should_indent = true;
191 state.output_cxx = true;
192
193 if state.output_cxx {
194 let part_name = name.to_owned()
195 + match state.kind {
196 ShaderKind::Vertex => "_vert",
197 ShaderKind::Fragment => "_frag",
198 };
199
200 if state.kind == ShaderKind::Vertex {
201 write_common_globals(&mut state, &inputs, &outputs, uniform_indices);
202 write!(state, "struct {0}_vert : VertexShaderImpl, {0}_common {{\nprivate:\n", name);
203 } else {
204 write!(state, "struct {0}_frag : FragmentShaderImpl, {0}_vert {{\nprivate:\n", name);
205 }
206
207 write!(state, "typedef {} Self;\n", part_name);
208
209 show_translation_unit(&mut state, &hir);
210
211 let pruned_inputs: Vec<_> = inputs
212 .iter()
213 .filter(|i| state.used_globals.borrow().contains(i))
214 .cloned()
215 .collect();
216
217 if state.kind == ShaderKind::Vertex {
218 write_set_uniform_1i(&mut state, uniform_indices);
219 write_set_uniform_4fv(&mut state, uniform_indices);
220 write_set_uniform_matrix4fv(&mut state, uniform_indices);
221 write_load_attribs(&mut state, &pruned_inputs);
222 write_store_outputs(&mut state, &outputs);
223 } else {
224 write_read_inputs(&mut state, &pruned_inputs);
225 }
226
227 write_abi(&mut state);
228 write!(state, "}};\n\n");
229
230 if state.kind == ShaderKind::Fragment {
231 write!(state, "struct {0}_program : ProgramImpl, {0}_frag {{\n", name);
232 write_get_uniform_index(&mut state, uniform_indices);
233 write!(state, "void bind_attrib(const char* name, int index) override {{\n");
234 write!(state, " attrib_locations.bind_loc(name, index);\n}}\n");
235 write!(state, "int get_attrib(const char* name) const override {{\n");
236 write!(state, " return attrib_locations.get_loc(name);\n}}\n");
237 write!(state, "size_t interpolants_size() const override {{ return sizeof(InterpOutputs); }}\n");
238 write!(state, "VertexShaderImpl* get_vertex_shader() override {{\n");
239 write!(state, " return this;\n}}\n");
240 write!(state, "FragmentShaderImpl* get_fragment_shader() override {{\n");
241 write!(state, " return this;\n}}\n");
242 write!(state, "const char* get_name() const override {{ return \"{}\"; }}\n", name);
243 write!(state, "static ProgramImpl* loader() {{ return new {}_program; }}\n", name);
244 write!(state, "}};\n\n");
245 }
246
247 define_global_consts(&mut state, &hir, &part_name);
248 } else {
249 show_translation_unit(&mut state, &hir);
250 }
251 let output_cxx = state.finish_output();
252
253 //let mut hir = std::fs::File::create("hir").unwrap();
254 //hir.write(output_glsl.as_bytes());
255
256 output_cxx
257 }
258
write_get_uniform_index(state: &mut OutputState, uniform_indices: &UniformIndices)259 fn write_get_uniform_index(state: &mut OutputState, uniform_indices: &UniformIndices) {
260 write!(
261 state,
262 "int get_uniform(const char *name) const override {{\n"
263 );
264 for (uniform_name, (index, _, _)) in uniform_indices.iter() {
265 write!(
266 state,
267 " if (strcmp(\"{}\", name) == 0) {{ return {}; }}\n",
268 uniform_name, index
269 );
270 }
271 write!(state, " return -1;\n");
272 write!(state, "}}\n");
273 }
274
float4_compatible(ty: hir::TypeKind) -> bool275 fn float4_compatible(ty: hir::TypeKind) -> bool {
276 match ty {
277 hir::TypeKind::Vec4 => true,
278 _ => false,
279 }
280 }
281
matrix4_compatible(ty: hir::TypeKind) -> bool282 fn matrix4_compatible(ty: hir::TypeKind) -> bool {
283 match ty {
284 hir::TypeKind::Mat4 => true,
285 _ => false,
286 }
287 }
288
write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndices)289 fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndices) {
290 write!(state, "struct Samplers {{\n");
291 for (name, (_, tk, storage)) in uniform_indices.iter() {
292 match tk {
293 hir::TypeKind::Sampler2D
294 | hir::TypeKind::Sampler2DRect
295 | hir::TypeKind::ISampler2D => {
296 write!(state, " ");
297 show_type_kind(state, &tk);
298 let suffix = if let hir::StorageClass::Sampler(format) = storage {
299 format.type_suffix()
300 } else {
301 None
302 };
303 write!(state, "{}_impl {}_impl;\n", suffix.unwrap_or(""), name);
304 write!(state, " int {}_slot;\n", name);
305 }
306 _ => {}
307 }
308 }
309 write!(
310 state,
311 " bool set_slot(int index, int value) {{\n"
312 );
313 write!(state, " switch (index) {{\n");
314 for (name, (index, tk, _)) in uniform_indices.iter() {
315 match tk {
316 hir::TypeKind::Sampler2D
317 | hir::TypeKind::Sampler2DRect
318 | hir::TypeKind::ISampler2D => {
319 write!(state, " case {}:\n", index);
320 write!(state, " {}_slot = value;\n", name);
321 write!(state, " return true;\n");
322 }
323 _ => {}
324 }
325 }
326 write!(state, " }}\n");
327 write!(state, " return false;\n");
328 write!(state, " }}\n");
329 write!(state, "}} samplers;\n");
330
331 }
332
write_bind_textures(state: &mut OutputState, uniforms: &UniformIndices)333 fn write_bind_textures(state: &mut OutputState, uniforms: &UniformIndices) {
334 write!(state, "void bind_textures() {{\n");
335 for (name, (_, tk, storage)) in uniforms {
336 match storage {
337 hir::StorageClass::Sampler(_format) => {
338 match tk {
339 hir::TypeKind::Sampler2D
340 | hir::TypeKind::Sampler2DRect => write!(state,
341 " {0} = lookup_sampler(&samplers.{0}_impl, samplers.{0}_slot);\n",
342 name),
343 hir::TypeKind::ISampler2D => write!(state,
344 " {0} = lookup_isampler(&samplers.{0}_impl, samplers.{0}_slot);\n",
345 name),
346 _ => {}
347 };
348 }
349 _ => {}
350 }
351 }
352 write!(state, "}}\n");
353 }
354
write_set_uniform_1i( state: &mut OutputState, uniforms: &UniformIndices, )355 fn write_set_uniform_1i(
356 state: &mut OutputState,
357 uniforms: &UniformIndices,
358 ) {
359 write!(
360 state,
361 "static void set_uniform_1i(Self *self, int index, int value) {{\n"
362 );
363 write!(state, " if (self->samplers.set_slot(index, value)) return;\n");
364 write!(state, " switch (index) {{\n");
365 for (name, (index, tk, _)) in uniforms {
366 write!(state, " case {}:\n", index);
367 match tk {
368 hir::TypeKind::Int => write!(
369 state,
370 " self->{} = {}(value);\n",
371 name,
372 tk.cxx_primitive_scalar_type_name().unwrap(),
373 ),
374 _ => write!(state, " assert(0); // {}\n", name),
375 };
376 write!(state, " break;\n");
377 }
378 write!(state, " }}\n");
379 write!(state, "}}\n");
380 }
381
write_set_uniform_4fv( state: &mut OutputState, uniforms: &UniformIndices, )382 fn write_set_uniform_4fv(
383 state: &mut OutputState,
384 uniforms: &UniformIndices,
385 ) {
386 write!(
387 state,
388 "static void set_uniform_4fv(Self *self, int index, const float *value) {{\n"
389 );
390 write!(state, " switch (index) {{\n");
391 for (name, (index, tk, _)) in uniforms {
392 write!(state, " case {}:\n", index);
393 if float4_compatible(tk.clone()) {
394 write!(
395 state,
396 " self->{} = vec4_scalar::load_from_ptr(value);\n",
397 name
398 );
399 } else {
400 write!(state, " assert(0); // {}\n", name);
401 }
402 write!(state, " break;\n");
403 }
404 write!(state, " }}\n");
405 write!(state, "}}\n");
406 }
407
write_set_uniform_matrix4fv( state: &mut OutputState, uniforms: &UniformIndices, )408 fn write_set_uniform_matrix4fv(
409 state: &mut OutputState,
410 uniforms: &UniformIndices,
411 ) {
412 write!(
413 state,
414 "static void set_uniform_matrix4fv(Self *self, int index, const float *value) {{\n"
415 );
416 write!(state, " switch (index) {{\n");
417 for (name, (index, tk, _)) in uniforms {
418 write!(state, " case {}:\n", index);
419 if matrix4_compatible(tk.clone()) {
420 write!(
421 state,
422 " self->{} = mat4_scalar::load_from_ptr(value);\n",
423 name
424 );
425 } else {
426 write!(state, " assert(0); // {}\n", name);
427 }
428 write!(state, " break;\n");
429 }
430 write!(state, " }}\n");
431 write!(state, "}}\n");
432 }
433
write_bind_attrib_location(state: &mut OutputState, attribs: &[hir::SymRef])434 fn write_bind_attrib_location(state: &mut OutputState, attribs: &[hir::SymRef]) {
435 write!(state, "struct AttribLocations {{\n");
436 for i in attribs {
437 let sym = state.hir.sym(*i);
438 write!(state, " int {} = NULL_ATTRIB;\n", sym.name.as_str());
439 }
440 write!(state, " void bind_loc(const char* name, int index) {{\n");
441 for i in attribs {
442 let sym = state.hir.sym(*i);
443 write!(
444 state,
445 " if (strcmp(\"{0}\", name) == 0) {{ {0} = index; return; }}\n",
446 sym.name.as_str()
447 );
448 }
449 write!(state, " }}\n");
450 write!(state, " int get_loc(const char* name) const {{\n");
451 for i in attribs {
452 let sym = state.hir.sym(*i);
453 write!(state,
454 " if (strcmp(\"{0}\", name) == 0) {{ \
455 return {0} != NULL_ATTRIB ? {0} : -1; \
456 }}\n",
457 sym.name.as_str());
458 }
459 write!(state, " return -1;\n");
460 write!(state, " }}\n");
461 write!(state, "}} attrib_locations;\n");
462 }
463
write_common_globals(state: &mut OutputState, attribs: &[hir::SymRef], outputs: &[hir::SymRef], uniforms: &UniformIndices)464 fn write_common_globals(state: &mut OutputState, attribs: &[hir::SymRef],
465 outputs: &[hir::SymRef], uniforms: &UniformIndices) {
466 write!(state, "struct {}_common {{\n", state.name);
467
468 write_program_samplers(state, uniforms);
469 write_bind_attrib_location(state, attribs);
470
471 let is_scalar = state.is_scalar.replace(true);
472 for i in outputs {
473 let sym = state.hir.sym(*i);
474 match &sym.decl {
475 hir::SymDecl::Global(hir::StorageClass::Out, _, ty, hir::RunClass::Scalar) => {
476 show_type(state, ty);
477 write!(state, " {};\n", sym.name.as_str());
478 }
479 _ => {}
480 }
481 }
482 for (name, (_, tk, storage)) in uniforms {
483 match storage {
484 hir::StorageClass::Sampler(format) => {
485 write!(state,
486 "{}{} {};\n",
487 tk.cxx_primitive_type_name().unwrap(),
488 format.type_suffix().unwrap_or(""),
489 name,
490 );
491 }
492 _ => {
493 show_type_kind(state, tk);
494 write!(state, " {};\n", name);
495 }
496 }
497 }
498 state.is_scalar.set(is_scalar);
499
500 write_bind_textures(state, uniforms);
501
502 write!(state, "}};\n");
503 }
504
505 //fn type_name(state: &OutputState, ty: &Type) -> String {
506 // let buffer = state.push_buffer();
507 // show_type(state, ty);
508 // state.pop_buffer(buffer)
509 //}
510
write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef])511 fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
512 write!(state, "static void load_attribs(\
513 Self *self, VertexAttrib *attribs, \
514 uint32_t start, int instance, int count) {{\n");
515 for i in attribs {
516 let sym = state.hir.sym(*i);
517 match &sym.decl {
518 hir::SymDecl::Global(_, _interpolation, _ty, run_class) => {
519 let name = sym.name.as_str();
520 let func = if *run_class == hir::RunClass::Scalar {
521 "load_flat_attrib"
522 } else {
523 "load_attrib"
524 };
525 write!(state,
526 " {0}(self->{1}, attribs[self->attrib_locations.{1}], start, instance, count);\n",
527 func, name);
528 }
529 _ => panic!(),
530 }
531 }
532 write!(state, "}}\n");
533 }
534
write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef])535 fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
536 let is_scalar = state.is_scalar.replace(true);
537 write!(state, "public:\nstruct InterpOutputs {{\n");
538 if state.hir.used_clip_dist != 0 {
539 state.write(" Float swgl_ClipDistance;\n");
540 }
541 for i in outputs {
542 let sym = state.hir.sym(*i);
543 match &sym.decl {
544 hir::SymDecl::Global(_, _, ty, run_class) => {
545 if *run_class != hir::RunClass::Scalar {
546 show_type(state, ty);
547 write!(state, " {};\n", sym.name.as_str());
548 }
549 }
550 _ => panic!(),
551 }
552 }
553
554 write!(state, "}};\nprivate:\n");
555 state.is_scalar.set(is_scalar);
556
557 write!(
558 state,
559 "ALWAYS_INLINE void store_interp_outputs(char* dest_ptr, size_t stride) {{\n"
560 );
561 write!(state, " for(int n = 0; n < 4; n++) {{\n");
562 write!(
563 state,
564 " auto* dest = reinterpret_cast<InterpOutputs*>(dest_ptr);\n"
565 );
566 if state.hir.used_clip_dist != 0 {
567 for (i, comp) in "xyzw".chars().enumerate() {
568 if (state.hir.used_clip_dist & (1 << i)) != 0 {
569 write!(state, " dest->swgl_ClipDistance.{} = get_nth(gl_ClipDistance[{}], n);\n", comp, i);
570 } else {
571 write!(state, " dest->swgl_ClipDistance.{} = 0.0f;\n", comp);
572 }
573 }
574 }
575 for i in outputs {
576 let sym = state.hir.sym(*i);
577 match &sym.decl {
578 hir::SymDecl::Global(_, _, _, run_class) => {
579 if *run_class != hir::RunClass::Scalar {
580 let name = sym.name.as_str();
581 write!(state, " dest->{} = get_nth({}, n);\n", name, name);
582 }
583 }
584 _ => panic!(),
585 }
586 }
587 write!(state, " dest_ptr += stride;\n");
588 write!(state, " }}\n");
589 write!(state, "}}\n");
590 }
591
write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef])592 fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
593 write!(
594 state,
595 "typedef {}_vert::InterpOutputs InterpInputs;\n",
596 state.name
597 );
598
599 write!(state, "InterpInputs interp_step;\n");
600
601 let mut has_varying = false;
602 for i in inputs {
603 let sym = state.hir.sym(*i);
604 match &sym.decl {
605 hir::SymDecl::Global(_, _, ty, run_class) => {
606 if *run_class != hir::RunClass::Scalar {
607 if !has_varying {
608 has_varying = true;
609 write!(state, "struct InterpPerspective {{\n");
610 }
611 show_type(state, ty);
612 write!(state, " {};\n", sym.name.as_str());
613 }
614 }
615 _ => panic!(),
616 }
617 }
618 if has_varying {
619 write!(state, "}};\n");
620 write!(state, "InterpPerspective interp_perspective;\n");
621 }
622
623 write!(state,
624 "static void read_interp_inputs(\
625 Self *self, const InterpInputs *init, const InterpInputs *step) {{\n");
626 for i in inputs {
627 let sym = state.hir.sym(*i);
628 match &sym.decl {
629 hir::SymDecl::Global(_, _, _, run_class) => {
630 if *run_class != hir::RunClass::Scalar {
631 let name = sym.name.as_str();
632 write!(
633 state,
634 " self->{0} = init_interp(init->{0}, step->{0});\n",
635 name
636 );
637 write!(
638 state,
639 " self->interp_step.{0} = step->{0} * 4.0f;\n",
640 name
641 );
642 }
643 }
644 _ => panic!(),
645 }
646 }
647 write!(state, "}}\n");
648
649 let used_fragcoord = state.used_fragcoord.get();
650 if has_varying || (used_fragcoord & (4 | 8)) != 0 {
651 state.use_perspective = true;
652 }
653 if state.use_perspective {
654 write!(state,
655 "static void read_perspective_inputs(\
656 Self *self, const InterpInputs *init, const InterpInputs *step) {{\n");
657 if has_varying {
658 write!(state, " Float w = 1.0f / self->gl_FragCoord.w;\n");
659 }
660 for i in inputs {
661 let sym = state.hir.sym(*i);
662 match &sym.decl {
663 hir::SymDecl::Global(_, _, _, run_class) => {
664 if *run_class != hir::RunClass::Scalar {
665 let name = sym.name.as_str();
666 write!(
667 state,
668 " self->interp_perspective.{0} = init_interp(init->{0}, step->{0});\n",
669 name
670 );
671 write!(state, " self->{0} = self->interp_perspective.{0} * w;\n", name);
672 write!(
673 state,
674 " self->interp_step.{0} = step->{0} * 4.0f;\n",
675 name
676 );
677 }
678 }
679 _ => panic!(),
680 }
681 }
682 write!(state, "}}\n");
683 }
684
685 write!(state, "ALWAYS_INLINE void step_interp_inputs(int steps = 4) {{\n");
686 if (used_fragcoord & 1) != 0 {
687 write!(state, " step_fragcoord(steps);\n");
688 }
689 if !inputs.is_empty() {
690 write!(state, " float chunks = steps * 0.25f;\n");
691 }
692 for i in inputs {
693 let sym = state.hir.sym(*i);
694 match &sym.decl {
695 hir::SymDecl::Global(_, _, _, run_class) => {
696 if *run_class != hir::RunClass::Scalar {
697 let name = sym.name.as_str();
698 write!(state, " {0} += interp_step.{0} * chunks;\n", name);
699 }
700 }
701 _ => panic!(),
702 }
703 }
704 write!(state, "}}\n");
705
706 if state.use_perspective {
707 write!(state, "ALWAYS_INLINE void step_perspective_inputs(int steps = 4) {{\n");
708 if (used_fragcoord & 1) != 0 {
709 write!(state, " step_fragcoord(steps);\n");
710 }
711 write!(state, " step_perspective(steps);\n");
712 if !inputs.is_empty() {
713 write!(state, " float chunks = steps * 0.25f;\n");
714 }
715 if has_varying {
716 write!(state, " Float w = 1.0f / gl_FragCoord.w;\n");
717 }
718 for i in inputs {
719 let sym = state.hir.sym(*i);
720 match &sym.decl {
721 hir::SymDecl::Global(_, _, _, run_class) => {
722 if *run_class != hir::RunClass::Scalar {
723 let name = sym.name.as_str();
724 write!(state, " interp_perspective.{0} += interp_step.{0} * chunks;\n", name);
725 write!(state, " {0} = w * interp_perspective.{0};\n", name);
726 }
727 }
728 _ => panic!(),
729 }
730 }
731 write!(state, "}}\n");
732 }
733 }
734
735 pub struct OutputState {
736 hir: hir::State,
737 output: String,
738 buffer: RefCell<String>,
739 should_indent: bool,
740 output_cxx: bool,
741 indent: i32,
742 mask: Option<Box<hir::Expr>>,
743 cond_index: usize,
744 return_type: Option<Box<hir::Type>>,
745 return_declared: bool,
746 return_vector: bool,
747 is_scalar: Cell<bool>,
748 is_lval: Cell<bool>,
749 name: String,
750 kind: ShaderKind,
751 functions: HashMap<(hir::SymRef, u32), bool>,
752 deps: RefCell<Vec<(hir::SymRef, u32)>>,
753 vector_mask: u32,
754 uses_discard: bool,
755 used_fragcoord: Cell<i32>,
756 use_perspective: bool,
757 used_globals: RefCell<Vec<hir::SymRef>>,
758 texel_fetches: RefCell<Vec<(hir::SymRef, hir::SymRef, hir::TexelFetchOffsets)>>,
759 }
760
761 use std::fmt::{Arguments, Write};
762
763 impl OutputState {
indent(&mut self)764 fn indent(&mut self) {
765 if self.should_indent {
766 self.indent += 1
767 }
768 }
outdent(&mut self)769 fn outdent(&mut self) {
770 if self.should_indent {
771 self.indent -= 1
772 }
773 }
774
write(&self, s: &str)775 fn write(&self, s: &str) {
776 self.buffer.borrow_mut().push_str(s);
777 }
778
flush_buffer(&mut self)779 fn flush_buffer(&mut self) {
780 self.output.push_str(&self.buffer.borrow());
781 self.buffer.borrow_mut().clear();
782 }
783
finish_output(&mut self) -> String784 fn finish_output(&mut self) -> String {
785 self.flush_buffer();
786
787 let mut s = String::new();
788 mem::swap(&mut self.output, &mut s);
789 s
790 }
791
push_buffer(&self) -> String792 fn push_buffer(&self) -> String {
793 self.buffer.replace(String::new())
794 }
795
pop_buffer(&self, s: String) -> String796 fn pop_buffer(&self, s: String) -> String {
797 self.buffer.replace(s)
798 }
799
write_fmt(&self, args: Arguments)800 fn write_fmt(&self, args: Arguments) {
801 let _ = self.buffer.borrow_mut().write_fmt(args);
802 }
803 }
804
show_identifier(state: &OutputState, i: &syntax::Identifier)805 pub fn show_identifier(state: &OutputState, i: &syntax::Identifier) {
806 state.write(&i.0);
807 }
808
glsl_primitive_type_name_to_cxx(glsl_name: &str) -> &str809 fn glsl_primitive_type_name_to_cxx(glsl_name: &str) -> &str {
810 hir::TypeKind::from_glsl_primitive_type_name(glsl_name)
811 .and_then(|kind| kind.cxx_primitive_type_name())
812 .unwrap_or(glsl_name)
813 }
814
add_used_global(state: &OutputState, i: &hir::SymRef)815 fn add_used_global(state: &OutputState, i: &hir::SymRef) {
816 let mut globals = state.used_globals.borrow_mut();
817 if !globals.contains(i) {
818 globals.push(*i);
819 }
820 }
821
show_sym(state: &OutputState, i: &hir::SymRef)822 pub fn show_sym(state: &OutputState, i: &hir::SymRef) {
823 let sym = state.hir.sym(*i);
824 match &sym.decl {
825 hir::SymDecl::NativeFunction(_, ref cxx_name, _) => {
826 let mut name = sym.name.as_str();
827 if state.output_cxx {
828 name = cxx_name.unwrap_or(name);
829 }
830 state.write(name);
831 }
832 hir::SymDecl::Global(..) => {
833 if state.output_cxx {
834 add_used_global(state, i);
835 }
836 let mut name = sym.name.as_str();
837 if state.output_cxx {
838 name = glsl_primitive_type_name_to_cxx(name);
839 }
840 state.write(name);
841 }
842 hir::SymDecl::UserFunction(..) | hir::SymDecl::Local(..) | hir::SymDecl::Struct(..) => {
843 let mut name = sym.name.as_str();
844 // we want to replace constructor names
845 if state.output_cxx {
846 name = glsl_primitive_type_name_to_cxx(name);
847 }
848 state.write(name);
849 }
850 }
851 }
852
show_variable(state: &OutputState, i: &hir::SymRef)853 pub fn show_variable(state: &OutputState, i: &hir::SymRef) {
854 let sym = state.hir.sym(*i);
855 match &sym.decl {
856 hir::SymDecl::Global(_, _, ty, _) => {
857 show_type(state, ty);
858 state.write(" ");
859 let mut name = sym.name.as_str();
860 if state.output_cxx {
861 name = glsl_primitive_type_name_to_cxx(name);
862 }
863 state.write(name);
864 }
865 _ => panic!(),
866 }
867 }
868
write_default_constructor(state: &OutputState, name: &str)869 pub fn write_default_constructor(state: &OutputState, name: &str) {
870 // write default constructor
871 let _ = write!(state, "{}() = default;\n", name);
872 }
873
write_constructor(state: &OutputState, name: &str, s: &hir::StructFields)874 pub fn write_constructor(state: &OutputState, name: &str, s: &hir::StructFields) {
875 if s.fields.len() == 1 {
876 state.write("explicit ");
877 }
878 let _ = write!(state, "{}(", name);
879 let mut first_field = true;
880 for field in &s.fields {
881 if !first_field {
882 state.write(", ");
883 }
884 show_type(state, &field.ty);
885 state.write(" ");
886 show_identifier_and_type(state, &field.name, &field.ty);
887 first_field = false;
888 }
889 state.write(") : ");
890
891 let mut first_field = true;
892 for field in &s.fields {
893 if !first_field {
894 state.write(", ");
895 }
896 let _ = write!(state, "{}({})", field.name, field.name);
897 first_field = false;
898 }
899 state.write("{}\n");
900 }
901
write_convert_constructor(state: &OutputState, name: &str, s: &hir::StructFields)902 pub fn write_convert_constructor(state: &OutputState, name: &str, s: &hir::StructFields) {
903 if s.fields.len() == 1 {
904 state.write("explicit ");
905 }
906 let _ = write!(state, "{}(", name);
907 let mut first_field = true;
908 for field in &s.fields {
909 if !first_field {
910 state.write(", ");
911 }
912
913 let is_scalar = state.is_scalar.replace(true);
914 show_type(state, &field.ty);
915 state.is_scalar.set(is_scalar);
916
917 state.write(" ");
918
919 show_identifier_and_type(state, &field.name, &field.ty);
920 first_field = false;
921 }
922 state.write(")");
923
924 let mut first_field = true;
925 for hir::StructField { ty, name } in &s.fields {
926 if ty.array_sizes.is_none() {
927 if first_field {
928 state.write(":");
929 } else {
930 state.write(",");
931 }
932 let _ = write!(state, "{}({})", name, name);
933 first_field = false;
934 }
935 }
936 state.write("{\n");
937 for hir::StructField { ty, name } in &s.fields {
938 if ty.array_sizes.is_some() {
939 let _ = write!(state, "this->{}.convert({});\n", name, name);
940 }
941 }
942 state.write("}\n");
943
944 let _ = write!(state, "IMPLICIT {}({}_scalar s)", name, name);
945 let mut first_field = true;
946 for hir::StructField { ty, name } in &s.fields {
947 if ty.array_sizes.is_none() {
948 if first_field {
949 state.write(":");
950 } else {
951 state.write(",");
952 }
953 let _ = write!(state, "{}(s.{})", name, name);
954 first_field = false;
955 }
956 }
957 state.write("{\n");
958 for hir::StructField { ty, name } in &s.fields {
959 if ty.array_sizes.is_some() {
960 let _ = write!(state, "{}.convert(s.{});\n", name, name);
961 }
962 }
963 state.write("}\n");
964 }
965
write_if_then_else(state: &OutputState, name: &str, s: &hir::StructFields)966 pub fn write_if_then_else(state: &OutputState, name: &str, s: &hir::StructFields) {
967 let _ = write!(
968 state,
969 "friend {} if_then_else(I32 c, {} t, {} e) {{ return {}(\n",
970 name, name, name, name
971 );
972 let mut first_field = true;
973 for field in &s.fields {
974 if !first_field {
975 state.write(", ");
976 }
977 let _ = write!(state, "if_then_else(c, t.{}, e.{})", field.name, field.name);
978 first_field = false;
979 }
980 state.write(");\n}");
981 }
982
show_storage_class(state: &OutputState, q: &hir::StorageClass)983 pub fn show_storage_class(state: &OutputState, q: &hir::StorageClass) {
984 match *q {
985 hir::StorageClass::None => {}
986 hir::StorageClass::Const => {
987 state.write("const ");
988 }
989 hir::StorageClass::In => {
990 state.write("in ");
991 }
992 hir::StorageClass::Out => {
993 state.write("out ");
994 }
995 hir::StorageClass::FragColor(index) => {
996 write!(state, "layout(location = 0, index = {}) out ", index);
997 }
998 hir::StorageClass::Uniform | hir::StorageClass::Sampler(..) => {
999 state.write("uniform ");
1000 }
1001 }
1002 }
1003
show_sym_decl(state: &OutputState, i: &hir::SymRef)1004 pub fn show_sym_decl(state: &OutputState, i: &hir::SymRef) {
1005 let sym = state.hir.sym(*i);
1006 match &sym.decl {
1007 hir::SymDecl::Global(storage, ..) => {
1008 if !state.output_cxx {
1009 show_storage_class(state, storage)
1010 }
1011 if storage == &hir::StorageClass::Const {
1012 state.write("static constexpr ");
1013 }
1014 let mut name = sym.name.as_str();
1015 if state.output_cxx {
1016 name = glsl_primitive_type_name_to_cxx(name);
1017 }
1018 state.write(name);
1019 }
1020 hir::SymDecl::Local(storage, ..) => {
1021 if !state.output_cxx {
1022 show_storage_class(state, storage)
1023 }
1024 if storage == &hir::StorageClass::Const {
1025 state.write("const ");
1026 }
1027 let mut name = sym.name.as_str();
1028 if state.output_cxx {
1029 name = glsl_primitive_type_name_to_cxx(name);
1030 }
1031 state.write(name);
1032 }
1033 hir::SymDecl::Struct(s) => {
1034 let name = sym.name.as_str();
1035
1036 if state.output_cxx {
1037 let name_scalar = format!("{}_scalar", name);
1038 write!(state, "struct {} {{\n", name_scalar);
1039 let is_scalar = state.is_scalar.replace(true);
1040 for field in &s.fields {
1041 show_struct_field(state, field);
1042 }
1043 write_default_constructor(state, &name_scalar);
1044 write_constructor(state, &name_scalar, s);
1045 state.is_scalar.set(is_scalar);
1046 state.write("};\n");
1047 }
1048
1049 write!(state, "struct {} {{\n", name);
1050 for field in &s.fields {
1051 show_struct_field(state, field);
1052 }
1053
1054 // write if_then_else
1055 if state.output_cxx {
1056 write_default_constructor(state, name);
1057 write_constructor(state, name, s);
1058 write_convert_constructor(state, name, s);
1059 write_if_then_else(state, name, s);
1060 }
1061 state.write("}");
1062 }
1063 _ => panic!(),
1064 }
1065 }
1066
show_type_name(state: &OutputState, t: &syntax::TypeName)1067 pub fn show_type_name(state: &OutputState, t: &syntax::TypeName) {
1068 state.write(&t.0);
1069 }
1070
show_type_specifier_non_array(state: &mut OutputState, t: &syntax::TypeSpecifierNonArray)1071 pub fn show_type_specifier_non_array(state: &mut OutputState, t: &syntax::TypeSpecifierNonArray) {
1072 if let Some(kind) = hir::TypeKind::from_primitive_type_specifier(t) {
1073 show_type_kind(state, &kind);
1074 } else {
1075 match t {
1076 syntax::TypeSpecifierNonArray::Struct(ref _s) => panic!(), //show_struct_non_declaration(state, s),
1077 syntax::TypeSpecifierNonArray::TypeName(ref tn) => show_type_name(state, tn),
1078 _ => unreachable!(),
1079 }
1080 }
1081 }
1082
show_type_kind(state: &OutputState, t: &hir::TypeKind)1083 pub fn show_type_kind(state: &OutputState, t: &hir::TypeKind) {
1084 if state.output_cxx {
1085 if state.is_scalar.get() {
1086 if let Some(name) = t.cxx_primitive_scalar_type_name() {
1087 state.write(name);
1088 } else if let Some(name) = t.cxx_primitive_type_name() {
1089 let mut scalar_name = String::from(name);
1090 scalar_name.push_str("_scalar");
1091 state.write(scalar_name.as_str());
1092 } else {
1093 match t {
1094 hir::TypeKind::Struct(ref s) => {
1095 let mut scalar_name = String::from(state.hir.sym(*s).name.as_str());
1096 scalar_name.push_str("_scalar");
1097 state.write(scalar_name.as_str());
1098 }
1099 _ => unreachable!(),
1100 }
1101 }
1102 } else if let Some(name) = t.cxx_primitive_type_name() {
1103 state.write(name);
1104 } else {
1105 match t {
1106 hir::TypeKind::Struct(ref s) => {
1107 state.write(state.hir.sym(*s).name.as_str());
1108 }
1109 _ => unreachable!(),
1110 }
1111 }
1112 } else if let Some(name) = t.glsl_primitive_type_name() {
1113 state.write(name);
1114 } else {
1115 match t {
1116 hir::TypeKind::Struct(ref s) => {
1117 state.write(state.hir.sym(*s).name.as_str());
1118 }
1119 _ => unreachable!(),
1120 }
1121 }
1122 }
1123
show_type_specifier(state: &mut OutputState, t: &syntax::TypeSpecifier)1124 pub fn show_type_specifier(state: &mut OutputState, t: &syntax::TypeSpecifier) {
1125 show_type_specifier_non_array(state, &t.ty);
1126
1127 if let Some(ref arr_spec) = t.array_specifier {
1128 show_array_spec(state, arr_spec);
1129 }
1130 }
1131
show_type(state: &OutputState, t: &Type)1132 pub fn show_type(state: &OutputState, t: &Type) {
1133 if !state.output_cxx {
1134 if let Some(ref precision) = t.precision {
1135 show_precision_qualifier(state, precision);
1136 state.write(" ");
1137 }
1138 }
1139
1140 if state.output_cxx {
1141 if let Some(ref array) = t.array_sizes {
1142 state.write("Array<");
1143 show_type_kind(state, &t.kind);
1144 let size = match &array.sizes[..] {
1145 [size] => size,
1146 _ => panic!(),
1147 };
1148 state.write(",");
1149 show_hir_expr(state, size);
1150 state.write(">");
1151 } else {
1152 show_type_kind(state, &t.kind);
1153 }
1154 } else {
1155 show_type_kind(state, &t.kind);
1156 }
1157
1158 /*if let Some(ref arr_spec) = t.array_sizes {
1159 panic!();
1160 }*/
1161 }
1162
1163 /*pub fn show_fully_specified_type(state: &mut OutputState, t: &FullySpecifiedType) {
1164 state.flat = false;
1165 if let Some(ref qual) = t.qualifier {
1166 if !state.output_cxx {
1167 show_type_qualifier(state, &qual);
1168 } else {
1169 state.flat =
1170 qual.qualifiers.0.iter()
1171 .flat_map(|q| match q { syntax::TypeQualifierSpec::Interpolation(Flat) => Some(()), _ => None})
1172 .next().is_some();
1173 }
1174 state.write(" ");
1175 }
1176
1177 show_type_specifier(state, &t.ty);
1178 }*/
1179
1180 /*pub fn show_struct_non_declaration(state: &mut OutputState, s: &syntax::StructSpecifier) {
1181 state.write("struct ");
1182
1183 if let Some(ref name) = s.name {
1184 let _ = write!(state, "{} ", name);
1185 }
1186
1187 state.write("{\n");
1188
1189 for field in &s.fields.0 {
1190 show_struct_field(state, field);
1191 }
1192
1193 state.write("}");
1194 }*/
1195
show_struct(_state: &OutputState, _s: &syntax::StructSpecifier)1196 pub fn show_struct(_state: &OutputState, _s: &syntax::StructSpecifier) {
1197 panic!();
1198 //show_struct_non_declaration(state, s);
1199 //state.write(";\n");
1200 }
1201
show_struct_field(state: &OutputState, field: &hir::StructField)1202 pub fn show_struct_field(state: &OutputState, field: &hir::StructField) {
1203 show_type(state, &field.ty);
1204 state.write(" ");
1205
1206 show_identifier_and_type(state, &field.name, &field.ty);
1207
1208 state.write(";\n");
1209 }
1210
show_array_spec(state: &OutputState, a: &syntax::ArraySpecifier)1211 pub fn show_array_spec(state: &OutputState, a: &syntax::ArraySpecifier) {
1212 match *a {
1213 syntax::ArraySpecifier::Unsized => {
1214 state.write("[]");
1215 }
1216 syntax::ArraySpecifier::ExplicitlySized(ref e) => {
1217 state.write("[");
1218 show_expr(state, &e);
1219 state.write("]");
1220 }
1221 }
1222 }
1223
show_identifier_and_type(state: &OutputState, ident: &syntax::Identifier, ty: &hir::Type)1224 pub fn show_identifier_and_type(state: &OutputState, ident: &syntax::Identifier, ty: &hir::Type) {
1225 let _ = write!(state, "{}", ident);
1226
1227 if !state.output_cxx {
1228 if let Some(ref arr_spec) = ty.array_sizes {
1229 show_array_sizes(state, &arr_spec);
1230 }
1231 }
1232 }
1233
show_arrayed_identifier(state: &OutputState, ident: &syntax::ArrayedIdentifier)1234 pub fn show_arrayed_identifier(state: &OutputState, ident: &syntax::ArrayedIdentifier) {
1235 let _ = write!(state, "{}", ident.ident);
1236
1237 if let Some(ref arr_spec) = ident.array_spec {
1238 show_array_spec(state, &arr_spec);
1239 }
1240 }
1241
show_array_sizes(state: &OutputState, a: &hir::ArraySizes)1242 pub fn show_array_sizes(state: &OutputState, a: &hir::ArraySizes) {
1243 state.write("[");
1244 match &a.sizes[..] {
1245 [a] => show_hir_expr(state, a),
1246 _ => panic!(),
1247 }
1248
1249 state.write("]");
1250 /*
1251 match *a {
1252 syntax::ArraySpecifier::Unsized => { state.write("[]"); }
1253 syntax::ArraySpecifier::ExplicitlySized(ref e) => {
1254 state.write("[");
1255 show_expr(state, &e);
1256 state.write("]");
1257 }
1258 }*/
1259 }
1260
show_type_qualifier(state: &OutputState, q: &hir::TypeQualifier)1261 pub fn show_type_qualifier(state: &OutputState, q: &hir::TypeQualifier) {
1262 let mut qualifiers = q.qualifiers.0.iter();
1263 let first = qualifiers.next().unwrap();
1264
1265 show_type_qualifier_spec(state, first);
1266
1267 for qual_spec in qualifiers {
1268 state.write(" ");
1269 show_type_qualifier_spec(state, qual_spec)
1270 }
1271 }
1272
show_type_qualifier_spec(state: &OutputState, q: &hir::TypeQualifierSpec)1273 pub fn show_type_qualifier_spec(state: &OutputState, q: &hir::TypeQualifierSpec) {
1274 match *q {
1275 hir::TypeQualifierSpec::Layout(ref l) => show_layout_qualifier(state, &l),
1276 hir::TypeQualifierSpec::Parameter(ref _p) => panic!(),
1277 hir::TypeQualifierSpec::Memory(ref _m) => panic!(),
1278 hir::TypeQualifierSpec::Invariant => {
1279 state.write("invariant");
1280 }
1281 hir::TypeQualifierSpec::Precise => {
1282 state.write("precise");
1283 }
1284 }
1285 }
1286
show_syntax_storage_qualifier(state: &OutputState, q: &syntax::StorageQualifier)1287 pub fn show_syntax_storage_qualifier(state: &OutputState, q: &syntax::StorageQualifier) {
1288 match *q {
1289 syntax::StorageQualifier::Const => {
1290 state.write("const");
1291 }
1292 syntax::StorageQualifier::InOut => {
1293 state.write("inout");
1294 }
1295 syntax::StorageQualifier::In => {
1296 state.write("in");
1297 }
1298 syntax::StorageQualifier::Out => {
1299 state.write("out");
1300 }
1301 syntax::StorageQualifier::Centroid => {
1302 state.write("centroid");
1303 }
1304 syntax::StorageQualifier::Patch => {
1305 state.write("patch");
1306 }
1307 syntax::StorageQualifier::Sample => {
1308 state.write("sample");
1309 }
1310 syntax::StorageQualifier::Uniform => {
1311 state.write("uniform");
1312 }
1313 syntax::StorageQualifier::Attribute => {
1314 state.write("attribute");
1315 }
1316 syntax::StorageQualifier::Varying => {
1317 state.write("varying");
1318 }
1319 syntax::StorageQualifier::Buffer => {
1320 state.write("buffer");
1321 }
1322 syntax::StorageQualifier::Shared => {
1323 state.write("shared");
1324 }
1325 syntax::StorageQualifier::Coherent => {
1326 state.write("coherent");
1327 }
1328 syntax::StorageQualifier::Volatile => {
1329 state.write("volatile");
1330 }
1331 syntax::StorageQualifier::Restrict => {
1332 state.write("restrict");
1333 }
1334 syntax::StorageQualifier::ReadOnly => {
1335 state.write("readonly");
1336 }
1337 syntax::StorageQualifier::WriteOnly => {
1338 state.write("writeonly");
1339 }
1340 syntax::StorageQualifier::Subroutine(ref n) => show_subroutine(state, &n),
1341 }
1342 }
1343
show_subroutine(state: &OutputState, types: &[syntax::TypeName])1344 pub fn show_subroutine(state: &OutputState, types: &[syntax::TypeName]) {
1345 state.write("subroutine");
1346
1347 if !types.is_empty() {
1348 state.write("(");
1349
1350 let mut types_iter = types.iter();
1351 let first = types_iter.next().unwrap();
1352
1353 show_type_name(state, first);
1354
1355 for type_name in types_iter {
1356 state.write(", ");
1357 show_type_name(state, type_name);
1358 }
1359
1360 state.write(")");
1361 }
1362 }
1363
show_layout_qualifier(state: &OutputState, l: &syntax::LayoutQualifier)1364 pub fn show_layout_qualifier(state: &OutputState, l: &syntax::LayoutQualifier) {
1365 let mut qualifiers = l.ids.0.iter();
1366 let first = qualifiers.next().unwrap();
1367
1368 state.write("layout (");
1369 show_layout_qualifier_spec(state, first);
1370
1371 for qual_spec in qualifiers {
1372 state.write(", ");
1373 show_layout_qualifier_spec(state, qual_spec);
1374 }
1375
1376 state.write(")");
1377 }
1378
show_layout_qualifier_spec(state: &OutputState, l: &syntax::LayoutQualifierSpec)1379 pub fn show_layout_qualifier_spec(state: &OutputState, l: &syntax::LayoutQualifierSpec) {
1380 match *l {
1381 syntax::LayoutQualifierSpec::Identifier(ref i, Some(ref e)) => {
1382 let _ = write!(state, "{} = ", i);
1383 show_expr(state, &e);
1384 }
1385 syntax::LayoutQualifierSpec::Identifier(ref i, None) => show_identifier(state, &i),
1386 syntax::LayoutQualifierSpec::Shared => {
1387 state.write("shared");
1388 }
1389 }
1390 }
1391
show_precision_qualifier(state: &OutputState, p: &syntax::PrecisionQualifier)1392 pub fn show_precision_qualifier(state: &OutputState, p: &syntax::PrecisionQualifier) {
1393 match *p {
1394 syntax::PrecisionQualifier::High => {
1395 state.write("highp");
1396 }
1397 syntax::PrecisionQualifier::Medium => {
1398 state.write("mediump");
1399 }
1400 syntax::PrecisionQualifier::Low => {
1401 state.write("low");
1402 }
1403 }
1404 }
1405
show_interpolation_qualifier(state: &OutputState, i: &syntax::InterpolationQualifier)1406 pub fn show_interpolation_qualifier(state: &OutputState, i: &syntax::InterpolationQualifier) {
1407 match *i {
1408 syntax::InterpolationQualifier::Smooth => {
1409 state.write("smooth");
1410 }
1411 syntax::InterpolationQualifier::Flat => {
1412 state.write("flat");
1413 }
1414 syntax::InterpolationQualifier::NoPerspective => {
1415 state.write("noperspective");
1416 }
1417 }
1418 }
1419
show_parameter_qualifier(state: &mut OutputState, i: &Option<hir::ParameterQualifier>)1420 pub fn show_parameter_qualifier(state: &mut OutputState, i: &Option<hir::ParameterQualifier>) {
1421 if let Some(i) = i {
1422 if state.output_cxx {
1423 match *i {
1424 hir::ParameterQualifier::Out => {
1425 state.write("&");
1426 }
1427 hir::ParameterQualifier::InOut => {
1428 state.write("&");
1429 }
1430 _ => {}
1431 }
1432 } else {
1433 match *i {
1434 hir::ParameterQualifier::Const => {
1435 state.write("const");
1436 }
1437 hir::ParameterQualifier::In => {
1438 state.write("in");
1439 }
1440 hir::ParameterQualifier::Out => {
1441 state.write("out");
1442 }
1443 hir::ParameterQualifier::InOut => {
1444 state.write("inout");
1445 }
1446 }
1447 }
1448 }
1449 }
1450
show_float(state: &OutputState, x: f32)1451 pub fn show_float(state: &OutputState, x: f32) {
1452 if x.fract() == 0. {
1453 write!(state, "{}.f", x);
1454 } else {
1455 write!(state, "{}f", x);
1456 }
1457 }
1458
show_double(state: &OutputState, x: f64)1459 pub fn show_double(state: &OutputState, x: f64) {
1460 // force doubles to print as floats
1461 if x.fract() == 0. {
1462 write!(state, "{}.f", x);
1463 } else {
1464 write!(state, "{}f", x);
1465 }
1466 }
1467
1468 trait SwizzelSelectorExt {
to_args(&self) -> String1469 fn to_args(&self) -> String;
1470 }
1471
1472 impl SwizzelSelectorExt for SwizzleSelector {
to_args(&self) -> String1473 fn to_args(&self) -> String {
1474 let mut s = Vec::new();
1475 let fs = match self.field_set {
1476 hir::FieldSet::Rgba => ["R", "G", "B", "A"],
1477 hir::FieldSet::Xyzw => ["X", "Y", "Z", "W"],
1478 hir::FieldSet::Stpq => ["S", "T", "P", "Q"],
1479 };
1480 for i in &self.components {
1481 s.push(fs[*i as usize])
1482 }
1483 s.join(", ")
1484 }
1485 }
1486
expr_run_class(state: &OutputState, expr: &hir::Expr) -> hir::RunClass1487 fn expr_run_class(state: &OutputState, expr: &hir::Expr) -> hir::RunClass {
1488 match &expr.kind {
1489 hir::ExprKind::Variable(i) => symbol_run_class(&state.hir.sym(*i).decl, state.vector_mask),
1490 hir::ExprKind::IntConst(_)
1491 | hir::ExprKind::UIntConst(_)
1492 | hir::ExprKind::BoolConst(_)
1493 | hir::ExprKind::FloatConst(_)
1494 | hir::ExprKind::DoubleConst(_) => hir::RunClass::Scalar,
1495 hir::ExprKind::Unary(_, ref e) => expr_run_class(state, e),
1496 hir::ExprKind::Binary(_, ref l, ref r) => {
1497 expr_run_class(state, l).merge(expr_run_class(state, r))
1498 }
1499 hir::ExprKind::Ternary(ref c, ref s, ref e) => expr_run_class(state, c)
1500 .merge(expr_run_class(state, s))
1501 .merge(expr_run_class(state, e)),
1502 hir::ExprKind::Assignment(ref v, _, ref e) => {
1503 expr_run_class(state, v).merge(expr_run_class(state, e))
1504 }
1505 hir::ExprKind::Bracket(ref e, ref indx) => {
1506 expr_run_class(state, e).merge(expr_run_class(state, indx))
1507 }
1508 hir::ExprKind::FunCall(ref fun, ref args) => {
1509 let arg_mask: u32 = args.iter().enumerate().fold(0, |mask, (idx, e)| {
1510 if expr_run_class(state, e) == hir::RunClass::Vector {
1511 mask | (1 << idx)
1512 } else {
1513 mask
1514 }
1515 });
1516 match fun {
1517 hir::FunIdentifier::Identifier(ref sym) => match &state.hir.sym(*sym).decl {
1518 hir::SymDecl::NativeFunction(_, _, ref ret_class) => {
1519 if *ret_class != hir::RunClass::Unknown {
1520 *ret_class
1521 } else if arg_mask != 0 {
1522 hir::RunClass::Vector
1523 } else {
1524 hir::RunClass::Scalar
1525 }
1526 }
1527 hir::SymDecl::UserFunction(ref fd, ref run_class) => {
1528 let param_mask: u32 = fd.prototype.parameters.iter().enumerate().fold(
1529 arg_mask,
1530 |mask, (idx, param)| {
1531 if let hir::FunctionParameterDeclaration::Named(Some(qual), p) =
1532 param
1533 {
1534 match qual {
1535 hir::ParameterQualifier::InOut
1536 | hir::ParameterQualifier::Out => {
1537 if symbol_run_class(
1538 &state.hir.sym(p.sym).decl,
1539 arg_mask,
1540 ) == hir::RunClass::Vector
1541 {
1542 mask | (1 << idx)
1543 } else {
1544 mask
1545 }
1546 }
1547 _ => mask,
1548 }
1549 } else {
1550 mask
1551 }
1552 },
1553 );
1554 match *run_class {
1555 hir::RunClass::Scalar => hir::RunClass::Scalar,
1556 hir::RunClass::Dependent(mask) => {
1557 if (mask & param_mask) != 0 {
1558 hir::RunClass::Vector
1559 } else {
1560 hir::RunClass::Scalar
1561 }
1562 }
1563 _ => hir::RunClass::Vector,
1564 }
1565 }
1566 hir::SymDecl::Struct(..) => {
1567 if arg_mask != 0 {
1568 hir::RunClass::Vector
1569 } else {
1570 hir::RunClass::Scalar
1571 }
1572 }
1573 _ => panic!(),
1574 },
1575 hir::FunIdentifier::Constructor(..) => {
1576 if arg_mask != 0 {
1577 hir::RunClass::Vector
1578 } else {
1579 hir::RunClass::Scalar
1580 }
1581 }
1582 }
1583 }
1584 hir::ExprKind::Dot(ref e, _) => expr_run_class(state, e),
1585 hir::ExprKind::SwizzleSelector(ref e, _) => expr_run_class(state, e),
1586 hir::ExprKind::PostInc(ref e) => expr_run_class(state, e),
1587 hir::ExprKind::PostDec(ref e) => expr_run_class(state, e),
1588 hir::ExprKind::Comma(_, ref e) => expr_run_class(state, e),
1589 hir::ExprKind::Cond(_, ref e) => expr_run_class(state, e),
1590 hir::ExprKind::CondMask => hir::RunClass::Vector,
1591 }
1592 }
1593
show_hir_expr(state: &OutputState, expr: &hir::Expr)1594 pub fn show_hir_expr(state: &OutputState, expr: &hir::Expr) {
1595 show_hir_expr_inner(state, expr, false);
1596 }
1597
show_hir_expr_inner(state: &OutputState, expr: &hir::Expr, top_level: bool)1598 pub fn show_hir_expr_inner(state: &OutputState, expr: &hir::Expr, top_level: bool) {
1599 match expr.kind {
1600 hir::ExprKind::Variable(ref i) => show_sym(state, i),
1601 hir::ExprKind::IntConst(ref x) => {
1602 let _ = write!(state, "{}", x);
1603 }
1604 hir::ExprKind::UIntConst(ref x) => {
1605 let _ = write!(state, "{}u", x);
1606 }
1607 hir::ExprKind::BoolConst(ref x) => {
1608 let _ = write!(state, "{}", x);
1609 }
1610 hir::ExprKind::FloatConst(ref x) => show_float(state, *x),
1611 hir::ExprKind::DoubleConst(ref x) => show_double(state, *x),
1612 hir::ExprKind::Unary(ref op, ref e) => {
1613 show_unary_op(state, &op);
1614 state.write("(");
1615 show_hir_expr(state, &e);
1616 state.write(")");
1617 }
1618 hir::ExprKind::Binary(ref op, ref l, ref r) => {
1619 state.write("(");
1620 show_hir_expr(state, &l);
1621 state.write(")");
1622 show_binary_op(state, &op);
1623 state.write("(");
1624 show_hir_expr(state, &r);
1625 state.write(")");
1626 }
1627 hir::ExprKind::Ternary(ref c, ref s, ref e) => {
1628 if state.output_cxx && expr_run_class(state, c) != hir::RunClass::Scalar {
1629 state.write("if_then_else(");
1630 show_hir_expr(state, &c);
1631 state.write(", ");
1632 show_hir_expr(state, &s);
1633 state.write(", ");
1634 show_hir_expr(state, &e);
1635 state.write(")");
1636 } else {
1637 show_hir_expr(state, &c);
1638 state.write(" ? ");
1639 show_hir_expr(state, &s);
1640 state.write(" : ");
1641 show_hir_expr(state, &e);
1642 }
1643 }
1644 hir::ExprKind::Assignment(ref v, ref op, ref e) => {
1645 let is_output = hir::is_output(v, &state.hir).is_some();
1646 let is_scalar_var = expr_run_class(state, v) == hir::RunClass::Scalar;
1647 let is_scalar_expr = expr_run_class(state, e) == hir::RunClass::Scalar;
1648 let force_scalar = is_scalar_var && !is_scalar_expr;
1649
1650 if let Some(mask) = &state.mask {
1651 let is_scalar_mask = expr_run_class(state, mask) == hir::RunClass::Scalar;
1652 let force_scalar_mask = is_scalar_var && is_scalar_expr && !is_scalar_mask;
1653
1654 if force_scalar || force_scalar_mask {
1655 if top_level {
1656 state.write("if (");
1657 } else {
1658 state.write("(");
1659 }
1660 } else {
1661 state.is_lval.set(true);
1662 show_hir_expr(state, &v);
1663 state.is_lval.set(false);
1664 state.write(" = if_then_else(");
1665 }
1666
1667 if is_output && state.return_declared {
1668 state.write("((");
1669 show_hir_expr(state, mask);
1670 state.write(")&ret_mask)");
1671 } else {
1672 show_hir_expr(state, mask);
1673 }
1674 if force_scalar || force_scalar_mask {
1675 if top_level {
1676 state.write("[0]) { ");
1677 } else {
1678 state.write("[0] ? ");
1679 }
1680 state.is_lval.set(true);
1681 show_hir_expr(state, &v);
1682 state.is_lval.set(false);
1683 state.write(" = ");
1684 } else {
1685 state.write(",");
1686 }
1687
1688 if op != &syntax::AssignmentOp::Equal {
1689 show_hir_expr(state, &v);
1690 }
1691
1692 match *op {
1693 syntax::AssignmentOp::Equal => {}
1694 syntax::AssignmentOp::Mult => {
1695 state.write("*");
1696 }
1697 syntax::AssignmentOp::Div => {
1698 state.write("/");
1699 }
1700 syntax::AssignmentOp::Mod => {
1701 state.write("%");
1702 }
1703 syntax::AssignmentOp::Add => {
1704 state.write("+");
1705 }
1706 syntax::AssignmentOp::Sub => {
1707 state.write("-");
1708 }
1709 syntax::AssignmentOp::LShift => {
1710 state.write("<<");
1711 }
1712 syntax::AssignmentOp::RShift => {
1713 state.write(">>");
1714 }
1715 syntax::AssignmentOp::And => {
1716 state.write("&");
1717 }
1718 syntax::AssignmentOp::Xor => {
1719 state.write("^");
1720 }
1721 syntax::AssignmentOp::Or => {
1722 state.write("|");
1723 }
1724 }
1725 if force_scalar {
1726 state.write("force_scalar(");
1727 }
1728 show_hir_expr(state, &e);
1729 if force_scalar {
1730 state.write(")");
1731 }
1732 if force_scalar || force_scalar_mask {
1733 if top_level {
1734 state.write("; }");
1735 } else {
1736 state.write(" : ");
1737 show_hir_expr(state, &v);
1738 state.write(")");
1739 }
1740 } else {
1741 state.write(",");
1742 show_hir_expr(state, &v);
1743 state.write(")");
1744 }
1745 } else {
1746 state.is_lval.set(true);
1747 show_hir_expr(state, &v);
1748 state.is_lval.set(false);
1749 state.write(" ");
1750
1751 if is_output && state.return_declared {
1752 state.write("= ");
1753 if force_scalar {
1754 state.write("force_scalar(");
1755 }
1756 state.write("if_then_else(ret_mask,");
1757
1758 if op != &syntax::AssignmentOp::Equal {
1759 show_hir_expr(state, &v);
1760 }
1761
1762 match *op {
1763 syntax::AssignmentOp::Equal => {}
1764 syntax::AssignmentOp::Mult => {
1765 state.write("*");
1766 }
1767 syntax::AssignmentOp::Div => {
1768 state.write("/");
1769 }
1770 syntax::AssignmentOp::Mod => {
1771 state.write("%");
1772 }
1773 syntax::AssignmentOp::Add => {
1774 state.write("+");
1775 }
1776 syntax::AssignmentOp::Sub => {
1777 state.write("-");
1778 }
1779 syntax::AssignmentOp::LShift => {
1780 state.write("<<");
1781 }
1782 syntax::AssignmentOp::RShift => {
1783 state.write(">>");
1784 }
1785 syntax::AssignmentOp::And => {
1786 state.write("&");
1787 }
1788 syntax::AssignmentOp::Xor => {
1789 state.write("^");
1790 }
1791 syntax::AssignmentOp::Or => {
1792 state.write("|");
1793 }
1794 }
1795 show_hir_expr(state, &e);
1796 state.write(",");
1797 show_hir_expr(state, &v);
1798 state.write(")");
1799 } else {
1800 show_assignment_op(state, &op);
1801 state.write(" ");
1802 if force_scalar {
1803 state.write("force_scalar(");
1804 }
1805 show_hir_expr(state, &e);
1806 }
1807
1808 if force_scalar {
1809 state.write(")");
1810 }
1811 }
1812 }
1813 hir::ExprKind::Bracket(ref e, ref indx) => {
1814 show_hir_expr(state, &e);
1815 state.write("[");
1816 show_hir_expr(state, indx);
1817 state.write("]");
1818 }
1819 hir::ExprKind::FunCall(ref fun, ref args) => {
1820 let mut cond_mask: u32 = 0;
1821 let mut adapt_mask: u32 = 0;
1822 let mut has_ret = false;
1823 let mut array_constructor = false;
1824
1825 let mut arg_mask: u32 = 0;
1826 for (idx, e) in args.iter().enumerate() {
1827 if expr_run_class(state, e) == hir::RunClass::Vector {
1828 arg_mask |= 1 << idx;
1829 }
1830 }
1831
1832 match fun {
1833 hir::FunIdentifier::Constructor(t) => {
1834 let is_scalar = state.is_scalar.replace(arg_mask == 0);
1835 show_type(state, t);
1836 state.is_scalar.set(is_scalar);
1837 array_constructor = t.array_sizes.is_some();
1838 }
1839 hir::FunIdentifier::Identifier(name) => {
1840 if state.output_cxx {
1841 let sym = state.hir.sym(*name);
1842 match &sym.decl {
1843 hir::SymDecl::NativeFunction(..) => {
1844 if sym.name == "texelFetchOffset" && args.len() >= 4 {
1845 if let Some((sampler, base, x, y)) = hir::get_texel_fetch_offset(
1846 &state.hir, &args[0], &args[1], &args[3],
1847 ) {
1848 let base_sym = state.hir.sym(base);
1849 let sampler_sym = state.hir.sym(sampler);
1850 add_used_global(state, &sampler);
1851 if let hir::SymDecl::Global(..) = &base_sym.decl {
1852 add_used_global(state, &base);
1853 }
1854 write!(
1855 state,
1856 "texelFetchUnchecked({}, {}_{}_fetch, {}, {})",
1857 sampler_sym.name,
1858 sampler_sym.name,
1859 base_sym.name,
1860 x,
1861 y,
1862 );
1863 return;
1864 }
1865 }
1866 show_sym(state, name)
1867 }
1868 hir::SymDecl::UserFunction(ref fd, ref _run_class) => {
1869 if (state.mask.is_some() || state.return_declared) &&
1870 !fd.globals.is_empty()
1871 {
1872 cond_mask |= 1 << 31;
1873 }
1874 let mut param_mask: u32 = 0;
1875 for (idx, (param, e)) in
1876 fd.prototype.parameters.iter().zip(args.iter()).enumerate()
1877 {
1878 if let hir::FunctionParameterDeclaration::Named(qual, p) = param
1879 {
1880 if symbol_run_class(&state.hir.sym(p.sym).decl, arg_mask)
1881 == hir::RunClass::Vector
1882 {
1883 param_mask |= 1 << idx;
1884 }
1885 match qual {
1886 Some(hir::ParameterQualifier::InOut)
1887 | Some(hir::ParameterQualifier::Out) => {
1888 if state.mask.is_some() || state.return_declared {
1889 cond_mask |= 1 << idx;
1890 }
1891 if (!arg_mask & param_mask & (1 << idx)) != 0 {
1892 if adapt_mask == 0 {
1893 state.write(if top_level {
1894 "{ "
1895 } else {
1896 "({ "
1897 });
1898 }
1899 show_type(state, &p.ty);
1900 write!(state, " _arg{}_ = ", idx);
1901 show_hir_expr(state, e);
1902 state.write("; ");
1903 adapt_mask |= 1 << idx;
1904 }
1905 }
1906 _ => {}
1907 }
1908 }
1909 }
1910 if adapt_mask != 0 &&
1911 fd.prototype.ty.kind != hir::TypeKind::Void &&
1912 !top_level
1913 {
1914 state.write("auto _ret_ = ");
1915 has_ret = true;
1916 }
1917 show_sym(state, name);
1918 let mut deps = state.deps.borrow_mut();
1919 let dep_key = (
1920 *name,
1921 if cond_mask != 0 {
1922 param_mask | (1 << 31)
1923 } else {
1924 param_mask
1925 },
1926 );
1927 if !deps.contains(&dep_key) {
1928 deps.push(dep_key);
1929 }
1930 }
1931 hir::SymDecl::Struct(..) => {
1932 show_sym(state, name);
1933 if arg_mask == 0 {
1934 state.write("_scalar");
1935 }
1936 }
1937 _ => panic!("bad identifier to function call"),
1938 }
1939 }
1940 }
1941 }
1942
1943 if array_constructor {
1944 state.write("{{");
1945 } else {
1946 state.write("(");
1947 }
1948
1949 for (idx, e) in args.iter().enumerate() {
1950 if idx != 0 {
1951 state.write(", ");
1952 }
1953 if (adapt_mask & (1 << idx)) != 0 {
1954 write!(state, "_arg{}_", idx);
1955 } else {
1956 show_hir_expr(state, e);
1957 }
1958 }
1959
1960 if cond_mask != 0 {
1961 if !args.is_empty() {
1962 state.write(", ");
1963 }
1964 if let Some(mask) = &state.mask {
1965 if state.return_declared {
1966 state.write("(");
1967 show_hir_expr(state, mask);
1968 state.write(")&ret_mask");
1969 } else {
1970 show_hir_expr(state, mask);
1971 }
1972 } else if state.return_declared {
1973 state.write("ret_mask");
1974 } else {
1975 state.write("~0");
1976 }
1977 }
1978
1979 if array_constructor {
1980 state.write("}}");
1981 } else {
1982 state.write(")");
1983 }
1984
1985 if adapt_mask != 0 {
1986 state.write("; ");
1987 for (idx, e) in args.iter().enumerate() {
1988 if (adapt_mask & (1 << idx)) != 0 {
1989 state.is_lval.set(true);
1990 show_hir_expr(state, e);
1991 state.is_lval.set(false);
1992 write!(state, " = force_scalar(_arg{}_); ", idx);
1993 }
1994 }
1995 if has_ret {
1996 state.write("_ret_; })");
1997 } else {
1998 state.write(if top_level { "}" } else { "})" });
1999 }
2000 }
2001 }
2002 hir::ExprKind::Dot(ref e, ref i) => {
2003 state.write("(");
2004 show_hir_expr(state, &e);
2005 state.write(")");
2006 state.write(".");
2007 show_identifier(state, i);
2008 }
2009 hir::ExprKind::SwizzleSelector(ref e, ref s) => {
2010 if state.output_cxx {
2011 if let hir::ExprKind::Variable(ref sym) = &e.kind {
2012 if state.hir.sym(*sym).name == "gl_FragCoord" {
2013 state.used_fragcoord.set(
2014 s.components.iter().fold(
2015 state.used_fragcoord.get(),
2016 |used, c| used | (1 << c)));
2017 }
2018 }
2019 state.write("(");
2020 show_hir_expr(state, &e);
2021 if state.is_lval.get() && s.components.len() > 1 {
2022 state.write(").lsel(");
2023 } else {
2024 state.write(").sel(");
2025 }
2026 state.write(&s.to_args());
2027 state.write(")");
2028 } else {
2029 state.write("(");
2030 show_hir_expr(state, &e);
2031 state.write(")");
2032 state.write(".");
2033 state.write(&s.to_string());
2034 }
2035 }
2036 hir::ExprKind::PostInc(ref e) => {
2037 show_hir_expr(state, &e);
2038 state.write("++");
2039 }
2040 hir::ExprKind::PostDec(ref e) => {
2041 show_hir_expr(state, &e);
2042 state.write("--");
2043 }
2044 hir::ExprKind::Comma(ref a, ref b) => {
2045 show_hir_expr(state, &a);
2046 state.write(", ");
2047 show_hir_expr(state, &b);
2048 }
2049 hir::ExprKind::Cond(index, _) => {
2050 write!(state, "_c{}_", index);
2051 }
2052 hir::ExprKind::CondMask => {
2053 state.write("_cond_mask_");
2054 }
2055 }
2056 }
2057
show_expr(state: &OutputState, expr: &syntax::Expr)2058 pub fn show_expr(state: &OutputState, expr: &syntax::Expr) {
2059 match *expr {
2060 syntax::Expr::Variable(ref i) => show_identifier(state, &i),
2061 syntax::Expr::IntConst(ref x) => {
2062 let _ = write!(state, "{}", x);
2063 }
2064 syntax::Expr::UIntConst(ref x) => {
2065 let _ = write!(state, "{}u", x);
2066 }
2067 syntax::Expr::BoolConst(ref x) => {
2068 let _ = write!(state, "{}", x);
2069 }
2070 syntax::Expr::FloatConst(ref x) => show_float(state, *x),
2071 syntax::Expr::DoubleConst(ref x) => show_double(state, *x),
2072 syntax::Expr::Unary(ref op, ref e) => {
2073 show_unary_op(state, &op);
2074 state.write("(");
2075 show_expr(state, &e);
2076 state.write(")");
2077 }
2078 syntax::Expr::Binary(ref op, ref l, ref r) => {
2079 state.write("(");
2080 show_expr(state, &l);
2081 state.write(")");
2082 show_binary_op(state, &op);
2083 state.write("(");
2084 show_expr(state, &r);
2085 state.write(")");
2086 }
2087 syntax::Expr::Ternary(ref c, ref s, ref e) => {
2088 show_expr(state, &c);
2089 state.write(" ? ");
2090 show_expr(state, &s);
2091 state.write(" : ");
2092 show_expr(state, &e);
2093 }
2094 syntax::Expr::Assignment(ref v, ref op, ref e) => {
2095 show_expr(state, &v);
2096 state.write(" ");
2097 show_assignment_op(state, &op);
2098 state.write(" ");
2099 show_expr(state, &e);
2100 }
2101 syntax::Expr::Bracket(ref e, ref a) => {
2102 show_expr(state, &e);
2103 show_array_spec(state, &a);
2104 }
2105 syntax::Expr::FunCall(ref fun, ref args) => {
2106 show_function_identifier(state, &fun);
2107 state.write("(");
2108
2109 if !args.is_empty() {
2110 let mut args_iter = args.iter();
2111 let first = args_iter.next().unwrap();
2112 show_expr(state, first);
2113
2114 for e in args_iter {
2115 state.write(", ");
2116 show_expr(state, e);
2117 }
2118 }
2119
2120 state.write(")");
2121 }
2122 syntax::Expr::Dot(ref e, ref i) => {
2123 state.write("(");
2124 show_expr(state, &e);
2125 state.write(")");
2126 state.write(".");
2127 show_identifier(state, &i);
2128 }
2129 syntax::Expr::PostInc(ref e) => {
2130 show_expr(state, &e);
2131 state.write("++");
2132 }
2133 syntax::Expr::PostDec(ref e) => {
2134 show_expr(state, &e);
2135 state.write("--");
2136 }
2137 syntax::Expr::Comma(ref a, ref b) => {
2138 show_expr(state, &a);
2139 state.write(", ");
2140 show_expr(state, &b);
2141 }
2142 }
2143 }
2144
show_unary_op(state: &OutputState, op: &syntax::UnaryOp)2145 pub fn show_unary_op(state: &OutputState, op: &syntax::UnaryOp) {
2146 match *op {
2147 syntax::UnaryOp::Inc => {
2148 state.write("++");
2149 }
2150 syntax::UnaryOp::Dec => {
2151 state.write("--");
2152 }
2153 syntax::UnaryOp::Add => {
2154 state.write("+");
2155 }
2156 syntax::UnaryOp::Minus => {
2157 state.write("-");
2158 }
2159 syntax::UnaryOp::Not => {
2160 state.write("!");
2161 }
2162 syntax::UnaryOp::Complement => {
2163 state.write("~");
2164 }
2165 }
2166 }
2167
show_binary_op(state: &OutputState, op: &syntax::BinaryOp)2168 pub fn show_binary_op(state: &OutputState, op: &syntax::BinaryOp) {
2169 match *op {
2170 syntax::BinaryOp::Or => {
2171 state.write("||");
2172 }
2173 syntax::BinaryOp::Xor => {
2174 state.write("^^");
2175 }
2176 syntax::BinaryOp::And => {
2177 state.write("&&");
2178 }
2179 syntax::BinaryOp::BitOr => {
2180 state.write("|");
2181 }
2182 syntax::BinaryOp::BitXor => {
2183 state.write("^");
2184 }
2185 syntax::BinaryOp::BitAnd => {
2186 state.write("&");
2187 }
2188 syntax::BinaryOp::Equal => {
2189 state.write("==");
2190 }
2191 syntax::BinaryOp::NonEqual => {
2192 state.write("!=");
2193 }
2194 syntax::BinaryOp::LT => {
2195 state.write("<");
2196 }
2197 syntax::BinaryOp::GT => {
2198 state.write(">");
2199 }
2200 syntax::BinaryOp::LTE => {
2201 state.write("<=");
2202 }
2203 syntax::BinaryOp::GTE => {
2204 state.write(">=");
2205 }
2206 syntax::BinaryOp::LShift => {
2207 state.write("<<");
2208 }
2209 syntax::BinaryOp::RShift => {
2210 state.write(">>");
2211 }
2212 syntax::BinaryOp::Add => {
2213 state.write("+");
2214 }
2215 syntax::BinaryOp::Sub => {
2216 state.write("-");
2217 }
2218 syntax::BinaryOp::Mult => {
2219 state.write("*");
2220 }
2221 syntax::BinaryOp::Div => {
2222 state.write("/");
2223 }
2224 syntax::BinaryOp::Mod => {
2225 state.write("%");
2226 }
2227 }
2228 }
2229
show_assignment_op(state: &OutputState, op: &syntax::AssignmentOp)2230 pub fn show_assignment_op(state: &OutputState, op: &syntax::AssignmentOp) {
2231 match *op {
2232 syntax::AssignmentOp::Equal => {
2233 state.write("=");
2234 }
2235 syntax::AssignmentOp::Mult => {
2236 state.write("*=");
2237 }
2238 syntax::AssignmentOp::Div => {
2239 state.write("/=");
2240 }
2241 syntax::AssignmentOp::Mod => {
2242 state.write("%=");
2243 }
2244 syntax::AssignmentOp::Add => {
2245 state.write("+=");
2246 }
2247 syntax::AssignmentOp::Sub => {
2248 state.write("-=");
2249 }
2250 syntax::AssignmentOp::LShift => {
2251 state.write("<<=");
2252 }
2253 syntax::AssignmentOp::RShift => {
2254 state.write(">>=");
2255 }
2256 syntax::AssignmentOp::And => {
2257 state.write("&=");
2258 }
2259 syntax::AssignmentOp::Xor => {
2260 state.write("^=");
2261 }
2262 syntax::AssignmentOp::Or => {
2263 state.write("|=");
2264 }
2265 }
2266 }
2267
show_function_identifier(state: &OutputState, i: &syntax::FunIdentifier)2268 pub fn show_function_identifier(state: &OutputState, i: &syntax::FunIdentifier) {
2269 match *i {
2270 syntax::FunIdentifier::Identifier(ref n) => show_identifier(state, &n),
2271 syntax::FunIdentifier::Expr(ref e) => show_expr(state, &*e),
2272 }
2273 }
2274
show_hir_function_identifier(state: &OutputState, i: &hir::FunIdentifier)2275 pub fn show_hir_function_identifier(state: &OutputState, i: &hir::FunIdentifier) {
2276 match *i {
2277 hir::FunIdentifier::Identifier(ref n) => show_sym(state, n),
2278 hir::FunIdentifier::Constructor(ref t) => show_type(state, &*t),
2279 }
2280 }
2281
show_declaration(state: &mut OutputState, d: &hir::Declaration)2282 pub fn show_declaration(state: &mut OutputState, d: &hir::Declaration) {
2283 show_indent(state);
2284 match *d {
2285 hir::Declaration::FunctionPrototype(ref proto) => {
2286 if !state.output_cxx {
2287 show_function_prototype(state, &proto);
2288 state.write(";\n");
2289 }
2290 }
2291 hir::Declaration::InitDeclaratorList(ref list) => {
2292 show_init_declarator_list(state, &list);
2293 state.write(";\n");
2294
2295 if state.output_cxx {
2296 let base = list.head.name;
2297 let base_sym = state.hir.sym(base);
2298 if let hir::SymDecl::Local(..) = &base_sym.decl {
2299 let mut texel_fetches = state.texel_fetches.borrow_mut();
2300 while let Some(idx) = texel_fetches.iter().position(|&(_, b, _)| b == base)
2301 {
2302 let (sampler, _, offsets) = texel_fetches.remove(idx);
2303 let sampler_sym = state.hir.sym(sampler);
2304 define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
2305 }
2306 }
2307 }
2308 }
2309 hir::Declaration::Precision(ref qual, ref ty) => {
2310 if !state.output_cxx {
2311 show_precision_qualifier(state, &qual);
2312 show_type_specifier(state, &ty);
2313 state.write(";\n");
2314 }
2315 }
2316 hir::Declaration::Block(ref _block) => {
2317 panic!();
2318 //show_block(state, &block);
2319 //state.write(";\n");
2320 }
2321 hir::Declaration::Global(ref qual, ref identifiers) => {
2322 // We only want to output GLSL layout qualifiers if not C++
2323 if !state.output_cxx {
2324 show_type_qualifier(state, &qual);
2325
2326 if !identifiers.is_empty() {
2327 let mut iter = identifiers.iter();
2328 let first = iter.next().unwrap();
2329 show_identifier(state, first);
2330
2331 for identifier in iter {
2332 let _ = write!(state, ", {}", identifier);
2333 }
2334 }
2335
2336 state.write(";\n");
2337 }
2338 }
2339 hir::Declaration::StructDefinition(ref sym) => {
2340 show_sym_decl(state, sym);
2341
2342 state.write(";\n");
2343 }
2344 }
2345 }
2346
show_function_prototype(state: &mut OutputState, fp: &hir::FunctionPrototype)2347 pub fn show_function_prototype(state: &mut OutputState, fp: &hir::FunctionPrototype) {
2348 let is_scalar = state.is_scalar.replace(!state.return_vector);
2349 show_type(state, &fp.ty);
2350 state.is_scalar.set(is_scalar);
2351
2352 state.write(" ");
2353 show_identifier(state, &fp.name);
2354
2355 state.write("(");
2356
2357 if !fp.parameters.is_empty() {
2358 let mut iter = fp.parameters.iter();
2359 let first = iter.next().unwrap();
2360 show_function_parameter_declaration(state, first);
2361
2362 for param in iter {
2363 state.write(", ");
2364 show_function_parameter_declaration(state, param);
2365 }
2366 }
2367
2368 if state.output_cxx && (state.vector_mask & (1 << 31)) != 0 {
2369 if !fp.parameters.is_empty() {
2370 state.write(", ");
2371 }
2372 state.write("I32 _cond_mask_");
2373 }
2374
2375 state.write(")");
2376 }
2377
show_function_parameter_declaration( state: &mut OutputState, p: &hir::FunctionParameterDeclaration, )2378 pub fn show_function_parameter_declaration(
2379 state: &mut OutputState,
2380 p: &hir::FunctionParameterDeclaration,
2381 ) {
2382 match *p {
2383 hir::FunctionParameterDeclaration::Named(ref qual, ref fpd) => {
2384 if state.output_cxx {
2385 let is_scalar = state.is_scalar.replace(
2386 symbol_run_class(&state.hir.sym(fpd.sym).decl, state.vector_mask)
2387 == hir::RunClass::Scalar,
2388 );
2389 show_type(state, &fpd.ty);
2390 state.is_scalar.set(is_scalar);
2391 show_parameter_qualifier(state, qual);
2392 } else {
2393 show_parameter_qualifier(state, qual);
2394 state.write(" ");
2395 show_type(state, &fpd.ty);
2396 }
2397 state.write(" ");
2398 show_identifier_and_type(state, &fpd.name, &fpd.ty);
2399 }
2400 hir::FunctionParameterDeclaration::Unnamed(ref qual, ref ty) => {
2401 if state.output_cxx {
2402 show_type_specifier(state, ty);
2403 show_parameter_qualifier(state, qual);
2404 } else {
2405 show_parameter_qualifier(state, qual);
2406 state.write(" ");
2407 show_type_specifier(state, ty);
2408 }
2409 }
2410 }
2411 }
2412
show_init_declarator_list(state: &mut OutputState, i: &hir::InitDeclaratorList)2413 pub fn show_init_declarator_list(state: &mut OutputState, i: &hir::InitDeclaratorList) {
2414 show_single_declaration(state, &i.head);
2415
2416 for decl in &i.tail {
2417 state.write(", ");
2418 show_single_declaration_no_type(state, decl);
2419 }
2420 }
2421
show_single_declaration(state: &mut OutputState, d: &hir::SingleDeclaration)2422 pub fn show_single_declaration(state: &mut OutputState, d: &hir::SingleDeclaration) {
2423 if state.output_cxx {
2424 show_single_declaration_cxx(state, d)
2425 } else {
2426 show_single_declaration_glsl(state, d)
2427 }
2428 }
2429
show_single_declaration_glsl(state: &mut OutputState, d: &hir::SingleDeclaration)2430 pub fn show_single_declaration_glsl(state: &mut OutputState, d: &hir::SingleDeclaration) {
2431 if let Some(ref qual) = d.qualifier {
2432 show_type_qualifier(state, &qual);
2433 state.write(" ");
2434 }
2435
2436 let sym = state.hir.sym(d.name);
2437 match &sym.decl {
2438 hir::SymDecl::Global(storage, interpolation, ..) => {
2439 show_storage_class(state, storage);
2440 if let Some(i) = interpolation {
2441 show_interpolation_qualifier(state, i);
2442 }
2443 }
2444 hir::SymDecl::Local(storage, ..) => show_storage_class(state, storage),
2445 _ => panic!("should be variable"),
2446 }
2447
2448 if let Some(ty_def) = d.ty_def {
2449 show_sym_decl(state, &ty_def);
2450 } else {
2451 show_type(state, &d.ty);
2452 }
2453
2454 state.write(" ");
2455 state.write(sym.name.as_str());
2456
2457 if let Some(ref arr_spec) = d.ty.array_sizes {
2458 show_array_sizes(state, &arr_spec);
2459 }
2460
2461 if let Some(ref initializer) = d.initializer {
2462 state.write(" = ");
2463 show_initializer(state, initializer);
2464 }
2465 }
2466
symbol_run_class(decl: &hir::SymDecl, vector_mask: u32) -> hir::RunClass2467 fn symbol_run_class(decl: &hir::SymDecl, vector_mask: u32) -> hir::RunClass {
2468 let run_class = match decl {
2469 hir::SymDecl::Global(_, _, _, run_class) => *run_class,
2470 hir::SymDecl::Local(_, _, run_class) => *run_class,
2471 _ => hir::RunClass::Vector,
2472 };
2473 match run_class {
2474 hir::RunClass::Scalar => hir::RunClass::Scalar,
2475 hir::RunClass::Dependent(mask) => {
2476 if (mask & vector_mask) != 0 {
2477 hir::RunClass::Vector
2478 } else {
2479 hir::RunClass::Scalar
2480 }
2481 }
2482 _ => hir::RunClass::Vector,
2483 }
2484 }
2485
show_single_declaration_cxx(state: &mut OutputState, d: &hir::SingleDeclaration)2486 pub fn show_single_declaration_cxx(state: &mut OutputState, d: &hir::SingleDeclaration) {
2487 let sym = state.hir.sym(d.name);
2488 if state.kind == ShaderKind::Vertex {
2489 match &sym.decl {
2490 hir::SymDecl::Global(hir::StorageClass::Uniform, ..) |
2491 hir::SymDecl::Global(hir::StorageClass::Sampler(_), ..) |
2492 hir::SymDecl::Global(hir::StorageClass::Out, _, _, hir::RunClass::Scalar) => {
2493 state.write("// ");
2494 }
2495 _ => {}
2496 }
2497 } else {
2498 match &sym.decl {
2499 hir::SymDecl::Global(hir::StorageClass::FragColor(index), ..) => {
2500 let fragcolor = match index {
2501 0 => "gl_FragColor",
2502 1 => "gl_SecondaryFragColor",
2503 _ => panic!(),
2504 };
2505 write!(state, "#define {} {}\n", sym.name, fragcolor);
2506 show_indent(state);
2507 state.write("// ");
2508 }
2509 hir::SymDecl::Global(hir::StorageClass::Out, ..) => {
2510 write!(state, "#define {} gl_FragColor\n", sym.name);
2511 show_indent(state);
2512 state.write("// ");
2513 }
2514 hir::SymDecl::Global(hir::StorageClass::Uniform, ..) |
2515 hir::SymDecl::Global(hir::StorageClass::Sampler(_), ..) |
2516 hir::SymDecl::Global(hir::StorageClass::In, _, _, hir::RunClass::Scalar) => {
2517 state.write("// ");
2518 }
2519 _ => {}
2520 }
2521 }
2522 let is_scalar = state
2523 .is_scalar
2524 .replace(symbol_run_class(&sym.decl, state.vector_mask) == hir::RunClass::Scalar);
2525
2526 if let Some(ref _array) = d.ty.array_sizes {
2527 show_type(state, &d.ty);
2528 } else {
2529 if let Some(ty_def) = d.ty_def {
2530 show_sym_decl(state, &ty_def);
2531 } else {
2532 show_type(state, &d.ty);
2533 }
2534 }
2535
2536 // XXX: this is pretty grotty
2537 state.write(" ");
2538 show_sym_decl(state, &d.name);
2539
2540 state.is_scalar.set(is_scalar);
2541
2542 if let Some(ref initializer) = d.initializer {
2543 state.write(" = ");
2544 show_initializer(state, initializer);
2545 }
2546 }
2547
show_single_declaration_no_type(state: &OutputState, d: &hir::SingleDeclarationNoType)2548 pub fn show_single_declaration_no_type(state: &OutputState, d: &hir::SingleDeclarationNoType) {
2549 show_arrayed_identifier(state, &d.ident);
2550
2551 if let Some(ref initializer) = d.initializer {
2552 state.write(" = ");
2553 show_initializer(state, initializer);
2554 }
2555 }
2556
show_initializer(state: &OutputState, i: &hir::Initializer)2557 pub fn show_initializer(state: &OutputState, i: &hir::Initializer) {
2558 match *i {
2559 hir::Initializer::Simple(ref e) => show_hir_expr(state, e),
2560 hir::Initializer::List(ref list) => {
2561 let mut iter = list.0.iter();
2562 let first = iter.next().unwrap();
2563
2564 state.write("{ ");
2565 show_initializer(state, first);
2566
2567 for ini in iter {
2568 state.write(", ");
2569 show_initializer(state, ini);
2570 }
2571
2572 state.write(" }");
2573 }
2574 }
2575 }
2576
2577 /*
2578 pub fn show_block(state: &mut OutputState, b: &hir::Block) {
2579 show_type_qualifier(state, &b.qualifier);
2580 state.write(" ");
2581 show_identifier(state, &b.name);
2582 state.write(" {");
2583
2584 for field in &b.fields {
2585 show_struct_field(state, field);
2586 state.write("\n");
2587 }
2588 state.write("}");
2589
2590 if let Some(ref ident) = b.identifier {
2591 show_arrayed_identifier(state, ident);
2592 }
2593 }
2594 */
2595
2596 // This is a hack to run through the first time with an empty writter to find if 'return' is declared.
has_conditional_return(state: &mut OutputState, cst: &hir::CompoundStatement) -> bool2597 pub fn has_conditional_return(state: &mut OutputState, cst: &hir::CompoundStatement) -> bool {
2598 let buffer = state.push_buffer();
2599 show_compound_statement(state, cst);
2600 state.pop_buffer(buffer);
2601 let result = state.return_declared;
2602 state.return_declared = false;
2603 result
2604 }
2605
define_texel_fetch_ptr( state: &OutputState, base_sym: &hir::Symbol, sampler_sym: &hir::Symbol, offsets: &hir::TexelFetchOffsets, )2606 fn define_texel_fetch_ptr(
2607 state: &OutputState,
2608 base_sym: &hir::Symbol,
2609 sampler_sym: &hir::Symbol,
2610 offsets: &hir::TexelFetchOffsets,
2611 ) {
2612 show_indent(state);
2613 write!(
2614 state,
2615 "auto {}_{}_fetch = texelFetchPtr({}, {}, {}, {}, {}, {});\n",
2616 sampler_sym.name,
2617 base_sym.name,
2618 sampler_sym.name,
2619 base_sym.name,
2620 offsets.min_x,
2621 offsets.max_x,
2622 offsets.min_y,
2623 offsets.max_y,
2624 );
2625 }
2626
show_function_definition( state: &mut OutputState, fd: &hir::FunctionDefinition, vector_mask: u32, )2627 pub fn show_function_definition(
2628 state: &mut OutputState,
2629 fd: &hir::FunctionDefinition,
2630 vector_mask: u32,
2631 ) {
2632 // println!("start {:?} {:?}", fd.prototype.name, vector_mask);
2633 if state.output_cxx && fd.prototype.name.as_str() == "main" {
2634 state.write("ALWAYS_INLINE ");
2635 }
2636 show_function_prototype(state, &fd.prototype);
2637 state.write(" ");
2638 state.return_type = Some(Box::new(fd.prototype.ty.clone()));
2639
2640 if state.output_cxx && (vector_mask & (1 << 31)) != 0 {
2641 state.mask = Some(Box::new(hir::Expr {
2642 kind: hir::ExprKind::CondMask,
2643 ty: hir::Type::new(hir::TypeKind::Bool),
2644 }));
2645 }
2646
2647 show_indent(state);
2648 state.write("{\n");
2649
2650 state.indent();
2651 if has_conditional_return(state, &fd.body) {
2652 show_indent(state);
2653 state.write(if state.return_vector {
2654 "I32"
2655 } else {
2656 "int32_t"
2657 });
2658 state.write(" ret_mask = ");
2659 if let Some(mask) = &state.mask {
2660 show_hir_expr(state, mask);
2661 } else {
2662 state.write("~0");
2663 }
2664 state.write(";\n");
2665 // XXX: the cloning here is bad
2666 show_indent(state);
2667 if fd.prototype.ty != Type::new(hir::TypeKind::Void) {
2668 let is_scalar = state.is_scalar.replace(!state.return_vector);
2669 show_type(state, &state.return_type.clone().unwrap());
2670 state.write(" ret;\n");
2671 state.is_scalar.set(is_scalar);
2672 }
2673 }
2674
2675 if state.output_cxx {
2676 match fd.prototype.name.as_str() {
2677 "swgl_drawSpanRGBA8" |
2678 "swgl_drawSpanR8" => {
2679 // Partial spans are not drawn using span shaders, but rather drawn with a fragment shader
2680 // where the span shader left off. We need to undo any changes to the interpolants made by
2681 // the span shaders so that we can reset the interpolants to where the fragment shader
2682 // expects them. We do this by saving them in an _Undo_ struct on entry to the span shader,
2683 // and then restore them in the _Undo_ struct destructor.
2684 let mut needs_undo = vec![];
2685 for global in &fd.globals {
2686 let sym = state.hir.sym(*global);
2687 match &sym.decl {
2688 hir::SymDecl::Global(hir::StorageClass::In, _, ty, hir::RunClass::Vector) => {
2689 if needs_undo.is_empty() {
2690 state.write("struct _Undo_ {\nSelf* self;\n");
2691 }
2692 show_type(state, ty);
2693 write!(state, " {};\n", sym.name);
2694 needs_undo.push(sym.name.clone());
2695 }
2696 _ => {}
2697 }
2698 }
2699 if !needs_undo.is_empty() {
2700 state.write("explicit _Undo_(Self* self) : self(self)");
2701 for name in &needs_undo {
2702 write!(state, ", {0}(self->{0})", name);
2703 }
2704 state.write(" {}\n");
2705 state.write("~_Undo_() {\n");
2706 for name in &needs_undo {
2707 write!(state, "self->{0} = {0};\n", name);
2708 }
2709 state.write("}} _undo_(this);\n");
2710 }
2711 }
2712 _ => {}
2713 }
2714
2715 let mut texel_fetches = state.texel_fetches.borrow_mut();
2716 texel_fetches.clear();
2717 for ((sampler, base), offsets) in fd.texel_fetches.iter() {
2718 add_used_global(state, sampler);
2719 let sampler_sym = state.hir.sym(*sampler);
2720 let base_sym = state.hir.sym(*base);
2721 match &base_sym.decl {
2722 hir::SymDecl::Global(..) => {
2723 add_used_global(state, base);
2724 define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
2725 }
2726 hir::SymDecl::Local(..) => {
2727 if fd.prototype.has_parameter(*base) {
2728 define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
2729 } else {
2730 texel_fetches.push((*sampler, *base, offsets.clone()));
2731 }
2732 }
2733 _ => panic!(),
2734 }
2735 }
2736 }
2737
2738 for st in &fd.body.statement_list {
2739 show_statement(state, st);
2740 }
2741
2742 if state.return_declared {
2743 show_indent(state);
2744 if fd.prototype.ty == Type::new(hir::TypeKind::Void) {
2745 state.write("return;\n");
2746 } else {
2747 state.write("return ret;\n");
2748 }
2749 }
2750 state.outdent();
2751
2752 show_indent(state);
2753 state.write("}\n");
2754 // println!("end {:?}", fd.prototype.name);
2755
2756 state.return_type = None;
2757 state.return_declared = false;
2758 state.mask = None;
2759 }
2760
show_compound_statement(state: &mut OutputState, cst: &hir::CompoundStatement)2761 pub fn show_compound_statement(state: &mut OutputState, cst: &hir::CompoundStatement) {
2762 show_indent(state);
2763 state.write("{\n");
2764
2765 state.indent();
2766 for st in &cst.statement_list {
2767 show_statement(state, st);
2768 }
2769 state.outdent();
2770
2771 show_indent(state);
2772 state.write("}\n");
2773 }
2774
show_statement(state: &mut OutputState, st: &hir::Statement)2775 pub fn show_statement(state: &mut OutputState, st: &hir::Statement) {
2776 match *st {
2777 hir::Statement::Compound(ref cst) => show_compound_statement(state, cst),
2778 hir::Statement::Simple(ref sst) => show_simple_statement(state, sst),
2779 }
2780 }
2781
show_simple_statement(state: &mut OutputState, sst: &hir::SimpleStatement)2782 pub fn show_simple_statement(state: &mut OutputState, sst: &hir::SimpleStatement) {
2783 match *sst {
2784 hir::SimpleStatement::Declaration(ref d) => show_declaration(state, d),
2785 hir::SimpleStatement::Expression(ref e) => show_expression_statement(state, e),
2786 hir::SimpleStatement::Selection(ref s) => show_selection_statement(state, s),
2787 hir::SimpleStatement::Switch(ref s) => show_switch_statement(state, s),
2788 hir::SimpleStatement::Iteration(ref i) => show_iteration_statement(state, i),
2789 hir::SimpleStatement::Jump(ref j) => show_jump_statement(state, j),
2790 }
2791 }
2792
show_indent(state: &OutputState)2793 pub fn show_indent(state: &OutputState) {
2794 for _ in 0 .. state.indent {
2795 state.write(" ");
2796 }
2797 }
2798
show_expression_statement(state: &mut OutputState, est: &hir::ExprStatement)2799 pub fn show_expression_statement(state: &mut OutputState, est: &hir::ExprStatement) {
2800 show_indent(state);
2801
2802 if let Some(ref e) = *est {
2803 show_hir_expr_inner(state, e, true);
2804 }
2805
2806 state.write(";\n");
2807 }
2808
show_selection_statement(state: &mut OutputState, sst: &hir::SelectionStatement)2809 pub fn show_selection_statement(state: &mut OutputState, sst: &hir::SelectionStatement) {
2810 show_indent(state);
2811
2812 if state.output_cxx &&
2813 (state.return_declared || expr_run_class(state, &sst.cond) != hir::RunClass::Scalar)
2814 {
2815 let (cond_index, mask) = if state.mask.is_none() || sst.else_stmt.is_some() {
2816 let cond = sst.cond.clone();
2817 state.cond_index += 1;
2818 let cond_index = state.cond_index;
2819 write!(state, "auto _c{}_ = ", cond_index);
2820 show_hir_expr(state, &cond);
2821 state.write(";\n");
2822 (
2823 cond_index,
2824 Box::new(hir::Expr {
2825 kind: hir::ExprKind::Cond(cond_index, cond),
2826 ty: hir::Type::new(hir::TypeKind::Bool),
2827 }),
2828 )
2829 } else {
2830 (0, sst.cond.clone())
2831 };
2832
2833 let previous = mem::replace(&mut state.mask, None);
2834 state.mask = Some(match previous.clone() {
2835 Some(e) => {
2836 let cond = Box::new(hir::Expr {
2837 kind: hir::ExprKind::Binary(syntax::BinaryOp::BitAnd, e, mask.clone()),
2838 ty: hir::Type::new(hir::TypeKind::Bool),
2839 });
2840 state.cond_index += 1;
2841 let nested_cond_index = state.cond_index;
2842 show_indent(state);
2843 write!(state, "auto _c{}_ = ", nested_cond_index);
2844 show_hir_expr(state, &cond);
2845 state.write(";\n");
2846 Box::new(hir::Expr {
2847 kind: hir::ExprKind::Cond(nested_cond_index, cond),
2848 ty: hir::Type::new(hir::TypeKind::Bool),
2849 })
2850 }
2851 None => mask.clone(),
2852 });
2853
2854 show_statement(state, &sst.body);
2855 state.mask = previous;
2856
2857 if let Some(rest) = &sst.else_stmt {
2858 // invert the condition
2859 let inverted_cond = Box::new(hir::Expr {
2860 kind: hir::ExprKind::Unary(UnaryOp::Complement, mask),
2861 ty: hir::Type::new(hir::TypeKind::Bool),
2862 });
2863 let previous = mem::replace(&mut state.mask, None);
2864 state.mask = Some(match previous.clone() {
2865 Some(e) => {
2866 let cond = Box::new(hir::Expr {
2867 kind: hir::ExprKind::Binary(syntax::BinaryOp::BitAnd, e, inverted_cond),
2868 ty: hir::Type::new(hir::TypeKind::Bool),
2869 });
2870 show_indent(state);
2871 write!(state, "_c{}_ = ", cond_index);
2872 show_hir_expr(state, &cond);
2873 state.write(";\n");
2874 Box::new(hir::Expr {
2875 kind: hir::ExprKind::Cond(cond_index, cond),
2876 ty: hir::Type::new(hir::TypeKind::Bool),
2877 })
2878 }
2879 None => inverted_cond,
2880 });
2881
2882 show_statement(state, rest);
2883 state.mask = previous;
2884 }
2885 } else {
2886 state.write("if (");
2887 show_hir_expr(state, &sst.cond);
2888 state.write(") {\n");
2889
2890 state.indent();
2891 show_statement(state, &sst.body);
2892 state.outdent();
2893
2894 show_indent(state);
2895 if let Some(rest) = &sst.else_stmt {
2896 state.write("} else ");
2897 show_statement(state, rest);
2898 } else {
2899 state.write("}\n");
2900 }
2901 }
2902 }
2903
case_stmts_to_if_stmts(stmts: &[Statement], last: bool) -> (Option<Box<Statement>>, bool)2904 fn case_stmts_to_if_stmts(stmts: &[Statement], last: bool) -> (Option<Box<Statement>>, bool) {
2905 // Look for jump statements and remove them
2906 // We currently are pretty strict on the form that the statement
2907 // list needs to be in. This can be loosened as needed.
2908 let mut fallthrough = false;
2909 let cstmt = match &stmts[..] {
2910 [hir::Statement::Compound(c)] => match c.statement_list.split_last() {
2911 Some((hir::Statement::Simple(s), rest)) => match **s {
2912 hir::SimpleStatement::Jump(hir::JumpStatement::Break) => hir::CompoundStatement {
2913 statement_list: rest.to_owned(),
2914 },
2915 _ => panic!("fall through not supported"),
2916 },
2917 _ => panic!("empty compound"),
2918 },
2919 [hir::Statement::Simple(s)] => {
2920 match **s {
2921 hir::SimpleStatement::Jump(hir::JumpStatement::Break) => hir::CompoundStatement {
2922 statement_list: Vec::new(),
2923 },
2924 _ => {
2925 if last {
2926 // we don't need a break at the end
2927 hir::CompoundStatement {
2928 statement_list: vec![hir::Statement::Simple(s.clone())],
2929 }
2930 } else {
2931 panic!("fall through not supported {:?}", s)
2932 }
2933 }
2934 }
2935 }
2936 [] => return (None, true),
2937 stmts => match stmts.split_last() {
2938 Some((hir::Statement::Simple(s), rest)) => match **s {
2939 hir::SimpleStatement::Jump(hir::JumpStatement::Break) => hir::CompoundStatement {
2940 statement_list: rest.to_owned(),
2941 },
2942 _ => {
2943 if !last {
2944 fallthrough = true;
2945 }
2946 hir::CompoundStatement {
2947 statement_list: stmts.to_owned(),
2948 }
2949 }
2950 },
2951 _ => panic!("unexpected empty"),
2952 },
2953 };
2954 let stmts = Box::new(hir::Statement::Compound(Box::new(cstmt)));
2955 (Some(stmts), fallthrough)
2956 }
2957
build_selection<'a, I: Iterator<Item = &'a hir::Case>>( head: &Box<hir::Expr>, case: &hir::Case, mut cases: I, default: Option<&hir::Case>, previous_condition: Option<Box<hir::Expr>>, previous_stmts: Option<Box<hir::Statement>>, ) -> hir::SelectionStatement2958 fn build_selection<'a, I: Iterator<Item = &'a hir::Case>>(
2959 head: &Box<hir::Expr>,
2960 case: &hir::Case,
2961 mut cases: I,
2962 default: Option<&hir::Case>,
2963 previous_condition: Option<Box<hir::Expr>>,
2964 previous_stmts: Option<Box<hir::Statement>>,
2965 ) -> hir::SelectionStatement {
2966 let cond = match &case.label {
2967 hir::CaseLabel::Case(e) => Some(Box::new(hir::Expr {
2968 kind: hir::ExprKind::Binary(syntax::BinaryOp::Equal, head.clone(), e.clone()),
2969 ty: hir::Type::new(hir::TypeKind::Bool),
2970 })),
2971 hir::CaseLabel::Def => None,
2972 };
2973
2974 // if we have two conditions join them
2975 let cond = match (&previous_condition, &cond) {
2976 (Some(prev), Some(cond)) => Some(Box::new(hir::Expr {
2977 kind: hir::ExprKind::Binary(syntax::BinaryOp::Or, prev.clone(), cond.clone()),
2978 ty: hir::Type::new(hir::TypeKind::Bool),
2979 })),
2980 (_, cond) => cond.clone(),
2981 };
2982
2983 /*
2984
2985 // find the next case that's not a default
2986 let next_case = loop {
2987 match cases.next() {
2988 Some(hir::Case { label: hir::CaseLabel::Def, ..}) => { },
2989 case => break case,
2990 }
2991 };*/
2992
2993 let (cond, body, else_stmt) = match (cond, cases.next()) {
2994 (None, Some(next_case)) => {
2995 assert!(previous_stmts.is_none());
2996 // default so just move on to the next
2997 return build_selection(head, next_case, cases, default, None, None);
2998 }
2999 (Some(cond), Some(next_case)) => {
3000 assert!(previous_stmts.is_none());
3001 let (stmts, fallthrough) = case_stmts_to_if_stmts(&case.stmts, false);
3002 if !fallthrough && stmts.is_some() {
3003 (
3004 cond,
3005 stmts.unwrap(),
3006 Some(Box::new(hir::Statement::Simple(Box::new(
3007 hir::SimpleStatement::Selection(build_selection(
3008 head, next_case, cases, default, None, None,
3009 )),
3010 )))),
3011 )
3012 } else {
3013 // empty so fall through to the next
3014 return build_selection(head, next_case, cases, default, Some(cond), stmts);
3015 }
3016 }
3017 (Some(cond), None) => {
3018 // non-default last
3019 assert!(previous_stmts.is_none());
3020 let (stmts, _) = case_stmts_to_if_stmts(&case.stmts, default.is_none());
3021 let stmts = stmts.expect("empty case labels unsupported at the end");
3022 // add the default case at the end if we have one
3023 (
3024 cond,
3025 stmts,
3026 match default {
3027 Some(default) => {
3028 let (default_stmts, fallthrough) =
3029 case_stmts_to_if_stmts(&default.stmts, true);
3030 assert!(!fallthrough);
3031 Some(default_stmts.expect("empty default unsupported"))
3032 }
3033 None => None,
3034 },
3035 )
3036 }
3037 (None, None) => {
3038 // default, last
3039
3040 assert!(default.is_some());
3041
3042 let (stmts, fallthrough) = case_stmts_to_if_stmts(&case.stmts, true);
3043 let stmts = stmts.expect("empty default unsupported");
3044 assert!(!fallthrough);
3045
3046 match previous_stmts {
3047 Some(previous_stmts) => {
3048 let cond = previous_condition.expect("must have previous condition");
3049 (cond, previous_stmts, Some(stmts))
3050 }
3051 None => {
3052 let cond = Box::new(hir::Expr {
3053 kind: hir::ExprKind::BoolConst(true),
3054 ty: hir::Type::new(hir::TypeKind::Bool),
3055 });
3056 (cond, stmts, None)
3057 }
3058 }
3059 }
3060 };
3061
3062 hir::SelectionStatement {
3063 cond,
3064 body,
3065 else_stmt,
3066 }
3067 }
3068
lower_switch_to_ifs(sst: &hir::SwitchStatement) -> hir::SelectionStatement3069 pub fn lower_switch_to_ifs(sst: &hir::SwitchStatement) -> hir::SelectionStatement {
3070 let default = sst.cases.iter().find(|x| x.label == hir::CaseLabel::Def);
3071 let mut cases = sst.cases.iter();
3072 let r = build_selection(&sst.head, cases.next().unwrap(), cases, default, None, None);
3073 r
3074 }
3075
is_declaration(stmt: &hir::Statement) -> bool3076 fn is_declaration(stmt: &hir::Statement) -> bool {
3077 if let hir::Statement::Simple(s) = stmt {
3078 if let hir::SimpleStatement::Declaration(..) = **s {
3079 return true;
3080 }
3081 }
3082 return false;
3083 }
3084
show_switch_statement(state: &mut OutputState, sst: &hir::SwitchStatement)3085 pub fn show_switch_statement(state: &mut OutputState, sst: &hir::SwitchStatement) {
3086 if state.output_cxx && expr_run_class(state, &sst.head) != hir::RunClass::Scalar {
3087 // XXX: when lowering switches we end up with a mask that has
3088 // a bunch of mutually exclusive conditions.
3089 // It would be nice if we could fold them together.
3090 let ifs = lower_switch_to_ifs(sst);
3091 return show_selection_statement(state, &ifs);
3092 }
3093
3094 show_indent(state);
3095 state.write("switch (");
3096 show_hir_expr(state, &sst.head);
3097 state.write(") {\n");
3098 state.indent();
3099
3100 for case in &sst.cases {
3101 show_case_label(state, &case.label);
3102 state.indent();
3103
3104 let has_declaration = case.stmts.iter().any(|x| is_declaration(x));
3105 // glsl allows declarations in switch statements while C requires them to be
3106 // in a compound statement. If we have a declaration wrap the statements in an block.
3107 // This will break some glsl shaders but keeps the saner ones working
3108 if has_declaration {
3109 show_indent(state);
3110 state.write("{\n");
3111 state.indent();
3112 }
3113 for st in &case.stmts {
3114 show_statement(state, st);
3115 }
3116
3117 if has_declaration {
3118 show_indent(state);
3119 state.write("}\n");
3120 state.outdent();
3121 }
3122
3123 state.outdent();
3124 }
3125 state.outdent();
3126 show_indent(state);
3127 state.write("}\n");
3128 }
3129
show_case_label(state: &mut OutputState, cl: &hir::CaseLabel)3130 pub fn show_case_label(state: &mut OutputState, cl: &hir::CaseLabel) {
3131 show_indent(state);
3132 match *cl {
3133 hir::CaseLabel::Case(ref e) => {
3134 state.write("case ");
3135 show_hir_expr(state, e);
3136 state.write(":\n");
3137 }
3138 hir::CaseLabel::Def => {
3139 state.write("default:\n");
3140 }
3141 }
3142 }
3143
show_iteration_statement(state: &mut OutputState, ist: &hir::IterationStatement)3144 pub fn show_iteration_statement(state: &mut OutputState, ist: &hir::IterationStatement) {
3145 show_indent(state);
3146 match *ist {
3147 hir::IterationStatement::While(ref cond, ref body) => {
3148 state.write("while (");
3149 show_condition(state, cond);
3150 state.write(") ");
3151 show_statement(state, body);
3152 }
3153 hir::IterationStatement::DoWhile(ref body, ref cond) => {
3154 state.write("do ");
3155 show_statement(state, body);
3156 state.write(" while (");
3157 show_hir_expr(state, cond);
3158 state.write(");\n");
3159 }
3160 hir::IterationStatement::For(ref init, ref rest, ref body) => {
3161 state.write("for (");
3162 show_for_init_statement(state, init);
3163 show_for_rest_statement(state, rest);
3164 state.write(") ");
3165 show_statement(state, body);
3166 }
3167 }
3168 }
3169
show_condition(state: &mut OutputState, c: &hir::Condition)3170 pub fn show_condition(state: &mut OutputState, c: &hir::Condition) {
3171 match *c {
3172 hir::Condition::Expr(ref e) => show_hir_expr(state, e),
3173 /*hir::Condition::Assignment(ref ty, ref name, ref initializer) => {
3174 show_type(state, ty);
3175 state.write(" ");
3176 show_identifier(f, name);
3177 state.write(" = ");
3178 show_initializer(state, initializer);
3179 }*/
3180 }
3181 }
3182
show_for_init_statement(state: &mut OutputState, i: &hir::ForInitStatement)3183 pub fn show_for_init_statement(state: &mut OutputState, i: &hir::ForInitStatement) {
3184 match *i {
3185 hir::ForInitStatement::Expression(ref expr) => {
3186 if let Some(ref e) = *expr {
3187 show_hir_expr(state, e);
3188 }
3189 }
3190 hir::ForInitStatement::Declaration(ref d) => {
3191 show_declaration(state, d);
3192 }
3193 }
3194 }
3195
show_for_rest_statement(state: &mut OutputState, r: &hir::ForRestStatement)3196 pub fn show_for_rest_statement(state: &mut OutputState, r: &hir::ForRestStatement) {
3197 if let Some(ref cond) = r.condition {
3198 show_condition(state, cond);
3199 }
3200
3201 state.write("; ");
3202
3203 if let Some(ref e) = r.post_expr {
3204 show_hir_expr(state, e);
3205 }
3206 }
3207
use_return_mask(state: &OutputState) -> bool3208 fn use_return_mask(state: &OutputState) -> bool {
3209 if let Some(mask) = &state.mask {
3210 mask.kind != hir::ExprKind::CondMask
3211 } else {
3212 false
3213 }
3214 }
3215
show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement)3216 pub fn show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement) {
3217 show_indent(state);
3218 match *j {
3219 hir::JumpStatement::Continue => {
3220 state.write("continue;\n");
3221 }
3222 hir::JumpStatement::Break => {
3223 state.write("break;\n");
3224 }
3225 hir::JumpStatement::Discard => {
3226 if state.output_cxx {
3227 state.uses_discard = true;
3228 if let Some(mask) = &state.mask {
3229 state.write("swgl_IsPixelDiscarded |= (");
3230 show_hir_expr(state, mask);
3231 state.write(")");
3232 if state.return_declared {
3233 state.write("&ret_mask");
3234 }
3235 state.write(";\n");
3236 } else {
3237 state.write("swgl_IsPixelDiscarded = true;\n");
3238 }
3239 } else {
3240 state.write("discard;\n");
3241 }
3242 }
3243 hir::JumpStatement::Return(ref e) => {
3244 if let Some(e) = e {
3245 if state.output_cxx {
3246 if use_return_mask(state) {
3247 // We cast any conditions by `ret_mask_type` so that scalars nicely
3248 // convert to -1. i.e. I32 &= bool will give the wrong result. while I32 &= I32(bool) works
3249 let ret_mask_type = if state.return_vector {
3250 "I32"
3251 } else {
3252 "int32_t"
3253 };
3254 if state.return_declared {
3255 // XXX: the cloning here is bad
3256 write!(state, "ret = if_then_else(ret_mask & {}(", ret_mask_type);
3257 show_hir_expr(state, &state.mask.clone().unwrap());
3258 state.write("), ");
3259 show_hir_expr(state, e);
3260 state.write(", ret);\n");
3261 } else {
3262 state.write("ret = ");
3263 show_hir_expr(state, e);
3264 state.write(";\n");
3265 }
3266
3267 show_indent(state);
3268
3269 if state.return_declared {
3270 write!(state, "ret_mask &= ~{}(", ret_mask_type);
3271 } else {
3272 write!(state, "ret_mask = ~{}(", ret_mask_type);
3273 }
3274 show_hir_expr(state, &state.mask.clone().unwrap());
3275 state.write(");\n");
3276 state.return_declared = true;
3277 } else {
3278 if state.return_declared {
3279 state.write("ret = if_then_else(ret_mask, ");
3280 show_hir_expr(state, e);
3281 state.write(", ret);\n");
3282 } else {
3283 state.write("return ");
3284 show_hir_expr(state, e);
3285 state.write(";\n");
3286 }
3287 }
3288 } else {
3289 state.write("return ");
3290 show_hir_expr(state, e);
3291 state.write(";\n");
3292 }
3293 } else {
3294 if state.output_cxx {
3295 if use_return_mask(state) {
3296 show_indent(state);
3297 let ret_mask_type = if state.return_vector {
3298 "I32"
3299 } else {
3300 "int32_t"
3301 };
3302 if state.return_declared {
3303 write!(state, "ret_mask &= ~{}(", ret_mask_type);
3304 } else {
3305 write!(state, "ret_mask = ~{}(", ret_mask_type);
3306 }
3307 show_hir_expr(state, &state.mask.clone().unwrap());
3308 state.write(");\n");
3309 state.return_declared = true;
3310 } else {
3311 state.write("return;\n");
3312 }
3313 } else {
3314 state.write("return;\n");
3315 }
3316 }
3317 }
3318 }
3319 }
3320
show_path(state: &OutputState, path: &syntax::Path)3321 pub fn show_path(state: &OutputState, path: &syntax::Path) {
3322 match path {
3323 syntax::Path::Absolute(s) => {
3324 let _ = write!(state, "<{}>", s);
3325 }
3326 syntax::Path::Relative(s) => {
3327 let _ = write!(state, "\"{}\"", s);
3328 }
3329 }
3330 }
3331
show_preprocessor(state: &OutputState, pp: &syntax::Preprocessor)3332 pub fn show_preprocessor(state: &OutputState, pp: &syntax::Preprocessor) {
3333 match *pp {
3334 syntax::Preprocessor::Define(ref pd) => show_preprocessor_define(state, pd),
3335 syntax::Preprocessor::Else => show_preprocessor_else(state),
3336 syntax::Preprocessor::ElseIf(ref pei) => show_preprocessor_elseif(state, pei),
3337 syntax::Preprocessor::EndIf => show_preprocessor_endif(state),
3338 syntax::Preprocessor::Error(ref pe) => show_preprocessor_error(state, pe),
3339 syntax::Preprocessor::If(ref pi) => show_preprocessor_if(state, pi),
3340 syntax::Preprocessor::IfDef(ref pid) => show_preprocessor_ifdef(state, pid),
3341 syntax::Preprocessor::IfNDef(ref pind) => show_preprocessor_ifndef(state, pind),
3342 syntax::Preprocessor::Include(ref pi) => show_preprocessor_include(state, pi),
3343 syntax::Preprocessor::Line(ref pl) => show_preprocessor_line(state, pl),
3344 syntax::Preprocessor::Pragma(ref pp) => show_preprocessor_pragma(state, pp),
3345 syntax::Preprocessor::Undef(ref pu) => show_preprocessor_undef(state, pu),
3346 syntax::Preprocessor::Version(ref pv) => show_preprocessor_version(state, pv),
3347 syntax::Preprocessor::Extension(ref pe) => show_preprocessor_extension(state, pe),
3348 }
3349 }
3350
show_preprocessor_define(state: &OutputState, pd: &syntax::PreprocessorDefine)3351 pub fn show_preprocessor_define(state: &OutputState, pd: &syntax::PreprocessorDefine) {
3352 match *pd {
3353 syntax::PreprocessorDefine::ObjectLike {
3354 ref ident,
3355 ref value,
3356 } => {
3357 let _ = write!(state, "#define {} {}\n", ident, value);
3358 }
3359
3360 syntax::PreprocessorDefine::FunctionLike {
3361 ref ident,
3362 ref args,
3363 ref value,
3364 } => {
3365 let _ = write!(state, "#define {}(", ident);
3366
3367 if !args.is_empty() {
3368 let _ = write!(state, "{}", &args[0]);
3369
3370 for arg in &args[1 .. args.len()] {
3371 let _ = write!(state, ", {}", arg);
3372 }
3373 }
3374
3375 let _ = write!(state, ") {}\n", value);
3376 }
3377 }
3378 }
3379
show_preprocessor_else(state: &OutputState)3380 pub fn show_preprocessor_else(state: &OutputState) {
3381 state.write("#else\n");
3382 }
3383
show_preprocessor_elseif(state: &OutputState, pei: &syntax::PreprocessorElseIf)3384 pub fn show_preprocessor_elseif(state: &OutputState, pei: &syntax::PreprocessorElseIf) {
3385 let _ = write!(state, "#elseif {}\n", pei.condition);
3386 }
3387
show_preprocessor_error(state: &OutputState, pe: &syntax::PreprocessorError)3388 pub fn show_preprocessor_error(state: &OutputState, pe: &syntax::PreprocessorError) {
3389 let _ = writeln!(state, "#error {}", pe.message);
3390 }
3391
show_preprocessor_endif(state: &OutputState)3392 pub fn show_preprocessor_endif(state: &OutputState) {
3393 state.write("#endif\n");
3394 }
3395
show_preprocessor_if(state: &OutputState, pi: &syntax::PreprocessorIf)3396 pub fn show_preprocessor_if(state: &OutputState, pi: &syntax::PreprocessorIf) {
3397 let _ = write!(state, "#if {}\n", pi.condition);
3398 }
3399
show_preprocessor_ifdef(state: &OutputState, pid: &syntax::PreprocessorIfDef)3400 pub fn show_preprocessor_ifdef(state: &OutputState, pid: &syntax::PreprocessorIfDef) {
3401 state.write("#ifdef ");
3402 show_identifier(state, &pid.ident);
3403 state.write("\n");
3404 }
3405
show_preprocessor_ifndef(state: &OutputState, pind: &syntax::PreprocessorIfNDef)3406 pub fn show_preprocessor_ifndef(state: &OutputState, pind: &syntax::PreprocessorIfNDef) {
3407 state.write("#ifndef ");
3408 show_identifier(state, &pind.ident);
3409 state.write("\n");
3410 }
3411
show_preprocessor_include(state: &OutputState, pi: &syntax::PreprocessorInclude)3412 pub fn show_preprocessor_include(state: &OutputState, pi: &syntax::PreprocessorInclude) {
3413 state.write("#include ");
3414 show_path(state, &pi.path);
3415 state.write("\n");
3416 }
3417
show_preprocessor_line(state: &OutputState, pl: &syntax::PreprocessorLine)3418 pub fn show_preprocessor_line(state: &OutputState, pl: &syntax::PreprocessorLine) {
3419 let _ = write!(state, "#line {}", pl.line);
3420 if let Some(source_string_number) = pl.source_string_number {
3421 let _ = write!(state, " {}", source_string_number);
3422 }
3423 state.write("\n");
3424 }
3425
show_preprocessor_pragma(state: &OutputState, pp: &syntax::PreprocessorPragma)3426 pub fn show_preprocessor_pragma(state: &OutputState, pp: &syntax::PreprocessorPragma) {
3427 let _ = writeln!(state, "#pragma {}", pp.command);
3428 }
3429
show_preprocessor_undef(state: &OutputState, pud: &syntax::PreprocessorUndef)3430 pub fn show_preprocessor_undef(state: &OutputState, pud: &syntax::PreprocessorUndef) {
3431 state.write("#undef ");
3432 show_identifier(state, &pud.name);
3433 state.write("\n");
3434 }
3435
show_preprocessor_version(state: &OutputState, pv: &syntax::PreprocessorVersion)3436 pub fn show_preprocessor_version(state: &OutputState, pv: &syntax::PreprocessorVersion) {
3437 let _ = write!(state, "#version {}", pv.version);
3438
3439 if let Some(ref profile) = pv.profile {
3440 match *profile {
3441 syntax::PreprocessorVersionProfile::Core => {
3442 state.write(" core");
3443 }
3444 syntax::PreprocessorVersionProfile::Compatibility => {
3445 state.write(" compatibility");
3446 }
3447 syntax::PreprocessorVersionProfile::ES => {
3448 state.write(" es");
3449 }
3450 }
3451 }
3452
3453 state.write("\n");
3454 }
3455
show_preprocessor_extension(state: &OutputState, pe: &syntax::PreprocessorExtension)3456 pub fn show_preprocessor_extension(state: &OutputState, pe: &syntax::PreprocessorExtension) {
3457 state.write("#extension ");
3458
3459 match pe.name {
3460 syntax::PreprocessorExtensionName::All => {
3461 state.write("all");
3462 }
3463 syntax::PreprocessorExtensionName::Specific(ref n) => {
3464 state.write(n);
3465 }
3466 }
3467
3468 if let Some(ref behavior) = pe.behavior {
3469 match *behavior {
3470 syntax::PreprocessorExtensionBehavior::Require => {
3471 state.write(" : require");
3472 }
3473 syntax::PreprocessorExtensionBehavior::Enable => {
3474 state.write(" : enable");
3475 }
3476 syntax::PreprocessorExtensionBehavior::Warn => {
3477 state.write(" : warn");
3478 }
3479 syntax::PreprocessorExtensionBehavior::Disable => {
3480 state.write(" : disable");
3481 }
3482 }
3483 }
3484
3485 state.write("\n");
3486 }
3487
show_external_declaration(state: &mut OutputState, ed: &hir::ExternalDeclaration)3488 pub fn show_external_declaration(state: &mut OutputState, ed: &hir::ExternalDeclaration) {
3489 match *ed {
3490 hir::ExternalDeclaration::Preprocessor(ref pp) => {
3491 if !state.output_cxx {
3492 show_preprocessor(state, pp)
3493 }
3494 }
3495 hir::ExternalDeclaration::FunctionDefinition(ref fd) => {
3496 if !state.output_cxx {
3497 show_function_definition(state, fd, !0)
3498 }
3499 }
3500 hir::ExternalDeclaration::Declaration(ref d) => show_declaration(state, d),
3501 }
3502 }
3503
show_cxx_function_definition(state: &mut OutputState, name: hir::SymRef, vector_mask: u32)3504 pub fn show_cxx_function_definition(state: &mut OutputState, name: hir::SymRef, vector_mask: u32) {
3505 if let Some((ref fd, run_class)) = state.hir.function_definition(name) {
3506 state.vector_mask = vector_mask;
3507 state.return_vector = (vector_mask & (1 << 31)) != 0
3508 || match run_class {
3509 hir::RunClass::Scalar => false,
3510 hir::RunClass::Dependent(mask) => (mask & vector_mask) != 0,
3511 _ => true,
3512 };
3513 match state.functions.get(&(name, vector_mask)) {
3514 Some(true) => {}
3515 Some(false) => {
3516 show_function_prototype(state, &fd.prototype);
3517 state.functions.insert((name, vector_mask), true);
3518 }
3519 None => {
3520 state.functions.insert((name, vector_mask), false);
3521 let buffer = state.push_buffer();
3522 show_function_definition(state, fd, vector_mask);
3523 for (name, vector_mask) in state.deps.replace(Vec::new()) {
3524 show_cxx_function_definition(state, name, vector_mask);
3525 }
3526 state.flush_buffer();
3527 state.pop_buffer(buffer);
3528 state.functions.insert((name, vector_mask), true);
3529 }
3530 }
3531 }
3532 }
3533
show_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit)3534 pub fn show_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit) {
3535 state.flush_buffer();
3536
3537 for ed in &(tu.0).0 {
3538 show_external_declaration(state, ed);
3539 state.flush_buffer();
3540 }
3541 if state.output_cxx {
3542 for name in &["main", "swgl_drawSpanRGBA8", "swgl_drawSpanR8"] {
3543 if let Some(sym) = state.hir.lookup(name) {
3544 show_cxx_function_definition(state, sym, 0);
3545 state.flush_buffer();
3546 }
3547 }
3548 }
3549 }
3550
write_abi(state: &mut OutputState)3551 fn write_abi(state: &mut OutputState) {
3552 match state.kind {
3553 ShaderKind::Fragment => {
3554 state.write("static void run(Self *self) {\n");
3555 if state.uses_discard {
3556 state.write(" self->swgl_IsPixelDiscarded = false;\n");
3557 }
3558 state.write(" self->main();\n");
3559 state.write(" self->step_interp_inputs();\n");
3560 state.write("}\n");
3561 state.write("static void skip(Self* self, int steps) {\n");
3562 state.write(" self->step_interp_inputs(steps);\n");
3563 state.write("}\n");
3564 if state.use_perspective {
3565 state.write("static void run_perspective(Self *self) {\n");
3566 if state.uses_discard {
3567 state.write(" self->swgl_IsPixelDiscarded = false;\n");
3568 }
3569 state.write(" self->main();\n");
3570 state.write(" self->step_perspective_inputs();\n");
3571 state.write("}\n");
3572 state.write("static void skip_perspective(Self* self, int steps) {\n");
3573 state.write(" self->step_perspective_inputs(steps);\n");
3574 state.write("}\n");
3575 }
3576 if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
3577 state.write(
3578 "static int draw_span_RGBA8(Self* self) { DISPATCH_DRAW_SPAN(self, RGBA8); }\n");
3579 }
3580 if state.hir.lookup("swgl_drawSpanR8").is_some() {
3581 state.write(
3582 "static int draw_span_R8(Self* self) { DISPATCH_DRAW_SPAN(self, R8); }\n");
3583 }
3584
3585 write!(state, "public:\n{}_frag() {{\n", state.name);
3586 }
3587 ShaderKind::Vertex => {
3588 state.write(
3589 "static void run(Self* self, char* interps, size_t interp_stride) {\n",
3590 );
3591 state.write(" self->main();\n");
3592 state.write(" self->store_interp_outputs(interps, interp_stride);\n");
3593 state.write("}\n");
3594 state.write("static void init_batch(Self *self) { self->bind_textures(); }\n");
3595
3596 write!(state, "public:\n{}_vert() {{\n", state.name);
3597 }
3598 }
3599 match state.kind {
3600 ShaderKind::Fragment => {
3601 state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n");
3602 state.write(" run_func = (RunFunc)&run;\n");
3603 state.write(" skip_func = (SkipFunc)&skip;\n");
3604 if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
3605 state.write(" draw_span_RGBA8_func = (DrawSpanRGBA8Func)&draw_span_RGBA8;\n");
3606 }
3607 if state.hir.lookup("swgl_drawSpanR8").is_some() {
3608 state.write(" draw_span_R8_func = (DrawSpanR8Func)&draw_span_R8;\n");
3609 }
3610 if state.uses_discard {
3611 state.write(" enable_discard();\n");
3612 }
3613 if state.use_perspective {
3614 state.write(" enable_perspective();\n");
3615 state.write(" init_span_w_func = (InitSpanWFunc)&read_perspective_inputs;\n");
3616 state.write(" run_w_func = (RunWFunc)&run_perspective;\n");
3617 state.write(" skip_w_func = (SkipWFunc)&skip_perspective;\n");
3618 } else {
3619 state.write(" init_span_w_func = (InitSpanWFunc)&read_interp_inputs;\n");
3620 state.write(" run_w_func = (RunWFunc)&run;\n");
3621 state.write(" skip_w_func = (SkipWFunc)&skip;\n");
3622 }
3623 }
3624 ShaderKind::Vertex => {
3625 state.write(" set_uniform_1i_func = (SetUniform1iFunc)&set_uniform_1i;\n");
3626 state.write(" set_uniform_4fv_func = (SetUniform4fvFunc)&set_uniform_4fv;\n");
3627 state.write(" set_uniform_matrix4fv_func = (SetUniformMatrix4fvFunc)&set_uniform_matrix4fv;\n");
3628 state.write(" init_batch_func = (InitBatchFunc)&init_batch;\n");
3629 state.write(" load_attribs_func = (LoadAttribsFunc)&load_attribs;\n");
3630 state.write(" run_primitive_func = (RunPrimitiveFunc)&run;\n");
3631 if state.hir.used_clip_dist != 0 {
3632 state.write(" enable_clip_distance();\n");
3633 }
3634 }
3635 }
3636 state.write("}\n");
3637 }
3638
define_global_consts(state: &mut OutputState, tu: &hir::TranslationUnit, part_name: &str)3639 pub fn define_global_consts(state: &mut OutputState, tu: &hir::TranslationUnit, part_name: &str) {
3640 for i in tu {
3641 match i {
3642 hir::ExternalDeclaration::Declaration(hir::Declaration::InitDeclaratorList(ref d)) => {
3643 let sym = state.hir.sym(d.head.name);
3644 match &sym.decl {
3645 hir::SymDecl::Global(hir::StorageClass::Const, ..) => {
3646 let is_scalar = state.is_scalar.replace(
3647 symbol_run_class(&sym.decl, state.vector_mask) == hir::RunClass::Scalar,
3648 );
3649 if let Some(ref _array) = d.head.ty.array_sizes {
3650 show_type(state, &d.head.ty);
3651 } else {
3652 if let Some(ty_def) = d.head.ty_def {
3653 show_sym_decl(state, &ty_def);
3654 } else {
3655 show_type(state, &d.head.ty);
3656 }
3657 }
3658 write!(state, " constexpr {}::{};\n", part_name, sym.name);
3659 state.is_scalar.set(is_scalar);
3660 }
3661 _ => {}
3662 }
3663 }
3664 _ => {}
3665 }
3666 }
3667 }
3668