2 # Copyright (c) 2015-2016 Intel Corporation
4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 # of this software and associated documentation files (the "Software"), to deal
6 # in the Software without restriction, including without limitation the rights
7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 # copies of the Software, and to permit persons to whom the Software is
9 # furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 """Generate tests for variable index writes.
24 This creates a TestParams object for each invocation (using a factory to reduce
25 the number of duplicate objects), and then passes that into a mako template.
26 The template then formats that information into a shader_test for either the
27 fragment shader stage or the vertex shader stage.
35 from mako
import exceptions
37 from modules
import utils
, glsl
38 from templates
import template_dir
40 _TEMPLATES
= template_dir(os
.path
.basename(os
.path
.splitext(__file__
)[0]))
41 _VS_TEMPLATE
= _TEMPLATES
.get_template('vs.shader_test.mako')
42 _FS_TEMPLATE
= _TEMPLATES
.get_template('fs.shader_test.mako')
43 _DIRNAME
= os
.path
.join('spec', 'glsl-{}', 'execution', 'variable-indexing')
46 class TestParams(object):
47 """Object representing all of the parameters of a single test instance.
49 Provides all of the values using lazy properties, which tie in with the
50 ParamsFactory to store all of the values, speeding up run times.
53 def __init__(self
, mode
, array_dim
, matrix_dim
, index_value
, col
,
54 value_type
, glsl_version
):
55 # pylint: disable=too-many-arguments
56 assert array_dim
in [0, 3]
57 assert matrix_dim
in [2, 3, 4]
60 self
.array_dim
= array_dim
61 self
.matrix_dim
= matrix_dim
62 self
.index_value
= index_value
63 self
.col
= '[{}]'.format(col
)
64 self
.value_type
= value_type
65 self
.version
= glsl
.Version(glsl_version
)
68 def varying_comps(self
):
69 if self
.array_dim
!= 0:
70 return self
.matrix_dim
**2 * self
.array_dim
72 return self
.matrix_dim
**2
76 if int(self
.version
) >= 120:
77 return 'mat{0}x{0}'.format(self
.matrix_dim
)
79 return 'mat{}'.format(self
.matrix_dim
)
83 if self
.array_dim
!= 0 and int(self
.version
) >= 120:
84 return '{}[{}]'.format(self
.base_type
, self
.array_dim
)
90 if self
.array_dim
!= 0 and int(self
.version
) < 120:
91 return '[{}]'.format(self
.array_dim
)
97 if self
.value_type
== 'float':
104 if self
.array_dim
!= 0:
105 return '[{}]'.format(self
.index_value
)
111 if self
.array_dim
!= 0:
112 if self
.index_value
== 'index':
113 return '[{}2]'.format(self
.index_value
)
115 return '[{}]'.format(self
.index_value
)
121 if self
.matrix_dim
== 2:
122 return ["0.803161418975390", "0.852987140792140"]
123 elif self
.matrix_dim
== 3:
124 return ["0.681652305322399", "0.210426138878113",
126 elif self
.matrix_dim
== 4:
127 return ["0.0394868046587045", "0.8922408276905568",
128 "0.3337495624366961", "0.8732295730825839"]
132 if self
.matrix_dim
== 2:
133 return ["0.708718134966688", "1.452243795483797"]
134 elif self
.matrix_dim
== 3:
135 return ["0.610649606928364", "0.711906885823636",
137 elif self
.matrix_dim
== 4:
138 return ["1.03935908892461", "1.18846180713529", "1.10078681232072",
143 if self
.matrix_dim
== 2:
144 return [["0.241498998195656", "0.861223395812970"],
145 ["0.603473877011433", "0.891622340451180"]]
146 elif self
.matrix_dim
== 3:
148 ["0.493944462129466", "0.722190133917966", "0.239853948232558"],
149 ["0.550143078409278", "0.591962645398579", "0.467616286531193"],
150 ["0.850846377186973", "0.511303112962423", "0.270815003356504"]
152 elif self
.matrix_dim
== 4:
153 return [["0.922040144261674", "0.158053783109488",
154 "0.357016429866574", "0.836368810383957"],
155 ["0.560251913703792", "0.171634921595771",
156 "0.602494709909111", "0.693273570571311"],
157 ["0.350720358904176", "0.912192627475775",
158 "0.688544081259531", "0.913891056231967"],
159 ["0.442058176039301", "0.829835836794679",
160 "0.365674411003021", "0.879197364462782"]]
163 def test_sizes(self
):
164 if self
.array_dim
== 0:
166 elif self
.index_value
== 'index':
167 return list(range(1, self
.array_dim
+ 1))
172 def test_columns(self
):
173 if self
.col
== '[col]':
174 return list(range(1, self
.matrix_dim
+ 1))
179 if self
.value_type
== 'float':
180 return list(range(1, self
.matrix_dim
+ 1))
185 # shader_runner always uses matDxD format
186 return 'mat{0}x{0}'.format(self
.matrix_dim
)
188 def test_matrix(self
, column
, row
):
189 """Generate the matrix used in a test section.
191 This will take the matrix used by the test, and replace specific values
192 with sentinel values, and return the matrix as a string.
195 bad
= ['666.0', '777.0', '888.0', '999.0']
196 mat
= copy
.deepcopy(self
.test_mat
)
198 if self
.value_type
== 'float':
199 mat
[column
][row
] = bad
[0]
201 mat
[column
] = bad
[0:self
.matrix_dim
]
210 def formated_version(self
):
211 # Note: GLSLVersion.float() does division by 100
212 return '{:.2f}'.format(float(self
.version
))
215 class ParamsFactory(object): # pylint: disable=too-few-public-methods
216 """A factory class that provides TestParam objects.
218 This cuts the number of new objects created by roughly 3/5.
224 def get(self
, *args
):
227 return self
.__stored
[args
]
229 params
= TestParams(*args
)
230 self
.__stored
[args
] = params
234 def make_vs(name
, params
):
235 """Create a vertex shader test."""
236 dirname
= _DIRNAME
.format(params
.formated_version
)
237 utils
.safe_makedirs(dirname
)
238 with
open(os
.path
.join(dirname
, name
), 'w') as f
:
240 f
.write(_VS_TEMPLATE
.render_unicode(params
=params
))
242 print(exceptions
.text_error_template().render(), file=sys
.stderr
)
247 def make_fs(name
, params
):
248 """Create a fragment shader test."""
249 dirname
= _DIRNAME
.format(params
.formated_version
)
250 utils
.safe_makedirs(dirname
)
251 with
open(os
.path
.join(dirname
, name
), 'w') as f
:
253 f
.write(_FS_TEMPLATE
.render_unicode(params
=params
))
255 print(exceptions
.text_error_template().render(), file=sys
.stderr
)
261 """The main function."""
262 # Various choices that can be put together to produce a single test.
263 iter_
= itertools
.product(
264 ['110', '120'], # GLSL versions
265 [0, 3], # Array dimensions
266 [2, 3, 4], # Matrix dimensions
267 ['varying', 'temp'], # modes
268 ['col', 1], # columns
269 ['fs', 'vs'], # shader stages
272 factory
= ParamsFactory()
274 # This can be filled in to produce the file name for the test.
275 # Note that idx, col, row, and arr will need to have a '-' added to the end
276 # of the value if it is not empty
277 name
= '{stage}-{mode}-{arr}mat{matrix_dim}-{idx}{col}{row}wr.shader_test'
279 for v
, a
, d
, m
, c
, s
in iter_
:
280 for t
in ['float', 'vec{}'.format(d
)]:
285 # Fragment shaders cannot write varyings
298 col
='col-' if c
== 'col' else '',
299 row
='row-' if t
== 'float' else ''),
300 factory
.get(m
, a
, d
, 1, c
, t
, v
))
309 idx
='index-' if a
!= 0 else '',
310 col
='col-' if c
== 'col' else '',
311 row
='row-' if t
== 'float' else ''),
312 factory
.get(m
, a
, d
, 'index', c
, t
, v
))
315 if __name__
== '__main__':