From: Neil Roberts <nrobe...@igalia.com> The test signatures now have an additional member called template_spirv. If this is not None then it is a template which can be used to generate an equivalent line of SPIR-V assembly. --- generated_tests/builtin_function.py | 547 ++++++++++++++++++++++------ 1 file changed, 428 insertions(+), 119 deletions(-)
diff --git a/generated_tests/builtin_function.py b/generated_tests/builtin_function.py index a5eafb278..d11f270ab 100644 --- a/generated_tests/builtin_function.py +++ b/generated_tests/builtin_function.py @@ -215,7 +215,7 @@ glsl_u64vec4 = GlslBuiltinType('u64vec4', glsl_uint64_t, 1, 4, 400) # argtypes=('float', 'vec3')) Signature = collections.namedtuple( 'Signature', - ('name', 'template', 'version_introduced', 'extension', 'rettype', 'argtypes')) + ('name', 'template', 'version_introduced', 'extension', 'rettype', 'argtypes', 'template_spirv')) # Named tuple representing a single piece of test data for testing a @@ -736,7 +736,7 @@ def _vectorize_test_vectors(test_vectors, scalar_arg_indices, vector_length): def _store_test_vector(test_suite_dict, name, glsl_version, extension, test_vector, - template=None): + template=None, template_spirv=None): """Store a test vector in the appropriate place in test_suite_dict. The dictionary key (which is a Signature tuple) is generated by consulting the argument and return types of the @@ -747,6 +747,12 @@ def _store_test_vector(test_suite_dict, name, glsl_version, extension, test_vect If template is supplied, it is used insted as the template for the Signature objects generated. + + If template_spirv is supplied it will stored in the signature as + an alternative template to generate SPIR-V sources. If it is a + callable object it will be called with the argument types as + arguments and it is expected to return a generated template or + None if the test is not possible on SPIR-V. """ if template is None: arg_indices = range(len(test_vector.arguments)) @@ -757,24 +763,31 @@ def _store_test_vector(test_suite_dict, name, glsl_version, extension, test_vect adjusted_glsl_version = max( glsl_version, rettype.version_introduced, *[t.version_introduced for t in argtypes]) + if callable(template_spirv): + template_spirv = template_spirv(*argtypes) signature = Signature( - name, template, adjusted_glsl_version, extension, rettype, argtypes) + name, template, adjusted_glsl_version, + extension, rettype, argtypes, template_spirv) if signature not in test_suite_dict: test_suite_dict[signature] = [] test_suite_dict[signature].append(test_vector) def _store_test_vectors(test_suite_dict, name, glsl_version, extension, - test_vectors, template=None): + test_vectors, template=None, template_spirv=None): """Store multiple test vectors in the appropriate places in test_suite_dict. If template is supplied, it is used insted as the template for the Signature objects generated. + + template_spirv can also be supplied as a template to generate + SPIR-V sources. See the comment for _store_test_vector. """ for test_vector in test_vectors: _store_test_vector(test_suite_dict, name, glsl_version, extension, - test_vector, template=template) + test_vector, template=template, + template_spirv=template_spirv) def make_arguments(input_generators): @@ -815,10 +828,25 @@ def _make_componentwise_test_vectors(test_suite_dict): uints = [np.uint32(x) for x in [0, 1, 2, 5, 34]] bools = [True, False] + def spirv_match_types(opcode, *types): + for t in types: + if t != types[0]: + return None + return '{} {{}} {}'.format( + opcode, " ".join(itertools.repeat('{}', len(types)))) + + def spirv_match_types_ext(opcode, ext, *types): + for t in types: + if t != types[0]: + return None + return 'OpExtInst {{}} {} {} {}'.format( + ext, opcode, " ".join(itertools.repeat('{}', len(types)))) + def f(name, arity, glsl_version, python_equivalent, alternate_scalar_arg_indices, test_inputs, tolerance_function=_strict_tolerance, - extension=None): + extension=None, + template_spirv=None): """Create test vectors for the function with the given name and arity, which was introduced in the given glsl_version. @@ -839,11 +867,15 @@ def _make_componentwise_test_vectors(test_suite_dict): If tolerance_function is supplied, it is a function which should be used to compute the tolerance for the test vectors. Otherwise, _strict_tolerance is used. + + template_spirv will be passed directly to _store_test_vectors + as a way to provide a SPIR-V alternative. """ scalar_test_vectors = _simulate_function( make_arguments(test_inputs), python_equivalent, tolerance_function) _store_test_vectors( - test_suite_dict, name, glsl_version, extension, scalar_test_vectors) + test_suite_dict, name, glsl_version, extension, + scalar_test_vectors, template_spirv=template_spirv) if alternate_scalar_arg_indices is None: scalar_arg_indices_list = [()] else: @@ -854,47 +886,74 @@ def _make_componentwise_test_vectors(test_suite_dict): test_suite_dict, name, glsl_version, extension, _vectorize_test_vectors( scalar_test_vectors, scalar_arg_indices, - vector_length)) + vector_length), template_spirv=template_spirv) - f('radians', 1, 110, np.radians, None, [np.linspace(-180.0, 180.0, 4)]) - f('degrees', 1, 110, np.degrees, None, [np.linspace(-np.pi, np.pi, 4)]) + f('radians', 1, 110, np.radians, None, [np.linspace(-180.0, 180.0, 4)], + template_spirv='OpExtInst {} %glsl450 Radians {}') + f('degrees', 1, 110, np.degrees, None, [np.linspace(-np.pi, np.pi, 4)], + template_spirv='OpExtInst {} %glsl450 Degrees {}') f('sin', 1, 110, np.sin, None, [np.linspace(-np.pi, np.pi, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Sin {}') f('cos', 1, 110, np.cos, None, [np.linspace(-np.pi, np.pi, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Cos {}') f('tan', 1, 110, np.tan, None, [np.linspace(-np.pi, np.pi, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Tan {}') f('asin', 1, 110, np.arcsin, None, [np.linspace(-1.0, 1.0, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Asin {}') f('acos', 1, 110, np.arccos, None, [np.linspace(-1.0, 1.0, 4)], - _trig_tolerance) - f('atan', 1, 110, np.arctan, None, [atan_inputs], _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Acos {}') + f('atan', 1, 110, np.arctan, None, [atan_inputs], _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Atan {}'), f('atan', 2, 110, _arctan2, None, [atan_inputs, atan_inputs], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Atan2 {} {}') f('sinh', 1, 130, np.sinh, None, [np.linspace(-2.0, 2.0, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Sinh {}') f('cosh', 1, 130, np.cosh, None, [np.linspace(-2.0, 2.0, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Cosh {}') f('tanh', 1, 130, np.tanh, None, [np.linspace(-2.0, 2.0, 4)], - _trig_tolerance) - f('asinh', 1, 130, np.arcsinh, None, [atan_inputs], _trig_tolerance) - f('acosh', 1, 130, np.arccosh, None, [acosh_inputs], _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Tanh {}') + f('asinh', 1, 130, np.arcsinh, None, [atan_inputs], _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Asinh {}') + f('acosh', 1, 130, np.arccosh, None, [acosh_inputs], _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Acosh {}') f('atanh', 1, 130, np.arctanh, None, [np.linspace(-0.99, 0.99, 4)], - _trig_tolerance) + _trig_tolerance, + template_spirv='OpExtInst {} %glsl450 Atanh {}') f('pow', 2, 110, _pow, None, [np.linspace(0.0, 2.0, 4), - np.linspace(-2.0, 2.0, 4)]) - f('exp', 1, 110, np.exp, None, [np.linspace(-2.0, 2.0, 4)]) - f('log', 1, 110, np.log, None, [np.linspace(0.01, 2.0, 4)]) - f('exp2', 1, 110, _exp2, None, [np.linspace(-2.0, 2.0, 4)]) - f('log2', 1, 110, np.log2, None, [np.linspace(0.01, 2.0, 4)]) - f('sqrt', 1, 110, np.sqrt, None, [np.linspace(0.0, 2.0, 4)]) + np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Pow {} {}') + f('exp', 1, 110, np.exp, None, [np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Exp {}') + f('log', 1, 110, np.log, None, [np.linspace(0.01, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Log {}') + f('exp2', 1, 110, _exp2, None, [np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Exp2 {}') + f('log2', 1, 110, np.log2, None, [np.linspace(0.01, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Log2 {}') + f('sqrt', 1, 110, np.sqrt, None, [np.linspace(0.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Sqrt {}') f('inversesqrt', 1, 110, lambda x: 1.0/np.sqrt(x), None, - [np.linspace(0.1, 2.0, 4)]) - f('abs', 1, 110, np.abs, None, [np.linspace(-1.5, 1.5, 5)]) - f('abs', 1, 130, np.abs, None, [ints]) - f('sign', 1, 110, np.sign, None, [np.linspace(-1.5, 1.5, 5)]) - f('sign', 1, 130, np.sign, None, [ints]) - f('floor', 1, 110, np.floor, None, [np.linspace(-2.0, 2.0, 4)]) + [np.linspace(0.1, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 InverseSqrt {}') + f('abs', 1, 110, np.abs, None, [np.linspace(-1.5, 1.5, 5)], + template_spirv='OpExtInst {} %glsl450 FAbs {}') + f('abs', 1, 130, np.abs, None, [ints], + template_spirv='OpExtInst {} %glsl450 SAbs {}') + f('sign', 1, 110, np.sign, None, [np.linspace(-1.5, 1.5, 5)], + template_spirv='OpExtInst {} %glsl450 FSign {}') + f('sign', 1, 130, np.sign, None, [ints], + template_spirv='OpExtInst {} %glsl450 SSign {}') + f('floor', 1, 110, np.floor, None, [np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Floor {}') # Note: with trunc we want to test values in which the floating # point exponent is < 0, > 23 or in the middle. Hence, we append @@ -906,7 +965,8 @@ def _make_componentwise_test_vectors(test_suite_dict): [np.append(np.linspace(-2.0, 2.0, 8), [0.0, 45027112.0, -45027112.0, 1.9584199e10, -1.9584199e10, - 4.5027112e19, -4.5027112e19])]) + 4.5027112e19, -4.5027112e19])], + template_spirv='OpExtInst {} %glsl450 Trunc {}') # Note: the direction of rounding used by round() is not specified # for half-integer values, so we test it over a range that doesn't @@ -916,84 +976,135 @@ def _make_componentwise_test_vectors(test_suite_dict): # values. In both cases, we can use numpy's round() function, # because it rounds half-integer values to even, and all other # values to nearest. - f('round', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 8)]) - f('roundEven', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 25)]) + f('round', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 8)], + template_spirv='OpExtInst {} %glsl450 Round {}') + f('roundEven', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 25)], + template_spirv='OpExtInst {} %glsl450 RoundEven {}') - f('ceil', 1, 110, np.ceil, None, [np.linspace(-2.0, 2.0, 4)]) + f('ceil', 1, 110, np.ceil, None, [np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Ceil {}') f('fract', 1, 110, lambda x: x-np.floor(x), None, - [np.linspace(-2.0, 2.0, 4)]) + [np.linspace(-2.0, 2.0, 4)], + template_spirv='OpExtInst {} %glsl450 Fract {}') f('mod', 2, 110, lambda x, y: x-y*np.floor(x/y), [1], - [np.linspace(-1.9, 1.9, 4), np.linspace(-2.0, 2.0, 4)]) + [np.linspace(-1.9, 1.9, 4), np.linspace(-2.0, 2.0, 4)], + template_spirv=lambda x, y: spirv_match_types('OpFMod', x, y)) f('min', 2, 110, min, [1], - [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)]) - f('min', 2, 130, min, [1], [ints, ints]) - f('min', 2, 130, min, [1], [uints, uints]) + [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], + template_spirv=lambda x, y: + spirv_match_types_ext('FMin', '%glsl450', x, y)) + f('min', 2, 130, min, [1], [ints, ints], + template_spirv=lambda x, y: + spirv_match_types_ext('SMin', '%glsl450', x, y)) + f('min', 2, 130, min, [1], [uints, uints], + template_spirv=lambda x, y: + spirv_match_types_ext('UMin', '%glsl450', x, y)) f('max', 2, 110, max, [1], - [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)]) - f('max', 2, 130, max, [1], [ints, ints]) - f('max', 2, 130, max, [1], [uints, uints]) + [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], + template_spirv=lambda x, y: + spirv_match_types_ext('FMax', '%glsl450', x, y)) + f('max', 2, 130, max, [1], [ints, ints], + template_spirv=lambda x, y: + spirv_match_types_ext('SMax', '%glsl450', x, y)) + f('max', 2, 130, max, [1], [uints, uints], + template_spirv=lambda x, y: + spirv_match_types_ext('UMax', '%glsl450', x, y)) f('min3', 2, 110, min, None, [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext FMin3AMD {} {} {}') f('min3', 2, 130, min, None, [ints, ints, ints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext SMin3AMD {} {} {}') f('min3', 2, 130, min, None, [uints, uints, uints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext UMin3AMD {} {} {}') f('max3', 2, 110, max, None, [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext FMax3AMD {} {} {}') f('max3', 2, 130, max, None, [ints, ints, ints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext SMax3AMD {} {} {}') f('max3', 2, 130, max, None, [uints, uints, uints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext UMax3AMD {} {} {}') f('mid3', 2, 110, _mid3, None, [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext FMid3AMD {} {} {}') f('mid3', 2, 130, _mid3, None, [ints, ints, ints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext SMid3AMD {} {} {}') f('mid3', 2, 130, _mid3, None, [uints, uints, uints], - extension="AMD_shader_trinary_minmax") + extension="AMD_shader_trinary_minmax", + template_spirv='OpExtInst {} %ext UMid3AMD {} {} {}') f('clamp', 3, 110, _clamp, [1, 2], [np.linspace(-2.0, 2.0, 4), - np.linspace(-1.5, 1.5, 3), np.linspace(-1.5, 1.5, 3)]) - f('clamp', 3, 130, _clamp, [1, 2], [ints, ints, ints]) - f('clamp', 3, 130, _clamp, [1, 2], [uints, uints, uints]) + np.linspace(-1.5, 1.5, 3), np.linspace(-1.5, 1.5, 3)], + template_spirv=lambda x, y, z: + spirv_match_types_ext('FClamp', '%glsl450', x, y, z)) + f('clamp', 3, 130, _clamp, [1, 2], [ints, ints, ints], + template_spirv=lambda x, y, z: + spirv_match_types_ext('SClamp', '%glsl450', x, y, z)) + f('clamp', 3, 130, _clamp, [1, 2], [uints, uints, uints], + template_spirv=lambda x, y, z: + spirv_match_types_ext('UClamp', '%glsl450', x, y, z)) f('mix', 3, 110, lambda x, y, a: x*(1-a)+y*a, [2], [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2), - np.linspace(0.0, 1.0, 4)]) + np.linspace(0.0, 1.0, 4)], + template_spirv=lambda x, y, a: + spirv_match_types_ext('FMix', '%glsl450', x, y, a)) f('mix', 3, 130, lambda x, y, a: y if a else x, None, - [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2), bools]) + [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2), bools], + template_spirv='OpSelect {0} {3} {2} {1}') f('step', 2, 110, lambda edge, x: 0.0 if x < edge else 1.0, [0], - [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)]) + [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)], + template_spirv=lambda x, y: + spirv_match_types_ext('Step', '%glsl450', x, y)) f('smoothstep', 3, 110, _smoothstep, [0, 1], [np.linspace(-1.9, 1.9, 4), np.linspace(-1.9, 1.9, 4), - np.linspace(-2.0, 2.0, 4)]) - + np.linspace(-2.0, 2.0, 4)], + template_spirv=lambda x, y, z: + spirv_match_types_ext('SmoothStep', '%glsl450', x, y, z)) f('abs', 1, 150, np.abs, None, [np.linspace(-10, 15, 54).astype(np.int64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv='OpExtInst {} %glsl450 SAbs {}') f('sign', 1, 150, np.sign, None, [np.linspace(-15, 15, 5).astype(np.int64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv='OpExtInst {} %glsl450 SSign {}') f('min', 2, 150, min, [1], [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv=lambda x, y: + spirv_match_types_ext('SMin', '%glsl450', x, y)) f('min', 2, 150, min, [1], [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv=lambda x, y: + spirv_match_types_ext('UMin', '%glsl450', x, y)) f('max', 2, 150, max, [1], [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv=lambda x, y: + spirv_match_types_ext('SMax', '%glsl450', x, y)) f('max', 2, 150, max, [1], [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv=lambda x, y: + spirv_match_types_ext('UMax', '%glsl450', x, y)) f('clamp', 3, 150, _clamp, [1, 2], [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-15, 15, 3).astype(np.int64), np.linspace(-15, 15, 3).astype(np.int64)], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv=lambda x, y, z: + spirv_match_types_ext('SClamp', '%glsl450', x, y, z)) f('mix', 3, 150, lambda x, y, a: y if a else x, None, [np.linspace(-20, 20, 2).astype(np.int64), np.linspace(-30, 30, 2).astype(np.int64), bools], - extension="ARB_gpu_shader_int64") + extension="ARB_gpu_shader_int64", + template_spirv='OpSelect {0} {3} {2} {1}') _make_componentwise_test_vectors(test_suite) @@ -1011,6 +1122,7 @@ def _make_vector_relational_test_vectors(test_suite_dict): } def f(name, arity, glsl_version, python_equivalent, arg_types, + template_spirv, tolerance_function=_strict_tolerance, extension=None): """Make test vectors for the function with the given name and @@ -1027,6 +1139,9 @@ def _make_vector_relational_test_vectors(test_suite_dict): If tolerance_function is supplied, it is a function which should be used to compute the tolerance for the test vectors. Otherwise, _strict_tolerance is used. + + template_spirv is a template for the equivalent instruction + in SPIR-V. """ for arg_type in arg_types: test_inputs = [_default_inputs[arg_type]]*arity @@ -1037,15 +1152,47 @@ def _make_vector_relational_test_vectors(test_suite_dict): _store_test_vectors( test_suite_dict, name, glsl_version, extension, _vectorize_test_vectors( - scalar_test_vectors, (), vector_length)) - - f('lessThan', 2, 110, lambda x, y: x < y, 'viu') - f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'viu') - f('greaterThan', 2, 110, lambda x, y: x > y, 'viu') - f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'viu') - f('equal', 2, 110, lambda x, y: x == y, 'viub') - f('notEqual', 2, 110, lambda x, y: x != y, 'viub') - f('not', 1, 110, lambda x: not x, 'b') + scalar_test_vectors, (), vector_length), + template_spirv=template_spirv) + + f('lessThan', 2, 110, lambda x, y: x < y, 'v', + 'OpFOrdLessThan {} {} {}') + f('lessThan', 2, 110, lambda x, y: x < y, 'i', + 'OpSLessThan {} {} {}') + f('lessThan', 2, 110, lambda x, y: x < y, 'u', + 'OpULessThan {} {} {}') + f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'v', + 'OpFOrdLessThanEqual {} {} {}') + f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'i', + 'OpSLessThanEqual {} {} {}') + f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'u', + 'OpULessThanEqual {} {} {}') + f('greaterThan', 2, 110, lambda x, y: x > y, 'v', + 'OpFOrdGreaterThan {} {} {}') + f('greaterThan', 2, 110, lambda x, y: x > y, 'i', + 'OpSGreaterThan {} {} {}') + f('greaterThan', 2, 110, lambda x, y: x > y, 'u', + 'OpUGreaterThan {} {} {}') + f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'v', + 'OpFOrdGreaterThanEqual {} {} {}') + f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'i', + 'OpSGreaterThanEqual {} {} {}') + f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'u', + 'OpUGreaterThanEqual {} {} {}') + f('equal', 2, 110, lambda x, y: x == y, 'v', + 'OpFOrdEqual {} {} {}') + f('equal', 2, 110, lambda x, y: x == y, 'iu', + 'OpIEqual {} {} {}') + f('equal', 2, 110, lambda x, y: x == y, 'b', + None) + f('notEqual', 2, 110, lambda x, y: x != y, 'v', + 'OpFOrdNotEqual {} {} {}') + f('notEqual', 2, 110, lambda x, y: x != y, 'iu', + 'OpINotEqual {} {} {}') + f('notEqual', 2, 110, lambda x, y: x != y, 'b', + None) + f('not', 1, 110, lambda x: not x, 'b', + 'OpLogicalNot {} {}') _make_vector_relational_test_vectors(test_suite) @@ -1184,6 +1331,111 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): return (x_type.num_cols == y_type.num_rows and x_type.num_cols == y_type.num_cols) + def spirv_operator(name, x, y): + if x != y or x.num_cols > 1: + return None + if x.base_type is glsl_float: + opcode_prefix = 'F' + elif x.base_type in (glsl_int, glsl_int64_t, glsl_uint, glsl_uint64_t): + opcode_prefix = 'I' + else: + return None + return "Op{}{} {{}} {{}} {{}}".format(opcode_prefix, name) + + def spirv_signed_operator(name, x, y): + if x != y or x.num_cols > 1: + return None + if x.base_type is glsl_float: + opcode_prefix = 'F' + elif x.base_type in (glsl_int, glsl_int64_t): + opcode_prefix = 'S' + elif x.base_type in (glsl_uint, glsl_uint64_t): + opcode_prefix = 'U' + else: + return None + return "Op{}{} {{}} {{}} {{}}".format(opcode_prefix, name) + + def spirv_comp_operator(name, x, y): + if x != y or x.num_cols > 1: + return None + if x.base_type is glsl_float: + opcode_prefix = 'FOrd' + elif x.base_type in (glsl_int, glsl_int64_t): + opcode_prefix = 'S' + elif x.base_type in (glsl_uint, glsl_uint64_t): + opcode_prefix = 'U' + else: + return None + return "Op{}{} {{}} {{}} {{}}".format(opcode_prefix, name) + + def spirv_equal_operator(name, x, y): + # There is no non-component-wise equal opcode in SPIR-V + if x != y or not x.is_scalar: + return None + if x.base_type is glsl_float: + opcode_prefix = 'FOrd' + elif x.base_type in (glsl_int, glsl_int64_t, glsl_uint, glsl_uint64_t): + opcode_prefix = 'I' + elif x.base_type is glsl_bool: + opcode_prefix = 'Logical' + else: + return None + return "Op{}{} {{}} {{}} {{}}".format(opcode_prefix, name) + + def spirv_bitwise_operator(name, x, y): + if x.num_rows != y.num_rows: + return None + return "OpBitwise{} {{}} {{}} {{}}".format(name) + + def spirv_negate_operator(x): + if x.num_cols > 1: + return None + if x.base_type is glsl_float: + opcode_prefix = 'F' + elif x.base_type in (glsl_int, glsl_int64_t, glsl_uint, glsl_uint64_t): + opcode_prefix = 'S' + else: + return None + return "Op{}Negate {{}} {{}}".format(opcode_prefix) + + def spirv_dot_operator(x, y): + if x.is_scalar: + return None + return "OpDot {} {} {}" + + def spirv_mult_operator(x, y): + template = spirv_operator('Mul', x, y) + if template is not None: + return template + if x.base_type != glsl_float and y.base_type != glsl_float: + return None + if x.is_vector and y.is_scalar: + op = 'VectorTimesScalar' + elif x.is_matrix and y.is_scalar: + op = 'MatrixTimesScalar' + elif x.is_vector and y.is_matrix: + op = 'VectorTimesMatrix' + elif x.is_matrix and x.is_vector: + op = 'MatrixTimesVector' + elif x.is_matrix and y.is_matrix: + op = 'MatrixTimesMatrix' + else: + return None + return "Op{} {{}} {{}} {{}}".format(op) + + def spirv_left_shift_operator(x, y): + if x.num_rows != y.num_rows: + return None + return 'OpShiftLeftLogical {} {} {}' + + def spirv_right_shift_operator(x, y): + if x.num_rows != y.num_rows: + return None + if 'u' in x.base_type.name: + return 'OpShiftRightLogical {} {} {}' + else: + return 'OpShiftRightArithmetic {} {} {}' + bools = [False, True] bvecs = [np.array(bs) for bs in itertools.product(bools, bools)] + \ [np.array(bs) for bs in itertools.product(bools, bools, bools)] + \ @@ -1363,6 +1615,7 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): def f(name, arity, glsl_version, python_equivalent, filter, test_inputs, tolerance_function=_strict_tolerance, template=None, + template_spirv=None, extension=None): """Make test vectors for the function with the given name and arity, which was introduced in the given glsl_version. @@ -1386,6 +1639,9 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): If template is supplied, it is used insted as the template for the Signature objects generated. + + If template_spirv is supplied then it will be used as a + template to generate the equivalent operation in SPIR-V. """ test_inputs = make_arguments(test_inputs) if filter is not None: @@ -1395,7 +1651,7 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): test_suite_dict, name, glsl_version, extension, _simulate_function( test_inputs, python_equivalent, tolerance_function), - template=template) + template=template, template_spirv=template_spirv) f('op-assign-add', 2, 110, lambda x, y: x + y, match_assignment_operators, [floats+vecs+mats+ints+ivecs+uints+uvecs, @@ -1446,76 +1702,99 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): f('op-add', 2, 110, lambda x, y: x + y, match_simple_binop, [floats+vecs+mats+ints+ivecs+uints+uvecs, floats+vecs+mats+ints+ivecs+uints+uvecs], - template='({0} + {1})') + template='({0} + {1})', + template_spirv=lambda x, y: spirv_operator('Add', x, y)) # This can generate an overflow warning, this is expected with warnings.catch_warnings(): warnings.simplefilter('ignore', RuntimeWarning) f('op-sub', 2, 110, lambda x, y: x - y, match_simple_binop, [floats+vecs+mats+ints+ivecs+uints+uvecs, floats+vecs+mats+ints+ivecs+uints+uvecs], - template='({0} - {1})') + template='({0} - {1})', + template_spirv=lambda x, y: spirv_operator('Sub', x, y)) f('op-mult', 2, 110, _multiply, match_multiply, [floats+vecs+mats+ints+ivecs+uints+uvecs, floats+vecs+mats+ints+ivecs+uints+uvecs], - template='({0} * {1})') + template='({0} * {1})', + template_spirv=spirv_mult_operator) f('op-div', 2, 110, _divide, match_simple_binop, [floats+vecs+mats+ints+ivecs+uints+uvecs, floats+vecs+mats+ints+ivecs+uints+uvecs], - template='({0} / {1})') + template='({0} / {1})', + template_spirv=lambda x, y: spirv_signed_operator('Div', x, y)) f('op-div-large', 2, 130, _divide, match_simple_binop, - [large_uints, large_uints+small_uints], template='({0} / {1})') + [large_uints, large_uints+small_uints], template='({0} / {1})', + template_spirv=lambda x, y: spirv_signed_operator('Div', x, y)) f('op-mod', 2, 130, _modulus, match_simple_binop, - [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], template='({0} % {1})') + [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], template='({0} % {1})', + template_spirv=lambda x, y: spirv_signed_operator('Mod', x, y)) f('op-uplus', 1, 110, lambda x: +x, None, [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(+ {0})') f('op-neg', 1, 110, lambda x: -x, None, - [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(- {0})') + [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(- {0})', + template_spirv=spirv_negate_operator) f('op-gt', 2, 110, lambda x, y: x > y, match_args(0, 1), - [ints+uints+floats, ints+uints+floats], template='({0} > {1})') + [ints+uints+floats, ints+uints+floats], template='({0} > {1})', + template_spirv=lambda x, y: spirv_comp_operator('GreaterThan', x, y)) f('op-lt', 2, 110, lambda x, y: x < y, match_args(0, 1), - [ints+uints+floats, ints+uints+floats], template='({0} < {1})') + [ints+uints+floats, ints+uints+floats], template='({0} < {1})', + template_spirv=lambda x, y: spirv_comp_operator('LessThan', x, y)) f('op-ge', 2, 110, lambda x, y: x >= y, match_args(0, 1), - [ints+uints+floats, ints+uints+floats], template='({0} >= {1})') + [ints+uints+floats, ints+uints+floats], template='({0} >= {1})', + template_spirv=lambda x, y: spirv_comp_operator('GreaterThanEqual', x, y)) f('op-le', 2, 110, lambda x, y: x <= y, match_args(0, 1), - [ints+uints+floats, ints+uints+floats], template='({0} <= {1})') + [ints+uints+floats, ints+uints+floats], template='({0} <= {1})', + template_spirv=lambda x, y: spirv_comp_operator('LessThanEqual', x, y)) f('op-eq', 2, 110, _equal, match_args(0, 1), [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs], - template='({0} == {1})') + template='({0} == {1})', + template_spirv=lambda x, y: spirv_equal_operator('Equal', x, y)) f('op-ne', 2, 110, _not_equal, match_args(0, 1), [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs], - template='({0} != {1})') + template='({0} != {1})', + template_spirv=lambda x, y: spirv_equal_operator('NotEqual', x, y)) f('op-and', 2, 110, lambda x, y: x and y, None, [bools, bools], - template='({0} && {1})') + template='({0} && {1})', + template_spirv='OpLogicalAnd {} {} {}') f('op-or', 2, 110, lambda x, y: x or y, None, [bools, bools], - template='({0} || {1})') + template='({0} || {1})', + template_spirv='OpLogicalOr {} {} {}') f('op-xor', 2, 110, lambda x, y: x != y, None, [bools, bools], - template='({0} ^^ {1})') - f('op-not', 1, 110, lambda x: not x, None, [bools], template='(! {0})') + template='({0} ^^ {1})', + template_spirv='OpLogicalNotEqual {} {} {}') + f('op-not', 1, 110, lambda x: not x, None, [bools], template='(! {0})', + template_spirv='OpLogicalNot {} {}') f('op-selection', 3, 110, lambda x, y, z: y if x else z, match_args(1, 2), [bools, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs], template='({0} ? {1} : {2})') f('op-complement', 1, 130, lambda x: ~x, None, [ints+ivecs+uints+uvecs], - template='(~ {0})') + template='(~ {0})', + template_spirv='OpNot {} {}') f('op-lshift', 2, 130, _lshift, match_shift, [small_ints+small_ivecs+small_uints+small_uvecs, small_ints+small_ivecs+small_uints+small_uvecs], - template='({0} << {1})') + template='({0} << {1})', + template_spirv=spirv_left_shift_operator) f('op-rshift', 2, 130, _rshift, match_shift, [small_ints+small_ivecs+small_uints+small_uvecs, small_ints+small_ivecs+small_uints+small_uvecs], - template='({0} >> {1})') + template='({0} >> {1})', + template_spirv=spirv_right_shift_operator) f('op-bitand', 2, 130, lambda x, y: x & y, match_simple_binop, [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], - template='({0} & {1})') + template='({0} & {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('And', x, y)) f('op-bitor', 2, 130, lambda x, y: x | y, match_simple_binop, [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], - template='({0} | {1})') + template='({0} | {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('Or', x, y)) f('op-bitxor', 2, 130, lambda x, y: x ^ y, match_simple_binop, [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], - template='({0} ^ {1})') + template='({0} ^ {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('Xor', x, y)) f('op-bitand-neg', 2, 130, lambda x, y: x & (-y), match_simple_binop, [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], template='({0} & (- {1}))') @@ -1570,19 +1849,27 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): f('op-bitxor-abs-not', 2, 130, lambda x, y: x ^ abs(~y), match_simple_binop, [ints+ivecs, ints+ivecs], template='({0} ^ abs(~ {1}))') - f('length', 1, 110, np.linalg.norm, None, [floats+vecs]) + f('length', 1, 110, np.linalg.norm, None, [floats+vecs], + template_spirv='OpExtInst {} %glsl450 Length {}') f('distance', 2, 110, lambda x, y: np.linalg.norm(x-y), match_args(0, 1), - [floats+vecs, floats+vecs]) - f('dot', 2, 110, np.dot, match_args(0, 1), [floats+vecs, floats+vecs]) + [floats+vecs, floats+vecs], + template_spirv='OpExtInst {} %glsl450 Distance {} {}') + f('dot', 2, 110, np.dot, match_args(0, 1), [floats+vecs, floats+vecs], + template_spirv=spirv_dot_operator) f('cross', 2, 110, np.cross, match_args(0, 1), [vec3s, vec3s], - _cross_product_tolerance) - f('normalize', 1, 110, _normalize, None, [nz_floats_vecs]) + _cross_product_tolerance, + template_spirv='OpExtInst {} %glsl450 Cross {} {}') + f('normalize', 1, 110, _normalize, None, [nz_floats_vecs], + template_spirv='OpExtInst {} %glsl450 Normalize {}') f('faceforward', 3, 110, _faceforward, match_args(0, 1, 2), - [floats+vecs, floats+vecs, floats+vecs]) + [floats+vecs, floats+vecs, floats+vecs], + template_spirv='OpExtInst {} %glsl450 FaceForward {} {} {}') f('reflect', 2, 110, _reflect, match_args(0, 1), - [floats+vecs, norm_floats_vecs]) + [floats+vecs, norm_floats_vecs], + template_spirv='OpExtInst {} %glsl450 Reflect {} {}') f('refract', 3, 110, _refract, match_args(0, 1), - [norm_floats_vecs, norm_floats_vecs, [0.5, 2.0]]) + [norm_floats_vecs, norm_floats_vecs, [0.5, 2.0]], + template_spirv='OpExtInst {} %glsl450 Refract {} {} {}') # Note: technically matrixCompMult operates componentwise. # However, since it is the only componentwise function to operate @@ -1591,19 +1878,26 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): f('matrixCompMult', 2, 110, lambda x, y: x*y, match_args(0, 1), [mats, mats]) - f('outerProduct', 2, 120, np.outer, None, [vecs, vecs]) - f('transpose', 1, 120, np.transpose, None, [mats]) - f('any', 1, 110, any, None, [bvecs]) - f('all', 1, 110, all, None, [bvecs]) + f('outerProduct', 2, 120, np.outer, None, [vecs, vecs], + template_spirv='OpOuterProduct {} {} {}') + f('transpose', 1, 120, np.transpose, None, [mats], + template_spirv='OpTranspose {} {}') + f('any', 1, 110, any, None, [bvecs], + template_spirv='OpAny {} {}') + f('all', 1, 110, all, None, [bvecs], + template_spirv='OpAll {} {}') - f('inverse', 1, 140, np.linalg.inv, None, [squaremats]) + f('inverse', 1, 140, np.linalg.inv, None, [squaremats], + template_spirv='OpExtInst {} %glsl450 MatrixInverse {}') - f('determinant', 1, 150, np.linalg.det, None, [squaremats]) + f('determinant', 1, 150, np.linalg.det, None, [squaremats], + template_spirv='OpExtInst {} %glsl450 Determinant {}') f('op-add', 2, 150, lambda x, y: x + y, match_simple_binop, [int64s+int64vecs+uint64s+uint64vecs, int64s+int64vecs+uint64s+uint64vecs], template='({0} + {1})', + template_spirv=lambda x, y: spirv_operator('Add', x, y), extension="ARB_gpu_shader_int64") with warnings.catch_warnings(): warnings.simplefilter('ignore', RuntimeWarning) @@ -1611,73 +1905,88 @@ def _make_vector_or_matrix_test_vectors(test_suite_dict): [int64s+int64vecs+uint64s+uint64vecs, int64s+int64vecs+uint64s+uint64vecs], template='({0} - {1})', + template_spirv=lambda x, y: spirv_operator('Sub', x, y), extension="ARB_gpu_shader_int64") f('op-mult', 2, 150, _multiply, match_multiply, [int64s+int64vecs+uint64s+uint64vecs, int64s+int64vecs+uint64s+uint64vecs], template='({0} * {1})', + template_spirv=lambda x, y: spirv_operator('Mul', x, y), extension="ARB_gpu_shader_int64") f('op-div', 2, 150, _divide, match_simple_binop, [int64s+int64vecs+uint64s+uint64vecs, int64s+int64vecs+uint64s+uint64vecs], template='({0} / {1})', + template_spirv=lambda x, y: spirv_signed_operator('Div', x, y), extension="ARB_gpu_shader_int64") f('op-mod', 2, 150, _modulus, match_simple_binop, [int64s+int64vecs+uint64s+uint64vecs, int64s+int64vecs+uint64s+uint64vecs], template='({0} % {1})', + template_spirv=lambda x, y: spirv_signed_operator('Mod', x, y), extension="ARB_gpu_shader_int64") f('op-gt', 2, 150, lambda x, y: x > y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} > {1})', + template_spirv=lambda x, y: spirv_comp_operator('GreaterThan', x, y), extension="ARB_gpu_shader_int64") f('op-lt', 2, 150, lambda x, y: x < y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} < {1})', + template_spirv=lambda x, y: spirv_comp_operator('LessThan', x, y), extension="ARB_gpu_shader_int64") f('op-ge', 2, 150, lambda x, y: x >= y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} >= {1})', + template_spirv=lambda x, y: spirv_comp_operator('GreaterThanEqual', x, y), extension="ARB_gpu_shader_int64") f('op-le', 2, 150, lambda x, y: x <= y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} <= {1})', + template_spirv=lambda x, y: spirv_comp_operator('LessThanEqual', x, y), extension="ARB_gpu_shader_int64") f('op-eq', 2, 150, lambda x, y: x == y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} == {1})', + template_spirv=lambda x, y: spirv_equal_operator('Equal', x, y), extension="ARB_gpu_shader_int64") f('op-ne', 2, 150, lambda x, y: x != y, match_args(0, 1), [int64s+uint64s, int64s+uint64s], template = '({0} != {1})', + template_spirv=lambda x, y: spirv_equal_operator('NotEqual', x, y), extension="ARB_gpu_shader_int64") f('op-bitand', 2, 150, lambda x, y: x & y, match_simple_binop, [int64s+uint64s, int64s+uint64s], template='({0} & {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('And', x, y), extension="ARB_gpu_shader_int64") f('op-bitor', 2, 150, lambda x, y: x | y, match_simple_binop, [int64s+uint64s, int64s+uint64s], template='({0} | {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('Or', x, y), extension="ARB_gpu_shader_int64") f('op-bitxor', 2, 150, lambda x, y: x ^ y, match_simple_binop, [int64s+uint64s, int64s+uint64s], template='({0} ^ {1})', + template_spirv=lambda x, y: spirv_bitwise_operator('Xor', x, y), extension="ARB_gpu_shader_int64") f('op-lshift', 2, 150, _lshift, match_shift, [int64s+uint64s, small_uints], template='({0} << {1})', + template_spirv='OpShiftLeftLogical {} {} {}', extension="ARB_gpu_shader_int64") f('op-rshift', 2, 150, _rshift, match_shift, [int64s+uint64s, small_uints], template='({0} >> {1})', + template_spirv=spirv_right_shift_operator, extension="ARB_gpu_shader_int64") _make_vector_or_matrix_test_vectors(test_suite) -- 2.19.1 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit