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