[56/63] generated_tests/builtin_function: Add templates for equivalent SPIR-V

Submitted by apinheiro on Feb. 23, 2019, 11:45 p.m.

Details

Message ID 20190223234551.21111-57-apinheiro@igalia.com
State New
Headers show
Series "ARB_gl_spirv full series" ( rev: 1 ) in Piglit

Not browsing as part of any series.

Commit Message

apinheiro Feb. 23, 2019, 11:45 p.m.
From: Neil Roberts <nroberts@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(-)

Patch hide | download patch | download mbox

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)