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