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