lib.rs (127389B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #![allow(unknown_lints, mismatched_lifetime_syntaxes)] 6 7 extern crate glsl; 8 9 mod hir; 10 11 use glsl::parser::Parse; 12 use glsl::syntax; 13 use glsl::syntax::{TranslationUnit, UnaryOp}; 14 use hir::{Statement, Type}; 15 use std::cell::{Cell, RefCell}; 16 use std::collections::{BTreeMap, HashMap}; 17 use std::io::Read; 18 use std::mem; 19 20 #[derive(PartialEq, Eq)] 21 enum ShaderKind { 22 Fragment, 23 Vertex, 24 } 25 26 type UniformIndices = BTreeMap<String, (i32, hir::TypeKind, hir::StorageClass)>; 27 28 fn 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 48 pub 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 // we use a BTree so that iteration is stable 70 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 94 fn 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 //println!("{:#?}", r); 104 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 fast = std::fs::File::create("ast").unwrap(); 111 //fast.write(ast_glsl.as_bytes()); 112 113 let mut state = hir::State::new(); 114 let hir = hir::ast_to_hir(&mut state, &r); 115 (state, hir, is_frag) 116 } 117 118 fn 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 //println!("{:#?}", state); 126 127 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 //println!("{:#?}", hir); 161 162 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 //let mut hir = std::fs::File::create("hir").unwrap(); 259 //hir.write(output_glsl.as_bytes()); 260 261 output_cxx 262 } 263 264 fn 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 280 fn float4_compatible(ty: hir::TypeKind) -> bool { 281 match ty { 282 hir::TypeKind::Vec4 => true, 283 _ => false, 284 } 285 } 286 287 fn matrix4_compatible(ty: hir::TypeKind) -> bool { 288 match ty { 289 hir::TypeKind::Mat4 => true, 290 _ => false, 291 } 292 } 293 294 fn 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 338 fn 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 360 fn 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 388 fn 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 415 fn 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 442 fn 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 472 fn 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 513 //fn type_name(state: &OutputState, ty: &Type) -> String { 514 // let buffer = state.push_buffer(); 515 // show_type(state, ty); 516 // state.pop_buffer(buffer) 517 //} 518 519 fn 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 544 fn 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 601 fn 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 750 pub 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 776 use std::fmt::{Arguments, Write}; 777 778 impl 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 820 pub fn show_identifier(state: &OutputState, i: &syntax::Identifier) { 821 state.write(&i.0); 822 } 823 824 fn 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 830 fn 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 837 pub 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 // we want to replace constructor names 860 if state.output_cxx { 861 name = glsl_primitive_type_name_to_cxx(name); 862 } 863 state.write(name); 864 } 865 } 866 } 867 868 pub 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 884 pub fn write_default_constructor(state: &OutputState, name: &str) { 885 // write default constructor 886 let _ = write!(state, "{}() = default;\n", name); 887 } 888 889 pub 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 917 pub 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 981 pub 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 998 pub 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 1019 pub 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 // write if_then_else 1070 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 1082 pub fn show_type_name(state: &OutputState, t: &syntax::TypeName) { 1083 state.write(&t.0); 1084 } 1085 1086 pub 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!(), //show_struct_non_declaration(state, s), 1092 syntax::TypeSpecifierNonArray::TypeName(ref tn) => show_type_name(state, tn), 1093 _ => unreachable!(), 1094 } 1095 } 1096 } 1097 1098 pub 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 1139 pub 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 1147 pub 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 /*if let Some(ref arr_spec) = t.array_sizes { 1174 panic!(); 1175 }*/ 1176 } 1177 1178 /*pub fn show_fully_specified_type(state: &mut OutputState, t: &FullySpecifiedType) { 1179 state.flat = false; 1180 if let Some(ref qual) = t.qualifier { 1181 if !state.output_cxx { 1182 show_type_qualifier(state, &qual); 1183 } else { 1184 state.flat = 1185 qual.qualifiers.0.iter() 1186 .flat_map(|q| match q { syntax::TypeQualifierSpec::Interpolation(Flat) => Some(()), _ => None}) 1187 .next().is_some(); 1188 } 1189 state.write(" "); 1190 } 1191 1192 show_type_specifier(state, &t.ty); 1193 }*/ 1194 1195 /*pub fn show_struct_non_declaration(state: &mut OutputState, s: &syntax::StructSpecifier) { 1196 state.write("struct "); 1197 1198 if let Some(ref name) = s.name { 1199 let _ = write!(state, "{} ", name); 1200 } 1201 1202 state.write("{\n"); 1203 1204 for field in &s.fields.0 { 1205 show_struct_field(state, field); 1206 } 1207 1208 state.write("}"); 1209 }*/ 1210 1211 pub fn show_struct(_state: &OutputState, _s: &syntax::StructSpecifier) { 1212 panic!(); 1213 //show_struct_non_declaration(state, s); 1214 //state.write(";\n"); 1215 } 1216 1217 pub 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 1226 pub 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 1241 pub 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 1251 pub 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 1259 pub 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 /* 1268 match *a { 1269 syntax::ArraySpecifier::Unsized => { state.write("[]"); } 1270 syntax::ArraySpecifier::ExplicitlySized(ref e) => { 1271 state.write("["); 1272 show_expr(state, &e); 1273 state.write("]"); 1274 } 1275 }*/ 1276 } 1277 1278 pub 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 1290 pub 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 1304 pub 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 1361 pub 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 1381 pub 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 1396 pub 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 1409 pub 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 1423 pub 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 1437 pub 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 1468 pub 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 1476 pub fn show_double(state: &OutputState, x: f64) { 1477 // force doubles to print as floats 1478 if x.fract() == 0. { 1479 write!(state, "{}.f", x); 1480 } else { 1481 write!(state, "{}f", x); 1482 } 1483 } 1484 1485 fn 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 1595 pub fn show_hir_expr(state: &OutputState, expr: &hir::Expr) { 1596 show_hir_expr_inner(state, expr, false); 1597 } 1598 1599 pub 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 // For single component swizzles, output a field access to 2030 // avoid stressing inlining of sel(). 2031 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 2076 pub 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 2163 pub 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 2186 pub 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 2248 pub 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 2286 pub 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 2293 pub 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 2300 pub 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 //show_block(state, &block); 2337 //state.write(";\n"); 2338 } 2339 hir::Declaration::Global(ref qual, ref identifiers) => { 2340 // We only want to output GLSL layout qualifiers if not C++ 2341 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 2365 pub 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 2396 pub 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 2431 pub 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 2440 pub 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 2448 pub 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 2485 fn 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 2504 pub 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 // XXX: this is pretty grotty 2555 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 2566 pub 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 2575 pub 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 2595 /* 2596 pub fn show_block(state: &mut OutputState, b: &hir::Block) { 2597 show_type_qualifier(state, &b.qualifier); 2598 state.write(" "); 2599 show_identifier(state, &b.name); 2600 state.write(" {"); 2601 2602 for field in &b.fields { 2603 show_struct_field(state, field); 2604 state.write("\n"); 2605 } 2606 state.write("}"); 2607 2608 if let Some(ref ident) = b.identifier { 2609 show_arrayed_identifier(state, ident); 2610 } 2611 } 2612 */ 2613 2614 // This is a hack to run through the first time with an empty writter to find if 'return' is declared. 2615 pub 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 2624 fn 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 2645 pub fn show_function_definition( 2646 state: &mut OutputState, 2647 fd: &hir::FunctionDefinition, 2648 vector_mask: u32, 2649 ) { 2650 // println!("start {:?} {:?}", fd.prototype.name, vector_mask); 2651 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 // XXX: the cloning here is bad 2684 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 // Partial spans are not drawn using span shaders, but rather drawn with a fragment shader 2698 // where the span shader left off. We need to undo any changes to the interpolants made by 2699 // the span shaders so that we can reset the interpolants to where the fragment shader 2700 // expects them. We do this by saving them in an _Undo_ struct on entry to the span shader, 2701 // and then restore them in the _Undo_ struct destructor. 2702 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 // println!("end {:?}", fd.prototype.name); 2773 2774 state.return_type = None; 2775 state.return_declared = false; 2776 state.mask = None; 2777 } 2778 2779 pub 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 2793 pub 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 2800 pub 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 2811 pub fn show_indent(state: &OutputState) { 2812 for _ in 0 .. state.indent { 2813 state.write(" "); 2814 } 2815 } 2816 2817 pub 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 2827 pub 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 // invert the condition 2877 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 2922 fn case_stmts_to_if_stmts(stmts: &[Statement], last: bool) -> (Option<Box<Statement>>, bool) { 2923 // Look for jump statements and remove them 2924 // We currently are pretty strict on the form that the statement 2925 // list needs to be in. This can be loosened as needed. 2926 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 // we don't need a break at the end 2945 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 2976 fn 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 // if we have two conditions join them 2993 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 /* 3002 3003 // find the next case that's not a default 3004 let next_case = loop { 3005 match cases.next() { 3006 Some(hir::Case { label: hir::CaseLabel::Def, ..}) => { }, 3007 case => break case, 3008 } 3009 };*/ 3010 3011 let (cond, body, else_stmt) = match (cond, cases.next()) { 3012 (None, Some(next_case)) => { 3013 assert!(previous_stmts.is_none()); 3014 // default so just move on to the next 3015 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 // empty so fall through to the next 3032 return build_selection(head, next_case, cases, default, Some(cond), stmts); 3033 } 3034 } 3035 (Some(cond), None) => { 3036 // non-default last 3037 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 // add the default case at the end if we have one 3041 ( 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 // default, last 3057 3058 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 3087 pub 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 3094 fn 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 3103 pub 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 // XXX: when lowering switches we end up with a mask that has 3106 // a bunch of mutually exclusive conditions. 3107 // It would be nice if we could fold them together. 3108 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 // glsl allows declarations in switch statements while C requires them to be 3124 // in a compound statement. If we have a declaration wrap the statements in an block. 3125 // This will break some glsl shaders but keeps the saner ones working 3126 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 3148 pub 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 3162 pub 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 3188 pub fn show_condition(state: &mut OutputState, c: &hir::Condition) { 3189 match *c { 3190 hir::Condition::Expr(ref e) => show_hir_expr(state, e), 3191 /*hir::Condition::Assignment(ref ty, ref name, ref initializer) => { 3192 show_type(state, ty); 3193 state.write(" "); 3194 show_identifier(f, name); 3195 state.write(" = "); 3196 show_initializer(state, initializer); 3197 }*/ 3198 } 3199 } 3200 3201 pub 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 3214 pub 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 3226 fn 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 3234 pub 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 // We cast any conditions by `ret_mask_type` so that scalars nicely 3266 // convert to -1. i.e. I32 &= bool will give the wrong result. while I32 &= I32(bool) works 3267 let ret_mask_type = if state.return_vector { 3268 "I32" 3269 } else { 3270 "int32_t" 3271 }; 3272 if state.return_declared { 3273 // XXX: the cloning here is bad 3274 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 3339 pub 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 3350 pub 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 3369 pub 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 3398 pub fn show_preprocessor_else(state: &OutputState) { 3399 state.write("#else\n"); 3400 } 3401 3402 pub fn show_preprocessor_elseif(state: &OutputState, pei: &syntax::PreprocessorElseIf) { 3403 let _ = write!(state, "#elseif {}\n", pei.condition); 3404 } 3405 3406 pub fn show_preprocessor_error(state: &OutputState, pe: &syntax::PreprocessorError) { 3407 let _ = writeln!(state, "#error {}", pe.message); 3408 } 3409 3410 pub fn show_preprocessor_endif(state: &OutputState) { 3411 state.write("#endif\n"); 3412 } 3413 3414 pub fn show_preprocessor_if(state: &OutputState, pi: &syntax::PreprocessorIf) { 3415 let _ = write!(state, "#if {}\n", pi.condition); 3416 } 3417 3418 pub 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 3424 pub 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 3430 pub 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 3436 pub 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 3444 pub fn show_preprocessor_pragma(state: &OutputState, pp: &syntax::PreprocessorPragma) { 3445 let _ = writeln!(state, "#pragma {}", pp.command); 3446 } 3447 3448 pub 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 3454 pub 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 3474 pub 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 3506 pub 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 3522 pub 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 3552 pub 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 3569 fn 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 3661 pub 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 }