1 use super::{
2 ast::Profile,
3 error::ExpectedToken,
4 error::{Error, ErrorKind},
5 token::TokenValue,
6 Options, Parser, Span,
7 };
8 use crate::ShaderStage;
9 use pp_rs::token::PreprocessorError;
10
11 #[test]
version()12 fn version() {
13 let mut parser = Parser::default();
14
15 // invalid versions
16 assert_eq!(
17 parser
18 .parse(
19 &Options::from(ShaderStage::Vertex),
20 "#version 99000\n void main(){}",
21 )
22 .err()
23 .unwrap(),
24 vec![Error {
25 kind: ErrorKind::InvalidVersion(99000),
26 meta: Span::new(9, 14)
27 }],
28 );
29
30 assert_eq!(
31 parser
32 .parse(
33 &Options::from(ShaderStage::Vertex),
34 "#version 449\n void main(){}",
35 )
36 .err()
37 .unwrap(),
38 vec![Error {
39 kind: ErrorKind::InvalidVersion(449),
40 meta: Span::new(9, 12)
41 }]
42 );
43
44 assert_eq!(
45 parser
46 .parse(
47 &Options::from(ShaderStage::Vertex),
48 "#version 450 smart\n void main(){}",
49 )
50 .err()
51 .unwrap(),
52 vec![Error {
53 kind: ErrorKind::InvalidProfile("smart".into()),
54 meta: Span::new(13, 18),
55 }]
56 );
57
58 assert_eq!(
59 parser
60 .parse(
61 &Options::from(ShaderStage::Vertex),
62 "#version 450\nvoid main(){} #version 450",
63 )
64 .err()
65 .unwrap(),
66 vec![
67 Error {
68 kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedHash,),
69 meta: Span::new(27, 28),
70 },
71 Error {
72 kind: ErrorKind::InvalidToken(
73 TokenValue::Identifier("version".into()),
74 vec![ExpectedToken::Eof]
75 ),
76 meta: Span::new(28, 35)
77 }
78 ]
79 );
80
81 // valid versions
82 parser
83 .parse(
84 &Options::from(ShaderStage::Vertex),
85 " # version 450\nvoid main() {}",
86 )
87 .unwrap();
88 assert_eq!(
89 (parser.metadata().version, parser.metadata().profile),
90 (450, Profile::Core)
91 );
92
93 parser
94 .parse(
95 &Options::from(ShaderStage::Vertex),
96 "#version 450\nvoid main() {}",
97 )
98 .unwrap();
99 assert_eq!(
100 (parser.metadata().version, parser.metadata().profile),
101 (450, Profile::Core)
102 );
103
104 parser
105 .parse(
106 &Options::from(ShaderStage::Vertex),
107 "#version 450 core\nvoid main(void) {}",
108 )
109 .unwrap();
110 assert_eq!(
111 (parser.metadata().version, parser.metadata().profile),
112 (450, Profile::Core)
113 );
114 }
115
116 #[test]
control_flow()117 fn control_flow() {
118 let mut parser = Parser::default();
119
120 parser
121 .parse(
122 &Options::from(ShaderStage::Vertex),
123 r#"
124 # version 450
125 void main() {
126 if (true) {
127 return 1;
128 } else {
129 return 2;
130 }
131 }
132 "#,
133 )
134 .unwrap();
135
136 parser
137 .parse(
138 &Options::from(ShaderStage::Vertex),
139 r#"
140 # version 450
141 void main() {
142 if (true) {
143 return 1;
144 }
145 }
146 "#,
147 )
148 .unwrap();
149
150 parser
151 .parse(
152 &Options::from(ShaderStage::Vertex),
153 r#"
154 # version 450
155 void main() {
156 int x;
157 int y = 3;
158 switch (5) {
159 case 2:
160 x = 2;
161 case 5:
162 x = 5;
163 y = 2;
164 break;
165 default:
166 x = 0;
167 }
168 }
169 "#,
170 )
171 .unwrap();
172
173 parser
174 .parse(
175 &Options::from(ShaderStage::Vertex),
176 r#"
177 # version 450
178 void main() {
179 int x = 0;
180 while(x < 5) {
181 x = x + 1;
182 }
183 do {
184 x = x - 1;
185 } while(x >= 4)
186 }
187 "#,
188 )
189 .unwrap();
190
191 parser
192 .parse(
193 &Options::from(ShaderStage::Vertex),
194 r#"
195 # version 450
196 void main() {
197 int x = 0;
198 for(int i = 0; i < 10;) {
199 x = x + 2;
200 }
201 for(;;);
202 return x;
203 }
204 "#,
205 )
206 .unwrap();
207 }
208
209 #[test]
declarations()210 fn declarations() {
211 let mut parser = Parser::default();
212
213 parser
214 .parse(
215 &Options::from(ShaderStage::Vertex),
216 r#"
217 #version 450
218 layout(location = 0) in vec2 v_uv;
219 layout(location = 0) out vec4 o_color;
220 layout(set = 1, binding = 1) uniform texture2D tex;
221 layout(set = 1, binding = 2) uniform sampler tex_sampler;
222
223 layout(early_fragment_tests) in;
224
225 void main() {}
226 "#,
227 )
228 .unwrap();
229
230 parser
231 .parse(
232 &Options::from(ShaderStage::Vertex),
233 r#"
234 #version 450
235 layout(std140, set = 2, binding = 0)
236 uniform u_locals {
237 vec3 model_offs;
238 float load_time;
239 ivec4 atlas_offs;
240 };
241
242 void main() {}
243 "#,
244 )
245 .unwrap();
246
247 parser
248 .parse(
249 &Options::from(ShaderStage::Vertex),
250 r#"
251 #version 450
252 layout(push_constant)
253 uniform u_locals {
254 vec3 model_offs;
255 float load_time;
256 ivec4 atlas_offs;
257 };
258
259 void main() {}
260 "#,
261 )
262 .unwrap();
263
264 parser
265 .parse(
266 &Options::from(ShaderStage::Vertex),
267 r#"
268 #version 450
269 layout(std430, set = 2, binding = 0)
270 uniform u_locals {
271 vec3 model_offs;
272 float load_time;
273 ivec4 atlas_offs;
274 };
275
276 void main() {}
277 "#,
278 )
279 .unwrap();
280
281 parser
282 .parse(
283 &Options::from(ShaderStage::Vertex),
284 r#"
285 #version 450
286 layout(std140, set = 2, binding = 0)
287 uniform u_locals {
288 vec3 model_offs;
289 float load_time;
290 } block_var;
291
292 void main() {
293 load_time * model_offs;
294 block_var.load_time * block_var.model_offs;
295 }
296 "#,
297 )
298 .unwrap();
299
300 parser
301 .parse(
302 &Options::from(ShaderStage::Vertex),
303 r#"
304 #version 450
305 float vector = vec4(1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0);
306
307 void main() {}
308 "#,
309 )
310 .unwrap();
311
312 parser
313 .parse(
314 &Options::from(ShaderStage::Vertex),
315 r#"
316 #version 450
317 precision highp float;
318
319 void main() {}
320 "#,
321 )
322 .unwrap();
323 }
324
325 #[test]
textures()326 fn textures() {
327 let mut parser = Parser::default();
328
329 parser
330 .parse(
331 &Options::from(ShaderStage::Vertex),
332 r#"
333 #version 450
334 layout(location = 0) in vec2 v_uv;
335 layout(location = 0) out vec4 o_color;
336 layout(set = 1, binding = 1) uniform texture2D tex;
337 layout(set = 1, binding = 2) uniform sampler tex_sampler;
338 void main() {
339 o_color = texture(sampler2D(tex, tex_sampler), v_uv);
340 o_color.a = texture(sampler2D(tex, tex_sampler), v_uv, 2.0).a;
341 }
342 "#,
343 )
344 .unwrap();
345 }
346
347 #[test]
functions()348 fn functions() {
349 let mut parser = Parser::default();
350
351 parser
352 .parse(
353 &Options::from(ShaderStage::Vertex),
354 r#"
355 # version 450
356 void test1(float);
357 void test1(float) {}
358
359 void main() {}
360 "#,
361 )
362 .unwrap();
363
364 parser
365 .parse(
366 &Options::from(ShaderStage::Vertex),
367 r#"
368 # version 450
369 void test2(float a) {}
370 void test3(float a, float b) {}
371 void test4(float, float) {}
372
373 void main() {}
374 "#,
375 )
376 .unwrap();
377
378 parser
379 .parse(
380 &Options::from(ShaderStage::Vertex),
381 r#"
382 # version 450
383 float test(float a) { return a; }
384
385 void main() {}
386 "#,
387 )
388 .unwrap();
389
390 parser
391 .parse(
392 &Options::from(ShaderStage::Vertex),
393 r#"
394 # version 450
395 float test(vec4 p) {
396 return p.x;
397 }
398
399 void main() {}
400 "#,
401 )
402 .unwrap();
403
404 // Function overloading
405 parser
406 .parse(
407 &Options::from(ShaderStage::Vertex),
408 r#"
409 # version 450
410 float test(vec2 p);
411 float test(vec3 p);
412 float test(vec4 p);
413
414 float test(vec2 p) {
415 return p.x;
416 }
417
418 float test(vec3 p) {
419 return p.x;
420 }
421
422 float test(vec4 p) {
423 return p.x;
424 }
425
426 void main() {}
427 "#,
428 )
429 .unwrap();
430
431 assert_eq!(
432 parser
433 .parse(
434 &Options::from(ShaderStage::Vertex),
435 r#"
436 # version 450
437 int test(vec4 p) {
438 return p.x;
439 }
440
441 float test(vec4 p) {
442 return p.x;
443 }
444
445 void main() {}
446 "#,
447 )
448 .err()
449 .unwrap(),
450 vec![Error {
451 kind: ErrorKind::SemanticError("Function already defined".into()),
452 meta: Span::new(134, 152),
453 }]
454 );
455
456 println!();
457
458 parser
459 .parse(
460 &Options::from(ShaderStage::Vertex),
461 r#"
462 # version 450
463 float callee(uint q) {
464 return float(q);
465 }
466
467 float caller() {
468 callee(1u);
469 }
470
471 void main() {}
472 "#,
473 )
474 .unwrap();
475
476 // Nested function call
477 parser
478 .parse(
479 &Options::from(ShaderStage::Vertex),
480 r#"
481 # version 450
482 layout(set = 0, binding = 1) uniform texture2D t_noise;
483 layout(set = 0, binding = 2) uniform sampler s_noise;
484
485 void main() {
486 textureLod(sampler2D(t_noise, s_noise), vec2(1.0), 0);
487 }
488 "#,
489 )
490 .unwrap();
491
492 parser
493 .parse(
494 &Options::from(ShaderStage::Vertex),
495 r#"
496 # version 450
497 void fun(vec2 in_parameter, out float out_parameter) {
498 ivec2 _ = ivec2(in_parameter);
499 }
500
501 void main() {
502 float a;
503 fun(vec2(1.0), a);
504 }
505 "#,
506 )
507 .unwrap();
508 }
509
510 #[test]
constants()511 fn constants() {
512 use crate::{Constant, ConstantInner, ScalarValue};
513 let mut parser = Parser::default();
514
515 let module = parser
516 .parse(
517 &Options::from(ShaderStage::Vertex),
518 r#"
519 # version 450
520 const float a = 1.0;
521 float global = a;
522 const float b = a;
523
524 void main() {}
525 "#,
526 )
527 .unwrap();
528
529 let mut constants = module.constants.iter();
530
531 assert_eq!(
532 constants.next().unwrap().1,
533 &Constant {
534 name: None,
535 specialization: None,
536 inner: ConstantInner::Scalar {
537 width: 4,
538 value: ScalarValue::Float(1.0)
539 }
540 }
541 );
542
543 assert!(constants.next().is_none());
544 }
545
546 #[test]
function_overloading()547 fn function_overloading() {
548 let mut parser = Parser::default();
549
550 parser
551 .parse(
552 &Options::from(ShaderStage::Vertex),
553 r#"
554 # version 450
555
556 float saturate(float v) { return clamp(v, 0.0, 1.0); }
557 vec2 saturate(vec2 v) { return clamp(v, vec2(0.0), vec2(1.0)); }
558 vec3 saturate(vec3 v) { return clamp(v, vec3(0.0), vec3(1.0)); }
559 vec4 saturate(vec4 v) { return clamp(v, vec4(0.0), vec4(1.0)); }
560
561 void main() {
562 float v1 = saturate(1.5);
563 vec2 v2 = saturate(vec2(0.5, 1.5));
564 vec3 v3 = saturate(vec3(0.5, 1.5, 2.5));
565 vec3 v4 = saturate(vec4(0.5, 1.5, 2.5, 3.5));
566 }
567 "#,
568 )
569 .unwrap();
570 }
571
572 #[test]
implicit_conversions()573 fn implicit_conversions() {
574 let mut parser = Parser::default();
575
576 parser
577 .parse(
578 &Options::from(ShaderStage::Vertex),
579 r#"
580 # version 450
581 void main() {
582 mat4 a = mat4(1);
583 float b = 1u;
584 float c = 1 + 2.0;
585 }
586 "#,
587 )
588 .unwrap();
589
590 assert_eq!(
591 parser
592 .parse(
593 &Options::from(ShaderStage::Vertex),
594 r#"
595 # version 450
596 void test(int a) {}
597 void test(uint a) {}
598
599 void main() {
600 test(1.0);
601 }
602 "#,
603 )
604 .err()
605 .unwrap(),
606 vec![Error {
607 kind: ErrorKind::SemanticError("Unknown function \'test\'".into()),
608 meta: Span::new(156, 165),
609 }]
610 );
611
612 assert_eq!(
613 parser
614 .parse(
615 &Options::from(ShaderStage::Vertex),
616 r#"
617 # version 450
618 void test(float a) {}
619 void test(uint a) {}
620
621 void main() {
622 test(1);
623 }
624 "#,
625 )
626 .err()
627 .unwrap(),
628 vec![Error {
629 kind: ErrorKind::SemanticError("Ambiguous best function for \'test\'".into()),
630 meta: Span::new(158, 165),
631 }]
632 );
633 }
634
635 #[test]
structs()636 fn structs() {
637 let mut parser = Parser::default();
638
639 parser
640 .parse(
641 &Options::from(ShaderStage::Vertex),
642 r#"
643 # version 450
644 Test {
645 vec4 pos;
646 } xx;
647
648 void main() {}
649 "#,
650 )
651 .unwrap_err();
652
653 parser
654 .parse(
655 &Options::from(ShaderStage::Vertex),
656 r#"
657 # version 450
658 struct Test {
659 vec4 pos;
660 };
661
662 void main() {}
663 "#,
664 )
665 .unwrap();
666
667 parser
668 .parse(
669 &Options::from(ShaderStage::Vertex),
670 r#"
671 # version 450
672 const int NUM_VECS = 42;
673 struct Test {
674 vec4 vecs[NUM_VECS];
675 };
676
677 void main() {}
678 "#,
679 )
680 .unwrap();
681
682 parser
683 .parse(
684 &Options::from(ShaderStage::Vertex),
685 r#"
686 # version 450
687 struct Hello {
688 vec4 test;
689 } test() {
690 return Hello( vec4(1.0) );
691 }
692
693 void main() {}
694 "#,
695 )
696 .unwrap();
697
698 parser
699 .parse(
700 &Options::from(ShaderStage::Vertex),
701 r#"
702 # version 450
703 struct Test {};
704
705 void main() {}
706 "#,
707 )
708 .unwrap_err();
709
710 parser
711 .parse(
712 &Options::from(ShaderStage::Vertex),
713 r#"
714 # version 450
715 inout struct Test {
716 vec4 x;
717 };
718
719 void main() {}
720 "#,
721 )
722 .unwrap_err();
723 }
724
725 #[test]
swizzles()726 fn swizzles() {
727 let mut parser = Parser::default();
728
729 parser
730 .parse(
731 &Options::from(ShaderStage::Vertex),
732 r#"
733 # version 450
734 void main() {
735 vec4 v = vec4(1);
736 v.xyz = vec3(2);
737 v.x = 5.0;
738 v.xyz.zxy.yx.xy = vec2(5.0, 1.0);
739 }
740 "#,
741 )
742 .unwrap();
743
744 parser
745 .parse(
746 &Options::from(ShaderStage::Vertex),
747 r#"
748 # version 450
749 void main() {
750 vec4 v = vec4(1);
751 v.xx = vec2(5.0);
752 }
753 "#,
754 )
755 .unwrap_err();
756
757 parser
758 .parse(
759 &Options::from(ShaderStage::Vertex),
760 r#"
761 # version 450
762 void main() {
763 vec3 v = vec3(1);
764 v.w = 2.0;
765 }
766 "#,
767 )
768 .unwrap_err();
769 }
770
771 #[test]
expressions()772 fn expressions() {
773 let mut parser = Parser::default();
774
775 // Vector indexing
776 parser
777 .parse(
778 &Options::from(ShaderStage::Vertex),
779 r#"
780 # version 450
781 float test(int index) {
782 vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
783 return v[index] + 1.0;
784 }
785
786 void main() {}
787 "#,
788 )
789 .unwrap();
790
791 // Prefix increment/decrement
792 parser
793 .parse(
794 &Options::from(ShaderStage::Vertex),
795 r#"
796 # version 450
797 void main() {
798 uint index = 0;
799
800 --index;
801 ++index;
802 }
803 "#,
804 )
805 .unwrap();
806
807 // Dynamic indexing of array
808 parser
809 .parse(
810 &Options::from(ShaderStage::Vertex),
811 r#"
812 # version 450
813 void main() {
814 const vec4 positions[1] = { vec4(0) };
815
816 gl_Position = positions[gl_VertexIndex];
817 }
818 "#,
819 )
820 .unwrap();
821 }
822