glsl: lower mediump integer types to int16 and uint16
[mesa.git] / src / compiler / glsl / tests / lower_precision_test.py
1 # encoding=utf-8
2 # Copyright © 2019 Google
3
4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 # of this software and associated documentation files (the "Software"), to deal
6 # in the Software without restriction, including without limitation the rights
7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 # copies of the Software, and to permit persons to whom the Software is
9 # furnished to do so, subject to the following conditions:
10
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
13
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 # SOFTWARE.
21
22 from __future__ import print_function
23 import sys
24 import subprocess
25 import tempfile
26 import re
27 from collections import namedtuple
28
29
30 Test = namedtuple("Test", "name source match_re")
31
32
33 TESTS = [
34 Test("f32 simple division",
35 """
36 uniform mediump float a, b;
37
38 void main()
39 {
40 gl_FragColor.rgba = vec4(a / b);
41 }
42 """,
43 r'\(expression +float16_t +/'),
44 Test("i32 simple division",
45 """
46 #version 300 es
47 precision mediump float;
48 precision mediump int;
49 uniform mediump int a, b;
50
51 out vec4 color;
52
53 void main()
54 {
55 color = vec4(a / b);
56 }
57 """,
58 r'\(expression +int16_t +/'),
59 Test("u32 simple division",
60 """
61 #version 300 es
62 precision mediump float;
63 precision mediump int;
64 uniform mediump uint a, b;
65
66 out vec4 color;
67
68 void main()
69 {
70 color = vec4(a / b);
71 }
72 """,
73 r'\(expression +uint16_t +/'),
74 Test("dot",
75 """
76 uniform mediump vec2 a, b;
77
78 void main()
79 {
80 gl_FragColor.rgba = vec4(dot(a, b));
81 }
82 """,
83 r'\(expression +float16_t +dot\b'),
84 Test("f32 array with const index",
85 """
86 precision mediump float;
87
88 uniform float in_simple[2];
89
90 void main()
91 {
92 gl_FragColor = vec4(in_simple[0] / in_simple[1]);
93 }
94 """,
95 r'\(expression +float16_t +/'),
96 Test("i32 array with const index",
97 """
98 #version 300 es
99 precision mediump float;
100 precision mediump int;
101
102 uniform int in_simple[2];
103
104 out vec4 color;
105
106 void main()
107 {
108 color = vec4(in_simple[0] / in_simple[1]);
109 }
110 """,
111 r'\(expression +int16_t +/'),
112 Test("u32 array with const index",
113 """
114 #version 300 es
115 precision mediump float;
116 precision mediump int;
117
118 uniform uint in_simple[2];
119
120 out vec4 color;
121
122 void main()
123 {
124 color = vec4(in_simple[0] / in_simple[1]);
125 }
126 """,
127 r'\(expression +uint16_t +/'),
128 Test("f32 array with uniform index",
129 """
130 precision mediump float;
131
132 uniform float in_simple[2];
133 uniform int i0, i1;
134
135 void main()
136 {
137 gl_FragColor = vec4(in_simple[i0] / in_simple[i1]);
138 }
139 """,
140 r'\(expression +float16_t +/'),
141 Test("i32 array with uniform index",
142 """
143 #version 300 es
144 precision mediump float;
145 precision mediump int;
146
147 uniform int in_simple[2];
148 uniform int i0, i1;
149
150 out vec4 color;
151
152 void main()
153 {
154 color = vec4(in_simple[i0] / in_simple[i1]);
155 }
156 """,
157 r'\(expression +int16_t +/'),
158 Test("u32 array with uniform index",
159 """
160 #version 300 es
161 precision mediump float;
162 precision mediump int;
163
164 uniform uint in_simple[2];
165 uniform int i0, i1;
166
167 out vec4 color;
168
169 void main()
170 {
171 color = vec4(in_simple[i0] / in_simple[i1]);
172 }
173 """,
174 r'\(expression +uint16_t +/'),
175 Test("f32 array-of-array with const index",
176 """
177 #version 310 es
178 precision mediump float;
179
180 uniform float in_aoa[2][2];
181
182 layout(location = 0) out float out_color;
183
184 void main()
185 {
186 out_color = in_aoa[0][0] / in_aoa[1][1];
187 }
188 """,
189 r'\(expression +float16_t +/'),
190 Test("i32 array-of-array with const index",
191 """
192 #version 310 es
193 precision mediump float;
194 precision mediump int;
195
196 uniform int in_aoa[2][2];
197
198 layout(location = 0) out highp int out_color;
199
200 void main()
201 {
202 out_color = in_aoa[0][0] / in_aoa[1][1];
203 }
204 """,
205 r'\(expression +int16_t +/'),
206 Test("u32 array-of-array with const index",
207 """
208 #version 310 es
209 precision mediump float;
210 precision mediump int;
211
212 uniform uint in_aoa[2][2];
213
214 layout(location = 0) out highp uint out_color;
215
216 void main()
217 {
218 out_color = in_aoa[0][0] / in_aoa[1][1];
219 }
220 """,
221 r'\(expression +uint16_t +/'),
222 Test("f32 array-of-array with uniform index",
223 """
224 #version 310 es
225 precision mediump float;
226
227 uniform float in_aoa[2][2];
228 uniform int i0, i1;
229
230 layout(location = 0) out float out_color;
231
232 void main()
233 {
234 out_color = in_aoa[i0][i0] / in_aoa[i1][i1];
235 }
236 """,
237 r'\(expression +float16_t +/'),
238 Test("i32 array-of-array with uniform index",
239 """
240 #version 310 es
241 precision mediump float;
242 precision mediump int;
243
244 uniform int in_aoa[2][2];
245 uniform int i0, i1;
246
247 layout(location = 0) out highp int out_color;
248
249 void main()
250 {
251 out_color = in_aoa[i0][i0] / in_aoa[i1][i1];
252 }
253 """,
254 r'\(expression +int16_t +/'),
255 Test("u32 array-of-array with uniform index",
256 """
257 #version 310 es
258 precision mediump float;
259 precision mediump int;
260
261 uniform uint in_aoa[2][2];
262 uniform int i0, i1;
263
264 layout(location = 0) out highp uint out_color;
265
266 void main()
267 {
268 out_color = in_aoa[i0][i0] / in_aoa[i1][i1];
269 }
270 """,
271 r'\(expression +uint16_t +/'),
272 Test("f32 array index",
273 """
274 uniform mediump float a, b;
275 uniform mediump float values[2];
276
277 void main()
278 {
279 gl_FragColor.rgba = vec4(values[int(a / b)]);
280 }
281 """,
282 r'\(expression +float16_t +/'),
283 Test("i32 array index",
284 """
285 #version 310 es
286 precision mediump float;
287 precision mediump int;
288
289 uniform mediump int a, b;
290 uniform mediump int values[2];
291
292 out highp int color;
293
294 void main()
295 {
296 color = values[a / b];
297 }
298 """,
299 r'\(expression +int16_t +/'),
300 Test("f32 function",
301 """
302 precision mediump float;
303
304 uniform float a, b;
305
306 mediump float
307 get_a()
308 {
309 return a;
310 }
311
312 float
313 get_b()
314 {
315 return b;
316 }
317
318 void main()
319 {
320 gl_FragColor = vec4(get_a() / get_b());
321 }
322 """,
323 r'\(expression +float16_t +/'),
324 Test("i32 function",
325 """
326 #version 310 es
327 precision mediump float;
328 precision mediump int;
329
330 uniform int a, b;
331
332 mediump int
333 get_a()
334 {
335 return a;
336 }
337
338 int
339 get_b()
340 {
341 return b;
342 }
343
344 out highp int color;
345
346 void main()
347 {
348 color = get_a() / get_b();
349 }
350 """,
351 r'\(expression +int16_t +/'),
352 Test("u32 function",
353 """
354 #version 310 es
355 precision mediump float;
356 precision mediump int;
357
358 uniform uint a, b;
359
360 mediump uint
361 get_a()
362 {
363 return a;
364 }
365
366 uint
367 get_b()
368 {
369 return b;
370 }
371
372 out highp uint color;
373
374 void main()
375 {
376 color = get_a() / get_b();
377 }
378 """,
379 r'\(expression +uint16_t +/'),
380 Test("f32 function mediump args",
381 """
382 precision mediump float;
383
384 uniform float a, b;
385
386 mediump float
387 do_div(float x, float y)
388 {
389 return x / y;
390 }
391
392 void main()
393 {
394 gl_FragColor = vec4(do_div(a, b));
395 }
396 """,
397 r'\(expression +float16_t +/'),
398 Test("i32 function mediump args",
399 """
400 #version 310 es
401 precision mediump float;
402 precision mediump int;
403
404 uniform int a, b;
405
406 mediump int
407 do_div(int x, int y)
408 {
409 return x / y;
410 }
411
412 out highp int color;
413
414 void main()
415 {
416 color = do_div(a, b);
417 }
418 """,
419 r'\(expression +int16_t +/'),
420 Test("u32 function mediump args",
421 """
422 #version 310 es
423 precision mediump float;
424 precision mediump int;
425
426 uniform uint a, b;
427
428 mediump uint
429 do_div(uint x, uint y)
430 {
431 return x / y;
432 }
433
434 out highp uint color;
435
436 void main()
437 {
438 color = do_div(a, b);
439 }
440 """,
441 r'\(expression +uint16_t +/'),
442 Test("f32 function highp args",
443 """
444 precision mediump float;
445
446 uniform float a, b;
447
448 mediump float
449 do_div(highp float x, highp float y)
450 {
451 return x / y;
452 }
453
454 void main()
455 {
456 gl_FragColor = vec4(do_div(a, b));
457 }
458 """,
459 r'\(expression +float +/'),
460 Test("i32 function highp args",
461 """
462 #version 310 es
463 precision mediump float;
464 precision mediump int;
465
466 uniform int a, b;
467
468 mediump int
469 do_div(highp int x, highp int y)
470 {
471 return x / y;
472 }
473
474 out highp int color;
475
476 void main()
477 {
478 color = do_div(a, b);
479 }
480 """,
481 r'\(expression +int +/'),
482 Test("u32 function highp args",
483 """
484 #version 310 es
485 precision mediump float;
486 precision mediump int;
487
488 uniform uint a, b;
489
490 mediump uint
491 do_div(highp uint x, highp uint y)
492 {
493 return x / y;
494 }
495
496 out highp uint color;
497
498 void main()
499 {
500 color = do_div(a, b);
501 }
502 """,
503 r'\(expression +uint +/'),
504 Test("f32 function inout different precision highp",
505 """
506 uniform mediump float a, b;
507
508 void
509 do_div(inout highp float x, highp float y)
510 {
511 x = x / y;
512 }
513
514 void main()
515 {
516 mediump float temp = a;
517 do_div(temp, b);
518 gl_FragColor = vec4(temp);
519 }
520 """,
521 r'\(expression +float +/'),
522 Test("i32 function inout different precision highp",
523 """
524 #version 310 es
525 uniform mediump int a, b;
526
527 void
528 do_div(inout highp int x, highp int y)
529 {
530 x = x / y;
531 }
532
533 out mediump int color;
534
535 void main()
536 {
537 mediump int temp = a;
538 do_div(temp, b);
539 color = temp;
540 }
541 """,
542 r'\(expression +int +/'),
543 Test("u32 function inout different precision highp",
544 """
545 #version 310 es
546 uniform mediump uint a, b;
547
548 void
549 do_div(inout highp uint x, highp uint y)
550 {
551 x = x / y;
552 }
553
554 out mediump uint color;
555
556 void main()
557 {
558 mediump uint temp = a;
559 do_div(temp, b);
560 color = temp;
561 }
562 """,
563 r'\(expression +uint +/'),
564 Test("f32 function inout different precision mediump",
565 """
566 uniform highp float a, b;
567
568 void
569 do_div(inout mediump float x, mediump float y)
570 {
571 x = x / y;
572 }
573
574 void main()
575 {
576 highp float temp = a;
577 do_div(temp, b);
578 gl_FragColor = vec4(temp);
579 }
580 """,
581 r'\(expression +float16_t +/'),
582 Test("i32 function inout different precision mediump",
583 """
584 #version 310 es
585 uniform highp int a, b;
586
587 out highp int color;
588
589 void
590 do_div(inout mediump int x, mediump int y)
591 {
592 x = x / y;
593 }
594
595 void main()
596 {
597 highp int temp = a;
598 do_div(temp, b);
599 color = temp;
600 }
601 """,
602 r'\(expression +int16_t +/'),
603 Test("u32 function inout different precision mediump",
604 """
605 #version 310 es
606 uniform highp uint a, b;
607
608 out highp uint color;
609
610 void
611 do_div(inout mediump uint x, mediump uint y)
612 {
613 x = x / y;
614 }
615
616 void main()
617 {
618 highp uint temp = a;
619 do_div(temp, b);
620 color = temp;
621 }
622 """,
623 r'\(expression +uint16_t +/'),
624 Test("f32 if",
625 """
626 precision mediump float;
627
628 uniform float a, b;
629
630 void
631 main()
632 {
633 if (a / b < 0.31)
634 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
635 else
636 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
637 }
638 """,
639 r'\(expression +float16_t +/'),
640 Test("i32 if",
641 """
642 #version 310 es
643 precision mediump float;
644 precision mediump int;
645
646 uniform int a, b;
647
648 out vec4 color;
649
650 void
651 main()
652 {
653 if (a / b < 10)
654 color = vec4(0.0, 1.0, 0.0, 1.0);
655 else
656 color = vec4(1.0, 0.0, 0.0, 1.0);
657 }
658 """,
659 r'\(expression +int16_t +/'),
660 Test("u32 if",
661 """
662 #version 310 es
663 precision mediump float;
664 precision mediump int;
665
666 uniform uint a, b;
667
668 out vec4 color;
669
670 void
671 main()
672 {
673 if (a / b < 10u)
674 color = vec4(0.0, 1.0, 0.0, 1.0);
675 else
676 color = vec4(1.0, 0.0, 0.0, 1.0);
677 }
678 """,
679 r'\(expression +uint16_t +/'),
680 Test("matrix",
681 """
682 precision mediump float;
683
684 uniform vec2 a;
685 uniform mat2 b;
686
687 void main()
688 {
689 gl_FragColor = vec4(b * a, 0.0, 0.0);
690 }
691 """,
692 r'\(expression +f16vec2 \*.*\bf16mat2\b'),
693 Test("f32 simple struct deref",
694 """
695 precision mediump float;
696
697 struct simple {
698 float a, b;
699 };
700
701 uniform simple in_simple;
702
703 void main()
704 {
705 gl_FragColor = vec4(in_simple.a / in_simple.b);
706 }
707 """,
708 r'\(expression +float16_t +/'),
709 Test("i32 simple struct deref",
710 """
711 #version 310 es
712 precision mediump float;
713 precision mediump int;
714
715 struct simple {
716 int a, b;
717 };
718
719 uniform simple in_simple;
720
721 out highp int color;
722
723 void main()
724 {
725 color = in_simple.a / in_simple.b;
726 }
727 """,
728 r'\(expression +int16_t +/'),
729 Test("u32 simple struct deref",
730 """
731 #version 310 es
732 precision mediump float;
733 precision mediump int;
734
735 struct simple {
736 uint a, b;
737 };
738
739 uniform simple in_simple;
740
741 out highp uint color;
742
743 void main()
744 {
745 color = in_simple.a / in_simple.b;
746 }
747 """,
748 r'\(expression +uint16_t +/'),
749 Test("f32 embedded struct deref",
750 """
751 precision mediump float;
752
753 struct simple {
754 float a, b;
755 };
756
757 struct embedded {
758 simple a, b;
759 };
760
761 uniform embedded in_embedded;
762
763 void main()
764 {
765 gl_FragColor = vec4(in_embedded.a.a / in_embedded.b.b);
766 }
767 """,
768 r'\(expression +float16_t +/'),
769 Test("i32 embedded struct deref",
770 """
771 #version 310 es
772 precision mediump float;
773 precision mediump int;
774
775 struct simple {
776 int a, b;
777 };
778
779 struct embedded {
780 simple a, b;
781 };
782
783 uniform embedded in_embedded;
784
785 out highp int color;
786
787 void main()
788 {
789 color = in_embedded.a.a / in_embedded.b.b;
790 }
791 """,
792 r'\(expression +int16_t +/'),
793 Test("u32 embedded struct deref",
794 """
795 #version 310 es
796 precision mediump float;
797 precision mediump int;
798
799 struct simple {
800 uint a, b;
801 };
802
803 struct embedded {
804 simple a, b;
805 };
806
807 uniform embedded in_embedded;
808
809 out highp uint color;
810
811 void main()
812 {
813 color = in_embedded.a.a / in_embedded.b.b;
814 }
815 """,
816 r'\(expression +uint16_t +/'),
817 Test("f32 arrayed struct deref",
818 """
819 precision mediump float;
820
821 struct simple {
822 float a, b;
823 };
824
825 struct arrayed {
826 simple a[2];
827 };
828
829 uniform arrayed in_arrayed;
830
831 void main()
832 {
833 gl_FragColor = vec4(in_arrayed.a[0].a / in_arrayed.a[1].b);
834 }
835 """,
836 r'\(expression +float16_t +/'),
837 Test("i32 arrayed struct deref",
838 """
839 #version 310 es
840 precision mediump float;
841 precision mediump int;
842
843 struct simple {
844 int a, b;
845 };
846
847 struct arrayed {
848 simple a[2];
849 };
850
851 uniform arrayed in_arrayed;
852
853 out highp int color;
854
855 void main()
856 {
857 color = in_arrayed.a[0].a / in_arrayed.a[1].b;
858 }
859 """,
860 r'\(expression +int16_t +/'),
861 Test("u32 arrayed struct deref",
862 """
863 #version 310 es
864 precision mediump float;
865 precision mediump int;
866
867 struct simple {
868 uint a, b;
869 };
870
871 struct arrayed {
872 simple a[2];
873 };
874
875 uniform arrayed in_arrayed;
876
877 out highp uint color;
878
879 void main()
880 {
881 color = in_arrayed.a[0].a / in_arrayed.a[1].b;
882 }
883 """,
884 r'\(expression +uint16_t +/'),
885 Test("f32 mixed precision not lowered",
886 """
887 uniform mediump float a;
888 uniform highp float b;
889
890 void main()
891 {
892 gl_FragColor = vec4(a / b);
893 }
894 """,
895 r'\(expression +float +/'),
896 Test("i32 mixed precision not lowered",
897 """
898 #version 310 es
899 uniform mediump int a;
900 uniform highp int b;
901
902 out mediump int color;
903
904 void main()
905 {
906 color = a / b;
907 }
908 """,
909 r'\(expression +int +/'),
910 Test("u32 mixed precision not lowered",
911 """
912 #version 310 es
913 uniform mediump uint a;
914 uniform highp uint b;
915
916 out mediump uint color;
917
918 void main()
919 {
920 color = a / b;
921 }
922 """,
923 r'\(expression +uint +/'),
924 Test("f32 texture sample",
925 """
926 precision mediump float;
927
928 uniform sampler2D tex;
929 uniform vec2 coord;
930 uniform float divisor;
931
932 void main()
933 {
934 gl_FragColor = texture2D(tex, coord) / divisor;
935 }
936 """,
937 r'\(expression +f16vec4 +/.*\(tex +f16vec4 +'),
938 Test("i32 texture sample",
939 """
940 #version 310 es
941 precision mediump float;
942 precision mediump int;
943
944 uniform mediump isampler2D tex;
945 uniform vec2 coord;
946 uniform int divisor;
947
948 out highp ivec4 color;
949
950 void main()
951 {
952 color = texture(tex, coord) / divisor;
953 }
954 """,
955 r'\(expression +i16vec4 +/.*\(tex +i16vec4 +'),
956 Test("u32 texture sample",
957 """
958 #version 310 es
959 precision mediump float;
960 precision mediump int;
961
962 uniform mediump usampler2D tex;
963 uniform vec2 coord;
964 uniform uint divisor;
965
966 out highp uvec4 color;
967
968 void main()
969 {
970 color = texture(tex, coord) / divisor;
971 }
972 """,
973 r'\(expression +u16vec4 +/.*\(tex +u16vec4 +'),
974 Test("f32 expression in lvalue",
975 """
976 uniform mediump float a, b;
977
978 void main()
979 {
980 gl_FragColor = vec4(1.0);
981 gl_FragColor[int(a / b)] = 0.5;
982 }
983 """,
984 r'\(expression +float16_t +/'),
985 Test("i32 expression in lvalue",
986 """
987 #version 310 es
988 precision mediump float;
989 precision mediump int;
990
991 uniform mediump int a, b;
992
993 out vec4 color;
994
995 void main()
996 {
997 color = vec4(1.0);
998 color[a / b] = 0.5;
999 }
1000 """,
1001 r'\(expression +int16_t +/'),
1002 Test("f32 builtin with const arg",
1003 """
1004 uniform mediump float a;
1005
1006 void main()
1007 {
1008 gl_FragColor = vec4(min(a, 3.0));
1009 }
1010 """,
1011 r'\(expression +float16_t min'),
1012 Test("i32 builtin with const arg",
1013 """
1014 #version 310 es
1015 uniform mediump int a;
1016
1017 out highp int color;
1018
1019 void main()
1020 {
1021 color = min(a, 3);
1022 }
1023 """,
1024 r'\(expression +int16_t min'),
1025 Test("u32 builtin with const arg",
1026 """
1027 #version 310 es
1028 uniform mediump uint a;
1029
1030 out highp uint color;
1031
1032 void main()
1033 {
1034 color = min(a, 3u);
1035 }
1036 """,
1037 r'\(expression +uint16_t min'),
1038 ]
1039
1040
1041 def compile_shader(standalone_compiler, source):
1042 with tempfile.NamedTemporaryFile(mode='wt', suffix='.frag') as source_file:
1043 print(source, file=source_file)
1044 source_file.flush()
1045 return subprocess.check_output([standalone_compiler,
1046 '--version', '300',
1047 '--lower-precision',
1048 '--dump-lir',
1049 source_file.name],
1050 universal_newlines=True)
1051
1052
1053 def run_test(standalone_compiler, test):
1054 ir = compile_shader(standalone_compiler, test.source)
1055
1056 if re.search(test.match_re, ir) is None:
1057 print(ir)
1058 return False
1059
1060 return True
1061
1062
1063 def main():
1064 standalone_compiler = sys.argv[1]
1065 passed = 0
1066
1067 for test in TESTS:
1068 print('Testing {} ... '.format(test.name), end='')
1069
1070 result = run_test(standalone_compiler, test)
1071
1072 if result:
1073 print('PASS')
1074 passed += 1
1075 else:
1076 print('FAIL')
1077
1078 print('{}/{} tests returned correct results'.format(passed, len(TESTS)))
1079 sys.exit(0 if passed == len(TESTS) else 1)
1080
1081
1082 if __name__ == '__main__':
1083 main()