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