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.
34 from modules
import utils
, glsl
35 from templates
import template_dir
37 _TEMPLATES
= template_dir(os
.path
.basename(os
.path
.splitext(__file__
)[0]))
38 _VS_TEMPLATE
= _TEMPLATES
.get_template('vs.shader_test.mako')
39 _FS_TEMPLATE
= _TEMPLATES
.get_template('fs.shader_test.mako')
40 _DIRNAME
= os
.path
.join('spec', 'glsl-{}', 'execution', 'variable-indexing')
43 class TestParams(object):
44 """Object representing all of the parameters of a single test instance.
46 Provides all of the values using lazy properties, which tie in with the
47 ParamsFactory to store all of the values, speeding up run times.
50 def __init__(self
, mode
, array_dim
, matrix_dim
, index_value
, col
,
51 value_type
, glsl_version
):
52 # pylint: disable=too-many-arguments
53 assert array_dim
in [0, 3]
54 assert matrix_dim
in [2, 3, 4]
57 self
.array_dim
= array_dim
58 self
.matrix_dim
= matrix_dim
59 self
.index_value
= index_value
60 self
.col
= '[{}]'.format(col
)
61 self
.value_type
= value_type
62 self
.version
= glsl
.Version(glsl_version
)
65 def varying_comps(self
):
66 if self
.array_dim
!= 0:
67 return self
.matrix_dim
**2 * self
.array_dim
69 return self
.matrix_dim
**2
73 if int(self
.version
) >= 120:
74 return 'mat{0}x{0}'.format(self
.matrix_dim
)
76 return 'mat{}'.format(self
.matrix_dim
)
80 if self
.array_dim
!= 0 and int(self
.version
) >= 120:
81 return '{}[{}]'.format(self
.base_type
, self
.array_dim
)
87 if self
.array_dim
!= 0 and int(self
.version
) < 120:
88 return '[{}]'.format(self
.array_dim
)
94 if self
.value_type
== 'float':
101 if self
.array_dim
!= 0:
102 return '[{}]'.format(self
.index_value
)
108 if self
.array_dim
!= 0:
109 if self
.index_value
== 'index':
110 return '[{}2]'.format(self
.index_value
)
112 return '[{}]'.format(self
.index_value
)
118 if self
.matrix_dim
== 2:
119 return ["0.803161418975390", "0.852987140792140"]
120 elif self
.matrix_dim
== 3:
121 return ["0.681652305322399", "0.210426138878113",
123 elif self
.matrix_dim
== 4:
124 return ["0.0394868046587045", "0.8922408276905568",
125 "0.3337495624366961", "0.8732295730825839"]
129 if self
.matrix_dim
== 2:
130 return ["0.708718134966688", "1.452243795483797"]
131 elif self
.matrix_dim
== 3:
132 return ["0.610649606928364", "0.711906885823636",
134 elif self
.matrix_dim
== 4:
135 return ["1.03935908892461", "1.18846180713529", "1.10078681232072",
140 if self
.matrix_dim
== 2:
141 return [["0.241498998195656", "0.861223395812970"],
142 ["0.603473877011433", "0.891622340451180"]]
143 elif self
.matrix_dim
== 3:
145 ["0.493944462129466", "0.722190133917966", "0.239853948232558"],
146 ["0.550143078409278", "0.591962645398579", "0.467616286531193"],
147 ["0.850846377186973", "0.511303112962423", "0.270815003356504"]
149 elif self
.matrix_dim
== 4:
150 return [["0.922040144261674", "0.158053783109488",
151 "0.357016429866574", "0.836368810383957"],
152 ["0.560251913703792", "0.171634921595771",
153 "0.602494709909111", "0.693273570571311"],
154 ["0.350720358904176", "0.912192627475775",
155 "0.688544081259531", "0.913891056231967"],
156 ["0.442058176039301", "0.829835836794679",
157 "0.365674411003021", "0.879197364462782"]]
160 def test_sizes(self
):
161 if self
.array_dim
== 0:
163 elif self
.index_value
== 'index':
164 return list(range(1, self
.array_dim
+ 1))
169 def test_columns(self
):
170 if self
.col
== '[col]':
171 return list(range(1, self
.matrix_dim
+ 1))
176 if self
.value_type
== 'float':
177 return list(range(1, self
.matrix_dim
+ 1))
182 # shader_runner always uses matDxD format
183 return 'mat{0}x{0}'.format(self
.matrix_dim
)
185 def test_matrix(self
, column
, row
):
186 """Generate the matrix used in a test section.
188 This will take the matrix used by the test, and replace specific values
189 with sentinel values, and return the matrix as a string.
192 bad
= ['666.0', '777.0', '888.0', '999.0']
193 mat
= copy
.deepcopy(self
.test_mat
)
195 if self
.value_type
== 'float':
196 mat
[column
][row
] = bad
[0]
198 mat
[column
] = bad
[0:self
.matrix_dim
]
207 def formated_version(self
):
208 # Note: GLSLVersion.float() does division by 100
209 return '{:.2f}'.format(float(self
.version
))
212 class ParamsFactory(object): # pylint: disable=too-few-public-methods
213 """A factory class that provides TestParam objects.
215 This cuts the number of new objects created by roughly 3/5.
221 def get(self
, *args
):
224 return self
.__stored
[args
]
226 params
= TestParams(*args
)
227 self
.__stored
[args
] = params
231 def make_vs(name
, params
):
232 """Create a vertex shader test."""
233 dirname
= _DIRNAME
.format(params
.formated_version
)
234 utils
.safe_makedirs(dirname
)
235 with
open(os
.path
.join(dirname
, name
), 'w') as f
:
236 f
.write(_VS_TEMPLATE
.render_unicode(params
=params
))
240 def make_fs(name
, params
):
241 """Create a fragment shader test."""
242 dirname
= _DIRNAME
.format(params
.formated_version
)
243 utils
.safe_makedirs(dirname
)
244 with
open(os
.path
.join(dirname
, name
), 'w') as f
:
245 f
.write(_FS_TEMPLATE
.render_unicode(params
=params
))
250 """The main function."""
251 # Various choices that can be put together to produce a single test.
252 iter_
= itertools
.product(
253 ['110', '120'], # GLSL versions
254 [0, 3], # Array dimensions
255 [2, 3, 4], # Matrix dimensions
256 ['varying', 'temp'], # modes
257 ['col', 1], # columns
258 ['fs', 'vs'], # shader stages
261 factory
= ParamsFactory()
263 # This can be filled in to produce the file name for the test.
264 # Note that idx, col, row, and arr will need to have a '-' added to the end
265 # of the value if it is not empty
266 name
= '{stage}-{mode}-{arr}mat{matrix_dim}-{idx}{col}{row}wr.shader_test'
268 for v
, a
, d
, m
, c
, s
in iter_
:
269 for t
in ['float', 'vec{}'.format(d
)]:
274 # Fragment shaders cannot write varyings
287 col
='col-' if c
== 'col' else '',
288 row
='row-' if t
== 'float' else ''),
289 factory
.get(m
, a
, d
, 1, c
, t
, v
))
298 idx
='index-' if a
!= 0 else '',
299 col
='col-' if c
== 'col' else '',
300 row
='row-' if t
== 'float' else ''),
301 factory
.get(m
, a
, d
, 'index', c
, t
, v
))
304 if __name__
== '__main__':