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