glsl-array-bounds: set out-of-bounds array index inside shader
[piglit.git] / generated_tests / builtin_function.py
blobe249ab00cfdddd3b2d72065f2110c37021f29bec
1 # coding=utf-8
3 # Copyright © 2011 Intel Corporation
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
24 # This source file defines a set of test vectors that can be used to
25 # test GLSL's built-in functions and operators. It is intended to be
26 # used by Python code that generates Piglit tests.
28 # The key export is the dictionary test_suite. It contains an entry
29 # for each possible overload of every pure built-in function and
30 # operator. By iterating through this dictionary you can find a set
31 # of test vectors for testing nearly every built-in GLSL function.
33 # The following functions are not included, since they are not pure,
34 # so they can't be tested using simple vectors:
35 # - dFdx()
36 # - dFdy()
37 # - fwidth()
38 # - ftransform()
39 # - Increment and decrement operators
41 # The following functions are not included, since they need to be
42 # tested in specialized ways:
43 # - modf(): not tested because it has an out parameter
44 # - isnan() and isinf(): not tested because special effort is required
45 # to create values that cause these functions to return true.
47 # Also not tested are array subscripting, field/method selection,
48 # swizzling, the function call operator, assignment, and the sequence
49 # operator.
51 import collections
52 import itertools
53 import functools
54 import warnings
56 import numpy as np
59 # Floating point types used by Python and numpy
60 FLOATING_TYPES = (float, np.float64, np.float32)
62 # Due to a bug in the Windows implementation of numpy, there are
63 # multiple int32 types (and multiple uint32 types). So we have to
64 # find them all when doing isinstance checks. The following code will
65 # create two-element tuples on numpy implementations that have the
66 # bug, and one-element tuples on numpy implementations that don't.
67 INT32_TYPES = tuple(set([np.int32, type(np.abs(np.int32(1)))]))
68 UINT32_TYPES = tuple(set([np.uint32,
69 type(np.dot(np.uint32(0), np.uint32(0)))]))
72 @functools.total_ordering
73 class GlslBuiltinType(object):
74 """Class representing a GLSL built-in type."""
75 def __init__(self, name, base_type, num_cols, num_rows,
76 version_introduced):
77 self.__name = name
78 if base_type is not None:
79 self.__base_type = base_type
80 else:
81 self.__base_type = self
82 self.__num_cols = num_cols
83 self.__num_rows = num_rows
84 self.__version_introduced = version_introduced
86 @property
87 def name(self):
88 """The name of the type, as a string."""
89 return self.__name
91 @property
92 def base_type(self):
93 """For vectors and matrices, the type of data stored in each
94 element. For scalars, equal to self.
95 """
96 return self.__base_type
98 @property
99 def num_cols(self):
100 """For matrices, the number of columns. For vectors and
101 scalars, 1.
103 return self.__num_cols
105 @property
106 def num_rows(self):
107 """For vectors and matrices, the number of rows. For scalars,
110 return self.__num_rows
112 @property
113 def is_scalar(self):
114 return self.__num_cols == 1 and self.__num_rows == 1
116 @property
117 def is_vector(self):
118 return self.__num_cols == 1 and self.__num_rows != 1
120 @property
121 def is_matrix(self):
122 return self.__num_cols != 1
124 @property
125 def version_introduced(self):
126 """The earliest version of GLSL that this type appears in (as
127 a string, e.g. 110).
129 return self.__version_introduced
131 def __eq__(self, other):
132 if isinstance(other, GlslBuiltinType):
133 return self.name == other.name
135 return NotImplemented
137 def __lt__(self, other):
138 if isinstance(other, GlslBuiltinType):
139 return self.name < other.name
141 return NotImplemented
143 def __hash__(self):
144 return hash('__GLslBuiltinType_{}__'.format(self.name))
146 def __str__(self):
147 return self.__name
149 def __repr__(self):
150 return 'glsl_{0}'.format(self.__name)
153 # Concrete declarations of GlslBuiltinType
154 glsl_bool = GlslBuiltinType('bool', None, 1, 1, 110)
155 glsl_int = GlslBuiltinType('int', None, 1, 1, 110)
156 glsl_uint = GlslBuiltinType('uint', None, 1, 1, 130)
157 glsl_float = GlslBuiltinType('float', None, 1, 1, 110)
158 glsl_vec2 = GlslBuiltinType('vec2', glsl_float, 1, 2, 110)
159 glsl_vec3 = GlslBuiltinType('vec3', glsl_float, 1, 3, 110)
160 glsl_vec4 = GlslBuiltinType('vec4', glsl_float, 1, 4, 110)
161 glsl_bvec2 = GlslBuiltinType('bvec2', glsl_bool, 1, 2, 110)
162 glsl_bvec3 = GlslBuiltinType('bvec3', glsl_bool, 1, 3, 110)
163 glsl_bvec4 = GlslBuiltinType('bvec4', glsl_bool, 1, 4, 110)
164 glsl_ivec2 = GlslBuiltinType('ivec2', glsl_int, 1, 2, 110)
165 glsl_ivec3 = GlslBuiltinType('ivec3', glsl_int, 1, 3, 110)
166 glsl_ivec4 = GlslBuiltinType('ivec4', glsl_int, 1, 4, 110)
167 glsl_uvec2 = GlslBuiltinType('uvec2', glsl_uint, 1, 2, 130)
168 glsl_uvec3 = GlslBuiltinType('uvec3', glsl_uint, 1, 3, 130)
169 glsl_uvec4 = GlslBuiltinType('uvec4', glsl_uint, 1, 4, 130)
170 glsl_mat2 = GlslBuiltinType('mat2', glsl_float, 2, 2, 110)
171 glsl_mat3 = GlslBuiltinType('mat3', glsl_float, 3, 3, 110)
172 glsl_mat4 = GlslBuiltinType('mat4', glsl_float, 4, 4, 110)
173 glsl_mat2x2 = glsl_mat2
174 glsl_mat3x2 = GlslBuiltinType('mat3x2', glsl_float, 3, 2, 120)
175 glsl_mat4x2 = GlslBuiltinType('mat4x2', glsl_float, 4, 2, 120)
176 glsl_mat2x3 = GlslBuiltinType('mat2x3', glsl_float, 2, 3, 120)
177 glsl_mat3x3 = glsl_mat3
178 glsl_mat4x3 = GlslBuiltinType('mat4x3', glsl_float, 4, 3, 120)
179 glsl_mat2x4 = GlslBuiltinType('mat2x4', glsl_float, 2, 4, 120)
180 glsl_mat3x4 = GlslBuiltinType('mat3x4', glsl_float, 3, 4, 120)
181 glsl_mat4x4 = glsl_mat4
182 glsl_int64_t = GlslBuiltinType('int64_t', None, 1, 1, 400)
183 glsl_i64vec2 = GlslBuiltinType('i64vec2', glsl_int64_t, 1, 2, 400)
184 glsl_i64vec3 = GlslBuiltinType('i64vec3', glsl_int64_t, 1, 3, 400)
185 glsl_i64vec4 = GlslBuiltinType('i64vec4', glsl_int64_t, 1, 4, 400)
186 glsl_uint64_t = GlslBuiltinType('uint64_t', None, 1, 1, 400)
187 glsl_u64vec2 = GlslBuiltinType('u64vec2', glsl_uint64_t, 1, 2, 400)
188 glsl_u64vec3 = GlslBuiltinType('u64vec3', glsl_uint64_t, 1, 3, 400)
189 glsl_u64vec4 = GlslBuiltinType('u64vec4', glsl_uint64_t, 1, 4, 400)
191 # Named tuple representing the signature of a single overload of a
192 # built-in GLSL function or operator:
193 # - name is a name suitable for use in test filenames. For functions,
194 # this is the name of the function. For operators, it is a short
195 # description of the operator, beginning with "op", e.g. "op-plus".
196 # - template is a Python format string that can be used to construct
197 # GLSL code that invokes the function or operator.
198 # - version_introduced earliest version of GLSL the test applies to
199 # (as a string, e.g. 110).
200 # - rettype is the return type of the function or operator (as a
201 # GlslBuiltinType).
202 # - argtypes is a tuple containing the types of each parameter (as
203 # GlslBuiltinTypes).
205 # For example, the function
207 # vec3 step(float edge, vec3 x)
209 # has a signature of
211 # Signature(name='step', template='step({0}, {1})',
212 # version_introduced=110, rettype='vec3',
213 # argtypes=('float', 'vec3'))
214 Signature = collections.namedtuple(
215 'Signature',
216 ('name', 'template', 'version_introduced', 'extension', 'rettype', 'argtypes'))
219 # Named tuple representing a single piece of test data for testing a
220 # built-in GLSL function:
221 # - arguments is a tuple containing the arguments to apply to the
222 # function. Each argument is of a type native to numpy (e.g.
223 # numpy.float32 or numpy.ndarray)
224 # - result is the value the function is expected to return. It is
225 # also of a type native to numpy.
226 # - tolerance is a float32 representing how much deviation from the
227 # result we expect, considering the floating point precision
228 # requirements of GLSL and OpenGL. The value may be zero for test
229 # vectors involving booleans and integers. If result is a vector or
230 # matrix, tolerance should be interpreted as the maximum permissible
231 # RMS error (as would be computed by the distance() function).
232 TestVector = collections.namedtuple(
233 'TestVector', ('arguments', 'result', 'tolerance'))
236 def glsl_type_of(value):
237 """Return the GLSL type corresponding to the given native numpy
238 value, as a GlslBuiltinType.
240 if isinstance(value, FLOATING_TYPES):
241 return glsl_float
242 elif isinstance(value, (bool, np.bool_)):
243 return glsl_bool
244 elif isinstance(value, INT32_TYPES):
245 return glsl_int
246 elif isinstance(value, UINT32_TYPES):
247 return glsl_uint
248 elif isinstance(value, np.int64):
249 return glsl_int64_t
250 elif isinstance(value, np.uint64):
251 return glsl_uint64_t
252 else:
253 assert isinstance(value, np.ndarray)
254 if len(value.shape) == 1:
255 # Vector
256 vector_length = value.shape[0]
257 assert 2 <= vector_length <= 4
258 if value.dtype in FLOATING_TYPES:
259 return (glsl_vec2, glsl_vec3, glsl_vec4)[vector_length - 2]
260 elif value.dtype == np.int64:
261 return (glsl_i64vec2, glsl_i64vec3, glsl_i64vec4)[vector_length - 2]
262 elif value.dtype == np.uint64:
263 return (glsl_u64vec2, glsl_u64vec3, glsl_u64vec4)[vector_length - 2]
264 elif value.dtype == bool:
265 return (glsl_bvec2, glsl_bvec3, glsl_bvec4)[vector_length - 2]
266 elif value.dtype in INT32_TYPES:
267 return (glsl_ivec2, glsl_ivec3, glsl_ivec4)[vector_length - 2]
268 elif value.dtype in UINT32_TYPES:
269 return (glsl_uvec2, glsl_uvec3, glsl_uvec4)[vector_length - 2]
270 else:
271 raise Exception(
272 'Unexpected vector base type {0}'.format(value.dtype))
273 else:
274 # Matrix
275 assert value.dtype in FLOATING_TYPES
276 assert len(value.shape) == 2
277 matrix_rows = value.shape[0]
278 assert 2 <= matrix_rows <= 4
279 matrix_columns = value.shape[1]
280 assert 2 <= matrix_columns <= 4
281 matrix_types = ((glsl_mat2x2, glsl_mat2x3, glsl_mat2x4),
282 (glsl_mat3x2, glsl_mat3x3, glsl_mat3x4),
283 (glsl_mat4x2, glsl_mat4x3, glsl_mat4x4))
284 return matrix_types[matrix_columns - 2][matrix_rows - 2]
287 def column_major_values(value):
288 """Given a native numpy value, return a list of the scalar values
289 comprising it, in column-major order."""
290 if isinstance(value, np.ndarray):
291 return list(np.reshape(value, -1, 'F'))
292 else:
293 return [value]
296 def glsl_constant(value):
297 """Given a native numpy value, return GLSL code that constructs
298 it."""
299 column_major = np.reshape(np.array(value), -1, 'F')
300 if column_major.dtype == bool:
301 values = ['true' if x else 'false' for x in column_major]
302 elif column_major.dtype == np.int64:
303 values = [repr(x) + 'l' for x in column_major]
304 elif column_major.dtype == np.uint64:
305 values = [repr(x) + 'ul' for x in column_major]
306 elif column_major.dtype in UINT32_TYPES:
307 values = [repr(x) + 'u' for x in column_major]
308 else:
309 values = [repr(x) for x in column_major]
310 if len(column_major) == 1:
311 return values[0]
312 else:
313 return '{0}({1})'.format(glsl_type_of(value), ', '.join(values))
316 def round_to_32_bits(value):
317 """If value is a floating point type, round it down to 32 bits.
318 Otherwise return it unchanged.
320 if isinstance(value, float):
321 return np.float32(value)
322 elif isinstance(value, np.ndarray) and value.dtype == np.float64:
323 return np.array(value, dtype=np.float32)
324 else:
325 return value
328 def extend_to_64_bits(value):
329 """If value is a floating point type, extend it to 64 bits.
330 Otherwise return it unchanged.
332 if isinstance(value, np.float32):
333 return np.float64(value)
334 elif isinstance(value, np.ndarray) and value.dtype == np.float32:
335 return np.array(value, dtype=np.float64)
336 else:
337 return value
340 # Dictionary containing the test vectors. Each entry in the
341 # dictionary represents a single overload of a single built-in
342 # function. Its key is a Signature tuple, and its value is a list of
343 # TestVector tuples.
345 # Note: the dictionary is initialized to {} here, but it is filled
346 # with test vectors by code later in this file.
347 test_suite = {}
350 # Implementation
351 # ==============
353 # The functions below shouldn't be necessary to call from outside this
354 # file. They exist solely to populate test_suite with test vectors.
356 # Functions that simulate GLSL built-in functions (in the cases where
357 # the GLSL built-in functions have no python or numpy equivalent, or
358 # in cases where there is a behavioral difference). These functions
359 # return None if the behavior of the GLSL built-in is undefined for
360 # the given set of inputs.
361 def _multiply(x, y):
362 x_type = glsl_type_of(x)
363 y_type = glsl_type_of(y)
365 if x_type.is_vector and y_type.is_vector:
366 # vector * vector is done componentwise.
367 return x * y
368 else:
369 # All other cases are standard linear algebraic
370 # multiplication, which numpy calls "dot".
371 return np.dot(x, y)
374 def _divide(x, y):
375 if any(y_element == 0 for y_element in column_major_values(y)):
376 # Division by zero is undefined.
377 return None
378 if glsl_type_of(x).base_type == glsl_int or glsl_type_of(x).base_type == glsl_int64_t:
379 # The GLSL spec does not make it clear what the rounding rules
380 # are when performing integer division. C99 requires
381 # round-toward-zero, so in the absence of any other
382 # information, assume that's the correct behavior for GLSL.
384 # Python and numpy's rounding rules are inconsistent, so to
385 # make sure we get round-toward-zero behavior, divide the
386 # absolute values of x and y, and then fix the sign.
387 return (np.abs(x) // np.abs(y)) * (np.sign(x) * np.sign(y))
388 elif glsl_type_of(x).base_type == glsl_uint or glsl_type_of(x).base_type == glsl_uint64_t:
389 return x // y
390 else:
391 return x / y
394 def _modulus(x, y):
395 if any(x_element < 0 for x_element in column_major_values(x)):
396 # Modulus operation with a negative first operand is
397 # undefined.
398 return None
399 if any(y_element <= 0 for y_element in column_major_values(y)):
400 # Modulus operation with a negative or zero second operand is
401 # undefined.
402 return None
403 return x % y
406 def _lshift(x, y):
407 base = glsl_type_of(x).base_type
408 if base in (glsl_int64_t, glsl_uint64_t):
409 bits = 64
410 shift_type = glsl_int if base == glsl_int64_t else glsl_uint
411 else:
412 bits = 32
413 shift_type = base
414 if not all(0 <= y_element < bits for y_element in column_major_values(y)):
415 # Shifts by less than 0 or more than the number of bits in the
416 # type being shifted are undefined.
417 return None
418 # When the arguments to << don't have the same signedness, numpy
419 # likes to promote them to int64. To avoid this, convert y to be
420 # the same type as x.
421 y_orig = y
422 if glsl_type_of(y).base_type != shift_type:
423 y = _change_signedness(y)
424 result = x << y
426 # Shifting should always produce a result with the same base type
427 # as the left argument.
428 assert glsl_type_of(result).base_type == glsl_type_of(x).base_type
430 return result
433 def _rshift(x, y):
434 base = glsl_type_of(x).base_type
435 if base in (glsl_int64_t, glsl_uint64_t):
436 bits = 64
437 shift_type = glsl_int if base == glsl_int64_t else glsl_uint
438 else:
439 bits = 32
440 shift_type = base
441 if not all(0 <= y_element < bits for y_element in column_major_values(y)):
442 # Shifts by less than 0 or more than the number of bits in the
443 # type being shifted are undefined.
444 return None
445 # When the arguments to >> don't have the same signedness, numpy
446 # likes to promote them to int64. To avoid this, convert y to be
447 # the same type as x.
448 y_orig = y
449 if glsl_type_of(y).base_type != shift_type:
450 y = _change_signedness(y)
451 result = x >> y
453 # Shifting should always produce a result with the same base type
454 # as the left argument.
455 assert glsl_type_of(result).base_type == glsl_type_of(x).base_type
457 return result
460 def _equal(x, y):
461 return all(column_major_values(x == y))
464 def _not_equal(x, y):
465 return not _equal(x, y)
468 def _arctan2(y, x):
469 if x == y == 0.0:
470 return None
471 return np.arctan2(y, x)
474 def _pow(x, y):
475 if x < 0.0:
476 return None
477 if x == 0.0 and y <= 0.0:
478 return None
479 return np.power(x, y)
482 def _exp2(x):
483 # exp2() is not available in versions of numpy < 1.3.0 so we
484 # emulate it with power().
485 return np.power(2, x)
488 def _trunc(x):
489 # trunc() rounds toward zero. It is not available in version
490 # 1.2.1 of numpy so we emulate it with floor(), sign(), and abs().
491 return np.sign(x) * np.floor(np.abs(x))
494 def _clamp(x, minVal, maxVal):
495 if minVal > maxVal:
496 return None
497 return min(max(x, minVal), maxVal)
500 # Inefficient, but obvious
501 def _mid3(x, y, z):
502 return np.sort([x, y, z])[1]
504 def _smoothstep(edge0, edge1, x):
505 if edge0 >= edge1:
506 return None
507 t = _clamp((x-edge0)/(edge1-edge0), 0.0, 1.0)
508 return t*t*(3.0-2.0*t)
511 def _normalize(x):
512 return x/np.linalg.norm(x)
515 def _faceforward(N, I, Nref):
516 if np.dot(Nref, I) < 0.0:
517 return N
518 else:
519 return -N
522 def _reflect(I, N):
523 return I-2*np.dot(N, I)*N
526 def _refract(I, N, eta):
527 k = 1.0-eta*eta*(1.0-np.dot(N, I)*np.dot(N, I))
528 if k < 0.0:
529 return I*0.0
530 else:
531 return eta*I-(eta*np.dot(N, I)+np.sqrt(k))*N
534 def _change_signedness(x):
535 """Change signed integer types to unsigned integer types and vice
536 versa."""
537 if isinstance(x, INT32_TYPES):
538 return np.uint32(x)
539 elif isinstance(x, UINT32_TYPES):
540 return np.int32(x)
541 elif isinstance(x, np.ndarray):
542 if (x.dtype in INT32_TYPES):
543 return np.array(x, dtype=np.uint32)
544 elif (x.dtype in UINT32_TYPES):
545 return np.array(x, dtype=np.int32)
546 raise Exception('Unexpected type passed to _change_signedness')
549 def _argument_types_match(arguments, argument_indices_to_match):
550 """Return True if all of the arguments indexed by
551 argument_indices_to_match have the same GLSL type.
553 types = [glsl_type_of(arguments[i]) for i in argument_indices_to_match]
554 return all(x == types[0] for x in types)
557 def _strict_tolerance(arguments, result):
558 """Compute tolerance using a strict interpretation of the GLSL and
559 OpenGL standards.
561 From the GLSL 1.20 spec (4.1.4 "Floats"):
563 "As an input value to one of the processing units, a
564 floating-point variable is expected to match the IEEE single
565 precision floating-point definition for precision and dynamic
566 range. It is not required that the precision of internal
567 processing match the IEEE floating-point specification for
568 floating-point operations, but the guidelines for precision
569 established by the OpenGL 1.4 specification must be met."
571 From the OpenGL 1.4 spec (2.1.1 "Floating-Point Computation"):
573 "We require simply that numbers' floating-point parts contain
574 enough bits ... so that individual results of floating-point
575 operations are accurate to about 1 part in 10^5."
577 A harsh interpretation of the above is that (a) no precision is
578 lost in moving numbers into or out of the GPU, and (b) any
579 built-in function constitutes a single operation, so therefore the
580 error in applying any built-in function should be off by no more
581 than 1e-5 times its theoretically correct value.
583 This is not the only possible interpretation, however. Certain
584 built-in functions, such as the cross product, are computed by a
585 formula consisting of many elementary multiplications and
586 additions, in which a large amount of cancellation sometimes
587 occurs. It's possible that these rules are meant to apply to
588 those elementary multiplications and additions, and not the full
589 built-in function. Other built-in functions, such as the trig
590 functions, are typically implemented by a series approximation, in
591 which 1 part in 10^5 accuracy seems like overkill. See below for
592 the tolerance computation we use on these other functions.
594 return 1e-5 * np.linalg.norm(result)
597 def _trig_tolerance(arguments, result):
598 """Compute a more lenient tolerance bound for trig functions.
600 The GLSL and OpenGL specs don't provide any guidance as to the
601 required accuracy of trig functions (other than the "1 part in
602 10^5" general accuracy requirement, which seems like overkill for
603 trig functions.
605 So the tolerance here is rather arbitrarily chosen to be either 1
606 part in 10^3 or 10^-4, whichever is larger.
608 return max(1e-4, 1e-3 * np.linalg.norm(result))
611 def _cross_product_tolerance(arguments, result):
612 """Compute a more lenient tolerance bound for cross product.
614 Since the computation of a cross product may involve a large
615 amount of cancellation, an error tolerance of 1 part in 10^5
616 (referred to the magnitude of the result vector) is overly tight.
618 So instead we allow the error to be 1 part in 10^5 referred to the
619 product of the magnitudes of the arguments.
621 assert len(arguments) == 2
622 return 1e-5 * np.linalg.norm(arguments[0]) * np.linalg.norm(arguments[1])
625 def _simulate_function(test_inputs, python_equivalent, tolerance_function):
626 """Construct test vectors by simulating a GLSL function on a list
627 of possible inputs, and return a list of test vectors.
629 test_inputs is a list of possible input sequences, each of which
630 represents a set of arguments that should be applied to the
631 function.
633 python_equivalent is the function to simulate--it should return
634 None if the GLSL function returns undefined results for the given
635 set of inputs, otherwise it should return the expected result.
636 Input sequences for which python_equivalent returns None are
637 ignored.
639 tolerance_function is the function to call to compute the
640 tolerance. It should take the set of arguments and the expected
641 result as its parameters. It is only used for functions that
642 return floating point values.
644 python_equivalent and tolerance_function are simulated using 64
645 bit floats for maximum possible accuracy. The vector, however, is
646 built with rounded to 32 bits values since that is the data type
647 that we expect to get back from OpenGL.
649 test_vectors = []
650 for inputs in test_inputs:
651 expected_output = python_equivalent(
652 *[extend_to_64_bits(x) for x in inputs])
653 if expected_output is not None:
654 if glsl_type_of(expected_output).base_type != glsl_float:
655 tolerance = 0.0
656 else:
657 tolerance = tolerance_function(inputs, expected_output)
658 test_vectors.append(TestVector(inputs,
659 round_to_32_bits(expected_output),
660 round_to_32_bits(tolerance)))
661 return test_vectors
664 def _vectorize_test_vectors(test_vectors, scalar_arg_indices, vector_length):
665 """Build a new set of test vectors by combining elements of
666 test_vectors into vectors of length vector_length. For example,
667 vectorizing the test vectors
669 [TestVector((10, 20), 30, tolerance), TestVector((11, 20), 31, tolerance)]
671 into vectors of length 2 would produce the result:
673 [TestVector((vec2(10, 11), vec2(20, 20)), vec2(30, 31), new_tolerance)].
675 Tolerances are combined in root-sum-square fashion.
677 scalar_arg_indices is a sequence of argument indices which should
678 not be vectorized. So, if scalar_arg_indices is [1] in the above
679 example, the result would be:
681 [TestVector((vec2(10, 11), 20), vec2(30, 31), new_tolerance)].
683 def make_groups(test_vectors):
684 """Group test vectors according to the values passed to the
685 arguments that should not be vectorized.
687 groups = {}
688 for tv in test_vectors:
689 key = tuple(tv.arguments[i] for i in scalar_arg_indices)
690 if key not in groups:
691 groups[key] = []
692 groups[key].append(tv)
693 return groups
695 def partition_vectors(test_vectors, partition_size):
696 """Partition test_vectors into lists of length partition_size.
697 If partition_size does not evenly divide the number of test
698 vectors, wrap around as necessary to ensure that every input
699 test vector is included.
701 for i in range(0, len(test_vectors), partition_size):
702 partition = []
703 for j in range(partition_size):
704 partition.append(test_vectors[(i + j) % len(test_vectors)])
705 yield partition
707 def merge_vectors(test_vectors):
708 """Merge the given set of test vectors (whose arguments and
709 result are scalars) into a single test vector whose arguments
710 and result are vectors. For argument indices in
711 scalar_arg_indices, leave the argument as a scalar.
713 arity = len(test_vectors[0].arguments)
714 arguments = []
715 for j in range(arity):
716 if j in scalar_arg_indices:
717 arguments.append(test_vectors[0].arguments[j])
718 else:
719 arguments.append(
720 np.array([tv.arguments[j] for tv in test_vectors]))
721 result = np.array([tv.result for tv in test_vectors])
722 tolerance = np.linalg.norm(
723 [tv.tolerance for tv in test_vectors])
724 return TestVector(arguments, result, tolerance)
726 vectorized_test_vectors = []
727 groups = make_groups(test_vectors)
728 for key in sorted(groups.keys()):
729 test_vectors = groups[key]
730 vectorized_test_vectors.extend(
731 merge_vectors(partition)
732 for partition in partition_vectors(test_vectors, vector_length))
733 return vectorized_test_vectors
736 def _store_test_vector(test_suite_dict, name, glsl_version, extension, test_vector,
737 template=None):
738 """Store a test vector in the appropriate place in
739 test_suite_dict. The dictionary key (which is a Signature tuple)
740 is generated by consulting the argument and return types of the
741 test vector, and combining them with name and glsl_version.
743 glsl_version is adjusted if necessary to reflect when the argument
744 and return types were introduced into GLSL.
746 If template is supplied, it is used insted as the template for the
747 Signature objects generated.
749 if template is None:
750 arg_indices = range(len(test_vector.arguments))
751 template = '{0}({1})'.format(
752 name, ', '.join('{{{0}}}'.format(i) for i in arg_indices))
753 rettype = glsl_type_of(test_vector.result)
754 argtypes = tuple(glsl_type_of(arg) for arg in test_vector.arguments)
755 adjusted_glsl_version = max(
756 glsl_version, rettype.version_introduced,
757 *[t.version_introduced for t in argtypes])
758 signature = Signature(
759 name, template, adjusted_glsl_version, extension, rettype, argtypes)
760 if signature not in test_suite_dict:
761 test_suite_dict[signature] = []
762 test_suite_dict[signature].append(test_vector)
765 def _store_test_vectors(test_suite_dict, name, glsl_version, extension,
766 test_vectors, template=None):
767 """Store multiple test vectors in the appropriate places in
768 test_suite_dict.
770 If template is supplied, it is used insted as the template for the
771 Signature objects generated.
773 for test_vector in test_vectors:
774 _store_test_vector(test_suite_dict, name, glsl_version, extension,
775 test_vector, template=template)
778 def make_arguments(input_generators):
779 """Construct a list of tuples of input arguments to test.
781 input_generators is a list, the ith element of which is a sequence
782 of values that are suitable for use as the ith argument of the
783 function under test.
785 Output is a list, each element of which is a tuple of arguments to
786 be passed to the function under test. These values are produced
787 by taking the cartesian product of the input sequences.
789 In addition, this function rounds floating point inputs to 32
790 bits, so that there will be no rounding errors when the input
791 values are passed into OpenGL.
793 input_generators = [
794 [round_to_32_bits(x) for x in seq] for seq in input_generators]
795 return list(itertools.product(*input_generators))
798 def _make_componentwise_test_vectors(test_suite_dict):
799 """Add test vectors to test_suite_dict for GLSL built-in
800 functions that operate on vectors in componentwise fashion.
801 Examples include sin(), cos(), min(), max(), and clamp().
803 # Make sure atan(x) and atan(x,y) don't misbehave for very large
804 # or very small input values.
805 atan_inputs = [0.0]
806 for exponent in (-10, -1, 0, 1, 10):
807 atan_inputs.append(pow(10.0, exponent))
808 atan_inputs.append(-pow(10.0, exponent))
809 # Make a similar set of inputs for acosh(), except don't use any
810 # values < 1, since acosh() is only defined for x >= 1.
811 acosh_inputs = [1.0 + x for x in atan_inputs if x >= 0]
812 ints = [np.int32(x) for x in [-5, -2, -1, 0, 1, 2, 5]]
813 uints = [np.uint32(x) for x in [0, 1, 2, 5, 34]]
814 bools = [True, False]
816 def f(name, arity, glsl_version, python_equivalent,
817 alternate_scalar_arg_indices, test_inputs,
818 tolerance_function=_strict_tolerance,
819 extension=None):
820 """Create test vectors for the function with the given name
821 and arity, which was introduced in the given glsl_version.
823 python_equivalent is a Python function which operates on scalars,
824 and simulates the GLSL function. This function should return None
825 in any case where the output of the GLSL function is undefined.
827 If alternate_scalar_arg_indices is not None, also create test
828 vectors for an alternate vectorized version of the function,
829 in which some arguments are scalars.
830 alternate_scalar_arg_indices is a sequence of the indices of
831 the arguments which are scalars.
833 test_inputs is a list, the ith element of which is a list of
834 values that are suitable for use as the ith argument of the
835 function.
837 If tolerance_function is supplied, it is a function which
838 should be used to compute the tolerance for the test vectors.
839 Otherwise, _strict_tolerance is used.
841 scalar_test_vectors = _simulate_function(
842 make_arguments(test_inputs), python_equivalent, tolerance_function)
843 _store_test_vectors(
844 test_suite_dict, name, glsl_version, extension, scalar_test_vectors)
845 if alternate_scalar_arg_indices is None:
846 scalar_arg_indices_list = [()]
847 else:
848 scalar_arg_indices_list = [(), alternate_scalar_arg_indices]
849 for scalar_arg_indices in scalar_arg_indices_list:
850 for vector_length in (2, 3, 4):
851 _store_test_vectors(
852 test_suite_dict, name, glsl_version, extension,
853 _vectorize_test_vectors(
854 scalar_test_vectors, scalar_arg_indices,
855 vector_length))
857 f('radians', 1, 110, np.radians, None, [np.linspace(-180.0, 180.0, 4)])
858 f('degrees', 1, 110, np.degrees, None, [np.linspace(-np.pi, np.pi, 4)])
859 f('sin', 1, 110, np.sin, None, [np.linspace(-np.pi, np.pi, 4)],
860 _trig_tolerance)
861 f('cos', 1, 110, np.cos, None, [np.linspace(-np.pi, np.pi, 4)],
862 _trig_tolerance)
863 f('tan', 1, 110, np.tan, None, [np.linspace(-np.pi, np.pi, 4)],
864 _trig_tolerance)
865 f('asin', 1, 110, np.arcsin, None, [np.linspace(-1.0, 1.0, 4)],
866 _trig_tolerance)
867 f('acos', 1, 110, np.arccos, None, [np.linspace(-1.0, 1.0, 4)],
868 _trig_tolerance)
869 f('atan', 1, 110, np.arctan, None, [atan_inputs], _trig_tolerance)
870 f('atan', 2, 110, _arctan2, None, [atan_inputs, atan_inputs],
871 _trig_tolerance)
872 f('sinh', 1, 130, np.sinh, None, [np.linspace(-2.0, 2.0, 4)],
873 _trig_tolerance)
874 f('cosh', 1, 130, np.cosh, None, [np.linspace(-2.0, 2.0, 4)],
875 _trig_tolerance)
876 f('tanh', 1, 130, np.tanh, None, [np.linspace(-2.0, 2.0, 4)],
877 _trig_tolerance)
878 f('asinh', 1, 130, np.arcsinh, None, [atan_inputs], _trig_tolerance)
879 f('acosh', 1, 130, np.arccosh, None, [acosh_inputs], _trig_tolerance)
880 f('atanh', 1, 130, np.arctanh, None, [np.linspace(-0.99, 0.99, 4)],
881 _trig_tolerance)
882 f('pow', 2, 110, _pow, None, [np.linspace(0.0, 2.0, 4),
883 np.linspace(-2.0, 2.0, 4)])
884 f('exp', 1, 110, np.exp, None, [np.linspace(-2.0, 2.0, 4)])
885 f('log', 1, 110, np.log, None, [np.linspace(0.01, 2.0, 4)])
886 f('exp2', 1, 110, _exp2, None, [np.linspace(-2.0, 2.0, 4)])
887 f('log2', 1, 110, np.log2, None, [np.linspace(0.01, 2.0, 4)])
888 f('sqrt', 1, 110, np.sqrt, None, [np.linspace(0.0, 2.0, 4)])
889 f('inversesqrt', 1, 110, lambda x: 1.0/np.sqrt(x), None,
890 [np.linspace(0.1, 2.0, 4)])
891 f('abs', 1, 110, np.abs, None, [np.linspace(-1.5, 1.5, 5)])
892 f('abs', 1, 130, np.abs, None, [ints])
893 f('sign', 1, 110, np.sign, None, [np.linspace(-1.5, 1.5, 5)])
894 f('sign', 1, 130, np.sign, None, [ints])
895 f('floor', 1, 110, np.floor, None, [np.linspace(-2.0, 2.0, 4)])
897 # Note: with trunc we want to test values in which the floating
898 # point exponent is < 0, > 23 or in the middle. Hence, we append
899 # some numbers to cover all possible scenarios. In addition, we
900 # want to check bitsize barriers (> 32, > 64, etc.) in case the
901 # conversion is done with a cast to and from another int based
902 # type.
903 f('trunc', 1, 130, _trunc, None,
904 [np.append(np.linspace(-2.0, 2.0, 8),
905 [0.0, 45027112.0, -45027112.0,
906 1.9584199e10, -1.9584199e10,
907 4.5027112e19, -4.5027112e19])])
909 # Note: the direction of rounding used by round() is not specified
910 # for half-integer values, so we test it over a range that doesn't
911 # include exact half-integer values. roundEven() is required to
912 # round half-integer values to the nearest even integer, so we
913 # test it over a range that does include exact half-integer
914 # values. In both cases, we can use numpy's round() function,
915 # because it rounds half-integer values to even, and all other
916 # values to nearest.
917 f('round', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 8)])
918 f('roundEven', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 25)])
920 f('ceil', 1, 110, np.ceil, None, [np.linspace(-2.0, 2.0, 4)])
921 f('fract', 1, 110, lambda x: x-np.floor(x), None,
922 [np.linspace(-2.0, 2.0, 4)])
923 f('mod', 2, 110, lambda x, y: x-y*np.floor(x/y), [1],
924 [np.linspace(-1.9, 1.9, 4), np.linspace(-2.0, 2.0, 4)])
925 f('min', 2, 110, min, [1],
926 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
927 f('min', 2, 130, min, [1], [ints, ints])
928 f('min', 2, 130, min, [1], [uints, uints])
929 f('max', 2, 110, max, [1],
930 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
931 f('max', 2, 130, max, [1], [ints, ints])
932 f('max', 2, 130, max, [1], [uints, uints])
933 f('min3', 2, 110, min, None,
934 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
935 np.linspace(-2.0, 2.0, 4)],
936 extension="AMD_shader_trinary_minmax")
937 f('min3', 2, 130, min, None, [ints, ints, ints],
938 extension="AMD_shader_trinary_minmax")
939 f('min3', 2, 130, min, None, [uints, uints, uints],
940 extension="AMD_shader_trinary_minmax")
941 f('max3', 2, 110, max, None,
942 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
943 np.linspace(-2.0, 2.0, 4)],
944 extension="AMD_shader_trinary_minmax")
945 f('max3', 2, 130, max, None, [ints, ints, ints],
946 extension="AMD_shader_trinary_minmax")
947 f('max3', 2, 130, max, None, [uints, uints, uints],
948 extension="AMD_shader_trinary_minmax")
949 f('mid3', 2, 110, _mid3, None,
950 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
951 np.linspace(-2.0, 2.0, 4)],
952 extension="AMD_shader_trinary_minmax")
953 f('mid3', 2, 130, _mid3, None, [ints, ints, ints],
954 extension="AMD_shader_trinary_minmax")
955 f('mid3', 2, 130, _mid3, None, [uints, uints, uints],
956 extension="AMD_shader_trinary_minmax")
957 f('clamp', 3, 110, _clamp, [1, 2], [np.linspace(-2.0, 2.0, 4),
958 np.linspace(-1.5, 1.5, 3), np.linspace(-1.5, 1.5, 3)])
959 f('clamp', 3, 130, _clamp, [1, 2], [ints, ints, ints])
960 f('clamp', 3, 130, _clamp, [1, 2], [uints, uints, uints])
961 f('mix', 3, 110, lambda x, y, a: x*(1-a)+y*a, [2],
962 [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2),
963 np.linspace(0.0, 1.0, 4)])
964 f('mix', 3, 130, lambda x, y, a: y if a else x, None,
965 [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2), bools])
966 f('step', 2, 110, lambda edge, x: 0.0 if x < edge else 1.0, [0],
967 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
968 f('smoothstep', 3, 110, _smoothstep, [0, 1],
969 [np.linspace(-1.9, 1.9, 4), np.linspace(-1.9, 1.9, 4),
970 np.linspace(-2.0, 2.0, 4)])
972 f('abs', 1, 150, np.abs, None, [np.linspace(-10, 15, 54).astype(np.int64)],
973 extension="ARB_gpu_shader_int64")
974 f('sign', 1, 150, np.sign, None, [np.linspace(-15, 15, 5).astype(np.int64)],
975 extension="ARB_gpu_shader_int64")
976 f('min', 2, 150, min, [1],
977 [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)],
978 extension="ARB_gpu_shader_int64")
979 f('min', 2, 150, min, [1],
980 [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)],
981 extension="ARB_gpu_shader_int64")
982 f('max', 2, 150, max, [1],
983 [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)],
984 extension="ARB_gpu_shader_int64")
985 f('max', 2, 150, max, [1],
986 [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)],
987 extension="ARB_gpu_shader_int64")
988 f('clamp', 3, 150, _clamp, [1, 2], [np.linspace(-20, 20, 4).astype(np.int64),
989 np.linspace(-15, 15, 3).astype(np.int64),
990 np.linspace(-15, 15, 3).astype(np.int64)],
991 extension="ARB_gpu_shader_int64")
992 f('mix', 3, 150, lambda x, y, a: y if a else x, None,
993 [np.linspace(-20, 20, 2).astype(np.int64), np.linspace(-30, 30, 2).astype(np.int64), bools],
994 extension="ARB_gpu_shader_int64")
995 _make_componentwise_test_vectors(test_suite)
998 def _make_vector_relational_test_vectors(test_suite_dict):
999 """Add test vectors to test_suite_dict for GLSL built-in functions
1000 that operate on vectors of floats, ints, or bools, but not on
1001 single floats, ints, or bools. Examples include lessThan(),
1002 equal(), and not().
1004 _default_inputs = {
1005 'v': np.linspace(-1.5, 1.5, 4),
1006 'i': np.array([-5, -2, -1, 0, 1, 2, 5], dtype=np.int32),
1007 'u': np.array([0, 1, 2, 5, 34], dtype=np.uint32),
1008 'b': np.array([False, True])
1011 def f(name, arity, glsl_version, python_equivalent, arg_types,
1012 tolerance_function=_strict_tolerance,
1013 extension=None):
1014 """Make test vectors for the function with the given name and
1015 arity, which was introduced in the given glsl_version.
1017 python_equivalent is a Python function which operates on scalars,
1018 and simulates the GLSL function.
1020 arg_types is a string containing 'v' if the function supports
1021 standard "vec" inputs, 'i' if it supports "ivec" inputs, and 'b'
1022 if it supports "bvec" inputs. The output type of the function is
1023 assumed to be the same as its input type.
1025 If tolerance_function is supplied, it is a function which
1026 should be used to compute the tolerance for the test vectors.
1027 Otherwise, _strict_tolerance is used.
1029 for arg_type in arg_types:
1030 test_inputs = [_default_inputs[arg_type]]*arity
1031 scalar_test_vectors = _simulate_function(
1032 make_arguments(test_inputs), python_equivalent,
1033 tolerance_function)
1034 for vector_length in (2, 3, 4):
1035 _store_test_vectors(
1036 test_suite_dict, name, glsl_version, extension,
1037 _vectorize_test_vectors(
1038 scalar_test_vectors, (), vector_length))
1040 f('lessThan', 2, 110, lambda x, y: x < y, 'viu')
1041 f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'viu')
1042 f('greaterThan', 2, 110, lambda x, y: x > y, 'viu')
1043 f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'viu')
1044 f('equal', 2, 110, lambda x, y: x == y, 'viub')
1045 f('notEqual', 2, 110, lambda x, y: x != y, 'viub')
1046 f('not', 1, 110, lambda x: not x, 'b')
1047 _make_vector_relational_test_vectors(test_suite)
1050 def _make_vector_or_matrix_test_vectors(test_suite_dict):
1051 """Add test vectors to test_suite_dict for GLSL built-in functions
1052 that operate on vectors/matrices as a whole. Examples include
1053 length(), dot(), cross(), normalize(), and refract().
1055 def match_args(*indices):
1056 """Return a function that determines whether the type of the
1057 arguments at the given indices match.
1059 For example:
1061 match(1, 3)
1063 is equivalent to:
1065 lambda a, b, c, d: glsl_type_of(b) == glsl_type_of(d)
1067 return lambda *args: _argument_types_match(args, indices)
1069 def match_simple_binop(x, y):
1070 """Detemine whether the type of the arguments is compatible
1071 for a simple binary operator (such as '+').
1073 Arguments are compatible if one is a scalar and the other is a
1074 vector/matrix with the same base type, or if they are the same
1075 type.
1077 x_type = glsl_type_of(x)
1078 y_type = glsl_type_of(y)
1079 if x_type.base_type != y_type.base_type:
1080 return False
1081 if x_type.is_scalar or y_type.is_scalar:
1082 return True
1083 return x_type == y_type
1085 def match_multiply(x, y):
1086 """Determine whether the type of the arguments is compatible
1087 for multiply.
1089 Arguments are compatible if they are scalars, vectors, or
1090 matrices with the same base type, and the vector/matrix sizes
1091 are properly matched.
1093 x_type = glsl_type_of(x)
1094 y_type = glsl_type_of(y)
1095 if x_type.base_type != y_type.base_type:
1096 return False
1097 if x_type.is_scalar or y_type.is_scalar:
1098 return True
1099 if x_type.is_vector and y_type.is_matrix:
1100 # When multiplying vector * matrix, the vector is
1101 # transposed to a row vector. So its row count must match
1102 # the row count of the matrix.
1103 return x_type.num_rows == y_type.num_rows
1104 elif x_type.is_vector:
1105 assert y_type.is_vector
1106 # When multiplying vector * vector, the multiplication is
1107 # done componentwise, so the types must match exactly.
1108 return x_type == y_type
1109 else:
1110 assert x_type.is_matrix
1111 # When multiplying matrix * matrix or matrix * vector, a
1112 # standard linear algebraic multiply is used, so x's
1113 # column count must match y's row count.
1114 return x_type.num_cols == y_type.num_rows
1116 def match_shift(x, y):
1117 """Determine whether the type of the arguments is compatible
1118 for shift operations.
1120 Arguments are compatible if they are the same length or the
1121 first one is a vector and the second is a scalar. Their base
1122 types need not be the same, but they both must be integral.
1124 x_type = glsl_type_of(x)
1125 y_type = glsl_type_of(y)
1126 if x_type.base_type not in (glsl_int, glsl_uint, glsl_int64_t, glsl_uint64_t):
1127 return False
1128 if y_type.base_type not in (glsl_int, glsl_uint):
1129 return False
1130 if y_type.is_scalar:
1131 return True
1132 assert not x_type.is_matrix
1133 assert not y_type.is_matrix
1134 return x_type.num_rows == y_type.num_rows
1136 def match_assignment_operators(x, y):
1137 """ Determine when scalar and matrix arithmetic works
1139 A matrix and a scalar can be combined, but only when being assigned
1140 into a large enough type.
1143 x_type = glsl_type_of(x)
1144 y_type = glsl_type_of(y)
1145 if x_type.base_type != y_type.base_type:
1146 return False
1147 if y_type.is_scalar:
1148 return True
1149 return x_type == y_type
1151 def match_assignment_multiply(x, y):
1152 """Determine whether the type of the arguments is compatible
1153 for multiply.
1155 Arguments are compatible if they are scalars, vectors, or
1156 matrices with the same base type, and the vector/matrix sizes
1157 are properly matched, and that y is scalar
1159 x_type = glsl_type_of(x)
1160 y_type = glsl_type_of(y)
1161 if x_type.base_type != y_type.base_type:
1162 return False
1163 if y_type.is_scalar:
1164 return True
1165 if x_type.is_scalar:
1166 return False
1167 if x_type.is_vector and y_type.is_matrix:
1168 # When multiplying vector * matrix, the vector is
1169 # transposed to a row vector. So its row count must match
1170 # the row count of the matrix.
1171 return x_type.num_rows == y_type.num_rows == y_type.num_cols
1172 elif x_type.is_vector:
1173 assert y_type.is_vector
1174 # When multiplying vector * vector, the multiplication is
1175 # done componentwise, so the types must match exactly.
1176 return x_type == y_type
1177 else:
1178 assert x_type.is_matrix
1179 # When multiplying matrix * matrix or matrix * vector, a
1180 # standard linear algebraic multiply is used, so x's
1181 # column count must match y's row count.
1182 return (x_type.num_cols == y_type.num_rows and
1183 x_type.num_cols == y_type.num_cols)
1185 bools = [False, True]
1186 bvecs = [np.array(bs) for bs in itertools.product(bools, bools)] + \
1187 [np.array(bs) for bs in itertools.product(bools, bools, bools)] + \
1188 [np.array(bs) for bs in itertools.product(bools, bools, bools, bools)]
1189 ints = [np.int32(x) for x in [12, -6, 76, -32, 0]]
1190 small_ints = \
1191 [np.int32(x) for x in [-31, -25, -5, -2, -1, 0, 1, 2, 5, 25, 31]]
1192 ivecs = [
1193 np.array([38, 35], dtype=np.int32),
1194 np.array([64, -9], dtype=np.int32),
1195 np.array([64, 9], dtype=np.int32),
1196 np.array([-36, 32, -88], dtype=np.int32),
1197 np.array([36, 32, 88], dtype=np.int32),
1198 np.array([59, 77, 68], dtype=np.int32),
1199 np.array([-64, 72, 88, -76], dtype=np.int32),
1200 np.array([64, 72, 88, 76], dtype=np.int32),
1201 np.array([-24, 40, -23, 64], dtype=np.int32),
1202 np.array([24, 40, 23, 64], dtype=np.int32),
1204 small_ivecs = [
1205 np.array([13, 26], dtype=np.int32),
1206 np.array([-2, 26], dtype=np.int32),
1207 np.array([2, 26], dtype=np.int32),
1208 np.array([22, -23, 4], dtype=np.int32),
1209 np.array([22, 23, 4], dtype=np.int32),
1210 np.array([-19, 1, -13], dtype=np.int32),
1211 np.array([19, 1, 13], dtype=np.int32),
1212 np.array([16, 24, -23, -25], dtype=np.int32),
1213 np.array([16, 24, 23, 25], dtype=np.int32),
1214 np.array([-23, -12, 14, 19], dtype=np.int32),
1215 np.array([23, 12, 14, 19], dtype=np.int32),
1217 uints = [np.uint32(x) for x in [0, 6, 12, 32, 74]]
1218 small_uints = [np.uint32(x) for x in [0, 1, 2, 5, 25, 31]]
1219 large_uints = [np.uint32(x) for x in [0xdeadbeef, 0xaffeaffe, 0xbadbad]]
1220 uvecs = [
1221 np.array([38, 35], dtype=np.uint32),
1222 np.array([64, 9], dtype=np.uint32),
1223 np.array([36, 32, 88], dtype=np.uint32),
1224 np.array([59, 77, 68], dtype=np.uint32),
1225 np.array([66, 72, 87, 75], dtype=np.uint32),
1226 np.array([24, 40, 23, 74], dtype=np.uint32)
1228 small_uvecs = [
1229 np.array([13, 26], dtype=np.uint32),
1230 np.array([2, 26], dtype=np.uint32),
1231 np.array([22, 23, 4], dtype=np.uint32),
1232 np.array([19, 1, 13], dtype=np.uint32),
1233 np.array([16, 24, 23, 25], dtype=np.uint32),
1234 np.array([23, 12, 14, 19], dtype=np.uint32),
1236 nz_floats = [-1.33, 0.85]
1237 floats = [0.0] + nz_floats
1238 vecs = [
1239 np.array([-0.10, -1.20]),
1240 np.array([-0.42, 0.48]),
1241 np.array([-0.03, -0.85, -0.94]),
1242 np.array([1.67, 0.66, 1.87]),
1243 np.array([-1.65, 1.33, 1.93, 0.76]),
1244 np.array([0.80, -0.15, -0.51, 0.0])
1246 nz_floats_vecs = nz_floats + vecs
1247 vec3s = [
1248 np.array([-0.03, -0.85, -0.94]),
1249 np.array([1.67, 0.66, 1.87]),
1251 norm_floats_vecs = [_normalize(x) for x in nz_floats_vecs]
1252 squaremats = [
1253 np.array([[ 1.60, 0.76],
1254 [ 1.53, -1.00]]), # mat2
1255 np.array([[-0.13, -0.87],
1256 [-1.40, 1.40]]), # mat2
1257 np.array([[-1.11, 1.67, -0.41],
1258 [ 0.13, 1.09, -0.02],
1259 [ 0.56, 0.95, 0.24]]), # mat3
1260 np.array([[-1.69, -0.46, -0.18],
1261 [-1.09, 1.75, 2.00],
1262 [-1.53, -0.70, -1.47]]), # mat3
1263 np.array([[-1.00, -0.55, -1.08, 1.79],
1264 [ 1.77, 0.62, 0.48, -1.35],
1265 [ 0.09, -0.71, -1.39, -1.21],
1266 [-0.91, -1.82, -1.43, 0.72]]), # mat4
1267 np.array([[ 0.06, 1.31, 1.52, -1.96],
1268 [ 1.60, -0.32, 0.51, -1.84],
1269 [ 1.25, 0.45, 1.90, -0.72],
1270 [-0.16, 0.45, -0.88, 0.39]]), # mat4
1272 mats = squaremats + [
1273 np.array([[ 0.09, 1.30, 1.25],
1274 [-1.19, 0.08, 1.08]]), # mat3x2
1275 np.array([[-0.36, -1.08, -0.60],
1276 [-0.53, 0.88, -1.79]]), # mat3x2
1277 np.array([[-0.46, 1.94],
1278 [-0.45, -0.75],
1279 [ 1.03, -0.50]]), # mat2x3
1280 np.array([[ 1.38, -1.08],
1281 [-1.27, 1.83],
1282 [ 1.00, -0.74]]), # mat2x3
1283 np.array([[ 1.81, -0.87, 0.81, 0.65],
1284 [-1.16, -1.52, 0.25, -1.51]]), # mat4x2
1285 np.array([[ 1.93, -1.63, 0.29, 1.60],
1286 [ 0.49, 0.27, 0.14, 0.94]]), # mat4x2
1287 np.array([[ 0.16, -1.69],
1288 [-0.80, 0.59],
1289 [-1.74, -1.43],
1290 [-0.02, -1.21]]), # mat2x4
1291 np.array([[-1.02, 0.74],
1292 [-1.64, -0.13],
1293 [-1.59, 0.47],
1294 [ 0.30, 1.13]]), # mat2x4
1295 np.array([[-0.27, -1.38, -1.41, -0.12],
1296 [-0.17, -0.56, 1.47, 1.86],
1297 [-1.85, -1.29, 1.77, 0.01]]), # mat4x3
1298 np.array([[-0.47, -0.15, 1.97, -1.05],
1299 [-0.20, 0.53, -1.82, -1.41],
1300 [-1.39, -0.19, 1.62, 1.58]]), # mat4x3
1301 np.array([[ 1.42, -0.86, 0.27],
1302 [ 1.80, -1.74, 0.04],
1303 [-1.88, -0.37, 0.43],
1304 [ 1.37, 1.90, 0.71]]), # mat3x4
1305 np.array([[-1.72, 0.09, 0.45],
1306 [-0.31, -1.58, 1.92],
1307 [ 0.14, 0.18, -0.56],
1308 [ 0.40, -0.77, 1.76]]), # mat3x4
1311 int64s = [np.int64(x) for x in [
1314 -1192,
1315 1048576,
1316 4251475,
1317 29852643761,
1318 -4398046511104,
1319 -3948976685146,
1320 -135763469567146206]]
1321 uint64s = [np.uint64(x) for x in [
1324 1192,
1325 1048576,
1326 4251475,
1327 29852643761,
1328 4398046511104,
1329 3948976685146,
1330 135763469567146206,
1331 11654173250180970009]]
1333 int64vecs = [
1334 np.array([-10, -12], dtype=np.int64),
1335 np.array([-42, 48], dtype=np.int64),
1336 np.array([-1333333333333333259, 85, 94], dtype=np.int64),
1337 np.array([167, 66, 187], dtype=np.int64),
1338 np.array([165, 133, 193, 76], dtype=np.int64),
1339 np.array([80, -15, -51, 0], dtype=np.int64)
1341 int64_i64vecs = int64s + int64vecs
1342 i64vec3s = [
1343 np.array([-3, -85, -94], dtype=np.int64),
1344 np.array([ 1333333333333333259, 66, 87], dtype=np.int64),
1347 uint64vecs = [
1348 np.array([10, 12], dtype=np.uint64),
1349 np.array([42, 48], dtype=np.uint64),
1350 np.array([1333333333333333259, 85, 94], dtype=np.uint64),
1351 np.array([167, 66, 187], dtype=np.uint64),
1352 np.array([165, 133, 193, 76], dtype=np.uint64),
1353 np.array([80, 15, 51, 0], dtype=np.uint64)
1355 uint64_u64vecs = uint64s + uint64vecs
1356 u64vec3s = [
1357 np.array([3, 85, 94], dtype=np.uint64),
1358 np.array([ 1333333333333333259, 66, 87], dtype=np.uint64),
1361 def f(name, arity, glsl_version, python_equivalent,
1362 filter, test_inputs, tolerance_function=_strict_tolerance,
1363 template=None,
1364 extension=None):
1365 """Make test vectors for the function with the given name and
1366 arity, which was introduced in the given glsl_version.
1368 python_equivalent is a Python function which simulates the GLSL
1369 function. This function should return None in any case where the
1370 output of the GLSL function is undefined. However, it need not
1371 check that the lengths of the input vectors are all the same.
1373 If filter is not None, it will be called with each set of
1374 arguments, and test cases will only be generated if the filter
1375 returns True.
1377 test_inputs is a list, the ith element of which is a list of
1378 vectors and/or scalars that are suitable for use as the ith
1379 argument of the function.
1381 If tolerance_function is supplied, it is a function which
1382 should be used to compute the tolerance for the test vectors.
1383 Otherwise, _strict_tolerance is used.
1385 If template is supplied, it is used insted as the template for
1386 the Signature objects generated.
1388 test_inputs = make_arguments(test_inputs)
1389 if filter is not None:
1390 test_inputs = \
1391 [arguments for arguments in test_inputs if filter(*arguments)]
1392 _store_test_vectors(
1393 test_suite_dict, name, glsl_version, extension,
1394 _simulate_function(
1395 test_inputs, python_equivalent, tolerance_function),
1396 template=template)
1398 f('op-assign-add', 2, 110, lambda x, y: x + y, match_assignment_operators,
1399 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1400 floats+vecs+mats+ints+ivecs+uints+uvecs],
1401 template='{0};\n result += {1}')
1402 # This can generate an overflow warning, this is expected
1403 with warnings.catch_warnings():
1404 warnings.simplefilter('ignore', RuntimeWarning)
1405 f('op-assign-sub', 2, 110,
1406 lambda x, y: x - y, match_assignment_operators,
1407 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1408 floats+vecs+mats+ints+ivecs+uints+uvecs],
1409 template='{0};\n result -= {1}')
1410 f('op-assign-mult', 2, 110, _multiply, match_assignment_multiply,
1411 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1412 floats+vecs+mats+ints+ivecs+uints+uvecs],
1413 template='{0};\n result *= {1}')
1414 f('op-assign-div', 2, 110, _divide, match_assignment_operators,
1415 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1416 floats+vecs+mats+ints+ivecs+uints+uvecs],
1417 template='{0};\n result /= {1}')
1418 f('op-assign-div-large', 2, 130, _divide, match_assignment_operators,
1419 [large_uints, large_uints+small_uints],
1420 template='{0};\n result /= {1}')
1421 f('op-assign-mod', 2, 130, _modulus, match_assignment_operators,
1422 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1423 template='{0};\n result %= {1}')
1424 f('op-assign-bitand', 2, 130, lambda x, y: x & y,
1425 match_assignment_operators,
1426 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1427 template='{0}; result &= {1}')
1428 f('op-assign-bitor', 2, 130, lambda x, y: x | y,
1429 match_assignment_operators,
1430 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1431 template='{0};\n result |= {1}')
1432 f('op-assign-bitxor', 2, 130, lambda x, y: x ^ y,
1433 match_assignment_operators,
1434 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1435 template='{0};\n result ^= {1}')
1436 f('op-assign-lshift', 2, 130, _lshift, match_shift,
1437 [small_ints+small_ivecs+small_uints+small_uvecs,
1438 small_ints+small_ivecs+small_uints+small_uvecs],
1439 template='{0}; result <<= {1}')
1440 f('op-assign-rshift', 2, 130, _rshift, match_shift,
1441 [small_ints+small_ivecs+small_uints+small_uvecs,
1442 small_ints+small_ivecs+small_uints+small_uvecs],
1443 template='{0}; result >>= {1}')
1444 f('op-add', 2, 110, lambda x, y: x + y, match_simple_binop,
1445 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1446 floats+vecs+mats+ints+ivecs+uints+uvecs],
1447 template='({0} + {1})')
1448 # This can generate an overflow warning, this is expected
1449 with warnings.catch_warnings():
1450 warnings.simplefilter('ignore', RuntimeWarning)
1451 f('op-sub', 2, 110, lambda x, y: x - y, match_simple_binop,
1452 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1453 floats+vecs+mats+ints+ivecs+uints+uvecs],
1454 template='({0} - {1})')
1455 f('op-mult', 2, 110, _multiply, match_multiply,
1456 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1457 floats+vecs+mats+ints+ivecs+uints+uvecs],
1458 template='({0} * {1})')
1459 f('op-div', 2, 110, _divide, match_simple_binop,
1460 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1461 floats+vecs+mats+ints+ivecs+uints+uvecs],
1462 template='({0} / {1})')
1463 f('op-div-large', 2, 130, _divide, match_simple_binop,
1464 [large_uints, large_uints+small_uints], template='({0} / {1})')
1465 f('op-mod', 2, 130, _modulus, match_simple_binop,
1466 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], template='({0} % {1})')
1467 f('op-uplus', 1, 110, lambda x: +x, None,
1468 [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(+ {0})')
1469 f('op-neg', 1, 110, lambda x: -x, None,
1470 [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(- {0})')
1471 f('op-gt', 2, 110, lambda x, y: x > y, match_args(0, 1),
1472 [ints+uints+floats, ints+uints+floats], template='({0} > {1})')
1473 f('op-lt', 2, 110, lambda x, y: x < y, match_args(0, 1),
1474 [ints+uints+floats, ints+uints+floats], template='({0} < {1})')
1475 f('op-ge', 2, 110, lambda x, y: x >= y, match_args(0, 1),
1476 [ints+uints+floats, ints+uints+floats], template='({0} >= {1})')
1477 f('op-le', 2, 110, lambda x, y: x <= y, match_args(0, 1),
1478 [ints+uints+floats, ints+uints+floats], template='({0} <= {1})')
1479 f('op-eq', 2, 110, _equal, match_args(0, 1),
1480 [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1481 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1482 template='({0} == {1})')
1483 f('op-ne', 2, 110, _not_equal, match_args(0, 1),
1484 [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1485 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1486 template='({0} != {1})')
1487 f('op-and', 2, 110, lambda x, y: x and y, None, [bools, bools],
1488 template='({0} && {1})')
1489 f('op-or', 2, 110, lambda x, y: x or y, None, [bools, bools],
1490 template='({0} || {1})')
1491 f('op-xor', 2, 110, lambda x, y: x != y, None, [bools, bools],
1492 template='({0} ^^ {1})')
1493 f('op-not', 1, 110, lambda x: not x, None, [bools], template='(! {0})')
1494 f('op-selection', 3, 110, lambda x, y, z: y if x else z, match_args(1, 2),
1495 [bools, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1496 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1497 template='({0} ? {1} : {2})')
1498 f('op-complement', 1, 130, lambda x: ~x, None, [ints+ivecs+uints+uvecs],
1499 template='(~ {0})')
1500 f('op-lshift', 2, 130, _lshift, match_shift,
1501 [small_ints+small_ivecs+small_uints+small_uvecs,
1502 small_ints+small_ivecs+small_uints+small_uvecs],
1503 template='({0} << {1})')
1504 f('op-rshift', 2, 130, _rshift, match_shift,
1505 [small_ints+small_ivecs+small_uints+small_uvecs,
1506 small_ints+small_ivecs+small_uints+small_uvecs],
1507 template='({0} >> {1})')
1508 f('op-bitand', 2, 130, lambda x, y: x & y, match_simple_binop,
1509 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1510 template='({0} & {1})')
1511 f('op-bitor', 2, 130, lambda x, y: x | y, match_simple_binop,
1512 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1513 template='({0} | {1})')
1514 f('op-bitxor', 2, 130, lambda x, y: x ^ y, match_simple_binop,
1515 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1516 template='({0} ^ {1})')
1517 f('op-bitand-neg', 2, 130, lambda x, y: x & (-y), match_simple_binop,
1518 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1519 template='({0} & (- {1}))')
1520 f('op-bitand-not', 2, 130, lambda x, y: x & (~y), match_simple_binop,
1521 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1522 template='({0} & (~ {1}))')
1523 f('op-bitor-neg', 2, 130, lambda x, y: x | (-y), match_simple_binop,
1524 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1525 template='({0} | (- {1}))')
1526 f('op-bitor-not', 2, 130, lambda x, y: x | (~y), match_simple_binop,
1527 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1528 template='({0} | (~ {1}))')
1529 f('op-bitxor-neg', 2, 130, lambda x, y: x ^ (-y), match_simple_binop,
1530 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1531 template='({0} ^ (- {1}))')
1532 f('op-bitxor-not', 2, 130, lambda x, y: x ^ (~y), match_simple_binop,
1533 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1534 template='({0} ^ (~ {1}))')
1535 f('op-bitand-neg-abs', 2, 130, lambda x, y: x & (-abs(y)), match_simple_binop,
1536 [ints+ivecs, ints+ivecs],
1537 template='({0} & (- abs({1})))')
1538 f('op-bitand-not-abs', 2, 130, lambda x, y: x & (~abs(y)), match_simple_binop,
1539 [ints+ivecs, ints+ivecs],
1540 template='({0} & (~ abs({1})))')
1541 f('op-bitor-neg-abs', 2, 130, lambda x, y: x | (-abs(y)), match_simple_binop,
1542 [ints+ivecs, ints+ivecs],
1543 template='({0} | (- abs({1})))')
1544 f('op-bitor-not-abs', 2, 130, lambda x, y: x | (~abs(y)), match_simple_binop,
1545 [ints+ivecs, ints+ivecs],
1546 template='({0} | (~ abs({1})))')
1547 f('op-bitxor-neg-abs', 2, 130, lambda x, y: x ^ (-abs(y)), match_simple_binop,
1548 [ints+ivecs, ints+ivecs],
1549 template='({0} ^ (- abs({1})))')
1550 f('op-bitxor-not-abs', 2, 130, lambda x, y: x ^ (~abs(y)), match_simple_binop,
1551 [ints+ivecs, ints+ivecs],
1552 template='({0} ^ (~ abs({1})))')
1553 f('op-bitand-abs-neg', 2, 130, lambda x, y: x & abs(-y), match_simple_binop,
1554 [ints+ivecs, ints+ivecs],
1555 template='({0} & abs(- {1}))')
1556 f('op-bitand-abs-not', 2, 130, lambda x, y: x & abs(~y), match_simple_binop,
1557 [ints+ivecs, ints+ivecs],
1558 template='({0} & abs(~ {1}))')
1559 f('op-bitor-abs-neg', 2, 130, lambda x, y: x | abs(-y), match_simple_binop,
1560 [ints+ivecs, ints+ivecs],
1561 template='({0} | abs(- {1}))')
1562 f('op-bitor-abs-not', 2, 130, lambda x, y: x | abs(~y), match_simple_binop,
1563 [ints+ivecs, ints+ivecs],
1564 template='({0} | abs(~ {1}))')
1565 f('op-bitxor-abs-neg', 2, 130, lambda x, y: x ^ abs(-y), match_simple_binop,
1566 [ints+ivecs, ints+ivecs],
1567 template='({0} ^ abs(- {1}))')
1568 f('op-bitxor-abs-not', 2, 130, lambda x, y: x ^ abs(~y), match_simple_binop,
1569 [ints+ivecs, ints+ivecs],
1570 template='({0} ^ abs(~ {1}))')
1571 f('length', 1, 110, np.linalg.norm, None, [floats+vecs])
1572 f('distance', 2, 110, lambda x, y: np.linalg.norm(x-y), match_args(0, 1),
1573 [floats+vecs, floats+vecs])
1574 f('dot', 2, 110, np.dot, match_args(0, 1), [floats+vecs, floats+vecs])
1575 f('cross', 2, 110, np.cross, match_args(0, 1), [vec3s, vec3s],
1576 _cross_product_tolerance)
1577 f('normalize', 1, 110, _normalize, None, [nz_floats_vecs])
1578 f('faceforward', 3, 110, _faceforward, match_args(0, 1, 2),
1579 [floats+vecs, floats+vecs, floats+vecs])
1580 f('reflect', 2, 110, _reflect, match_args(0, 1),
1581 [floats+vecs, norm_floats_vecs])
1582 f('refract', 3, 110, _refract, match_args(0, 1),
1583 [norm_floats_vecs, norm_floats_vecs, [0.5, 2.0]])
1585 # Note: technically matrixCompMult operates componentwise.
1586 # However, since it is the only componentwise function to operate
1587 # on matrices, it is easier to generate test cases for it here
1588 # than to add matrix support to _make_componentwise_test_vectors.
1589 f('matrixCompMult', 2, 110, lambda x, y: x*y, match_args(0, 1),
1590 [mats, mats])
1592 f('outerProduct', 2, 120, np.outer, None, [vecs, vecs])
1593 f('transpose', 1, 120, np.transpose, None, [mats])
1594 f('any', 1, 110, any, None, [bvecs])
1595 f('all', 1, 110, all, None, [bvecs])
1597 f('inverse', 1, 140, np.linalg.inv, None, [squaremats])
1599 f('determinant', 1, 150, np.linalg.det, None, [squaremats])
1601 f('op-add', 2, 150, lambda x, y: x + y, match_simple_binop,
1602 [int64s+int64vecs+uint64s+uint64vecs,
1603 int64s+int64vecs+uint64s+uint64vecs],
1604 template='({0} + {1})',
1605 extension="ARB_gpu_shader_int64")
1606 with warnings.catch_warnings():
1607 warnings.simplefilter('ignore', RuntimeWarning)
1608 f('op-sub', 2, 150, lambda x, y: x - y, match_simple_binop,
1609 [int64s+int64vecs+uint64s+uint64vecs,
1610 int64s+int64vecs+uint64s+uint64vecs],
1611 template='({0} - {1})',
1612 extension="ARB_gpu_shader_int64")
1613 f('op-mult', 2, 150, _multiply, match_multiply,
1614 [int64s+int64vecs+uint64s+uint64vecs,
1615 int64s+int64vecs+uint64s+uint64vecs],
1616 template='({0} * {1})',
1617 extension="ARB_gpu_shader_int64")
1618 f('op-div', 2, 150, _divide, match_simple_binop,
1619 [int64s+int64vecs+uint64s+uint64vecs,
1620 int64s+int64vecs+uint64s+uint64vecs],
1621 template='({0} / {1})',
1622 extension="ARB_gpu_shader_int64")
1623 f('op-mod', 2, 150, _modulus, match_simple_binop,
1624 [int64s+int64vecs+uint64s+uint64vecs,
1625 int64s+int64vecs+uint64s+uint64vecs],
1626 template='({0} % {1})',
1627 extension="ARB_gpu_shader_int64")
1628 f('op-gt', 2, 150, lambda x, y: x > y, match_args(0, 1),
1629 [int64s+uint64s,
1630 int64s+uint64s],
1631 template = '({0} > {1})',
1632 extension="ARB_gpu_shader_int64")
1633 f('op-lt', 2, 150, lambda x, y: x < y, match_args(0, 1),
1634 [int64s+uint64s,
1635 int64s+uint64s],
1636 template = '({0} < {1})',
1637 extension="ARB_gpu_shader_int64")
1638 f('op-ge', 2, 150, lambda x, y: x >= y, match_args(0, 1),
1639 [int64s+uint64s,
1640 int64s+uint64s],
1641 template = '({0} >= {1})',
1642 extension="ARB_gpu_shader_int64")
1643 f('op-le', 2, 150, lambda x, y: x <= y, match_args(0, 1),
1644 [int64s+uint64s,
1645 int64s+uint64s],
1646 template = '({0} <= {1})',
1647 extension="ARB_gpu_shader_int64")
1648 f('op-eq', 2, 150, lambda x, y: x == y, match_args(0, 1),
1649 [int64s+uint64s,
1650 int64s+uint64s],
1651 template = '({0} == {1})',
1652 extension="ARB_gpu_shader_int64")
1653 f('op-ne', 2, 150, lambda x, y: x != y, match_args(0, 1),
1654 [int64s+uint64s,
1655 int64s+uint64s],
1656 template = '({0} != {1})',
1657 extension="ARB_gpu_shader_int64")
1658 f('op-bitand', 2, 150, lambda x, y: x & y, match_simple_binop,
1659 [int64s+uint64s, int64s+uint64s],
1660 template='({0} & {1})',
1661 extension="ARB_gpu_shader_int64")
1662 f('op-bitor', 2, 150, lambda x, y: x | y, match_simple_binop,
1663 [int64s+uint64s, int64s+uint64s],
1664 template='({0} | {1})',
1665 extension="ARB_gpu_shader_int64")
1666 f('op-bitxor', 2, 150, lambda x, y: x ^ y, match_simple_binop,
1667 [int64s+uint64s, int64s+uint64s],
1668 template='({0} ^ {1})',
1669 extension="ARB_gpu_shader_int64")
1670 f('op-lshift', 2, 150, _lshift, match_shift,
1671 [int64s+uint64s,
1672 small_uints],
1673 template='({0} << {1})',
1674 extension="ARB_gpu_shader_int64")
1675 f('op-rshift', 2, 150, _rshift, match_shift,
1676 [int64s+uint64s,
1677 small_uints],
1678 template='({0} >> {1})',
1679 extension="ARB_gpu_shader_int64")
1680 _make_vector_or_matrix_test_vectors(test_suite)
1683 def _check_signature_safety(test_suite_dict):
1684 """As a final safety check, verify that for each possible
1685 combination of name and argtypes, there is exactly one
1686 signature.
1688 name_argtype_combos = set()
1689 for signature in test_suite_dict:
1690 name_argtype_combo = (signature.name, signature.argtypes)
1691 if name_argtype_combo in name_argtype_combos:
1692 raise Exception(
1693 'Duplicate signature found for {0}'.format(name_argtype_combo))
1694 name_argtype_combos.add(name_argtype_combo)
1695 _check_signature_safety(test_suite)