1import sys
2import itertools
3from collections import namedtuple
4from genutil import *
5
6# Templates
7
8declarationTemplate = """
9case ${{NAME}}
10	${{COMPILE_FAIL}}
11	values {}
12
13	vertex ""
14		precision mediump float;
15		attribute highp vec4 dEQP_Position;
16
17		${{VARIABLE_VTX}}
18
19		void main()
20		{
21			x0 = 1.0;
22			gl_Position = dEQP_Position;
23		}
24	""
25
26	fragment ""
27		precision mediump float;
28
29		${{VARIABLE_FRG}}
30
31		void main()
32		{
33			float result = x0 + x1;
34			gl_FragColor = vec4(result, result, result, 1.0);
35		}
36	""
37end
38"""[1:-1]
39
40parameterTemplate = """
41case ${{NAME}}
42	${{COMPILE_FAIL}}
43	values {}
44
45	both ""
46		precision mediump float;
47		${DECLARATIONS}
48
49		float foo0 (${{PARAMETER0}})
50		{
51			return x + 1.0;
52		}
53
54		void foo1 (${{PARAMETER1}})
55		{
56			x = 1.0;
57		}
58
59		float foo2 (${{PARAMETER2}})
60		{
61			return x + 1.0;
62		}
63
64		void main()
65		{
66			${SETUP}
67			float result;
68			foo1(result);
69			float x0 = foo0(1.0);
70			foo2(result);
71			${OUTPUT}
72		}
73	""
74end
75"""[1:-1]
76
77# Classes
78
79class DeclarationCase(ShaderCase):
80	def __init__(self, compileFail, paramList):
81		self.compileFail	= "expect compile_fail" if compileFail else "expect pass"
82		self.name			= ''
83		var0				= ''
84		var1				= ''
85		var2				= ''
86
87		for p in paramList:
88			self.name += p.name
89			if paramList.index(p) != len(paramList)-1:
90				self.name += '_'
91
92			var0 += p.vars[0] + ' '
93			var1 += p.vars[1] + ' '
94			var2 += p.vars[2] + ' '
95
96		var0 += 'float x0;\n'
97		var1 += 'float x1;\n'
98		var2 += 'float x2;'
99
100		self.variableVtx 	= (var0 + var1 + var2).strip()
101		self.variableFrg 	= (var0 + var1).strip()			# Omit 'attribute' in frag shader
102		self.variableVtx 	= self.variableVtx.replace("  ", " ")
103		self.variableFrg 	= self.variableFrg.replace("  ", " ")
104
105	def __str__(self):
106		params = {
107			"NAME"			: self.name,
108			"COMPILE_FAIL"	: self.compileFail,
109			"VARIABLE_VTX"	: self.variableVtx,
110			"VARIABLE_FRG"	: self.variableFrg
111		}
112		return fillTemplate(declarationTemplate, params)
113
114class ParameterCase(ShaderCase):
115	def __init__(self, compileFail, paramList):
116		self.compileFail	= "expect compile_fail" if compileFail else "expect pass"
117		self.name			= ''
118		self.param0			= ''
119		self.param1			= ''
120		self.param2			= ''
121
122		for p in paramList:
123			self.name += p.name
124			if paramList.index(p) != len(paramList)-1:
125				self.name += '_'
126
127			self.param0 += p.vars[0] + ' '
128			self.param1 += p.vars[1] + ' '
129			self.param2 += p.vars[2] + ' '
130
131		self.param0 += 'float x'
132		self.param1 += 'float x'
133		self.param2 += 'float x'
134		self.param0	= self.param0.replace("  ", " ")
135		self.param1	= self.param1.replace("  ", " ")
136		self.param2	= self.param2.replace("  ", " ")
137
138	def __str__(self):
139		params = {
140			"NAME"			: self.name,
141			"COMPILE_FAIL"	: self.compileFail,
142			"PARAMETER0"	: self.param0,
143			"PARAMETER1"	: self.param1,
144			"PARAMETER2"	: self.param2,
145		}
146		return fillTemplate(parameterTemplate, params)
147
148# Declarations
149
150CaseFormat			= namedtuple('CaseFormat', 'name vars')
151
152DECL_INVARIANT		= CaseFormat("invariant",	["invariant", 	"",			""])
153DECL_STORAGE		= CaseFormat("storage", 	["varying", 	"uniform",	"attribute"])
154DECL_PRECISION		= CaseFormat("precision", 	["lowp", 		"mediump",	"mediump"])
155
156PARAM_STORAGE		= CaseFormat("storage",		[ "const", 		"", 				""])
157PARAM_PARAMETER 	= CaseFormat("parameter",	[ "in", 		"out", 				"inout" ])
158PARAM_PRECISION		= CaseFormat("precision",	[ "lowp", 		"mediump",			"mediump" ])
159
160# Order of qualification tests
161
162validDeclarationCases	= []
163invalidDeclarationCases = []
164validParameterCases		= []
165invalidParameterCases	= []
166
167declFormats = [
168	[DECL_INVARIANT, DECL_STORAGE, DECL_PRECISION],
169	[DECL_STORAGE, DECL_PRECISION],
170	[DECL_INVARIANT, DECL_STORAGE]
171]
172
173paramFormats = [
174	[PARAM_STORAGE, PARAM_PARAMETER, PARAM_PRECISION],
175	[PARAM_STORAGE, PARAM_PARAMETER],
176	[PARAM_STORAGE, PARAM_PRECISION],
177	[PARAM_PARAMETER, PARAM_PRECISION]
178]
179
180for f in declFormats:
181	for p in itertools.permutations(f):
182		if list(p) == f:
183			validDeclarationCases.append(DeclarationCase(False, p))		# Correct order
184		else:
185			invalidDeclarationCases.append(DeclarationCase(True, p))	# Incorrect order
186
187for f in paramFormats:
188	for p in itertools.permutations(f):
189		if list(p) == f:
190			validParameterCases.append(ParameterCase(False, p))			# Correct order
191		else:
192			invalidParameterCases.append(ParameterCase(True, p))		# Incorrect order
193
194qualificationOrderCases = [
195	CaseGroup("variables",	"Order of qualification in variable declarations.", children = [
196		CaseGroup("valid", 		"Valid orderings.", 	validDeclarationCases),
197		CaseGroup("invalid",	"Invalid orderings.", 	invalidDeclarationCases)
198	]),
199	CaseGroup("parameters", "Order of qualification in function parameters.", children = [
200		CaseGroup("valid", 		"Valid orderings.", 	validParameterCases),
201		CaseGroup("invalid",	"Invalid orderings.", 	invalidParameterCases)
202	])
203]
204
205# Main program
206
207if __name__ == "__main__":
208	print "Generating shader case files."
209	writeAllCases("qualification_order.test", qualificationOrderCases)
210