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