xref: /aosp_15_r20/external/deqp/modules/gles31/scripts/gen-implicit-conversions.py (revision 35238bce31c2a825756842865a792f8cf7f89930)
1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# drawElements Quality Program utilities
5# --------------------------------------
6#
7# Copyright 2015 The Android Open Source Project
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13#      http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20#
21#-------------------------------------------------------------------------
22
23import sys
24import itertools
25import operator
26
27import genutil
28
29from genutil import Scalar, Vec2, Vec3, Vec4, Uint, UVec2, UVec3, UVec4, CaseGroup
30
31
32# Templates
33
34ARTIHMETIC_CASE_TEMPLATE = """
35case ${{NAME}}
36    version 310 es
37    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
38    values
39    {
40        ${{VALUES}}
41    }
42
43    both ""
44        #version 310 es
45        precision highp float;
46        ${DECLARATIONS}
47
48        void main()
49        {
50            ${SETUP}
51            out0 = ${{EXPR}};
52            ${OUTPUT}
53        }
54    ""
55end
56""".strip()
57
58FUNCTIONS_CASE_TEMPLATE = """
59case ${{NAME}}
60    version 310 es
61    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
62    values
63    {
64        ${{VALUES}}
65    }
66
67    both ""
68        #version 310 es
69        precision highp float;
70        ${DECLARATIONS}
71
72        ${{OUTTYPE}} func (${{OUTTYPE}} a)
73        {
74            return a * ${{OUTTYPE}}(2);
75        }
76
77        void main()
78        {
79            ${SETUP}
80            out0 = func(in0);
81            ${OUTPUT}
82        }
83    ""
84end
85""".strip()
86
87ARRAY_CASE_TEMPLATE = """
88case ${{NAME}}
89    version 310 es
90    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
91    values
92    {
93        ${{VALUES}}
94    }
95
96    both ""
97        #version 310 es
98        precision highp float;
99        ${DECLARATIONS}
100
101        void main()
102        {
103            ${SETUP}
104            ${{ARRAYTYPE}}[] x = ${{ARRAYTYPE}}[] (${{ARRAYVALUES}});
105            out0 = ${{EXPR}};
106            ${OUTPUT}
107        }
108    ""
109end
110""".strip()
111
112STRUCT_CASE_TEMPLATE = """
113case ${{NAME}}
114    version 310 es
115    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
116    values
117    {
118        ${{VALUES}}
119    }
120
121    both ""
122        #version 310 es
123        precision highp float;
124        ${DECLARATIONS}
125
126        void main()
127        {
128            ${SETUP}
129            struct {
130                ${{OUTTYPE}} val;
131            } x;
132
133            x.val = ${{STRUCTVALUE}};
134
135            out0 = ${{EXPR}};
136            ${OUTPUT}
137        }
138    ""
139end
140""".strip()
141
142INVALID_CASE_TEMPLATE = """
143case ${{NAME}}
144    expect compile_fail
145    version 310 es
146    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
147    values
148    {
149        ${{VALUES}}
150    }
151
152    both ""
153        #version 310 es
154        precision highp float;
155        ${DECLARATIONS}
156
157        void main()
158        {
159            ${SETUP}
160            out0 = in0 + ${{OPERAND}};
161            ${OUTPUT}
162        }
163    ""
164end
165""".strip()
166
167INVALID_ARRAY_CASE_TEMPLATE = """
168case ${{NAME}}
169    expect compile_fail
170    version 310 es
171    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
172    values {}
173
174    both ""
175        #version 310 es
176        precision highp float;
177        ${DECLARATIONS}
178
179        void main()
180        {
181            ${SETUP}
182            ${{EXPR}}
183            ${OUTPUT}
184        }
185    ""
186end
187""".strip()
188
189INVALID_STRUCT_CASE_TEMPLATE = """
190case ${{NAME}}
191    expect compile_fail
192    version 310 es
193    require extension { "GL_EXT_shader_implicit_conversions" } in { vertex, fragment }
194    values {}
195
196    both ""
197        #version 310 es
198        precision highp float;
199        ${DECLARATIONS}
200
201        void main()
202        {
203            ${SETUP}
204            struct { ${{INTYPE}} value; } a;
205            struct { ${{OUTTYPE}} value; } b;
206            a = ${{INVALUE}};
207            b = a;
208            ${OUTPUT}
209        }
210    ""
211end
212""".strip()
213
214
215# Input values
216
217IN_ISCALAR = [  2,  1,  1,  3,  5 ]
218IN_USCALAR = [  1,  3,  4,  7, 11 ]
219
220IN_IVECTOR = [
221    ( 1,  2,  3,  4),
222    ( 2,  1,  2,  6),
223    ( 3,  7,  2,  5),
224]
225
226IN_UVECTOR = [
227    ( 2,  3,  5,  8),
228    ( 4,  6,  2,  9),
229    ( 1, 13,  7,  4),
230]
231
232IN_VALUES = {
233    "int": [Scalar(x)                                for x in IN_ISCALAR],
234    "uint": [Scalar(x)                                for x in IN_USCALAR],
235    "ivec2": [Vec2(x[0], x[1])                        for x in IN_IVECTOR],
236    "uvec2": [Vec2(x[0], x[1])                        for x in IN_UVECTOR],
237    "ivec3": [Vec3(x[0], x[1], x[2])                    for x in IN_IVECTOR],
238    "uvec3": [Vec3(x[0], x[1], x[2])                    for x in IN_UVECTOR],
239    "ivec4": [Vec4(x[0], x[1], x[2], x[3])            for x in IN_IVECTOR],
240    "uvec4": [Vec4(x[0], x[1], x[2], x[3])            for x in IN_UVECTOR],
241    "float": [Scalar(x).toFloat()                    for x in IN_ISCALAR],
242    "vec2": [Vec2(x[0], x[1]).toFloat()                for x in IN_IVECTOR],
243    "vec3": [Vec3(x[0], x[1], x[2]).toFloat()        for x in IN_IVECTOR],
244    "vec4": [Vec4(x[0], x[1], x[2], x[3]).toFloat()    for x in IN_IVECTOR],
245}
246
247VALID_CONVERSIONS = {
248    "int": ["float", "uint"],
249    "uint": ["float"],
250    "ivec2": ["uvec2", "vec2"],
251    "uvec2": ["vec2"],
252    "ivec3": ["uvec3", "vec3"],
253    "uvec3": ["vec3"],
254    "ivec4": ["uvec4", "vec4"],
255    "uvec4": ["vec4"]
256}
257
258SCALAR_TO_VECTOR_CONVERSIONS = {
259    "int": ["vec2", "vec3", "vec4", "uvec2", "uvec3", "uvec4"],
260    "uint": ["vec2", "vec3", "vec4"]
261}
262
263VALID_ASSIGNMENTS = {
264    "int": ["ivec2", "ivec3", "ivec4"],
265    "uint": ["uvec2", "uvec3", "uvec4"],
266    "ivec2": ["int", "float"],
267    "ivec3": ["int", "float"],
268    "ivec4": ["int", "float"],
269    "uvec2": ["uint", "float"],
270    "uvec3": ["uint", "float"],
271    "uvec4": ["uint", "float"],
272    "float": ["vec2", "vec3", "vec4"],
273    "vec2": ["float"],
274    "vec3": ["float"],
275    "vec4": ["float"]
276}
277
278IN_TYPE_ORDER = [
279    "int",  "uint",
280    "ivec2", "uvec2", "ivec3",
281    "uvec3", "ivec4", "uvec4",
282
283    "float",
284    "vec2",  "vec3",  "vec4"
285]
286
287def isScalarTypeName (name):
288    return name in ["float", "int", "uint"]
289
290def isVec2TypeName (name):
291    return name in ["vec2", "ivec2", "uvec2"]
292
293def isVec3TypeName (name):
294    return name in ["vec3", "ivec3", "uvec3"]
295
296def isVec4TypeName (name):
297    return name in ["vec4", "ivec4", "uvec4"]
298
299# Utilities
300
301def scalarToVector(a, b):
302    if isinstance(a, Scalar) and isinstance(b, Vec2):
303        a = a.toVec2()
304    elif isinstance(a, Scalar) and isinstance(b, Vec3):
305        a = a.toVec3()
306    elif isinstance(a, Scalar) and isinstance(b, Vec4):
307        a = a.toVec4()
308    return a
309
310def isUintTypeName (type_name):
311    return type_name in ["uint", "uvec2", "uvec3", "uvec4"]
312
313def convLiteral (type, value):
314    if isUintTypeName(type):
315        return int(value)
316    else:
317        return value
318
319def valueToStr(value_type, value):
320    if isinstance(value, Scalar):
321        return str(value)
322    else:
323        assert isinstance(value, genutil.Vec)
324        out = value_type + "("
325        out += ", ".join([str(convLiteral(value_type, x)) for x in value.getScalars()])
326        out += ")"
327        return out
328
329
330def valuesToStr(prefix, value_type, values):
331    def gen_value_strs(value_list, value_type):
332        for value in value_list:
333            yield valueToStr(value_type, value)
334    return "%s = [ %s ];" % (prefix, " | ".join(gen_value_strs(values, value_type)))
335
336
337# Test cases
338
339class ArithmeticCase(genutil.ShaderCase):
340    def __init__(self, name, op, in_type, out_type, reverse=False):
341        self.op_func = {
342            "+": operator.add,
343            "-": operator.sub,
344            "*": operator.mul,
345            "/": operator.div,
346        }
347        self.name = name
348        self.op = op
349        self.in_type = in_type
350        self.out_type = out_type
351        self.reverse = reverse
352
353    def __str__(self):
354        params = {
355            "NAME": self.name,
356            "EXPR": self.get_expr(),
357            "VALUES": self.gen_values(),
358        }
359        return genutil.fillTemplate(ARTIHMETIC_CASE_TEMPLATE, params)
360
361    def apply(self, a, b):
362        assert(self.op in self.op_func)
363        a = scalarToVector(a, b)
364
365        if self.reverse:
366            b, a = a, b
367
368        return self.op_func[self.op](a, b)
369
370    def get_expr(self):
371        expr = ["in0", self.op, str(self.get_operand())]
372
373        if self.reverse:
374            expr.reverse()
375
376        return " ".join(expr)
377
378    def get_operand(self):
379        operands = {
380            "float": Scalar(2.0),
381            "vec2": Vec2(1.0, 2.0),
382            "vec3": Vec3(1.0, 2.0, 3.0),
383            "vec4": Vec4(1.0, 2.0, 3.0, 4.0),
384            "uint": Uint(2),
385            "uvec2": UVec2(1, 2),
386            "uvec3": UVec3(1, 2, 3),
387            "uvec4": UVec4(1, 2, 3, 4),
388        }
389        assert self.out_type in operands
390        return operands[self.out_type]
391
392    def gen_values(self):
393        in_values = IN_VALUES[self.in_type]
394
395        y = self.get_operand()
396        out_values = [self.apply(x, y) for x in in_values]
397
398        out = []
399        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
400        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
401
402        return "\n".join(out)
403
404
405class ComparisonsCase(ArithmeticCase):
406    def __init__(self, name, op, in_type, out_type, reverse=False):
407        super(ComparisonsCase, self).__init__(name, op, in_type, out_type, reverse)
408
409        self.op_func = {
410            "==": operator.eq,
411            "!=": operator.ne,
412            "<": operator.lt,
413            ">": operator.gt,
414            "<=": operator.le,
415            ">=": operator.ge,
416        }
417
418    def apply(self, a, b):
419        assert(self.op in self.op_func)
420
421        if isinstance(a, Scalar) and isinstance(b, Scalar):
422            a, b = float(a), float(b)
423
424        if self.reverse:
425            b, a = a, b
426
427        return Scalar(self.op_func[self.op](a, b))
428
429    def gen_values(self):
430        in_values = IN_VALUES[self.in_type]
431
432        y = self.get_operand()
433        out_values = [self.apply(x, y) for x in in_values]
434
435        out = []
436        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
437        out.append(valuesToStr("output bool out0", "bool", out_values))
438
439        return "\n".join(out)
440
441
442class ParenthesizedCase(genutil.ShaderCase):
443    def __init__(self, name, in_type, out_type, reverse=False, input_in_parens=False):
444        self.name = name
445        self.in_type = in_type
446        self.out_type = out_type
447        self.reverse = reverse
448        self.input_in_parens = input_in_parens
449
450    def __str__(self):
451        params = {
452            "NAME": self.name,
453            "EXPR": self.get_expr(),
454            "VALUES": self.gen_values(),
455        }
456        return genutil.fillTemplate(ARTIHMETIC_CASE_TEMPLATE, params)
457
458    def apply(self, a):
459        b, c = self.get_operand(0), self.get_operand(1)
460        a = scalarToVector(a, b)
461
462        if self.input_in_parens:
463            return b*(a+c)
464        else:
465            return a*(b+c)
466
467    def get_expr(self):
468        def make_paren_expr():
469            out = [
470                "in0" if self.input_in_parens else self.get_operand(0),
471                "+",
472                self.get_operand(1)
473            ]
474            return "(%s)" % (" ".join([str(x) for x in out]))
475
476        expr = [
477            "in0" if not self.input_in_parens else self.get_operand(0),
478            "*",
479            make_paren_expr()
480        ]
481
482        if self.reverse:
483            expr.reverse()
484
485        return " ".join([str(x) for x in expr])
486
487    def get_operand(self, ndx=0):
488        return IN_VALUES[self.out_type][ndx]
489
490    def gen_values(self):
491        in_values = IN_VALUES[self.in_type]
492
493        out_values = [self.apply(x) for x in in_values]
494
495        out = []
496        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
497        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
498
499        return "\n".join(out)
500
501
502class FunctionsCase(genutil.ShaderCase):
503    def __init__(self, name, in_type, out_type):
504        self.name = name
505        self.in_type = in_type
506        self.out_type = out_type
507
508    def __str__(self):
509        params = {
510            "NAME": self.name,
511            "OUTTYPE": self.out_type,
512            "VALUES": self.gen_values(),
513        }
514        return genutil.fillTemplate(FUNCTIONS_CASE_TEMPLATE, params)
515
516    def apply(self, a):
517        if isUintTypeName(self.out_type):
518            return a.toUint() * Uint(2)
519        else:
520            return a.toFloat() * Scalar(2.0)
521
522    def gen_values(self):
523        in_values = IN_VALUES[self.in_type]
524        out_values = [self.apply(x) for x in in_values]
525
526        out = []
527        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
528        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
529
530        return "\n".join(out)
531
532
533class ArrayCase(genutil.ShaderCase):
534    def __init__(self, name, in_type, out_type, reverse=False):
535        self.name = name
536        self.in_type = in_type
537        self.out_type = out_type
538        self.reverse = reverse
539
540    def __str__(self):
541        params = {
542            "NAME": self.name,
543            "VALUES": self.gen_values(),
544            "ARRAYTYPE": self.out_type,
545            "ARRAYVALUES": self.gen_array_values(),
546            "EXPR": self.get_expr(),
547        }
548        return genutil.fillTemplate(ARRAY_CASE_TEMPLATE, params)
549
550    def apply(self, a):
551        b = IN_VALUES[self.out_type][1]
552        a = scalarToVector(a, b)
553
554        return a + b
555
556    def get_expr(self):
557        if not self.reverse:
558            return "in0 + x[1]"
559        else:
560            return "x[1] + in0"
561
562    def gen_values(self):
563        in_values = IN_VALUES[self.in_type]
564        out_values = [self.apply(x) for x in in_values]
565
566        out = []
567        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
568        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
569
570        return "\n".join(out)
571
572    def gen_array_values(self):
573        out = [valueToStr(self.out_type, x) for x in IN_VALUES[self.out_type]]
574        return ", ".join(out)
575
576
577class ArrayUnpackCase(genutil.ShaderCase):
578    def __init__(self, name, in_type, out_type):
579        self.name = name
580        self.in_type = in_type
581        self.out_type = out_type
582
583    def __str__(self):
584        params = {
585            "NAME": self.name,
586            "VALUES": self.gen_values(),
587            "ARRAYTYPE": "float",
588            "ARRAYVALUES": self.gen_array_values(),
589            "EXPR": self.get_expr(),
590        }
591        return genutil.fillTemplate(ARRAY_CASE_TEMPLATE, params)
592
593    def apply(self, a):
594        if isinstance(a, Scalar) and isVec2TypeName(self.out_type):
595            a = a.toVec2()
596        elif isinstance(a, Scalar) and isVec3TypeName(self.out_type):
597            a = a.toVec3()
598        elif isinstance(a, Scalar) and isVec4TypeName(self.out_type):
599            a = a.toVec4()
600
601        b = IN_VALUES["float"]
602
603        out = [Scalar(x)+y for x, y in zip(a.getScalars(), b)]
604
605        if self.out_type == "float":
606            return out[0].toFloat()
607        elif self.out_type == "uint":
608            return out[0].toUint()
609        elif self.out_type == "vec2":
610            return Vec2(out[0], out[1]).toFloat()
611        elif self.out_type == "uvec2":
612            return Vec2(out[0], out[1]).toUint()
613        elif self.out_type == "vec3":
614            return Vec3(out[0], out[1], out[2]).toFloat()
615        elif self.out_type == "uvec3":
616            return Vec3(out[0], out[1], out[2]).toUint()
617        elif self.out_type == "vec4":
618            return Vec4(out[0], out[1], out[2], out[3]).toFloat()
619        elif self.out_type == "uvec4":
620            return Vec4(out[0], out[1], out[2], out[3]).toUint()
621
622    def get_expr(self):
623        def num_scalars(typename):
624            return IN_VALUES[typename][0].getNumScalars()
625
626        def gen_sums():
627            in_scalars = num_scalars(self.in_type)
628            out_scalars = num_scalars(self.out_type)
629
630            for ndx in range(out_scalars):
631                if in_scalars > 1:
632                    yield "in0[%i] + x[%i]" % (ndx, ndx)
633                else:
634                    yield "in0 + x[%i]" % (ndx)
635
636        return "%s(%s)" % (self.out_type, ", ".join(gen_sums()))
637
638    def gen_values(self):
639        in_values = IN_VALUES[self.in_type]
640        out_values = [self.apply(x) for x in in_values]
641
642        out = []
643        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
644        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
645
646        return "\n".join(out)
647
648    def gen_array_values(self):
649        out = [valueToStr(self.out_type, x) for x in IN_VALUES["float"]]
650        return ", ".join(out)
651
652
653class StructCase(genutil.ShaderCase):
654    def __init__(self, name, in_type, out_type, reverse=False):
655        self.name = name
656        self.in_type = in_type
657        self.out_type = out_type
658        self.reverse = reverse
659
660    def __str__(self):
661        params = {
662            "NAME": self.name,
663            "VALUES": self.gen_values(),
664            "OUTTYPE": self.out_type,
665            "STRUCTVALUE": self.get_struct_value(),
666            "EXPR": self.get_expr(),
667        }
668        return genutil.fillTemplate(STRUCT_CASE_TEMPLATE, params)
669
670    def apply(self, a):
671        if isinstance(a, Scalar) and isVec2TypeName(self.out_type):
672            a = a.toVec2()
673        elif isinstance(a, Scalar) and isVec3TypeName(self.out_type):
674            a = a.toVec3()
675        elif isinstance(a, Scalar) and isVec4TypeName(self.out_type):
676            a = a.toVec4()
677
678        b = IN_VALUES[self.out_type][0]
679
680        return a + b
681
682    def get_expr(self):
683        if not self.reverse:
684            return "in0 + x.val"
685        else:
686            return "x.val + in0"
687
688    def gen_values(self):
689        in_values = IN_VALUES[self.in_type]
690        out_values = [self.apply(x) for x in in_values]
691
692        out = []
693        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
694        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
695
696        return "\n".join(out)
697
698    def get_struct_value(self):
699        return valueToStr(self.out_type, IN_VALUES[self.out_type][0])
700
701
702class InvalidCase(genutil.ShaderCase):
703    def __init__(self, name, in_type, out_type):
704        self.name = name
705        self.in_type = in_type
706        self.out_type = out_type
707
708    def __str__(self):
709        params = {
710            "NAME": self.name,
711            "OPERAND": str(self.get_operand()),
712            "VALUES": self.gen_values(),
713        }
714        return genutil.fillTemplate(INVALID_CASE_TEMPLATE, params)
715
716    def apply(self, a, b):
717        return b
718
719    def get_operand(self):
720        return IN_VALUES[self.out_type][0]
721
722    def gen_values(self):
723        in_values = IN_VALUES[self.in_type]
724
725        y = self.get_operand()
726        out_values = [self.apply(x, y) for x in in_values]
727
728        out = []
729        out.append(valuesToStr("input %s in0" % (self.in_type), self.in_type, in_values))
730        out.append(valuesToStr("output %s out0" % (self.out_type), self.out_type, out_values))
731
732        return "\n".join(out)
733
734
735class InvalidArrayCase(genutil.ShaderCase):
736    def __init__(self, name, in_type, out_type):
737        self.name = name
738        self.in_type = in_type
739        self.out_type = out_type
740
741    def __str__(self):
742        params = {
743            "NAME": self.name,
744            "EXPR": self.gen_expr(),
745        }
746        return genutil.fillTemplate(INVALID_ARRAY_CASE_TEMPLATE, params)
747
748    def gen_expr(self):
749        in_values = [valueToStr(self.out_type, x) for x in IN_VALUES[self.in_type]]
750
751        out = "%s a[] = %s[] (%s);" % (self.out_type, self.in_type, ", ".join(in_values))
752
753        return out
754
755
756class InvalidStructCase(genutil.ShaderCase):
757    def __init__(self, name, in_type, out_type):
758        self.name = name
759        self.in_type = in_type
760        self.out_type = out_type
761
762    def __str__(self):
763        params = {
764            "NAME": self.name,
765            "INTYPE": self.in_type,
766            "OUTTYPE": self.out_type,
767            "INVALUE": self.get_value(),
768        }
769        return genutil.fillTemplate(INVALID_STRUCT_CASE_TEMPLATE, params)
770
771    def get_value(self):
772        return valueToStr(self.in_type, IN_VALUES[self.in_type][0])
773
774
775# Case file generation
776
777def genConversionPairs(order=IN_TYPE_ORDER, scalar_to_vector=True, additional={}):
778    def gen_order(conversions):
779        key_set = set(conversions.iterkeys())
780        for typename in order:
781            if typename in key_set:
782                yield typename
783    conversions = {}
784
785    for in_type in VALID_CONVERSIONS:
786        conversions[in_type] = [] + VALID_CONVERSIONS[in_type]
787        if in_type in SCALAR_TO_VECTOR_CONVERSIONS and scalar_to_vector:
788            conversions[in_type] += SCALAR_TO_VECTOR_CONVERSIONS[in_type]
789
790    for key in additional.iterkeys():
791            value = conversions.get(key, [])
792            conversions[key] = value + additional[key]
793
794    for in_type in gen_order(conversions):
795        for out_type in conversions[in_type]:
796            yield (in_type, out_type)
797
798
799def genInvalidConversions():
800    types = IN_TYPE_ORDER
801    valid_pairs = set(genConversionPairs(additional=VALID_ASSIGNMENTS))
802
803    for pair in itertools.permutations(types, 2):
804        if pair not in valid_pairs:
805            yield pair
806
807
808def genArithmeticCases(reverse=False):
809    op_names = [
810        ("add", "Addition", "+"),
811        ("sub", "Subtraction", "-"),
812        ("mul", "Multiplication", "*"),
813        ("div", "Division", "/")
814    ]
815
816    for name, desc, op in op_names:
817        casegroup = CaseGroup(name, desc, [])
818        for in_type, out_type in genConversionPairs():
819            if op == "-" and isUintTypeName(out_type):
820                continue # Can't handle at the moment
821            name = in_type + "_to_" + out_type
822            casegroup.children.append(ArithmeticCase(name, op, in_type, out_type, reverse))
823        yield casegroup
824
825
826def genComparisonCases(reverse=False):
827    op_names = [
828        ("equal", "Equal", "=="),
829        ("not_equal", "Not equal", "!="),
830        ("less", "Less than", "<"),
831        ("greater", "Greater than", ">"),
832        ("less_or_equal", "Less than or equal", "<="),
833        ("greater_or_equal", "Greater than or equal", ">="),
834    ]
835
836    for name, desc, op in op_names:
837        casegroup = CaseGroup(name, desc, [])
838        type_order = IN_TYPE_ORDER if name in ["equal", "not_equal"] else ["int", "uint"]
839
840        for in_type, out_type in genConversionPairs(order=type_order, scalar_to_vector=False):
841            name = in_type + "_to_" + out_type
842            casegroup.children.append(ComparisonsCase(name, op, in_type, out_type, reverse))
843        yield casegroup
844
845
846def genParenthesizedCases():
847    for reverse in [True, False]:
848        if reverse:
849            name = "paren_expr_before_literal"
850            desc = "Parenthesized expression before literal"
851        else:
852            name = "literal_before_paren_expr"
853            desc = "Literal before parenthesized expression"
854        reversegroup = CaseGroup(name, desc, [])
855
856        for input_in_parens in [True, False]:
857            if input_in_parens:
858                name = "input_in_parens"
859                desc = "Input variable in parenthesized expression"
860            else:
861                name = "input_outside_parens"
862                desc = "Input variable outside parenthesized expression"
863            casegroup = CaseGroup(name, desc, [])
864
865            for in_type, out_type in genConversionPairs():
866                name = in_type + "_to_" + out_type
867                casegroup.children.append(
868                    ParenthesizedCase(name, in_type, out_type, reverse, input_in_parens)
869                )
870            reversegroup.children.append(casegroup)
871        yield reversegroup
872
873
874def genArrayCases(reverse=False):
875    for in_type, out_type in genConversionPairs():
876        name = in_type + "_to_" + out_type
877        yield ArrayCase(name, in_type, out_type, reverse)
878
879
880def genArrayUnpackCases(reverse=False):
881    for in_type, out_type in genConversionPairs():
882        name = in_type + "_to_" + out_type
883        yield ArrayUnpackCase(name, in_type, out_type)
884
885
886def genFunctionsCases():
887    for in_type, out_type in genConversionPairs(scalar_to_vector=False):
888        name = in_type + "_to_" + out_type
889        yield FunctionsCase(name, in_type, out_type)
890
891
892def genStructCases(reverse=False):
893    for in_type, out_type in genConversionPairs():
894        name = in_type + "_to_" + out_type
895        yield StructCase(name, in_type, out_type, reverse)
896
897
898def genInvalidCases(reverse=False):
899    for in_type, out_type in genInvalidConversions():
900        name = in_type + "_to_" + out_type
901        yield InvalidCase(name, in_type, out_type)
902
903
904def genInvalidArrayCases():
905    for in_type, out_type in genConversionPairs(scalar_to_vector=False):
906        name = in_type + "_to_" + out_type
907        yield InvalidArrayCase(name, in_type, out_type)
908
909
910def genInvalidStructCases():
911    for in_type, out_type in genConversionPairs(scalar_to_vector=False):
912        name = in_type + "_to_" + out_type
913        yield InvalidStructCase(name, in_type, out_type)
914
915
916def genAllCases():
917    yield CaseGroup(
918        "arithmetic", "Arithmetic operations",
919        [
920            CaseGroup("input_before_literal", "Input before literal",
921                      genArithmeticCases(reverse=False)),
922            CaseGroup("literal_before_input", "Literal before input",
923                      genArithmeticCases(reverse=True)),
924        ]
925    )
926
927    yield CaseGroup(
928        "comparisons", "Comparisons",
929        [
930            CaseGroup("input_before_literal", "Input before literal",
931                      genComparisonCases(reverse=False)),
932            CaseGroup("literal_before_input", "Literal before input",
933                      genComparisonCases(reverse=True)),
934        ]
935    )
936
937    yield CaseGroup(
938        "array_subscripts", "Array subscripts",
939        [
940            CaseGroup("input_before_subscript", "Input before subscript",
941                      genArrayCases(reverse=False)),
942            CaseGroup("subscript_before_input", "Subscript before input",
943                      genArrayCases(reverse=True)),
944        #    CaseGroup("unpack", "Unpack array and repack as value",
945        #              genArrayUnpackCases()),
946        ]
947    )
948
949    yield CaseGroup("functions", "Function calls",
950                    genFunctionsCases())
951
952    yield CaseGroup("struct_fields", "Struct field selectors",
953        [
954            CaseGroup("input_before_field", "Input before field",
955                      genStructCases(reverse=False)),
956            CaseGroup("field_before_input", "Field before input",
957                      genStructCases(reverse=True)),
958        ]
959    )
960
961    yield CaseGroup("parenthesized_expressions", "Parenthesized expressions",
962                    genParenthesizedCases())
963
964    yield CaseGroup(
965        "invalid", "Invalid conversions",
966        [
967            CaseGroup("variables", "Single variables",
968                      genInvalidCases()),
969            CaseGroup("arrays", "Arrays",
970                      genInvalidArrayCases()),
971            CaseGroup("structs", "Structs",
972                      genInvalidStructCases()),
973        ]
974    )
975
976
977if __name__ == "__main__":
978    print("Generating shader case files.")
979    genutil.writeAllCases("implicit_conversions.test", genAllCases())
980