[gtk+/wip/otte/shader: 91/150] gskpsv: Completely redo SPV writing



commit ce65345054cbc9f162a4f6ba55fe731440049d31
Author: Benjamin Otte <otte redhat com>
Date:   Fri Oct 6 03:48:45 2017 +0200

    gskpsv: Completely redo SPV writing
    
    Autogenerate the headers for SPIR-V from the JSON file provided by the
    spec (and now included here).
    This provides a way more readable and on top of that type-safe way to
    emit bytecodes when generating code.
    
    As a result of this, the whole bytecode emission was rewritten, so there
    are probably lots of different bugs in it now.
    
    Note: If statement SPV generation was disabled. Code generation needs
    some more support for control flow before I can reenable if statements.

 gsk/gskslexpression.c              |  629 +---
 gsk/gskslfunction.c                |   44 +-
 gsk/gskslpointertype.c             |   16 +-
 gsk/gskslstatement.c               |   32 +-
 gsk/gsksltype.c                    |  287 +--
 gsk/gskslvariable.c                |   39 +-
 gsk/gskslvariableprivate.h         |    3 +-
 gsk/gskspvenumsprivate.h           |  855 +++++
 gsk/gskspvwriter.c                 |  195 +-
 gsk/gskspvwritergeneratedprivate.h | 6367 ++++++++++++++++++++++++++++++++++++
 gsk/gskspvwriterprivate.h          |  264 +--
 gsk/meson.build                    |    5 +
 gsk/spirv.core.grammar.json        | 5630 +++++++++++++++++++++++++++++++
 gsk/spirv.js                       |  715 ++++
 14 files changed, 13927 insertions(+), 1154 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 6e4fd52..05ff561 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -509,9 +509,10 @@ gsk_sl_expression_multiplication_write_spv (const GskSlExpression *expression,
                                             GskSpvWriter          *writer)
 {
   const GskSlExpressionMultiplication *multiplication = (const GskSlExpressionMultiplication *) expression;
-  GskSlType *ltype, *rtype;
-  guint32 left_id, right_id, result_id, result_type_id;
+  GskSlType *ltype, *rtype, *type;
+  guint32 left_id, right_id;
 
+  type = multiplication->type;
   ltype = gsk_sl_expression_get_return_type (multiplication->left);
   rtype = gsk_sl_expression_get_return_type (multiplication->right);
 
@@ -519,72 +520,37 @@ gsk_sl_expression_multiplication_write_spv (const GskSlExpression *expression,
   if (gsk_sl_type_get_scalar_type (ltype) != gsk_sl_type_get_scalar_type (multiplication->type))
     {
       GskSlType *new_type = gsk_sl_type_get_matching (ltype, gsk_sl_type_get_scalar_type 
(multiplication->type));
-      left_id = gsk_spv_writer_add_conversion (writer, left_id, ltype, new_type);
+      left_id = gsk_spv_writer_convert (writer, left_id, ltype, new_type);
       ltype = new_type;
     }
   right_id = gsk_sl_expression_write_spv (multiplication->right, writer);
   if (gsk_sl_type_get_scalar_type (rtype) != gsk_sl_type_get_scalar_type (multiplication->type))
     {
       GskSlType *new_type = gsk_sl_type_get_matching (rtype, gsk_sl_type_get_scalar_type 
(multiplication->type));
-      right_id = gsk_spv_writer_add_conversion (writer, right_id, rtype, new_type);
+      right_id = gsk_spv_writer_convert (writer, right_id, rtype, new_type);
       rtype = new_type;
     }
 
-  result_type_id = gsk_spv_writer_get_id_for_type (writer, multiplication->type);
-  result_id = gsk_spv_writer_next_id (writer);
-
   if (gsk_sl_type_is_matrix (ltype))
     {
       if (gsk_sl_type_is_matrix (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_MATRIX_TIMES_MATRIX,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-
-          return result_id;
+          return gsk_spv_writer_matrix_times_matrix (writer, type, left_id, right_id);
         }
       else if (gsk_sl_type_is_vector (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_VECTOR_TIMES_MATRIX,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             right_id,
-                                             left_id });
-
-          return result_id;
+          return gsk_spv_writer_vector_times_matrix (writer, type, right_id, left_id);
         }
       else if (gsk_sl_type_is_scalar (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-
-          return result_id;
+          return gsk_spv_writer_matrix_times_scalar (writer, type, left_id, right_id);
         }
     }
   else if (gsk_sl_type_is_vector (ltype))
     {
       if (gsk_sl_type_is_matrix (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_MATRIX_TIMES_VECTOR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             right_id,
-                                             left_id });
-
-          return result_id;
+          return gsk_spv_writer_matrix_times_vector (writer, type, right_id, left_id);
         }
       else if (gsk_sl_type_is_vector (rtype))
         {
@@ -592,71 +558,31 @@ gsk_sl_expression_multiplication_write_spv (const GskSlExpression *expression,
             {
             case GSK_SL_FLOAT:
             case GSK_SL_DOUBLE:
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_F_MUL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 left_id,
-                                                 right_id });
-              break;
+              return gsk_spv_writer_f_mul (writer, type, left_id, right_id);
             case GSK_SL_INT:
             case GSK_SL_UINT:
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_I_MUL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 left_id,
-                                                 right_id });
-              break;
+              return gsk_spv_writer_i_mul (writer, type, left_id, right_id);
             case GSK_SL_VOID:
             case GSK_SL_BOOL:
             default:
               g_assert_not_reached ();
               break;
             }
-
-          return result_id;
         }
       else if (gsk_sl_type_is_scalar (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_VECTOR_TIMES_SCALAR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-
-          return result_id;
+          return gsk_spv_writer_vector_times_scalar (writer, type, left_id, right_id);
         }
     }
   else if (gsk_sl_type_is_scalar (ltype))
     {
       if (gsk_sl_type_is_matrix (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             right_id,
-                                             left_id });
-
-          return result_id;
+          return gsk_spv_writer_matrix_times_scalar (writer, type, right_id, left_id);
         }
       else if (gsk_sl_type_is_vector (rtype))
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_VECTOR_TIMES_SCALAR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             right_id,
-                                             left_id });
-
-          return result_id;
+          return gsk_spv_writer_vector_times_scalar (writer, type, right_id, left_id);
         }
       else if (gsk_sl_type_is_scalar (rtype))
         {
@@ -664,32 +590,18 @@ gsk_sl_expression_multiplication_write_spv (const GskSlExpression *expression,
             {
             case GSK_SL_FLOAT:
             case GSK_SL_DOUBLE:
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_F_MUL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 left_id,
-                                                 right_id });
-              break;
+              return gsk_spv_writer_f_mul (writer, type, left_id, right_id);
+
             case GSK_SL_INT:
             case GSK_SL_UINT:
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_I_MUL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 left_id,
-                                                 right_id });
-              break;
+              return gsk_spv_writer_i_mul (writer, type, left_id, right_id);
+
             case GSK_SL_VOID:
             case GSK_SL_BOOL:
             default:
               g_assert_not_reached ();
               break;
             }
-
-          return result_id;
         }
     }
 
@@ -954,7 +866,7 @@ gsk_sl_expression_division_write_spv (const GskSlExpression *expression,
 {
   const GskSlExpressionArithmetic *arithmetic = (const GskSlExpressionArithmetic *) expression;
   GskSlType *ltype, *rtype;
-  guint32 left_id, right_id, result_id, result_type_id;
+  guint32 left_id, right_id;
 
   ltype = gsk_sl_expression_get_return_type (arithmetic->left);
   rtype = gsk_sl_expression_get_return_type (arithmetic->right);
@@ -963,90 +875,60 @@ gsk_sl_expression_division_write_spv (const GskSlExpression *expression,
   if (gsk_sl_type_get_scalar_type (ltype) != gsk_sl_type_get_scalar_type (arithmetic->type))
     {
       GskSlType *new_type = gsk_sl_type_get_matching (ltype, gsk_sl_type_get_scalar_type (arithmetic->type));
-      left_id = gsk_spv_writer_add_conversion (writer, left_id, ltype, new_type);
+      left_id = gsk_spv_writer_convert (writer, left_id, ltype, new_type);
       ltype = new_type;
     }
   right_id = gsk_sl_expression_write_spv (arithmetic->right, writer);
   if (gsk_sl_type_get_scalar_type (rtype) != gsk_sl_type_get_scalar_type (arithmetic->type))
     {
       GskSlType *new_type = gsk_sl_type_get_matching (rtype, gsk_sl_type_get_scalar_type (arithmetic->type));
-      right_id = gsk_spv_writer_add_conversion (writer, right_id, rtype, new_type);
+      right_id = gsk_spv_writer_convert (writer, right_id, rtype, new_type);
       rtype = new_type;
     }
 
-  result_type_id = gsk_spv_writer_get_id_for_type (writer, arithmetic->type);
-
   if (gsk_sl_type_is_matrix (ltype))
     {
       if (gsk_sl_type_is_matrix (rtype))
         {
+          GskSlType *col_type = gsk_sl_type_get_index_type (ltype);
           gsize cols = gsk_sl_type_get_length (ltype);
           gsize c;
-          guint32 col_type_id, left_part_id, right_part_id, ids[cols + 2];
+          guint32 left_part_id, right_part_id, ids[cols];
 
-          col_type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_index_type (ltype));
           for (c = 0; c < cols; c++)
             {
-              left_part_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                                  (guint32[4]) { col_type_id,
-                                                 left_part_id,
-                                                 left_id,
-                                                 c });
-              right_part_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                                  (guint32[4]) { col_type_id,
-                                                 right_part_id,
-                                                 right_id,
-                                                 c });
-              ids[2 + c] = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_F_DIV,
-                                  (guint32[4]) { col_type_id,
-                                                 ids[2 + c],
-                                                 left_part_id,
-                                                 right_part_id });
+              left_part_id = gsk_spv_writer_composite_extract (writer, 
+                                                               col_type,
+                                                               left_id,
+                                                               (guint32[1]) { 1 }, c);
+              right_part_id = gsk_spv_writer_composite_extract (writer, 
+                                                                col_type,
+                                                                right_id,
+                                                                (guint32[1]) { 1 }, c);
+              ids[c] = gsk_spv_writer_f_div (writer,
+                                             col_type,
+                                             left_part_id,
+                                             right_part_id);
             }
 
-          ids[0] = result_type_id;
-          ids[1] = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              3 + cols, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              ids);
-
-          return ids[1];
+          return gsk_spv_writer_composite_construct (writer, 
+                                                     arithmetic->type,
+                                                     ids,
+                                                     cols);
         }
       else if (gsk_sl_type_is_scalar (rtype))
         {
-          guint32 tmp_id, one_id, rtype_id;
-
-          rtype_id = gsk_spv_writer_get_id_for_type (writer, rtype);
-          one_id = gsk_spv_writer_get_id_for_one (writer, gsk_sl_type_get_scalar_type (arithmetic->type));
-          tmp_id = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_F_DIV,
-                              (guint32[4]) { rtype_id,
-                                             tmp_id,
-                                             one_id,
-                                             right_id });
-
-          result_id = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             tmp_id });
-
-          return result_id;
+          guint32 tmp_id;
+
+          tmp_id = gsk_spv_writer_f_div (writer,
+                                         rtype,
+                                         gsk_spv_writer_get_id_for_one (writer, gsk_sl_type_get_scalar_type 
(arithmetic->type)),
+                                         right_id);
+
+          return gsk_spv_writer_matrix_times_scalar (writer,
+                                                     arithmetic->type,
+                                                     left_id,
+                                                     tmp_id);
         }
       else
         {
@@ -1056,98 +938,58 @@ gsk_sl_expression_division_write_spv (const GskSlExpression *expression,
     }
   else if (gsk_sl_type_is_matrix (rtype))
     {
-      guint32 tmp_id, one_id, ltype_id;
-
-      ltype_id = gsk_spv_writer_get_id_for_type (writer, ltype);
-      one_id = gsk_spv_writer_get_id_for_one (writer, gsk_sl_type_get_scalar_type (arithmetic->type));
-      tmp_id = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          5, GSK_SPV_OP_F_DIV,
-                          (guint32[4]) { ltype_id,
-                                         tmp_id,
-                                         one_id,
-                                         left_id });
-
-      result_id = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
-                          (guint32[4]) { result_type_id,
-                                         result_id,
-                                         right_id,
-                                         tmp_id });
-
-      return result_id;
+      guint32 tmp_id;
+
+      tmp_id = gsk_spv_writer_f_div (writer,
+                                     ltype,
+                                     gsk_spv_writer_get_id_for_one (writer, gsk_sl_type_get_scalar_type 
(arithmetic->type)),
+                                     left_id);
+      return gsk_spv_writer_matrix_times_scalar (writer,
+                                                 arithmetic->type,
+                                                 right_id,
+                                                 tmp_id);
     }
   else
     {
-      /* ltype and rtype are not matices */
+      /* ltype and rtype are not matrices */
 
       if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_vector (rtype))
         {
-           guint32 tmp_id = gsk_spv_writer_next_id (writer);
-           gsk_spv_writer_add (writer,
-                               GSK_SPV_WRITER_SECTION_CODE,
-                               3 + gsk_sl_type_get_length (rtype), GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              (guint32[6]) { result_type_id,
-                                             tmp_id,
-                                             left_id, left_id, left_id, left_id });
+           guint32 tmp_id = gsk_spv_writer_composite_construct (writer,
+                                                                arithmetic->type,
+                                                                (guint32[4]) { left_id, left_id, left_id, 
left_id },
+                                                                gsk_sl_type_get_length (rtype));
            left_id = tmp_id;
         }
       else if (gsk_sl_type_is_scalar (rtype) && gsk_sl_type_is_vector (ltype))
         {
-           guint32 tmp_id = gsk_spv_writer_next_id (writer);
-           gsk_spv_writer_add (writer,
-                               GSK_SPV_WRITER_SECTION_CODE,
-                               3 + gsk_sl_type_get_length (ltype), GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              (guint32[6]) { result_type_id,
-                                             tmp_id,
-                                             right_id, right_id, right_id, right_id });
+           guint32 tmp_id = gsk_spv_writer_composite_construct (writer,
+                                                                arithmetic->type,
+                                                                (guint32[4]) { right_id, right_id, right_id, 
right_id },
+                                                                gsk_sl_type_get_length (ltype));
            right_id = tmp_id;
         }
 
       /* ltype and rtype have the same number of components now */
 
-      result_id = gsk_spv_writer_next_id (writer);
       switch (gsk_sl_type_get_scalar_type (arithmetic->type))
         {
         case GSK_SL_FLOAT:
         case GSK_SL_DOUBLE:
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_F_DIV,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-          break;
+          return gsk_spv_writer_f_div (writer, arithmetic->type, left_id, right_id);
+
         case GSK_SL_INT:
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_S_DIV,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-          break;
+          return gsk_spv_writer_s_div (writer, arithmetic->type, left_id, right_id);
+
         case GSK_SL_UINT:
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_U_DIV,
-                              (guint32[4]) { result_type_id,
-                                             result_id,
-                                             left_id,
-                                             right_id });
-          break;
+          return gsk_spv_writer_u_div (writer, arithmetic->type, left_id, right_id);
+
         case GSK_SL_VOID:
         case GSK_SL_BOOL:
         default:
           g_assert_not_reached ();
-          break;
+          return 0;
         }
-
-      return result_id;
     }
 }
 
@@ -1491,7 +1333,7 @@ gsk_sl_expression_reference_get_return_type (const GskSlExpression *expression)
 {
   const GskSlExpressionReference *reference = (const GskSlExpressionReference *) expression;
 
-  return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (reference->variable));
+  return gsk_sl_variable_get_type (reference->variable);
 }
 
 static GskSlValue *
@@ -1515,19 +1357,11 @@ gsk_sl_expression_reference_write_spv (const GskSlExpression *expression,
                                        GskSpvWriter          *writer)
 {
   GskSlExpressionReference *reference = (GskSlExpressionReference *) expression;
-  guint32 declaration_id, result_id, type_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type 
(reference->variable)));
-  declaration_id = gsk_spv_writer_get_id_for_variable (writer, reference->variable);
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_CODE,
-                      4, GSK_SPV_OP_LOAD,
-                      (guint32[3]) { type_id,
-                                     result_id,
-                                     declaration_id });
 
-  return result_id;
+  return gsk_spv_writer_load (writer,
+                              gsk_sl_variable_get_type (reference->variable),
+                              gsk_spv_writer_get_id_for_variable (writer, reference->variable),
+                              0);
 }
 
 static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
@@ -1717,25 +1551,19 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
 
       if (gsk_sl_type_is_scalar (type))
         {
-          return gsk_spv_writer_add_conversion (writer, value_id, value_type, type);
+          return gsk_spv_writer_convert (writer, value_id, value_type, type);
         }
       else if (gsk_sl_type_is_vector (type))
         {
           GskSlType *scalar_type = gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (type));
-          guint32 scalar_id, result_type_id, result_id;
+          guint32 scalar_id;
 
-          scalar_id = gsk_spv_writer_add_conversion (writer, value_id, value_type, scalar_type);
-          result_type_id = gsk_spv_writer_get_id_for_type (writer, type);
-          result_id = gsk_spv_writer_next_id (writer);
+          scalar_id = gsk_spv_writer_convert (writer, value_id, value_type, scalar_type);
 
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              3 + gsk_sl_type_get_n_components (type), GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              (guint32[6]) { result_type_id,
-                                             result_id,
-                                             scalar_id, scalar_id, scalar_id, scalar_id });
-
-          return result_id;
+          return gsk_spv_writer_composite_construct (writer,
+                                                     type,
+                                                     (guint[4]) { scalar_id, scalar_id, scalar_id, scalar_id 
},
+                                                     gsk_sl_type_get_n_components (type));
         }
       else if (gsk_sl_type_is_matrix (type))
         {
@@ -1743,34 +1571,26 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
           GskSlType *col_type = gsk_sl_type_get_index_type (type);
           gsize cols = gsk_sl_type_get_length (type);
           gsize rows = gsk_sl_type_get_length (col_type);
-          guint32 ids[2 + gsk_sl_type_get_length (type)];
-          guint32 scalar_id, zero_id, col_type_id;
+          guint32 ids[gsk_sl_type_get_length (type)];
+          guint32 scalar_id, zero_id;
           gsize c;
 
-          scalar_id = gsk_spv_writer_add_conversion (writer, value_id, value_type, scalar_type);
+          scalar_id = gsk_spv_writer_convert (writer, value_id, value_type, scalar_type);
           zero_id = gsk_spv_writer_get_id_for_zero (writer, gsk_sl_type_get_scalar_type (scalar_type));
-          col_type_id = gsk_spv_writer_get_id_for_type (writer, col_type);
 
           for (c = 0; c < cols; c++)
             {
-              ids[2 + c] = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  3 + rows, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                                  (guint32[6]) { col_type_id,
-                                                 ids[2 + c],
-                                                 c == 0 ? scalar_id : zero_id,
-                                                 c == 1 ? scalar_id : zero_id,
-                                                 c == 2 ? scalar_id : zero_id,
-                                                 c == 3 ? scalar_id : zero_id });
+              ids[c] = gsk_spv_writer_composite_construct (writer,
+                                                           type,
+                                                           (guint32[4]) {
+                                                               c == 0 ? scalar_id : zero_id,
+                                                               c == 1 ? scalar_id : zero_id,
+                                                               c == 2 ? scalar_id : zero_id,
+                                                               c == 3 ? scalar_id : zero_id
+                                                           },
+                                                           rows);
             }
-          ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
-          ids[1] = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              3 + cols, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              ids);
-          return ids[1];
+          return gsk_spv_writer_composite_construct (writer, type, ids, cols);
         }
       else
         {
@@ -1788,14 +1608,15 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
       gsize value_cols = gsk_sl_type_get_length (type);
       gsize value_rows = gsk_sl_type_get_length (value_col_type);
       gsize c, r;
-      guint32 col_ids[6], ids[6], one_id, zero_id, scalar_type_id;
+      guint32 col_ids[4], ids[4], one_id, zero_id;
       GskSlValue *value;
 
       value_id = gsk_sl_expression_write_spv (constructor->arguments[0], writer);
+
       if (gsk_sl_type_get_scalar_type (value_type) != gsk_sl_type_get_scalar_type (type))
         {
           GskSlType *new_value_type = gsk_sl_type_get_matching (value_type, gsk_sl_type_get_scalar_type 
(type));
-          value_id = gsk_spv_writer_add_conversion (writer, value_id, value_type, new_value_type);
+          value_id = gsk_spv_writer_convert (writer, value_id, value_type, new_value_type);
           value_type = new_value_type;
         }
       
@@ -1804,79 +1625,64 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
       one_id = gsk_spv_writer_get_id_for_one (writer, gsk_sl_type_get_scalar_type (scalar_type));
       gsk_sl_value_free (value);
 
-      scalar_type_id = gsk_spv_writer_get_id_for_type (writer, scalar_type);
-      col_ids[0] = gsk_spv_writer_get_id_for_type (writer, col_type);
       for (c = 0; c < cols; c++)
         {
           for (r = 0; r < rows; r++)
             {
               if (c < value_cols && r < value_rows)
                 {
-                  col_ids[2 + r] = gsk_spv_writer_next_id (writer);
-                  gsk_spv_writer_add (writer,
-                                      GSK_SPV_WRITER_SECTION_CODE,
-                                      6, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                                      (guint32[5]) { scalar_type_id,
-                                                     col_ids[2 + r],
-                                                     value_id,
-                                                     c,
-                                                     r });
+                  col_ids[r] = gsk_spv_writer_composite_extract (writer,
+                                                                 scalar_type,
+                                                                 value_id,
+                                                                 (guint32[2]) { c, r },
+                                                                 2);
                 }
               else if (c == r)
-                col_ids[2 + r] = one_id;
+                col_ids[r] = one_id;
               else
-                col_ids[2 + r] = zero_id;
+                col_ids[r] = zero_id;
             }
-          col_ids[1] = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              3 + rows, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              col_ids);
-          ids[c + 2] = col_ids[1];
-        }
-      ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
-      ids[1] = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          3 + cols, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                          ids);
-      return ids[1];
+          ids[c] = gsk_spv_writer_composite_construct (writer, col_type, col_ids, rows);
+        }
+      return gsk_spv_writer_composite_construct (writer, type, ids, cols);
     }
   else
     {
       gsize n_components = gsk_sl_type_get_n_components (type);
       GskSlScalarType scalar = gsk_sl_type_get_scalar_type (type);
-      guint32 component_ids[16], component_type_id;
+      GskSlType *component_type;
+      guint32 component_ids[16];
       gsize component = 0, arg, i;
 
-      component_type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (scalar));
+      component_type = gsk_sl_type_get_scalar (scalar);
       for (arg = 0; arg < constructor->n_arguments; arg++)
         {
           value_type = gsk_sl_expression_get_return_type (constructor->arguments[arg]);
           value_id = gsk_sl_expression_write_spv (constructor->arguments[arg], writer);
+          if (gsk_sl_type_get_scalar_type (value_type) != scalar)
+            {
+              GskSlType *new_type = gsk_sl_type_get_matching (value_type, scalar);
+              value_id = gsk_spv_writer_convert (writer,
+                                                 value_id,
+                                                 value_type,
+                                                 new_type);
+              value_type = new_type;
+            }
+
           if (gsk_sl_type_is_scalar (value_type))
             {
-              component_ids[component] = gsk_spv_writer_add_conversion (writer,
-                                                                        value_id,
-                                                                        value_type,
-                                                                        gsk_sl_type_get_scalar (scalar));
+              component_ids[component] = value_id;
               component++;
             }
           else if (gsk_sl_type_is_vector (value_type))
             {
-              GskSlType *converted_type = gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length 
(value_type));
-              value_id = gsk_spv_writer_add_conversion (writer, value_id, value_type, converted_type);
-
               for (i = 0; component < n_components && i < gsk_sl_type_get_length (value_type); i++)
                 {
-                  component_ids[component] = gsk_spv_writer_next_id (writer);
-                  gsk_spv_writer_add (writer,
-                                      GSK_SPV_WRITER_SECTION_CODE,
-                                      5, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                                      (guint32[4]) { component_type_id,
-                                                     component_ids[component],
-                                                     value_id,
-                                                     i });
+                  component_ids[component] = gsk_spv_writer_composite_extract (writer,
+                                                                               component_type,
+                                                                               value_id,
+                                                                               (guint32[1]) { i },
+                                                                               1);
                   component++;
                 }
             }
@@ -1890,19 +1696,11 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
                 {
                   for (r = 0; r < rows && component < n_components; r++)
                     {
-                      component_ids[component] = gsk_spv_writer_next_id (writer);
-                      gsk_spv_writer_add (writer,
-                                          GSK_SPV_WRITER_SECTION_CODE,
-                                          6, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                                          (guint32[5]) { component_type_id,
-                                                         component_ids[component],
-                                                         value_id,
-                                                         c,
-                                                         r });
-                      component_ids[component] = gsk_spv_writer_add_conversion (writer,
-                                                                                component_ids[component],
-                                                                                gsk_sl_type_get_scalar 
(gsk_sl_type_get_scalar_type (value_type)),
-                                                                                gsk_sl_type_get_scalar 
(scalar));
+                      component_ids[component] = gsk_spv_writer_composite_extract (writer,
+                                                                                   component_type,
+                                                                                   value_id,
+                                                                                   (guint32[2]) { c, r },
+                                                                                   2);
                       component++;
                     }
                 }
@@ -1919,47 +1717,20 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
         }
       else if (gsk_sl_type_is_vector (type))
         {
-          guint32 ids[2 + gsk_sl_type_get_length (type)];
-          guint i;
-
-          ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
-          ids[1] = gsk_spv_writer_next_id (writer);
-          for (i = 0; i < gsk_sl_type_get_length (type); i++)
-            ids[2 + i] = component_ids[i];
-
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              2 + gsk_sl_type_get_length (type), GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              ids);
-          return ids[1];
+          return gsk_spv_writer_composite_construct (writer, type, component_ids, gsk_sl_type_get_length 
(type));
         }
       else if (gsk_sl_type_is_matrix (type))
         {
           GskSlType *col_type = gsk_sl_type_get_index_type (type);
           gsize c, cols = gsk_sl_type_get_length (type);
-          gsize r, rows = gsk_sl_type_get_length (col_type);
-          guint32 ids[cols + 2], col_ids[rows + 2];
+          gsize rows = gsk_sl_type_get_length (col_type);
+          guint32 ids[cols];
 
-          col_ids[1] = gsk_spv_writer_get_id_for_type (writer, col_type);
           for (c = 0; c < cols; c++)
             {
-              for (r = 0; r < rows; r++)
-                {
-                }
-              col_ids[1] = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  3 + rows, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                                  col_ids);
-              ids[c + 2] = col_ids[1];
+              ids[c] = gsk_spv_writer_composite_construct (writer, col_type, &component_ids[c * rows], rows);
             }
-          ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
-          ids[1] = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              3 + cols, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              ids);
-          return ids[1];
+          return gsk_spv_writer_composite_construct (writer, type, ids, cols);
         }
       else
         {
@@ -2145,22 +1916,14 @@ gsk_sl_expression_member_write_spv (const GskSlExpression *expression,
 {
   const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
   GskSlType *type;
-  guint32 expr_id, type_id, result_id;
 
   type = gsk_sl_expression_get_return_type (member->expr);
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_member_type (type, member->id));
-  expr_id = gsk_sl_expression_write_spv (member->expr, writer);
-  result_id = gsk_spv_writer_next_id (writer);
-
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_CODE,
-                      5, GSK_SPV_OP_ACCESS_CHAIN,
-                      (guint32[4]) { type_id,
-                                     result_id,
-                                     expr_id,
-                                     member->id });
 
-  return result_id;
+  return gsk_spv_writer_composite_extract (writer,
+                                           gsk_sl_type_get_member_type (type, member->id),
+                                           gsk_sl_expression_write_spv (member->expr, writer),
+                                           (guint32[1]) { member->id },
+                                           1);
 }
 
 static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = {
@@ -2271,7 +2034,7 @@ gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
 {
   const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
   GskSlType *type;
-  guint32 expr_id, type_id, result_id;
+  guint32 expr_id;
 
   type = gsk_sl_expression_get_return_type (swizzle->expr);
   expr_id = gsk_sl_expression_write_spv (swizzle->expr, writer);
@@ -2281,51 +2044,35 @@ gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
       if (swizzle->length == 1)
         return expr_id;
 
-      type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
-      result_id = gsk_spv_writer_next_id (writer);
-
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          3 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                          (guint32[6]) { type_id,
-                                         result_id,
-                                         expr_id,
-                                         expr_id,
-                                         expr_id,
-                                         expr_id });
-
-      return result_id;
+      return gsk_spv_writer_composite_construct (writer,
+                                                 gsk_sl_expression_get_return_type (expression),
+                                                 (guint32[4]) { expr_id, expr_id, expr_id, expr_id },
+                                                 swizzle->length);
     }
   else if (gsk_sl_type_is_vector (type))
     {
-      type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
-      result_id = gsk_spv_writer_next_id (writer);
-
       if (swizzle->length == 1)
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              4, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                              (guint32[6]) { type_id,
-                                             result_id,
-                                             swizzle->indexes[0] });
+          return gsk_spv_writer_composite_extract (writer,
+                                                   type,
+                                                   expr_id,
+                                                   (guint32[1]) { swizzle->indexes[0] },
+                                                   1);
         }
       else
         {
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                              (guint32[8]) { type_id,
-                                             result_id,
-                                             expr_id,
-                                             expr_id,
-                                             swizzle->indexes[0],
-                                             swizzle->indexes[1],
-                                             swizzle->indexes[2],
-                                             swizzle->indexes[3] });
+          return gsk_spv_writer_vector_shuffle (writer,
+                                                type,
+                                                expr_id,
+                                                expr_id,
+                                                (guint32[4]) {
+                                                    swizzle->indexes[0],
+                                                    swizzle->indexes[1],
+                                                    swizzle->indexes[2],
+                                                    swizzle->indexes[3]
+                                                },
+                                                swizzle->length);
         }
-
-      return result_id;
     }
   else
     {
@@ -2432,42 +2179,28 @@ gsk_sl_expression_negation_write_spv (const GskSlExpression *expression,
                                       GskSpvWriter          *writer)
 {
   const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
-  guint type_id, expr_id, result_id;
-  GskSlType *type;
-
-  type = gsk_sl_expression_get_return_type (negation->expr);
-  type_id = gsk_spv_writer_get_id_for_type (writer, type);
-  expr_id = gsk_sl_expression_write_spv (negation->expr, writer);
-  result_id = gsk_spv_writer_next_id (writer);
+  GskSlType *type = gsk_sl_expression_get_return_type (negation->expr);
 
   switch (gsk_sl_type_get_scalar_type (type))
     {
     case GSK_SL_INT:
     case GSK_SL_UINT:
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          4, GSK_SPV_OP_S_NEGATE,
-                          (guint32[3]) { type_id,
-                                         result_id,
-                                         expr_id });
-      break;
+      return gsk_spv_writer_s_negate (writer,
+                                      type,
+                                      gsk_sl_expression_write_spv (negation->expr, writer));
+
     case GSK_SL_FLOAT:
     case GSK_SL_DOUBLE:
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          4, GSK_SPV_OP_F_NEGATE,
-                          (guint32[3]) { type_id,
-                                         result_id,
-                                         expr_id });
-      break;
+      return gsk_spv_writer_f_negate (writer,
+                                      type,
+                                      gsk_sl_expression_write_spv (negation->expr, writer));
+
     case GSK_SL_VOID:
     case GSK_SL_BOOL:
     default:
       g_assert_not_reached ();
-      break;
+      return 0;
     }
-
-  return result_id;
 }
 
 static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 2fc2032..0f26119 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -307,7 +307,7 @@ gsk_sl_function_declared_get_argument_type (const GskSlFunction *function,
 {
   const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
 
-  return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i]));
+  return gsk_sl_variable_get_type (declared->arguments[i]);
 }
 
 static GskSlValue *
@@ -356,7 +356,8 @@ gsk_sl_function_declared_write_spv (const GskSlFunction *function,
                                     GskSpvWriter        *writer)
 {
   GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
-  guint32 return_type_id, function_type_id, function_id, label_id;
+  guint32 return_type_id, function_type_id, function_id;
+  guint32 argument_types[declared->n_arguments];
   gsize i;
 
   if (declared->statement == NULL)
@@ -364,24 +365,16 @@ gsk_sl_function_declared_write_spv (const GskSlFunction *function,
 
   /* declare type of function */
   return_type_id = gsk_spv_writer_get_id_for_type (writer, declared->return_type);
-  function_type_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3, GSK_SPV_OP_TYPE_FUNCTION,
-                      (guint32[2]) { function_type_id,
-                                     return_type_id });
+  for (i = 0; i < declared->n_arguments; i++)
+    {
+      argument_types[i] = gsk_spv_writer_get_id_for_type (writer, gsk_sl_variable_get_type 
(declared->arguments[i]));
+    }
+  function_type_id = gsk_spv_writer_type_function (writer, return_type_id, argument_types, 
declared->n_arguments);
 
   /* add debug info */
   /* FIXME */
 
-  function_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_CODE,
-                      5, GSK_SPV_OP_FUNCTION,
-                      (guint32[4]) { return_type_id,
-                                     function_id,
-                                     0,
-                                     function_type_id });
+  function_id = gsk_spv_writer_function (writer, declared->return_type, 0, function_type_id);
   /* add function header */
   for (i = 0; i < declared->n_arguments; i++)
     {
@@ -389,26 +382,15 @@ gsk_sl_function_declared_write_spv (const GskSlFunction *function,
     }
 
   /* add function body */
-  label_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_CODE,
-                      2, GSK_SPV_OP_LABEL,
-                      (guint32[1]) { label_id });
+  gsk_spv_writer_label (writer);
 
   gsk_sl_statement_write_spv (declared->statement, writer);
 
   if (gsk_sl_type_is_void (declared->return_type) &&
       gsk_sl_statement_get_jump (declared->statement) < GSK_SL_JUMP_RETURN)
-    {
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          1, GSK_SPV_OP_RETURN,
-                          NULL);
-    }
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_CODE,
-                      1, GSK_SPV_OP_FUNCTION_END,
-                      NULL);
+    gsk_spv_writer_return (writer);
+
+  gsk_spv_writer_function_end (writer);
 
   return function_id;
 }
diff --git a/gsk/gskslpointertype.c b/gsk/gskslpointertype.c
index 380d4a8..6cfa2ed 100644
--- a/gsk/gskslpointertype.c
+++ b/gsk/gskslpointertype.c
@@ -115,17 +115,7 @@ guint32
 gsk_sl_pointer_type_write_spv (const GskSlPointerType *type,
                                GskSpvWriter           *writer)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, type->type);
-  result_id = gsk_spv_writer_next_id (writer);
-
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_TYPE_POINTER,
-                      (guint32[3]) { result_id,
-                                     gsk_sl_qualifier_get_storage_class (&type->qualifier),
-                                     type_id });
-
-  return result_id;
+  return gsk_spv_writer_type_pointer (writer, 
+                                      gsk_sl_qualifier_get_storage_class (&type->qualifier),
+                                      gsk_spv_writer_get_id_for_type (writer, type->type));
 }
diff --git a/gsk/gskslstatement.c b/gsk/gskslstatement.c
index e2bc0f5..7d2eb11 100644
--- a/gsk/gskslstatement.c
+++ b/gsk/gskslstatement.c
@@ -234,17 +234,16 @@ gsk_sl_statement_declaration_write_spv (const GskSlStatement *statement,
                                         GskSpvWriter         *writer)
 {
   GskSlStatementDeclaration *declaration = (GskSlStatementDeclaration *) statement;
-  guint32 variable_id;
-
-  variable_id = gsk_spv_writer_get_id_for_variable (writer, declaration->variable);
   
+  /* make sure it's written */
+  gsk_spv_writer_get_id_for_variable (writer, declaration->variable);
+
   if (declaration->initial && ! gsk_sl_variable_get_initial_value (declaration->variable))
     {
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          3, GSK_SPV_OP_STORE,
-                          (guint32[2]) { variable_id,
-                                         gsk_sl_expression_write_spv (declaration->initial, writer)});
+      gsk_spv_writer_store (writer,
+                            gsk_spv_writer_get_id_for_variable (writer, declaration->variable),
+                            gsk_sl_expression_write_spv (declaration->initial, writer),
+                            0);
     }
 }
 
@@ -305,20 +304,12 @@ gsk_sl_statement_return_write_spv (const GskSlStatement *statement,
 
   if (return_statement->value)
     {
-      guint32 value_id;
-      
-      value_id = gsk_sl_expression_write_spv (return_statement->value, writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          2, GSK_SPV_OP_RETURN_VALUE,
-                          (guint32[1]) { value_id });
+      gsk_spv_writer_return_value (writer,
+                                   gsk_sl_expression_write_spv (return_statement->value, writer));
     }
   else
     {
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          1, GSK_SPV_OP_RETURN,
-                          NULL);
+      gsk_spv_writer_return (writer);
     }
 }
 
@@ -401,6 +392,7 @@ static void
 gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
                                GskSpvWriter         *writer)
 {
+#if 0 
   GskSlStatementIf *if_stmt = (GskSlStatementIf *) statement;
   guint32 label_id, if_id, else_id, condition_id;
 
@@ -451,6 +443,8 @@ gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
                       GSK_SPV_WRITER_SECTION_CODE,
                       2, GSK_SPV_OP_LABEL,
                       (guint32[1]) { label_id });
+#endif
+  g_assert_not_reached ();
 }
 
 static const GskSlStatementClass GSK_SL_STATEMENT_IF = {
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index c5433af..29fdc1d 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -102,18 +102,10 @@ static guint32
 write_float_spv (GskSpvWriter  *writer,
                  gconstpointer  value)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_FLOAT));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_CONSTANT,
-                      (guint32[3]) { type_id,
-                                     result_id,
-                                     *(const guint32 *) value });
-
-  return result_id;
+  return gsk_spv_writer_constant (writer,
+                                  gsk_sl_type_get_scalar (GSK_SL_FLOAT),
+                                  (guint32 *) value,
+                                  1);
 }
 
 static void
@@ -129,19 +121,10 @@ static guint32
 write_double_spv (GskSpvWriter  *writer,
                   gconstpointer  value)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_DOUBLE));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      5, GSK_SPV_OP_CONSTANT,
-                      (guint32[4]) { type_id,
-                                     result_id,
-                                     *(const guint32 *) value,
-                                     *(((const guint32 *) value) + 1) });
-
-  return result_id;
+  return gsk_spv_writer_constant (writer,
+                                  gsk_sl_type_get_scalar (GSK_SL_DOUBLE),
+                                  (guint32 *) value,
+                                  2);
 }
 
 static void
@@ -157,18 +140,10 @@ static guint32
 write_int_spv (GskSpvWriter  *writer,
                gconstpointer  value)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_INT));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_CONSTANT,
-                      (guint32[3]) { type_id,
-                                     result_id,
-                                     *(const guint32 *) value });
-
-  return result_id;
+  return gsk_spv_writer_constant (writer,
+                                  gsk_sl_type_get_scalar (GSK_SL_INT),
+                                  (guint32 *) value,
+                                  1);
 }
 
 static void
@@ -185,18 +160,10 @@ static guint32
 write_uint_spv (GskSpvWriter  *writer,
                 gconstpointer  value)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_UINT));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_CONSTANT,
-                      (guint32[3]) { type_id,
-                                     result_id,
-                                     *(const guint32 *) value });
-
-  return result_id;
+  return gsk_spv_writer_constant (writer,
+                                  gsk_sl_type_get_scalar (GSK_SL_UINT),
+                                  (guint32 *) value,
+                                  1);
 }
 
 static void
@@ -212,17 +179,12 @@ static guint32
 write_bool_spv (GskSpvWriter  *writer,
                 gconstpointer  value)
 {
-  guint32 type_id, result_id;
-
-  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_BOOL));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3, *(const guint32 *) value ? GSK_SPV_OP_CONSTANT_TRUE : GSK_SPV_OP_CONSTANT_FALSE,
-                      (guint32[2]) { type_id,
-                                     result_id });
-  
-  return result_id;
+  if (*(const guint32 *) value)
+    return gsk_spv_writer_constant_true (writer, 
+                                         gsk_sl_type_get_scalar (GSK_SL_BOOL));
+  else
+    return gsk_spv_writer_constant_false (writer, 
+                                          gsk_sl_type_get_scalar (GSK_SL_BOOL));
 }
 
 #define SIMPLE_CONVERSION(source_name, target_name, source_type, target_type) \
@@ -452,15 +414,7 @@ static guint32
 gsk_sl_type_void_write_spv (GskSlType    *type,
                             GskSpvWriter *writer)
 {
-  guint32 result;
-
-  result = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      2, GSK_SPV_OP_TYPE_VOID,
-                      (guint32[1]) { result });
-
-  return result;
+  return gsk_spv_writer_type_void (writer);
 }
 
 static void
@@ -602,70 +556,29 @@ gsk_sl_type_scalar_write_spv (GskSlType    *type,
                               GskSpvWriter *writer)
 {
   GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
-  guint32 result;
 
   switch (scalar->scalar)
   {
-    case GSK_SL_VOID:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          2, GSK_SPV_OP_TYPE_VOID,
-                          (guint32[1]) { result });
-      break;
-
     case GSK_SL_FLOAT:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          3, GSK_SPV_OP_TYPE_FLOAT,
-                          (guint32[2]) { result,
-                                         32 });
-      break;
+      return gsk_spv_writer_type_float (writer, 32);
 
     case GSK_SL_DOUBLE:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          3, GSK_SPV_OP_TYPE_FLOAT,
-                          (guint32[2]) { result,
-                                         64 });
-      break;
+      return gsk_spv_writer_type_float (writer, 64);
 
     case GSK_SL_INT:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          4, GSK_SPV_OP_TYPE_INT,
-                          (guint32[3]) { result,
-                                         32,
-                                         1 });
-      break;
+      return gsk_spv_writer_type_int (writer, 32, 1);
 
     case GSK_SL_UINT:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          4, GSK_SPV_OP_TYPE_INT,
-                          (guint32[3]) { result,
-                                         32,
-                                         0 });
-      break;
+      return gsk_spv_writer_type_int (writer, 32, 0);
 
     case GSK_SL_BOOL:
-      result = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_DECLARE,
-                          2, GSK_SPV_OP_TYPE_BOOL,
-                          (guint32[1]) { result });
-      break;
+      return gsk_spv_writer_type_bool (writer);
 
+    case GSK_SL_VOID:
     default:
       g_assert_not_reached ();
-      break;
+      return 0;
   }
-
-  return result;
 }
 
 static void
@@ -824,18 +737,10 @@ gsk_sl_type_vector_write_spv (GskSlType    *type,
                               GskSpvWriter *writer)
 {
   GskSlTypeVector *vector = (GskSlTypeVector *) type;
-  guint32 result_id, scalar_id;
-
-  scalar_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (vector->scalar));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_TYPE_VECTOR,
-                      (guint32[3]) { result_id,
-                                     scalar_id,
-                                     vector->length });
-  
-  return result_id;
+
+  return gsk_spv_writer_type_vector (writer,
+                                     gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar 
(vector->scalar)),
+                                     vector->length);
 }
 
 static void
@@ -891,7 +796,7 @@ gsk_sl_type_vector_write_value_spv (GskSlType     *type,
                                     gconstpointer  value)
 {
   GskSlTypeVector *vector = (GskSlTypeVector *) type;
-  guint32 ids[vector->length + 2];
+  guint32 ids[vector->length];
   GskSlType *scalar_type;
   GskSlValue *v;
   const guchar *data;
@@ -900,23 +805,18 @@ gsk_sl_type_vector_write_value_spv (GskSlType     *type,
   data = value;
   scalar_type = gsk_sl_type_get_scalar (vector->scalar);
 
-  ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
   for (i = 0; i < vector->length; i++)
     {
       v = gsk_sl_value_new_for_data (scalar_type, (gpointer) data, NULL, NULL);
-      ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
+      ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
       gsk_sl_value_free (v);
       data += scalar_infos[vector->scalar].size;
     }
-  ids[1] = gsk_spv_writer_next_id (writer);
 
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3 + vector->length,
-                      GSK_SPV_OP_CONSTANT_COMPOSITE,
-                      ids);
-  
-  return ids[1];
+  return gsk_spv_writer_constant_composite (writer,
+                                            type,
+                                            ids,
+                                            vector->length);
 }
 
 static const GskSlTypeClass GSK_SL_TYPE_VECTOR = {
@@ -1047,18 +947,10 @@ gsk_sl_type_matrix_write_spv (GskSlType    *type,
                               GskSpvWriter *writer)
 {
   GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
-  guint32 result_id, vector_id;
-
-  vector_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_index_type (type));
-  result_id = gsk_spv_writer_next_id (writer);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      4, GSK_SPV_OP_TYPE_MATRIX,
-                      (guint32[3]) { result_id,
-                                     vector_id,
-                                     matrix->columns });
-  
-  return result_id;
+
+  return gsk_spv_writer_type_matrix (writer,
+                                     gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_index_type 
(type)),
+                                     matrix->columns);
 }
 
 static void
@@ -1114,7 +1006,7 @@ gsk_sl_type_matrix_write_value_spv (GskSlType     *type,
                                     gconstpointer  value)
 {
   GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
-  guint32 ids[matrix->rows + 2];
+  guint32 ids[matrix->rows];
   GskSlType *vector_type;
   GskSlValue *v;
   const guchar *data;
@@ -1123,23 +1015,18 @@ gsk_sl_type_matrix_write_value_spv (GskSlType     *type,
   data = value;
   vector_type = gsk_sl_type_get_index_type (type);
 
-  ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
   for (i = 0; i < matrix->columns; i++)
     {
       v = gsk_sl_value_new_for_data (vector_type, (gpointer) data, NULL, NULL);
-      ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
+      ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
       gsk_sl_value_free (v);
       data += gsk_sl_type_get_size (vector_type);
     }
-  ids[1] = gsk_spv_writer_next_id (writer);
 
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3 + matrix->columns,
-                      GSK_SPV_OP_CONSTANT_COMPOSITE,
-                      ids);
-  
-  return ids[1];
+  return gsk_spv_writer_constant_composite (writer,
+                                            type,
+                                            ids,
+                                            matrix->columns);
 }
 
 static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
@@ -1267,22 +1154,17 @@ gsk_sl_type_struct_write_spv (GskSlType    *type,
                               GskSpvWriter *writer)
 {
   GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
-  guint32 ids[struc->n_members + 1];
+  guint32 ids[struc->n_members];
   guint i;
 
-  ids[0] = gsk_spv_writer_next_id (writer);
-
   for (i = 0; i < struc->n_members; i++)
     {
-      ids[i + 1] = gsk_spv_writer_get_id_for_type (writer, struc->members[i].type);
+      ids[i] = gsk_spv_writer_get_id_for_type (writer, struc->members[i].type);
     }
 
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      2 + struc->n_members, GSK_SPV_OP_TYPE_STRUCT,
-                      ids);
-  
-  return ids[0];
+  return gsk_spv_writer_type_struct (writer,
+                                     ids,
+                                     struc->n_members);
 }
 
 static void
@@ -1337,29 +1219,23 @@ gsk_sl_type_struct_write_value_spv (GskSlType     *type,
                                     gconstpointer  value)
 {
   GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
-  guint32 ids[struc->n_members + 2];
+  guint32 ids[struc->n_members];
   GskSlValue *v;
   guint i;
 
-  ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
   for (i = 0; i < struc->n_members; i++)
     {
       v = gsk_sl_value_new_for_data (struc->members[i].type,
                                      (guchar *) value + struc->members[i].offset,
                                      NULL, NULL);
-      ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
+      ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
       gsk_sl_value_free (v);
     }
 
-  ids[1] = gsk_spv_writer_next_id (writer);
-
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3 + struc->n_members,
-                      GSK_SPV_OP_CONSTANT_COMPOSITE,
-                      ids);
-  
-  return ids[1];
+  return gsk_spv_writer_constant_composite (writer,
+                                            type,
+                                            ids,
+                                            struc->n_members);
 }
 
 static const GskSlTypeClass GSK_SL_TYPE_STRUCT = {
@@ -1487,28 +1363,21 @@ gsk_sl_type_block_write_spv (GskSlType    *type,
                              GskSpvWriter *writer)
 {
   GskSlTypeBlock *block = (GskSlTypeBlock *) type;
-  guint32 ids[block->n_members + 1];
+  guint32 ids[block->n_members], result_id;
   guint i;
 
-  ids[0] = gsk_spv_writer_next_id (writer);
-
   for (i = 0; i < block->n_members; i++)
     {
-      ids[i + 1] = gsk_spv_writer_get_id_for_type (writer, block->members[i].type);
+      ids[i] = gsk_spv_writer_get_id_for_type (writer, block->members[i].type);
     }
 
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DEBUG,
-                      3, GSK_SPV_OP_DECORATE,
-                      (guint32[2]) { ids[0],
-                                     GSK_SPV_DECORATION_BLOCK });
+  result_id = gsk_spv_writer_type_struct (writer,
+                                          ids, 
+                                          block->n_members);
   
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      2 + block->n_members, GSK_SPV_OP_TYPE_STRUCT,
-                      ids);
-  
-  return ids[0];
+  gsk_spv_writer_decorate (writer, result_id, GSK_SPV_DECORATION_BLOCK);
+
+  return result_id;
 }
 
 static void
@@ -1563,29 +1432,23 @@ gsk_sl_type_block_write_value_spv (GskSlType     *type,
                                    gconstpointer  value)
 {
   GskSlTypeBlock *block = (GskSlTypeBlock *) type;
-  guint32 ids[block->n_members + 2];
+  guint32 ids[block->n_members];
   GskSlValue *v;
   guint i;
 
-  ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
   for (i = 0; i < block->n_members; i++)
     {
       v = gsk_sl_value_new_for_data (block->members[i].type,
                                      (guchar *) value + block->members[i].offset,
                                      NULL, NULL);
-      ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
+      ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
       gsk_sl_value_free (v);
     }
 
-  ids[1] = gsk_spv_writer_next_id (writer);
-
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_DECLARE,
-                      3 + block->n_members,
-                      GSK_SPV_OP_CONSTANT_COMPOSITE,
-                      ids);
-  
-  return ids[1];
+  return gsk_spv_writer_constant_composite (writer,
+                                            type,
+                                            ids,
+                                            block->n_members);
 }
 
 static const GskSlTypeClass GSK_SL_TYPE_BLOCK = {
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index b223650..60e1dba 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -117,9 +117,15 @@ gsk_sl_variable_print (const GskSlVariable *variable,
     }
 }
 
-GskSlPointerType *
+GskSlType *
 gsk_sl_variable_get_type (const GskSlVariable *variable)
 {
+  return gsk_sl_pointer_type_get_type (variable->type);
+}
+
+GskSlPointerType *
+gsk_sl_variable_get_pointer_type (const GskSlVariable *variable)
+{
   return variable->type;
 }
 
@@ -147,36 +153,21 @@ gsk_sl_variable_write_spv (const GskSlVariable *variable,
 {
   if (gsk_sl_qualifier_get_location (gsk_sl_pointer_type_get_qualifier (variable->type)) == 
GSK_SL_QUALIFIER_PARAMETER)
     {
-      guint32 type_id, variable_id;
-
-      type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_pointer_type_get_type (variable->type));
-      variable_id = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          3, GSK_SPV_OP_FUNCTION_PARAMETER,
-                          (guint32[2]) { type_id,
-                                         variable_id });
-
-      return variable_id;
+      return gsk_spv_writer_function_parameter (writer,
+                                                gsk_sl_pointer_type_get_type (variable->type));
     }
   else
     {
-      guint32 pointer_type_id, variable_id, value_id;
+      guint32 value_id;
 
-      pointer_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, variable->type);
-      variable_id = gsk_spv_writer_next_id (writer);
       if (variable->initial_value)
         value_id = gsk_spv_writer_get_id_for_value (writer, variable->initial_value);
       else
         value_id = 0;
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          variable->initial_value ? 5 : 4, GSK_SPV_OP_VARIABLE,
-                          (guint32[4]) { pointer_type_id,
-                                         variable_id,
-                                         gsk_sl_qualifier_get_storage_class 
(gsk_sl_pointer_type_get_qualifier (variable->type)),
-                                         value_id });
-
-      return variable_id;
+
+      return gsk_spv_writer_variable (writer,
+                                      variable->type,
+                                      gsk_sl_qualifier_get_storage_class (gsk_sl_pointer_type_get_qualifier 
(variable->type)),
+                                      value_id);
     }
 }
diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h
index 2c169ff..917f47b 100644
--- a/gsk/gskslvariableprivate.h
+++ b/gsk/gskslvariableprivate.h
@@ -35,7 +35,8 @@ void                    gsk_sl_variable_unref                   (GskSlVariable
 void                    gsk_sl_variable_print                   (const GskSlVariable    *variable,
                                                                  GskSlPrinter           *printer);
 
-GskSlPointerType *      gsk_sl_variable_get_type                (const GskSlVariable    *variable);
+GskSlType *             gsk_sl_variable_get_type                (const GskSlVariable    *variable);
+GskSlPointerType *      gsk_sl_variable_get_pointer_type        (const GskSlVariable    *variable);
 const char *            gsk_sl_variable_get_name                (const GskSlVariable    *variable);
 const GskSlValue *      gsk_sl_variable_get_initial_value       (const GskSlVariable    *variable);
 gboolean                gsk_sl_variable_is_constant             (const GskSlVariable    *variable);
diff --git a/gsk/gskspvenumsprivate.h b/gsk/gskspvenumsprivate.h
new file mode 100644
index 0000000..40c1a2e
--- /dev/null
+++ b/gsk/gskspvenumsprivate.h
@@ -0,0 +1,855 @@
+/* GTK - The GIMP Toolkit
+ *   
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * !!! THIS FILE WAS AUTOGENERATED !!!
+ * 
+ * This file was created using the command
+ *   gjs spirv.js enums spirv.core.grammar.json
+ * Apply any changes to those files and then regenerate using above command.
+ */
+
+#ifndef __GSK_SPV_ENUMS_H__
+#define __GSK_SPV_ENUMS_H__
+
+typedef enum {
+  GSK_SPV_IMAGE_OPERANDS_NONE = 0x0000,
+  GSK_SPV_IMAGE_OPERANDS_BIAS = 0x0001,
+  GSK_SPV_IMAGE_OPERANDS_LOD = 0x0002,
+  GSK_SPV_IMAGE_OPERANDS_GRAD = 0x0004,
+  GSK_SPV_IMAGE_OPERANDS_CONST_OFFSET = 0x0008,
+  GSK_SPV_IMAGE_OPERANDS_OFFSET = 0x0010,
+  GSK_SPV_IMAGE_OPERANDS_CONST_OFFSETS = 0x0020,
+  GSK_SPV_IMAGE_OPERANDS_SAMPLE = 0x0040,
+  GSK_SPV_IMAGE_OPERANDS_MIN_LOD = 0x0080
+} GskSpvImageOperands;
+
+typedef enum {
+  GSK_SPV_FP_FAST_MATH_MODE_NONE = 0x0000,
+  GSK_SPV_FP_FAST_MATH_MODE_NOT_NA_N = 0x0001,
+  GSK_SPV_FP_FAST_MATH_MODE_NOT_INF = 0x0002,
+  GSK_SPV_FP_FAST_MATH_MODE_NSZ = 0x0004,
+  GSK_SPV_FP_FAST_MATH_MODE_ALLOW_RECIP = 0x0008,
+  GSK_SPV_FP_FAST_MATH_MODE_FAST = 0x0010
+} GskSpvFPFastMathMode;
+
+typedef enum {
+  GSK_SPV_SELECTION_CONTROL_NONE = 0x0000,
+  GSK_SPV_SELECTION_CONTROL_FLATTEN = 0x0001,
+  GSK_SPV_SELECTION_CONTROL_DONT_FLATTEN = 0x0002
+} GskSpvSelectionControl;
+
+typedef enum {
+  GSK_SPV_LOOP_CONTROL_NONE = 0x0000,
+  GSK_SPV_LOOP_CONTROL_UNROLL = 0x0001,
+  GSK_SPV_LOOP_CONTROL_DONT_UNROLL = 0x0002
+} GskSpvLoopControl;
+
+typedef enum {
+  GSK_SPV_FUNCTION_CONTROL_NONE = 0x0000,
+  GSK_SPV_FUNCTION_CONTROL_INLINE = 0x0001,
+  GSK_SPV_FUNCTION_CONTROL_DONT_INLINE = 0x0002,
+  GSK_SPV_FUNCTION_CONTROL_PURE = 0x0004,
+  GSK_SPV_FUNCTION_CONTROL_CONST = 0x0008
+} GskSpvFunctionControl;
+
+typedef enum {
+  GSK_SPV_MEMORY_SEMANTICS_RELAXED = 0x0000,
+  GSK_SPV_MEMORY_SEMANTICS_NONE = 0x0000,
+  GSK_SPV_MEMORY_SEMANTICS_ACQUIRE = 0x0002,
+  GSK_SPV_MEMORY_SEMANTICS_RELEASE = 0x0004,
+  GSK_SPV_MEMORY_SEMANTICS_ACQUIRE_RELEASE = 0x0008,
+  GSK_SPV_MEMORY_SEMANTICS_SEQUENTIALLY_CONSISTENT = 0x0010,
+  GSK_SPV_MEMORY_SEMANTICS_UNIFORM_MEMORY = 0x0040,
+  GSK_SPV_MEMORY_SEMANTICS_SUBGROUP_MEMORY = 0x0080,
+  GSK_SPV_MEMORY_SEMANTICS_WORKGROUP_MEMORY = 0x0100,
+  GSK_SPV_MEMORY_SEMANTICS_CROSS_WORKGROUP_MEMORY = 0x0200,
+  GSK_SPV_MEMORY_SEMANTICS_ATOMIC_COUNTER_MEMORY = 0x0400,
+  GSK_SPV_MEMORY_SEMANTICS_IMAGE_MEMORY = 0x0800
+} GskSpvMemorySemantics;
+
+typedef enum {
+  GSK_SPV_MEMORY_ACCESS_NONE = 0x0000,
+  GSK_SPV_MEMORY_ACCESS_VOLATILE = 0x0001,
+  GSK_SPV_MEMORY_ACCESS_ALIGNED = 0x0002,
+  GSK_SPV_MEMORY_ACCESS_NONTEMPORAL = 0x0004
+} GskSpvMemoryAccess;
+
+typedef enum {
+  GSK_SPV_KERNEL_PROFILING_INFO_NONE = 0x0000,
+  GSK_SPV_KERNEL_PROFILING_INFO_CMD_EXEC_TIME = 0x0001
+} GskSpvKernelProfilingInfo;
+
+typedef enum {
+  GSK_SPV_SOURCE_LANGUAGE_UNKNOWN = 0,
+  GSK_SPV_SOURCE_LANGUAGE_ESSL = 1,
+  GSK_SPV_SOURCE_LANGUAGE_GLSL = 2,
+  GSK_SPV_SOURCE_LANGUAGE_OPEN_CL_C = 3,
+  GSK_SPV_SOURCE_LANGUAGE_OPEN_CL_CPP = 4,
+  GSK_SPV_SOURCE_LANGUAGE_HLSL = 5
+} GskSpvSourceLanguage;
+
+typedef enum {
+  GSK_SPV_EXECUTION_MODEL_VERTEX = 0,
+  GSK_SPV_EXECUTION_MODEL_TESSELLATION_CONTROL = 1,
+  GSK_SPV_EXECUTION_MODEL_TESSELLATION_EVALUATION = 2,
+  GSK_SPV_EXECUTION_MODEL_GEOMETRY = 3,
+  GSK_SPV_EXECUTION_MODEL_FRAGMENT = 4,
+  GSK_SPV_EXECUTION_MODEL_GL_COMPUTE = 5,
+  GSK_SPV_EXECUTION_MODEL_KERNEL = 6
+} GskSpvExecutionModel;
+
+typedef enum {
+  GSK_SPV_ADDRESSING_MODEL_LOGICAL = 0,
+  GSK_SPV_ADDRESSING_MODEL_PHYSICAL32 = 1,
+  GSK_SPV_ADDRESSING_MODEL_PHYSICAL64 = 2
+} GskSpvAddressingModel;
+
+typedef enum {
+  GSK_SPV_MEMORY_MODEL_SIMPLE = 0,
+  GSK_SPV_MEMORY_MODEL_GLSL450 = 1,
+  GSK_SPV_MEMORY_MODEL_OPEN_CL = 2
+} GskSpvMemoryModel;
+
+typedef enum {
+  GSK_SPV_EXECUTION_MODE_INVOCATIONS = 0,
+  GSK_SPV_EXECUTION_MODE_SPACING_EQUAL = 1,
+  GSK_SPV_EXECUTION_MODE_SPACING_FRACTIONAL_EVEN = 2,
+  GSK_SPV_EXECUTION_MODE_SPACING_FRACTIONAL_ODD = 3,
+  GSK_SPV_EXECUTION_MODE_VERTEX_ORDER_CW = 4,
+  GSK_SPV_EXECUTION_MODE_VERTEX_ORDER_CCW = 5,
+  GSK_SPV_EXECUTION_MODE_PIXEL_CENTER_INTEGER = 6,
+  GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT = 7,
+  GSK_SPV_EXECUTION_MODE_ORIGIN_LOWER_LEFT = 8,
+  GSK_SPV_EXECUTION_MODE_EARLY_FRAGMENT_TESTS = 9,
+  GSK_SPV_EXECUTION_MODE_POINT_MODE = 10,
+  GSK_SPV_EXECUTION_MODE_XFB = 11,
+  GSK_SPV_EXECUTION_MODE_DEPTH_REPLACING = 12,
+  GSK_SPV_EXECUTION_MODE_DEPTH_GREATER = 14,
+  GSK_SPV_EXECUTION_MODE_DEPTH_LESS = 15,
+  GSK_SPV_EXECUTION_MODE_DEPTH_UNCHANGED = 16,
+  GSK_SPV_EXECUTION_MODE_LOCAL_SIZE = 17,
+  GSK_SPV_EXECUTION_MODE_LOCAL_SIZE_HINT = 18,
+  GSK_SPV_EXECUTION_MODE_INPUT_POINTS = 19,
+  GSK_SPV_EXECUTION_MODE_INPUT_LINES = 20,
+  GSK_SPV_EXECUTION_MODE_INPUT_LINES_ADJACENCY = 21,
+  GSK_SPV_EXECUTION_MODE_TRIANGLES = 22,
+  GSK_SPV_EXECUTION_MODE_INPUT_TRIANGLES_ADJACENCY = 23,
+  GSK_SPV_EXECUTION_MODE_QUADS = 24,
+  GSK_SPV_EXECUTION_MODE_ISOLINES = 25,
+  GSK_SPV_EXECUTION_MODE_OUTPUT_VERTICES = 26,
+  GSK_SPV_EXECUTION_MODE_OUTPUT_POINTS = 27,
+  GSK_SPV_EXECUTION_MODE_OUTPUT_LINE_STRIP = 28,
+  GSK_SPV_EXECUTION_MODE_OUTPUT_TRIANGLE_STRIP = 29,
+  GSK_SPV_EXECUTION_MODE_VEC_TYPE_HINT = 30,
+  GSK_SPV_EXECUTION_MODE_CONTRACTION_OFF = 31,
+  GSK_SPV_EXECUTION_MODE_POST_DEPTH_COVERAGE = 4446,
+  GSK_SPV_EXECUTION_MODE_STENCIL_REF_REPLACING_EXT = 5027
+} GskSpvExecutionMode;
+
+typedef enum {
+  GSK_SPV_STORAGE_CLASS_UNIFORM_CONSTANT = 0,
+  GSK_SPV_STORAGE_CLASS_INPUT = 1,
+  GSK_SPV_STORAGE_CLASS_UNIFORM = 2,
+  GSK_SPV_STORAGE_CLASS_OUTPUT = 3,
+  GSK_SPV_STORAGE_CLASS_WORKGROUP = 4,
+  GSK_SPV_STORAGE_CLASS_CROSS_WORKGROUP = 5,
+  GSK_SPV_STORAGE_CLASS_PRIVATE = 6,
+  GSK_SPV_STORAGE_CLASS_FUNCTION = 7,
+  GSK_SPV_STORAGE_CLASS_GENERIC = 8,
+  GSK_SPV_STORAGE_CLASS_PUSH_CONSTANT = 9,
+  GSK_SPV_STORAGE_CLASS_ATOMIC_COUNTER = 10,
+  GSK_SPV_STORAGE_CLASS_IMAGE = 11,
+  GSK_SPV_STORAGE_CLASS_STORAGE_BUFFER = 12
+} GskSpvStorageClass;
+
+typedef enum {
+  GSK_SPV_DIM_1_D = 0,
+  GSK_SPV_DIM_2_D = 1,
+  GSK_SPV_DIM_3_D = 2,
+  GSK_SPV_DIM_CUBE = 3,
+  GSK_SPV_DIM_RECT = 4,
+  GSK_SPV_DIM_BUFFER = 5,
+  GSK_SPV_DIM_SUBPASS_DATA = 6
+} GskSpvDim;
+
+typedef enum {
+  GSK_SPV_SAMPLER_ADDRESSING_MODE_NONE = 0,
+  GSK_SPV_SAMPLER_ADDRESSING_MODE_CLAMP_TO_EDGE = 1,
+  GSK_SPV_SAMPLER_ADDRESSING_MODE_CLAMP = 2,
+  GSK_SPV_SAMPLER_ADDRESSING_MODE_REPEAT = 3,
+  GSK_SPV_SAMPLER_ADDRESSING_MODE_REPEAT_MIRRORED = 4
+} GskSpvSamplerAddressingMode;
+
+typedef enum {
+  GSK_SPV_SAMPLER_FILTER_MODE_NEAREST = 0,
+  GSK_SPV_SAMPLER_FILTER_MODE_LINEAR = 1
+} GskSpvSamplerFilterMode;
+
+typedef enum {
+  GSK_SPV_IMAGE_FORMAT_UNKNOWN = 0,
+  GSK_SPV_IMAGE_FORMAT_RGBA32F = 1,
+  GSK_SPV_IMAGE_FORMAT_RGBA16F = 2,
+  GSK_SPV_IMAGE_FORMAT_R32F = 3,
+  GSK_SPV_IMAGE_FORMAT_RGBA8 = 4,
+  GSK_SPV_IMAGE_FORMAT_RGBA8_SNORM = 5,
+  GSK_SPV_IMAGE_FORMAT_RG32F = 6,
+  GSK_SPV_IMAGE_FORMAT_RG16F = 7,
+  GSK_SPV_IMAGE_FORMAT_R11F_G11F_B10F = 8,
+  GSK_SPV_IMAGE_FORMAT_R16F = 9,
+  GSK_SPV_IMAGE_FORMAT_RGBA16 = 10,
+  GSK_SPV_IMAGE_FORMAT_RGB10_A2 = 11,
+  GSK_SPV_IMAGE_FORMAT_RG16 = 12,
+  GSK_SPV_IMAGE_FORMAT_RG8 = 13,
+  GSK_SPV_IMAGE_FORMAT_R16 = 14,
+  GSK_SPV_IMAGE_FORMAT_R8 = 15,
+  GSK_SPV_IMAGE_FORMAT_RGBA16_SNORM = 16,
+  GSK_SPV_IMAGE_FORMAT_RG16_SNORM = 17,
+  GSK_SPV_IMAGE_FORMAT_RG8_SNORM = 18,
+  GSK_SPV_IMAGE_FORMAT_R16_SNORM = 19,
+  GSK_SPV_IMAGE_FORMAT_R8_SNORM = 20,
+  GSK_SPV_IMAGE_FORMAT_RGBA32I = 21,
+  GSK_SPV_IMAGE_FORMAT_RGBA16I = 22,
+  GSK_SPV_IMAGE_FORMAT_RGBA8I = 23,
+  GSK_SPV_IMAGE_FORMAT_R32I = 24,
+  GSK_SPV_IMAGE_FORMAT_RG32I = 25,
+  GSK_SPV_IMAGE_FORMAT_RG16I = 26,
+  GSK_SPV_IMAGE_FORMAT_RG8I = 27,
+  GSK_SPV_IMAGE_FORMAT_R16I = 28,
+  GSK_SPV_IMAGE_FORMAT_R8I = 29,
+  GSK_SPV_IMAGE_FORMAT_RGBA32UI = 30,
+  GSK_SPV_IMAGE_FORMAT_RGBA16UI = 31,
+  GSK_SPV_IMAGE_FORMAT_RGBA8UI = 32,
+  GSK_SPV_IMAGE_FORMAT_R32UI = 33,
+  GSK_SPV_IMAGE_FORMAT_RGB10A2UI = 34,
+  GSK_SPV_IMAGE_FORMAT_RG32UI = 35,
+  GSK_SPV_IMAGE_FORMAT_RG16UI = 36,
+  GSK_SPV_IMAGE_FORMAT_RG8UI = 37,
+  GSK_SPV_IMAGE_FORMAT_R16UI = 38,
+  GSK_SPV_IMAGE_FORMAT_R8UI = 39
+} GskSpvImageFormat;
+
+typedef enum {
+  GSK_SPV_IMAGE_CHANNEL_ORDER_R = 0,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_A = 1,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RG = 2,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RA = 3,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RGB = 4,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RGBA = 5,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_BGRA = 6,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_ARGB = 7,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_INTENSITY = 8,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_LUMINANCE = 9,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RX = 10,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_R_GX = 11,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_RG_BX = 12,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_DEPTH = 13,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_DEPTH_STENCIL = 14,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_S_RGB = 15,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_S_RG_BX = 16,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_S_RGBA = 17,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_S_BGRA = 18,
+  GSK_SPV_IMAGE_CHANNEL_ORDER_ABGR = 19
+} GskSpvImageChannelOrder;
+
+typedef enum {
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SNORM_INT8 = 0,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SNORM_INT16 = 1,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT8 = 2,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT16 = 3,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_SHORT565 = 4,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_SHORT555 = 5,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT101010 = 6,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT8 = 7,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT16 = 8,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT32 = 9,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT8 = 10,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT16 = 11,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT32 = 12,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_HALF_FLOAT = 13,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_FLOAT = 14,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT24 = 15,
+  GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT101010_2 = 16
+} GskSpvImageChannelDataType;
+
+typedef enum {
+  GSK_SPV_FP_ROUNDING_MODE_RTE = 0,
+  GSK_SPV_FP_ROUNDING_MODE_RTZ = 1,
+  GSK_SPV_FP_ROUNDING_MODE_RTP = 2,
+  GSK_SPV_FP_ROUNDING_MODE_RTN = 3
+} GskSpvFPRoundingMode;
+
+typedef enum {
+  GSK_SPV_LINKAGE_TYPE_EXPORT = 0,
+  GSK_SPV_LINKAGE_TYPE_IMPORT = 1
+} GskSpvLinkageType;
+
+typedef enum {
+  GSK_SPV_ACCESS_QUALIFIER_READ_ONLY = 0,
+  GSK_SPV_ACCESS_QUALIFIER_WRITE_ONLY = 1,
+  GSK_SPV_ACCESS_QUALIFIER_READ_WRITE = 2
+} GskSpvAccessQualifier;
+
+typedef enum {
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_ZEXT = 0,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_SEXT = 1,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_BY_VAL = 2,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_SRET = 3,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_ALIAS = 4,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_CAPTURE = 5,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_WRITE = 6,
+  GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_READ_WRITE = 7
+} GskSpvFunctionParameterAttribute;
+
+typedef enum {
+  GSK_SPV_DECORATION_RELAXED_PRECISION = 0,
+  GSK_SPV_DECORATION_SPEC_ID = 1,
+  GSK_SPV_DECORATION_BLOCK = 2,
+  GSK_SPV_DECORATION_BUFFER_BLOCK = 3,
+  GSK_SPV_DECORATION_ROW_MAJOR = 4,
+  GSK_SPV_DECORATION_COL_MAJOR = 5,
+  GSK_SPV_DECORATION_ARRAY_STRIDE = 6,
+  GSK_SPV_DECORATION_MATRIX_STRIDE = 7,
+  GSK_SPV_DECORATION_GLSL_SHARED = 8,
+  GSK_SPV_DECORATION_GLSL_PACKED = 9,
+  GSK_SPV_DECORATION_C_PACKED = 10,
+  GSK_SPV_DECORATION_BUILT_IN = 11,
+  GSK_SPV_DECORATION_NO_PERSPECTIVE = 13,
+  GSK_SPV_DECORATION_FLAT = 14,
+  GSK_SPV_DECORATION_PATCH = 15,
+  GSK_SPV_DECORATION_CENTROID = 16,
+  GSK_SPV_DECORATION_SAMPLE = 17,
+  GSK_SPV_DECORATION_INVARIANT = 18,
+  GSK_SPV_DECORATION_RESTRICT = 19,
+  GSK_SPV_DECORATION_ALIASED = 20,
+  GSK_SPV_DECORATION_VOLATILE = 21,
+  GSK_SPV_DECORATION_CONSTANT = 22,
+  GSK_SPV_DECORATION_COHERENT = 23,
+  GSK_SPV_DECORATION_NON_WRITABLE = 24,
+  GSK_SPV_DECORATION_NON_READABLE = 25,
+  GSK_SPV_DECORATION_UNIFORM = 26,
+  GSK_SPV_DECORATION_SATURATED_CONVERSION = 28,
+  GSK_SPV_DECORATION_STREAM = 29,
+  GSK_SPV_DECORATION_LOCATION = 30,
+  GSK_SPV_DECORATION_COMPONENT = 31,
+  GSK_SPV_DECORATION_INDEX = 32,
+  GSK_SPV_DECORATION_BINDING = 33,
+  GSK_SPV_DECORATION_DESCRIPTOR_SET = 34,
+  GSK_SPV_DECORATION_OFFSET = 35,
+  GSK_SPV_DECORATION_XFB_BUFFER = 36,
+  GSK_SPV_DECORATION_XFB_STRIDE = 37,
+  GSK_SPV_DECORATION_FUNC_PARAM_ATTR = 38,
+  GSK_SPV_DECORATION_FP_ROUNDING_MODE = 39,
+  GSK_SPV_DECORATION_FP_FAST_MATH_MODE = 40,
+  GSK_SPV_DECORATION_LINKAGE_ATTRIBUTES = 41,
+  GSK_SPV_DECORATION_NO_CONTRACTION = 42,
+  GSK_SPV_DECORATION_INPUT_ATTACHMENT_INDEX = 43,
+  GSK_SPV_DECORATION_ALIGNMENT = 44,
+  GSK_SPV_DECORATION_EXPLICIT_INTERP_AMD = 4999,
+  GSK_SPV_DECORATION_OVERRIDE_COVERAGE_NV = 5248,
+  GSK_SPV_DECORATION_PASSTHROUGH_NV = 5250,
+  GSK_SPV_DECORATION_VIEWPORT_RELATIVE_NV = 5252,
+  GSK_SPV_DECORATION_SECONDARY_VIEWPORT_RELATIVE_NV = 5256
+} GskSpvDecoration;
+
+typedef enum {
+  GSK_SPV_BUILT_IN_POSITION = 0,
+  GSK_SPV_BUILT_IN_POINT_SIZE = 1,
+  GSK_SPV_BUILT_IN_CLIP_DISTANCE = 3,
+  GSK_SPV_BUILT_IN_CULL_DISTANCE = 4,
+  GSK_SPV_BUILT_IN_VERTEX_ID = 5,
+  GSK_SPV_BUILT_IN_INSTANCE_ID = 6,
+  GSK_SPV_BUILT_IN_PRIMITIVE_ID = 7,
+  GSK_SPV_BUILT_IN_INVOCATION_ID = 8,
+  GSK_SPV_BUILT_IN_LAYER = 9,
+  GSK_SPV_BUILT_IN_VIEWPORT_INDEX = 10,
+  GSK_SPV_BUILT_IN_TESS_LEVEL_OUTER = 11,
+  GSK_SPV_BUILT_IN_TESS_LEVEL_INNER = 12,
+  GSK_SPV_BUILT_IN_TESS_COORD = 13,
+  GSK_SPV_BUILT_IN_PATCH_VERTICES = 14,
+  GSK_SPV_BUILT_IN_FRAG_COORD = 15,
+  GSK_SPV_BUILT_IN_POINT_COORD = 16,
+  GSK_SPV_BUILT_IN_FRONT_FACING = 17,
+  GSK_SPV_BUILT_IN_SAMPLE_ID = 18,
+  GSK_SPV_BUILT_IN_SAMPLE_POSITION = 19,
+  GSK_SPV_BUILT_IN_SAMPLE_MASK = 20,
+  GSK_SPV_BUILT_IN_FRAG_DEPTH = 22,
+  GSK_SPV_BUILT_IN_HELPER_INVOCATION = 23,
+  GSK_SPV_BUILT_IN_NUM_WORKGROUPS = 24,
+  GSK_SPV_BUILT_IN_WORKGROUP_SIZE = 25,
+  GSK_SPV_BUILT_IN_WORKGROUP_ID = 26,
+  GSK_SPV_BUILT_IN_LOCAL_INVOCATION_ID = 27,
+  GSK_SPV_BUILT_IN_GLOBAL_INVOCATION_ID = 28,
+  GSK_SPV_BUILT_IN_LOCAL_INVOCATION_INDEX = 29,
+  GSK_SPV_BUILT_IN_WORK_DIM = 30,
+  GSK_SPV_BUILT_IN_GLOBAL_SIZE = 31,
+  GSK_SPV_BUILT_IN_ENQUEUED_WORKGROUP_SIZE = 32,
+  GSK_SPV_BUILT_IN_GLOBAL_OFFSET = 33,
+  GSK_SPV_BUILT_IN_GLOBAL_LINEAR_ID = 34,
+  GSK_SPV_BUILT_IN_SUBGROUP_SIZE = 36,
+  GSK_SPV_BUILT_IN_SUBGROUP_MAX_SIZE = 37,
+  GSK_SPV_BUILT_IN_NUM_SUBGROUPS = 38,
+  GSK_SPV_BUILT_IN_NUM_ENQUEUED_SUBGROUPS = 39,
+  GSK_SPV_BUILT_IN_SUBGROUP_ID = 40,
+  GSK_SPV_BUILT_IN_SUBGROUP_LOCAL_INVOCATION_ID = 41,
+  GSK_SPV_BUILT_IN_VERTEX_INDEX = 42,
+  GSK_SPV_BUILT_IN_INSTANCE_INDEX = 43,
+  GSK_SPV_BUILT_IN_SUBGROUP_EQ_MASK_KHR = 4416,
+  GSK_SPV_BUILT_IN_SUBGROUP_GE_MASK_KHR = 4417,
+  GSK_SPV_BUILT_IN_SUBGROUP_GT_MASK_KHR = 4418,
+  GSK_SPV_BUILT_IN_SUBGROUP_LE_MASK_KHR = 4419,
+  GSK_SPV_BUILT_IN_SUBGROUP_LT_MASK_KHR = 4420,
+  GSK_SPV_BUILT_IN_BASE_VERTEX = 4424,
+  GSK_SPV_BUILT_IN_BASE_INSTANCE = 4425,
+  GSK_SPV_BUILT_IN_DRAW_INDEX = 4426,
+  GSK_SPV_BUILT_IN_DEVICE_INDEX = 4438,
+  GSK_SPV_BUILT_IN_VIEW_INDEX = 4440,
+  GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_AMD = 4992,
+  GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_CENTROID_AMD = 4993,
+  GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_SAMPLE_AMD = 4994,
+  GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_AMD = 4995,
+  GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_CENTROID_AMD = 4996,
+  GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_SAMPLE_AMD = 4997,
+  GSK_SPV_BUILT_IN_BARY_COORD_PULL_MODEL_AMD = 4998,
+  GSK_SPV_BUILT_IN_FRAG_STENCIL_REF_EXT = 5014,
+  GSK_SPV_BUILT_IN_VIEWPORT_MASK_NV = 5253,
+  GSK_SPV_BUILT_IN_SECONDARY_POSITION_NV = 5257,
+  GSK_SPV_BUILT_IN_SECONDARY_VIEWPORT_MASK_NV = 5258,
+  GSK_SPV_BUILT_IN_POSITION_PER_VIEW_NV = 5261,
+  GSK_SPV_BUILT_IN_VIEWPORT_MASK_PER_VIEW_NV = 5262
+} GskSpvBuiltIn;
+
+typedef enum {
+  GSK_SPV_SCOPE_CROSS_DEVICE = 0,
+  GSK_SPV_SCOPE_DEVICE = 1,
+  GSK_SPV_SCOPE_WORKGROUP = 2,
+  GSK_SPV_SCOPE_SUBGROUP = 3,
+  GSK_SPV_SCOPE_INVOCATION = 4
+} GskSpvScope;
+
+typedef enum {
+  GSK_SPV_GROUP_OPERATION_REDUCE = 0,
+  GSK_SPV_GROUP_OPERATION_INCLUSIVE_SCAN = 1,
+  GSK_SPV_GROUP_OPERATION_EXCLUSIVE_SCAN = 2
+} GskSpvGroupOperation;
+
+typedef enum {
+  GSK_SPV_KERNEL_ENQUEUE_FLAGS_NO_WAIT = 0,
+  GSK_SPV_KERNEL_ENQUEUE_FLAGS_WAIT_KERNEL = 1,
+  GSK_SPV_KERNEL_ENQUEUE_FLAGS_WAIT_WORK_GROUP = 2
+} GskSpvKernelEnqueueFlags;
+
+typedef enum {
+  GSK_SPV_CAPABILITY_MATRIX = 0,
+  GSK_SPV_CAPABILITY_SHADER = 1,
+  GSK_SPV_CAPABILITY_GEOMETRY = 2,
+  GSK_SPV_CAPABILITY_TESSELLATION = 3,
+  GSK_SPV_CAPABILITY_ADDRESSES = 4,
+  GSK_SPV_CAPABILITY_LINKAGE = 5,
+  GSK_SPV_CAPABILITY_KERNEL = 6,
+  GSK_SPV_CAPABILITY_VECTOR16 = 7,
+  GSK_SPV_CAPABILITY_FLOAT16_BUFFER = 8,
+  GSK_SPV_CAPABILITY_FLOAT16 = 9,
+  GSK_SPV_CAPABILITY_FLOAT64 = 10,
+  GSK_SPV_CAPABILITY_INT64 = 11,
+  GSK_SPV_CAPABILITY_INT64_ATOMICS = 12,
+  GSK_SPV_CAPABILITY_IMAGE_BASIC = 13,
+  GSK_SPV_CAPABILITY_IMAGE_READ_WRITE = 14,
+  GSK_SPV_CAPABILITY_IMAGE_MIPMAP = 15,
+  GSK_SPV_CAPABILITY_PIPES = 17,
+  GSK_SPV_CAPABILITY_GROUPS = 18,
+  GSK_SPV_CAPABILITY_DEVICE_ENQUEUE = 19,
+  GSK_SPV_CAPABILITY_LITERAL_SAMPLER = 20,
+  GSK_SPV_CAPABILITY_ATOMIC_STORAGE = 21,
+  GSK_SPV_CAPABILITY_INT16 = 22,
+  GSK_SPV_CAPABILITY_TESSELLATION_POINT_SIZE = 23,
+  GSK_SPV_CAPABILITY_GEOMETRY_POINT_SIZE = 24,
+  GSK_SPV_CAPABILITY_IMAGE_GATHER_EXTENDED = 25,
+  GSK_SPV_CAPABILITY_STORAGE_IMAGE_MULTISAMPLE = 27,
+  GSK_SPV_CAPABILITY_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING = 28,
+  GSK_SPV_CAPABILITY_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING = 29,
+  GSK_SPV_CAPABILITY_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING = 30,
+  GSK_SPV_CAPABILITY_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING = 31,
+  GSK_SPV_CAPABILITY_CLIP_DISTANCE = 32,
+  GSK_SPV_CAPABILITY_CULL_DISTANCE = 33,
+  GSK_SPV_CAPABILITY_IMAGE_CUBE_ARRAY = 34,
+  GSK_SPV_CAPABILITY_SAMPLE_RATE_SHADING = 35,
+  GSK_SPV_CAPABILITY_IMAGE_RECT = 36,
+  GSK_SPV_CAPABILITY_SAMPLED_RECT = 37,
+  GSK_SPV_CAPABILITY_GENERIC_POINTER = 38,
+  GSK_SPV_CAPABILITY_INT8 = 39,
+  GSK_SPV_CAPABILITY_INPUT_ATTACHMENT = 40,
+  GSK_SPV_CAPABILITY_SPARSE_RESIDENCY = 41,
+  GSK_SPV_CAPABILITY_MIN_LOD = 42,
+  GSK_SPV_CAPABILITY_SAMPLED1_D = 43,
+  GSK_SPV_CAPABILITY_IMAGE1_D = 44,
+  GSK_SPV_CAPABILITY_SAMPLED_CUBE_ARRAY = 45,
+  GSK_SPV_CAPABILITY_SAMPLED_BUFFER = 46,
+  GSK_SPV_CAPABILITY_IMAGE_BUFFER = 47,
+  GSK_SPV_CAPABILITY_IMAGE_MS_ARRAY = 48,
+  GSK_SPV_CAPABILITY_STORAGE_IMAGE_EXTENDED_FORMATS = 49,
+  GSK_SPV_CAPABILITY_IMAGE_QUERY = 50,
+  GSK_SPV_CAPABILITY_DERIVATIVE_CONTROL = 51,
+  GSK_SPV_CAPABILITY_INTERPOLATION_FUNCTION = 52,
+  GSK_SPV_CAPABILITY_TRANSFORM_FEEDBACK = 53,
+  GSK_SPV_CAPABILITY_GEOMETRY_STREAMS = 54,
+  GSK_SPV_CAPABILITY_STORAGE_IMAGE_READ_WITHOUT_FORMAT = 55,
+  GSK_SPV_CAPABILITY_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT = 56,
+  GSK_SPV_CAPABILITY_MULTI_VIEWPORT = 57,
+  GSK_SPV_CAPABILITY_SUBGROUP_BALLOT_KHR = 4423,
+  GSK_SPV_CAPABILITY_DRAW_PARAMETERS = 4427,
+  GSK_SPV_CAPABILITY_SUBGROUP_VOTE_KHR = 4431,
+  GSK_SPV_CAPABILITY_STORAGE_BUFFER16_BIT_ACCESS = 4433,
+  GSK_SPV_CAPABILITY_STORAGE_UNIFORM_BUFFER_BLOCK16 = 4433,
+  GSK_SPV_CAPABILITY_UNIFORM_AND_STORAGE_BUFFER16_BIT_ACCESS = 4434,
+  GSK_SPV_CAPABILITY_STORAGE_UNIFORM16 = 4434,
+  GSK_SPV_CAPABILITY_STORAGE_PUSH_CONSTANT16 = 4435,
+  GSK_SPV_CAPABILITY_STORAGE_INPUT_OUTPUT16 = 4436,
+  GSK_SPV_CAPABILITY_DEVICE_GROUP = 4437,
+  GSK_SPV_CAPABILITY_MULTI_VIEW = 4439,
+  GSK_SPV_CAPABILITY_VARIABLE_POINTERS_STORAGE_BUFFER = 4441,
+  GSK_SPV_CAPABILITY_VARIABLE_POINTERS = 4442,
+  GSK_SPV_CAPABILITY_ATOMIC_STORAGE_OPS = 4445,
+  GSK_SPV_CAPABILITY_SAMPLE_MASK_POST_DEPTH_COVERAGE = 4447,
+  GSK_SPV_CAPABILITY_IMAGE_GATHER_BIAS_LOD_AMD = 5009,
+  GSK_SPV_CAPABILITY_FRAGMENT_MASK_AMD = 5010,
+  GSK_SPV_CAPABILITY_STENCIL_EXPORT_EXT = 5013,
+  GSK_SPV_CAPABILITY_IMAGE_READ_WRITE_LOD_AMD = 5015,
+  GSK_SPV_CAPABILITY_SAMPLE_MASK_OVERRIDE_COVERAGE_NV = 5249,
+  GSK_SPV_CAPABILITY_GEOMETRY_SHADER_PASSTHROUGH_NV = 5251,
+  GSK_SPV_CAPABILITY_SHADER_VIEWPORT_INDEX_LAYER_EXT = 5254,
+  GSK_SPV_CAPABILITY_SHADER_VIEWPORT_INDEX_LAYER_NV = 5254,
+  GSK_SPV_CAPABILITY_SHADER_VIEWPORT_MASK_NV = 5255,
+  GSK_SPV_CAPABILITY_SHADER_STEREO_VIEW_NV = 5259,
+  GSK_SPV_CAPABILITY_PER_VIEW_ATTRIBUTES_NV = 5260
+} GskSpvCapability;
+
+typedef enum {
+  GSK_SPV_OP_NOP = 0,
+  GSK_SPV_OP_UNDEF = 1,
+  GSK_SPV_OP_SOURCE_CONTINUED = 2,
+  GSK_SPV_OP_SOURCE = 3,
+  GSK_SPV_OP_SOURCE_EXTENSION = 4,
+  GSK_SPV_OP_NAME = 5,
+  GSK_SPV_OP_MEMBER_NAME = 6,
+  GSK_SPV_OP_STRING = 7,
+  GSK_SPV_OP_LINE = 8,
+  GSK_SPV_OP_EXTENSION = 10,
+  GSK_SPV_OP_EXT_INST_IMPORT = 11,
+  GSK_SPV_OP_EXT_INST = 12,
+  GSK_SPV_OP_MEMORY_MODEL = 14,
+  GSK_SPV_OP_ENTRY_POINT = 15,
+  GSK_SPV_OP_EXECUTION_MODE = 16,
+  GSK_SPV_OP_CAPABILITY = 17,
+  GSK_SPV_OP_TYPE_VOID = 19,
+  GSK_SPV_OP_TYPE_BOOL = 20,
+  GSK_SPV_OP_TYPE_INT = 21,
+  GSK_SPV_OP_TYPE_FLOAT = 22,
+  GSK_SPV_OP_TYPE_VECTOR = 23,
+  GSK_SPV_OP_TYPE_MATRIX = 24,
+  GSK_SPV_OP_TYPE_IMAGE = 25,
+  GSK_SPV_OP_TYPE_SAMPLER = 26,
+  GSK_SPV_OP_TYPE_SAMPLED_IMAGE = 27,
+  GSK_SPV_OP_TYPE_ARRAY = 28,
+  GSK_SPV_OP_TYPE_RUNTIME_ARRAY = 29,
+  GSK_SPV_OP_TYPE_STRUCT = 30,
+  GSK_SPV_OP_TYPE_OPAQUE = 31,
+  GSK_SPV_OP_TYPE_POINTER = 32,
+  GSK_SPV_OP_TYPE_FUNCTION = 33,
+  GSK_SPV_OP_TYPE_EVENT = 34,
+  GSK_SPV_OP_TYPE_DEVICE_EVENT = 35,
+  GSK_SPV_OP_TYPE_RESERVE_ID = 36,
+  GSK_SPV_OP_TYPE_QUEUE = 37,
+  GSK_SPV_OP_TYPE_PIPE = 38,
+  GSK_SPV_OP_TYPE_FORWARD_POINTER = 39,
+  GSK_SPV_OP_CONSTANT_TRUE = 41,
+  GSK_SPV_OP_CONSTANT_FALSE = 42,
+  GSK_SPV_OP_CONSTANT = 43,
+  GSK_SPV_OP_CONSTANT_COMPOSITE = 44,
+  GSK_SPV_OP_CONSTANT_SAMPLER = 45,
+  GSK_SPV_OP_CONSTANT_NULL = 46,
+  GSK_SPV_OP_SPEC_CONSTANT_TRUE = 48,
+  GSK_SPV_OP_SPEC_CONSTANT_FALSE = 49,
+  GSK_SPV_OP_SPEC_CONSTANT = 50,
+  GSK_SPV_OP_SPEC_CONSTANT_COMPOSITE = 51,
+  GSK_SPV_OP_SPEC_CONSTANT_OP = 52,
+  GSK_SPV_OP_FUNCTION = 54,
+  GSK_SPV_OP_FUNCTION_PARAMETER = 55,
+  GSK_SPV_OP_FUNCTION_END = 56,
+  GSK_SPV_OP_FUNCTION_CALL = 57,
+  GSK_SPV_OP_VARIABLE = 59,
+  GSK_SPV_OP_IMAGE_TEXEL_POINTER = 60,
+  GSK_SPV_OP_LOAD = 61,
+  GSK_SPV_OP_STORE = 62,
+  GSK_SPV_OP_COPY_MEMORY = 63,
+  GSK_SPV_OP_COPY_MEMORY_SIZED = 64,
+  GSK_SPV_OP_ACCESS_CHAIN = 65,
+  GSK_SPV_OP_IN_BOUNDS_ACCESS_CHAIN = 66,
+  GSK_SPV_OP_PTR_ACCESS_CHAIN = 67,
+  GSK_SPV_OP_ARRAY_LENGTH = 68,
+  GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS = 69,
+  GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN = 70,
+  GSK_SPV_OP_DECORATE = 71,
+  GSK_SPV_OP_MEMBER_DECORATE = 72,
+  GSK_SPV_OP_DECORATION_GROUP = 73,
+  GSK_SPV_OP_GROUP_DECORATE = 74,
+  GSK_SPV_OP_GROUP_MEMBER_DECORATE = 75,
+  GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC = 77,
+  GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
+  GSK_SPV_OP_VECTOR_SHUFFLE = 79,
+  GSK_SPV_OP_COMPOSITE_CONSTRUCT = 80,
+  GSK_SPV_OP_COMPOSITE_EXTRACT = 81,
+  GSK_SPV_OP_COMPOSITE_INSERT = 82,
+  GSK_SPV_OP_COPY_OBJECT = 83,
+  GSK_SPV_OP_TRANSPOSE = 84,
+  GSK_SPV_OP_SAMPLED_IMAGE = 86,
+  GSK_SPV_OP_IMAGE_SAMPLE_IMPLICIT_LOD = 87,
+  GSK_SPV_OP_IMAGE_SAMPLE_EXPLICIT_LOD = 88,
+  GSK_SPV_OP_IMAGE_SAMPLE_DREF_IMPLICIT_LOD = 89,
+  GSK_SPV_OP_IMAGE_SAMPLE_DREF_EXPLICIT_LOD = 90,
+  GSK_SPV_OP_IMAGE_SAMPLE_PROJ_IMPLICIT_LOD = 91,
+  GSK_SPV_OP_IMAGE_SAMPLE_PROJ_EXPLICIT_LOD = 92,
+  GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_IMPLICIT_LOD = 93,
+  GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_EXPLICIT_LOD = 94,
+  GSK_SPV_OP_IMAGE_FETCH = 95,
+  GSK_SPV_OP_IMAGE_GATHER = 96,
+  GSK_SPV_OP_IMAGE_DREF_GATHER = 97,
+  GSK_SPV_OP_IMAGE_READ = 98,
+  GSK_SPV_OP_IMAGE_WRITE = 99,
+  GSK_SPV_OP_IMAGE = 100,
+  GSK_SPV_OP_IMAGE_QUERY_FORMAT = 101,
+  GSK_SPV_OP_IMAGE_QUERY_ORDER = 102,
+  GSK_SPV_OP_IMAGE_QUERY_SIZE_LOD = 103,
+  GSK_SPV_OP_IMAGE_QUERY_SIZE = 104,
+  GSK_SPV_OP_IMAGE_QUERY_LOD = 105,
+  GSK_SPV_OP_IMAGE_QUERY_LEVELS = 106,
+  GSK_SPV_OP_IMAGE_QUERY_SAMPLES = 107,
+  GSK_SPV_OP_CONVERT_F_TO_U = 109,
+  GSK_SPV_OP_CONVERT_F_TO_S = 110,
+  GSK_SPV_OP_CONVERT_S_TO_F = 111,
+  GSK_SPV_OP_CONVERT_U_TO_F = 112,
+  GSK_SPV_OP_U_CONVERT = 113,
+  GSK_SPV_OP_S_CONVERT = 114,
+  GSK_SPV_OP_F_CONVERT = 115,
+  GSK_SPV_OP_QUANTIZE_TO_F16 = 116,
+  GSK_SPV_OP_CONVERT_PTR_TO_U = 117,
+  GSK_SPV_OP_SAT_CONVERT_S_TO_U = 118,
+  GSK_SPV_OP_SAT_CONVERT_U_TO_S = 119,
+  GSK_SPV_OP_CONVERT_U_TO_PTR = 120,
+  GSK_SPV_OP_PTR_CAST_TO_GENERIC = 121,
+  GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
+  GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
+  GSK_SPV_OP_BITCAST = 124,
+  GSK_SPV_OP_S_NEGATE = 126,
+  GSK_SPV_OP_F_NEGATE = 127,
+  GSK_SPV_OP_I_ADD = 128,
+  GSK_SPV_OP_F_ADD = 129,
+  GSK_SPV_OP_I_SUB = 130,
+  GSK_SPV_OP_F_SUB = 131,
+  GSK_SPV_OP_I_MUL = 132,
+  GSK_SPV_OP_F_MUL = 133,
+  GSK_SPV_OP_U_DIV = 134,
+  GSK_SPV_OP_S_DIV = 135,
+  GSK_SPV_OP_F_DIV = 136,
+  GSK_SPV_OP_U_MOD = 137,
+  GSK_SPV_OP_S_REM = 138,
+  GSK_SPV_OP_S_MOD = 139,
+  GSK_SPV_OP_F_REM = 140,
+  GSK_SPV_OP_F_MOD = 141,
+  GSK_SPV_OP_VECTOR_TIMES_SCALAR = 142,
+  GSK_SPV_OP_MATRIX_TIMES_SCALAR = 143,
+  GSK_SPV_OP_VECTOR_TIMES_MATRIX = 144,
+  GSK_SPV_OP_MATRIX_TIMES_VECTOR = 145,
+  GSK_SPV_OP_MATRIX_TIMES_MATRIX = 146,
+  GSK_SPV_OP_OUTER_PRODUCT = 147,
+  GSK_SPV_OP_DOT = 148,
+  GSK_SPV_OP_I_ADD_CARRY = 149,
+  GSK_SPV_OP_I_SUB_BORROW = 150,
+  GSK_SPV_OP_U_MUL_EXTENDED = 151,
+  GSK_SPV_OP_S_MUL_EXTENDED = 152,
+  GSK_SPV_OP_ANY = 154,
+  GSK_SPV_OP_ALL = 155,
+  GSK_SPV_OP_IS_NAN = 156,
+  GSK_SPV_OP_IS_INF = 157,
+  GSK_SPV_OP_IS_FINITE = 158,
+  GSK_SPV_OP_IS_NORMAL = 159,
+  GSK_SPV_OP_SIGN_BIT_SET = 160,
+  GSK_SPV_OP_LESS_OR_GREATER = 161,
+  GSK_SPV_OP_ORDERED = 162,
+  GSK_SPV_OP_UNORDERED = 163,
+  GSK_SPV_OP_LOGICAL_EQUAL = 164,
+  GSK_SPV_OP_LOGICAL_NOT_EQUAL = 165,
+  GSK_SPV_OP_LOGICAL_OR = 166,
+  GSK_SPV_OP_LOGICAL_AND = 167,
+  GSK_SPV_OP_LOGICAL_NOT = 168,
+  GSK_SPV_OP_SELECT = 169,
+  GSK_SPV_OP_I_EQUAL = 170,
+  GSK_SPV_OP_I_NOT_EQUAL = 171,
+  GSK_SPV_OP_U_GREATER_THAN = 172,
+  GSK_SPV_OP_S_GREATER_THAN = 173,
+  GSK_SPV_OP_U_GREATER_THAN_EQUAL = 174,
+  GSK_SPV_OP_S_GREATER_THAN_EQUAL = 175,
+  GSK_SPV_OP_U_LESS_THAN = 176,
+  GSK_SPV_OP_S_LESS_THAN = 177,
+  GSK_SPV_OP_U_LESS_THAN_EQUAL = 178,
+  GSK_SPV_OP_S_LESS_THAN_EQUAL = 179,
+  GSK_SPV_OP_F_ORD_EQUAL = 180,
+  GSK_SPV_OP_F_UNORD_EQUAL = 181,
+  GSK_SPV_OP_F_ORD_NOT_EQUAL = 182,
+  GSK_SPV_OP_F_UNORD_NOT_EQUAL = 183,
+  GSK_SPV_OP_F_ORD_LESS_THAN = 184,
+  GSK_SPV_OP_F_UNORD_LESS_THAN = 185,
+  GSK_SPV_OP_F_ORD_GREATER_THAN = 186,
+  GSK_SPV_OP_F_UNORD_GREATER_THAN = 187,
+  GSK_SPV_OP_F_ORD_LESS_THAN_EQUAL = 188,
+  GSK_SPV_OP_F_UNORD_LESS_THAN_EQUAL = 189,
+  GSK_SPV_OP_F_ORD_GREATER_THAN_EQUAL = 190,
+  GSK_SPV_OP_F_UNORD_GREATER_THAN_EQUAL = 191,
+  GSK_SPV_OP_SHIFT_RIGHT_LOGICAL = 194,
+  GSK_SPV_OP_SHIFT_RIGHT_ARITHMETIC = 195,
+  GSK_SPV_OP_SHIFT_LEFT_LOGICAL = 196,
+  GSK_SPV_OP_BITWISE_OR = 197,
+  GSK_SPV_OP_BITWISE_XOR = 198,
+  GSK_SPV_OP_BITWISE_AND = 199,
+  GSK_SPV_OP_NOT = 200,
+  GSK_SPV_OP_BIT_FIELD_INSERT = 201,
+  GSK_SPV_OP_BIT_FIELD_S_EXTRACT = 202,
+  GSK_SPV_OP_BIT_FIELD_U_EXTRACT = 203,
+  GSK_SPV_OP_BIT_REVERSE = 204,
+  GSK_SPV_OP_BIT_COUNT = 205,
+  GSK_SPV_OP_D_PDX = 207,
+  GSK_SPV_OP_D_PDY = 208,
+  GSK_SPV_OP_FWIDTH = 209,
+  GSK_SPV_OP_D_PDX_FINE = 210,
+  GSK_SPV_OP_D_PDY_FINE = 211,
+  GSK_SPV_OP_FWIDTH_FINE = 212,
+  GSK_SPV_OP_D_PDX_COARSE = 213,
+  GSK_SPV_OP_D_PDY_COARSE = 214,
+  GSK_SPV_OP_FWIDTH_COARSE = 215,
+  GSK_SPV_OP_EMIT_VERTEX = 218,
+  GSK_SPV_OP_END_PRIMITIVE = 219,
+  GSK_SPV_OP_EMIT_STREAM_VERTEX = 220,
+  GSK_SPV_OP_END_STREAM_PRIMITIVE = 221,
+  GSK_SPV_OP_CONTROL_BARRIER = 224,
+  GSK_SPV_OP_MEMORY_BARRIER = 225,
+  GSK_SPV_OP_ATOMIC_LOAD = 227,
+  GSK_SPV_OP_ATOMIC_STORE = 228,
+  GSK_SPV_OP_ATOMIC_EXCHANGE = 229,
+  GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE = 230,
+  GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE_WEAK = 231,
+  GSK_SPV_OP_ATOMIC_I_INCREMENT = 232,
+  GSK_SPV_OP_ATOMIC_I_DECREMENT = 233,
+  GSK_SPV_OP_ATOMIC_I_ADD = 234,
+  GSK_SPV_OP_ATOMIC_I_SUB = 235,
+  GSK_SPV_OP_ATOMIC_S_MIN = 236,
+  GSK_SPV_OP_ATOMIC_U_MIN = 237,
+  GSK_SPV_OP_ATOMIC_S_MAX = 238,
+  GSK_SPV_OP_ATOMIC_U_MAX = 239,
+  GSK_SPV_OP_ATOMIC_AND = 240,
+  GSK_SPV_OP_ATOMIC_OR = 241,
+  GSK_SPV_OP_ATOMIC_XOR = 242,
+  GSK_SPV_OP_PHI = 245,
+  GSK_SPV_OP_LOOP_MERGE = 246,
+  GSK_SPV_OP_SELECTION_MERGE = 247,
+  GSK_SPV_OP_LABEL = 248,
+  GSK_SPV_OP_BRANCH = 249,
+  GSK_SPV_OP_BRANCH_CONDITIONAL = 250,
+  GSK_SPV_OP_SWITCH = 251,
+  GSK_SPV_OP_KILL = 252,
+  GSK_SPV_OP_RETURN = 253,
+  GSK_SPV_OP_RETURN_VALUE = 254,
+  GSK_SPV_OP_UNREACHABLE = 255,
+  GSK_SPV_OP_LIFETIME_START = 256,
+  GSK_SPV_OP_LIFETIME_STOP = 257,
+  GSK_SPV_OP_GROUP_ASYNC_COPY = 259,
+  GSK_SPV_OP_GROUP_WAIT_EVENTS = 260,
+  GSK_SPV_OP_GROUP_ALL = 261,
+  GSK_SPV_OP_GROUP_ANY = 262,
+  GSK_SPV_OP_GROUP_BROADCAST = 263,
+  GSK_SPV_OP_GROUP_I_ADD = 264,
+  GSK_SPV_OP_GROUP_F_ADD = 265,
+  GSK_SPV_OP_GROUP_F_MIN = 266,
+  GSK_SPV_OP_GROUP_U_MIN = 267,
+  GSK_SPV_OP_GROUP_S_MIN = 268,
+  GSK_SPV_OP_GROUP_F_MAX = 269,
+  GSK_SPV_OP_GROUP_U_MAX = 270,
+  GSK_SPV_OP_GROUP_S_MAX = 271,
+  GSK_SPV_OP_READ_PIPE = 274,
+  GSK_SPV_OP_WRITE_PIPE = 275,
+  GSK_SPV_OP_RESERVED_READ_PIPE = 276,
+  GSK_SPV_OP_RESERVED_WRITE_PIPE = 277,
+  GSK_SPV_OP_RESERVE_READ_PIPE_PACKETS = 278,
+  GSK_SPV_OP_RESERVE_WRITE_PIPE_PACKETS = 279,
+  GSK_SPV_OP_COMMIT_READ_PIPE = 280,
+  GSK_SPV_OP_COMMIT_WRITE_PIPE = 281,
+  GSK_SPV_OP_IS_VALID_RESERVE_ID = 282,
+  GSK_SPV_OP_GET_NUM_PIPE_PACKETS = 283,
+  GSK_SPV_OP_GET_MAX_PIPE_PACKETS = 284,
+  GSK_SPV_OP_GROUP_RESERVE_READ_PIPE_PACKETS = 285,
+  GSK_SPV_OP_GROUP_RESERVE_WRITE_PIPE_PACKETS = 286,
+  GSK_SPV_OP_GROUP_COMMIT_READ_PIPE = 287,
+  GSK_SPV_OP_GROUP_COMMIT_WRITE_PIPE = 288,
+  GSK_SPV_OP_ENQUEUE_MARKER = 291,
+  GSK_SPV_OP_ENQUEUE_KERNEL = 292,
+  GSK_SPV_OP_GET_KERNEL_N_DRANGE_SUB_GROUP_COUNT = 293,
+  GSK_SPV_OP_GET_KERNEL_N_DRANGE_MAX_SUB_GROUP_SIZE = 294,
+  GSK_SPV_OP_GET_KERNEL_WORK_GROUP_SIZE = 295,
+  GSK_SPV_OP_GET_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE = 296,
+  GSK_SPV_OP_RETAIN_EVENT = 297,
+  GSK_SPV_OP_RELEASE_EVENT = 298,
+  GSK_SPV_OP_CREATE_USER_EVENT = 299,
+  GSK_SPV_OP_IS_VALID_EVENT = 300,
+  GSK_SPV_OP_SET_USER_EVENT_STATUS = 301,
+  GSK_SPV_OP_CAPTURE_EVENT_PROFILING_INFO = 302,
+  GSK_SPV_OP_GET_DEFAULT_QUEUE = 303,
+  GSK_SPV_OP_BUILD_ND_RANGE = 304,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_IMPLICIT_LOD = 305,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_EXPLICIT_LOD = 306,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_IMPLICIT_LOD = 307,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_EXPLICIT_LOD = 308,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_IMPLICIT_LOD = 309,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_EXPLICIT_LOD = 310,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_IMPLICIT_LOD = 311,
+  GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_EXPLICIT_LOD = 312,
+  GSK_SPV_OP_IMAGE_SPARSE_FETCH = 313,
+  GSK_SPV_OP_IMAGE_SPARSE_GATHER = 314,
+  GSK_SPV_OP_IMAGE_SPARSE_DREF_GATHER = 315,
+  GSK_SPV_OP_IMAGE_SPARSE_TEXELS_RESIDENT = 316,
+  GSK_SPV_OP_NO_LINE = 317,
+  GSK_SPV_OP_ATOMIC_FLAG_TEST_AND_SET = 318,
+  GSK_SPV_OP_ATOMIC_FLAG_CLEAR = 319,
+  GSK_SPV_OP_IMAGE_SPARSE_READ = 320,
+  GSK_SPV_OP_SUBGROUP_BALLOT_KHR = 4421,
+  GSK_SPV_OP_SUBGROUP_FIRST_INVOCATION_KHR = 4422,
+  GSK_SPV_OP_SUBGROUP_ALL_KHR = 4428,
+  GSK_SPV_OP_SUBGROUP_ANY_KHR = 4429,
+  GSK_SPV_OP_SUBGROUP_ALL_EQUAL_KHR = 4430,
+  GSK_SPV_OP_SUBGROUP_READ_INVOCATION_KHR = 4432,
+  GSK_SPV_OP_GROUP_I_ADD_NON_UNIFORM_AMD = 5000,
+  GSK_SPV_OP_GROUP_F_ADD_NON_UNIFORM_AMD = 5001,
+  GSK_SPV_OP_GROUP_F_MIN_NON_UNIFORM_AMD = 5002,
+  GSK_SPV_OP_GROUP_U_MIN_NON_UNIFORM_AMD = 5003,
+  GSK_SPV_OP_GROUP_S_MIN_NON_UNIFORM_AMD = 5004,
+  GSK_SPV_OP_GROUP_F_MAX_NON_UNIFORM_AMD = 5005,
+  GSK_SPV_OP_GROUP_U_MAX_NON_UNIFORM_AMD = 5006,
+  GSK_SPV_OP_GROUP_S_MAX_NON_UNIFORM_AMD = 5007,
+  GSK_SPV_OP_FRAGMENT_MASK_FETCH_AMD = 5011,
+  GSK_SPV_OP_FRAGMENT_FETCH_AMD = 5012
+} GskSpvOpcode;
+
+#endif /* __GSK_SPV_ENUMS_H__ */
diff --git a/gsk/gskspvwriter.c b/gsk/gskspvwriter.c
index b789fe4..d68cabd 100644
--- a/gsk/gskspvwriter.c
+++ b/gsk/gskspvwriter.c
@@ -106,34 +106,21 @@ gsk_spv_writer_unref (GskSpvWriter *writer)
 static void
 gsk_spv_writer_write_header (GskSpvWriter *writer)
 {
-  guchar instruction_set[] = "\0\0\0\0GLSL.std.450\0\0\0\0";
-
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_HEADER,
-                      2, GSK_SPV_OP_CAPABILITY,
-                      (guint32[1]) { GSK_SPV_CAPABILITY_SHADER });
-  *(guint32 *) instruction_set = 1;
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_HEADER,
-                      1 + sizeof (instruction_set) / 4, GSK_SPV_OP_EXT_INST_IMPORT,
-                      (guint32 *) instruction_set);
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_HEADER,
-                      3, GSK_SPV_OP_MEMORY_MODEL,
-                      (guint32[2]) { GSK_SPV_ADDRESSING_LOGICAL,
-                                     GSK_SPV_MEMORY_GLSL450 });
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_HEADER,
-                      5, GSK_SPV_OP_ENTRY_POINT,
-                      (guint32[4]) { GSK_SPV_EXECUTION_MODEL_FRAGMENT,
-                                     writer->entry_point,
-                                     STRING ("main", 0),
-                                     0 });
-  gsk_spv_writer_add (writer,
-                      GSK_SPV_WRITER_SECTION_HEADER,
-                      3, GSK_SPV_OP_EXECUTION_MODE,
-                      (guint32[4]) { writer->entry_point,
-                                     GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT });
+  gsk_spv_writer_capability (writer, GSK_SPV_CAPABILITY_SHADER);
+  gsk_spv_writer_ext_inst_import (writer,
+                                  "GLSL.std.450");
+  gsk_spv_writer_memory_model (writer,
+                               GSK_SPV_ADDRESSING_MODEL_LOGICAL,
+                               GSK_SPV_MEMORY_MODEL_GLSL450);
+  gsk_spv_writer_entry_point (writer,
+                              GSK_SPV_EXECUTION_MODEL_FRAGMENT,
+                              writer->entry_point,
+                              "main",
+                              NULL,
+                              0);
+  gsk_spv_writer_execution_mode (writer,
+                                 writer->entry_point,
+                                 GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT);
 }
 
 static void
@@ -288,7 +275,7 @@ gsk_spv_writer_get_id_for_variable (GskSpvWriter  *writer,
 }
 
 guint32
-gsk_spv_writer_next_id (GskSpvWriter *writer)
+gsk_spv_writer_make_id (GskSpvWriter *writer)
 {
   writer->last_id++;
 
@@ -302,18 +289,11 @@ gsk_spv_writer_set_entry_point (GskSpvWriter *writer,
   writer->entry_point = entry_point;
 }
 
-void
-gsk_spv_writer_add (GskSpvWriter        *writer,
-                    GskSpvWriterSection  section,
-                    guint16              word_count,
-                    guint16              opcode,
-                    guint32             *words)
+GArray *
+gsk_spv_writer_get_bytes (GskSpvWriter        *writer,
+                          GskSpvWriterSection  section)
 {
-  guint32 word;
-
-  word = word_count << 16 | opcode;
-  g_array_append_val (writer->code[section], word);
-  g_array_append_vals (writer->code[section], words, word_count - 1);
+  return writer->code[section];
 }
 
 static void
@@ -329,10 +309,10 @@ copy_8_bytes (gpointer dest, gpointer src)
 }
 
 guint32
-gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
-                               guint32          id,
-                               GskSlType       *type,
-                               GskSlType       *new_type)
+gsk_spv_writer_convert (GskSpvWriter *writer,
+                        guint32       id,
+                        GskSlType    *type,
+                        GskSlType    *new_type)
 {
   GskSlScalarType scalar = gsk_sl_type_get_scalar_type (type);
   GskSlScalarType new_scalar = gsk_sl_type_get_scalar_type (new_type);
@@ -344,7 +324,6 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
       gsk_sl_type_is_vector (type))
     {
       GskSlValue *value;
-      guint32 result_type_id, result_id;
       guint32 true_id, false_id, zero_id;
 
       switch (new_scalar)
@@ -360,27 +339,14 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
             {
             case GSK_SL_INT:
             case GSK_SL_UINT:
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  4, GSK_SPV_OP_BITCAST,
-                                  (guint32[3]) { result_type_id,
-                                                 result_id,
-                                                 id });
-              return result_id;
+              return gsk_spv_writer_bitcast (writer, new_type, id);
 
             case GSK_SL_FLOAT:
             case GSK_SL_DOUBLE:
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  4, new_scalar == GSK_SL_UINT ? GSK_SPV_OP_CONVERT_F_TO_U : 
GSK_SPV_OP_CONVERT_F_TO_S,
-                                  (guint32[3]) { result_type_id,
-                                                 result_id,
-                                                 id });
-              return result_id;
+              if (new_scalar == GSK_SL_UINT)
+                return gsk_spv_writer_convert_f_to_u (writer, new_type, id);
+              else
+                return gsk_spv_writer_convert_f_to_s (writer, new_type, id);
 
             case GSK_SL_BOOL:
               value = gsk_sl_value_new (new_type);
@@ -388,17 +354,7 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
               gsk_sl_value_componentwise (value, copy_4_bytes, &(gint32) { 1 });
               true_id = gsk_spv_writer_get_id_for_value (writer, value);
               gsk_sl_value_free (value);
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  6, GSK_SPV_OP_SELECT,
-                                  (guint32[5]) { result_type_id,
-                                                 result_id,
-                                                 id,
-                                                 true_id,
-                                                 false_id });
-              return result_id;
+              return gsk_spv_writer_select (writer, new_type, id, true_id, false_id);
 
             case GSK_SL_VOID:
             default:
@@ -412,38 +368,14 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
           switch (scalar)
             {
             case GSK_SL_INT:
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  4, GSK_SPV_OP_CONVERT_S_TO_F,
-                                  (guint32[3]) { result_type_id,
-                                                 result_id,
-                                                 id });
-              return result_id;
+              return gsk_spv_writer_convert_s_to_f (writer, new_type, id);
 
             case GSK_SL_UINT:
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  4, GSK_SPV_OP_CONVERT_U_TO_F,
-                                  (guint32[3]) { result_type_id,
-                                                 result_id,
-                                                 id });
-              return result_id;
+              return gsk_spv_writer_convert_u_to_f (writer, new_type, id);
 
             case GSK_SL_FLOAT:
             case GSK_SL_DOUBLE:
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  4, GSK_SPV_OP_F_CONVERT,
-                                  (guint32[3]) { result_type_id,
-                                                 result_id,
-                                                 id });
-              return result_id;
+              return gsk_spv_writer_f_convert (writer, new_type, id);
 
             case GSK_SL_BOOL:
               value = gsk_sl_value_new (new_type);
@@ -454,17 +386,11 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
                 gsk_sl_value_componentwise (value, copy_4_bytes, &(float) { 1 });
               true_id = gsk_spv_writer_get_id_for_value (writer, value);
               gsk_sl_value_free (value);
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  6, GSK_SPV_OP_SELECT,
-                                  (guint32[5]) { result_type_id,
-                                                 result_id,
-                                                 id,
-                                                 true_id,
-                                                 false_id });
-              return result_id;
+              return gsk_spv_writer_select (writer,
+                                            new_type,
+                                            id,
+                                            true_id,
+                                            false_id);
 
             case GSK_SL_VOID:
             default:
@@ -481,32 +407,14 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
               value = gsk_sl_value_new (new_type);
               zero_id = gsk_spv_writer_get_id_for_value (writer, value);
               gsk_sl_value_free (value);
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_I_NOT_EQUAL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 id,
-                                                 zero_id });
-              return result_id;
+              return gsk_spv_writer_i_not_equal (writer, new_type, id, zero_id);
 
             case GSK_SL_FLOAT:
             case GSK_SL_DOUBLE:
               value = gsk_sl_value_new (new_type);
               zero_id = gsk_spv_writer_get_id_for_value (writer, value);
               gsk_sl_value_free (value);
-              result_type_id = gsk_spv_writer_get_id_for_type (writer, new_type);
-              result_id = gsk_spv_writer_next_id (writer);
-              gsk_spv_writer_add (writer,
-                                  GSK_SPV_WRITER_SECTION_CODE,
-                                  5, GSK_SPV_OP_F_ORD_NOT_EQUAL,
-                                  (guint32[4]) { result_type_id,
-                                                 result_id,
-                                                 id,
-                                                 zero_id });
-              return result_id;
+              return gsk_spv_writer_f_ord_not_equal (writer, new_type, id, zero_id);
 
             case GSK_SL_BOOL:
             case GSK_SL_VOID:
@@ -522,32 +430,17 @@ gsk_spv_writer_add_conversion (GskSpvWriter    *writer,
     {
       GskSlType *row_type, *new_row_type;
       guint i, n = gsk_sl_type_get_length (type);
-      guint32 ids[n + 2], row_id;
+      guint32 ids[n];
 
       row_type = gsk_sl_type_get_index_type (type);
       new_row_type = gsk_sl_type_get_index_type (new_type);
-      row_id = gsk_spv_writer_get_id_for_type (writer, row_type);
       for (i = 0; i < n; i++)
         {
-          guint tmp_id = gsk_spv_writer_next_id (writer);
-          gsk_spv_writer_add (writer,
-                              GSK_SPV_WRITER_SECTION_CODE,
-                              5, GSK_SPV_OP_COMPOSITE_EXTRACT,
-                              (guint32[4]) { row_id,
-                                             tmp_id,
-                                             id,
-                                             i });
-          ids[i + 2] = gsk_spv_writer_add_conversion (writer, tmp_id, row_type, new_row_type);
+          ids[i] = gsk_spv_writer_composite_extract (writer, row_type, id, (guint32[1]) { i }, 1);
+          ids[i] = gsk_spv_writer_convert (writer, ids[i], row_type, new_row_type);
         }
 
-      ids[0] = gsk_spv_writer_get_id_for_type (writer, new_type);
-      ids[1] = gsk_spv_writer_next_id (writer);
-      gsk_spv_writer_add (writer,
-                          GSK_SPV_WRITER_SECTION_CODE,
-                          3 + n, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
-                          ids);
-
-      return ids[1];
+      return gsk_spv_writer_composite_construct (writer, new_type, ids, n);
     }
   else
     {
diff --git a/gsk/gskspvwritergeneratedprivate.h b/gsk/gskspvwritergeneratedprivate.h
new file mode 100644
index 0000000..fc2de3c
--- /dev/null
+++ b/gsk/gskspvwritergeneratedprivate.h
@@ -0,0 +1,6367 @@
+/* GTK - The GIMP Toolkit
+ *   
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * !!! THIS FILE WAS AUTOGENERATED !!!
+ * 
+ * This file was created using the command
+ *   gjs spirv.js functions spirv.core.grammar.json
+ * Apply any changes to those files and then regenerate using above command.
+ */
+
+#include <string.h>
+
+static inline void
+append_string (GArray     *bytes,
+               const char *str)
+{
+  gsize len = strlen (str);
+  guint size = bytes->len;
+  g_array_set_size (bytes, size + len / 4 + 1);
+  memcpy (&g_array_index (bytes, guint32, size), str, len);
+}
+
+static inline void
+gsk_spv_writer_nop (GskSpvWriter *writer,
+                    GskSpvWriterSection section)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_NOP;
+}
+
+static inline guint32
+gsk_spv_writer_undef (GskSpvWriter *writer,
+                      GskSpvWriterSection section,
+                      GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_UNDEF;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_source_continued (GskSpvWriter *writer,
+                                 GskSpvWriterSection section,
+                                 const char * continued_source)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  append_string (bytes, continued_source);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SOURCE_CONTINUED;
+}
+
+static inline void
+gsk_spv_writer_source (GskSpvWriter *writer,
+                       GskSpvSourceLanguage source_language,
+                       guint32 version,
+                       guint32 opt_file,
+                       const char * opt_source)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEBUG);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, (guint32) { source_language });
+  g_array_append_val (bytes, version);
+  if (opt_file != 0)
+    g_array_append_val (bytes, opt_file);
+  if (opt_source != NULL)
+    append_string (bytes, opt_source);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SOURCE;
+}
+
+static inline void
+gsk_spv_writer_source_extension (GskSpvWriter *writer,
+                                 const char * extension)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEBUG);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  append_string (bytes, extension);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SOURCE_EXTENSION;
+}
+
+static inline void
+gsk_spv_writer_name (GskSpvWriter *writer,
+                     guint32 target,
+                     const char * name)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEBUG);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, target);
+  append_string (bytes, name);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_NAME;
+}
+
+static inline void
+gsk_spv_writer_member_name (GskSpvWriter *writer,
+                            guint32 type,
+                            guint32 member,
+                            const char * name)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEBUG);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, type);
+  g_array_append_val (bytes, member);
+  append_string (bytes, name);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_MEMBER_NAME;
+}
+
+static inline guint32
+gsk_spv_writer_string (GskSpvWriter *writer,
+                       GskSpvWriterSection section,
+                       const char * string)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  append_string (bytes, string);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_STRING;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_line (GskSpvWriter *writer,
+                     GskSpvWriterSection section,
+                     guint32 file,
+                     guint32 line,
+                     guint32 column)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, file);
+  g_array_append_val (bytes, line);
+  g_array_append_val (bytes, column);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LINE;
+}
+
+static inline void
+gsk_spv_writer_extension (GskSpvWriter *writer,
+                          const char * name)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  append_string (bytes, name);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_EXTENSION;
+}
+
+static inline guint32
+gsk_spv_writer_ext_inst_import (GskSpvWriter *writer,
+                                const char * name)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  append_string (bytes, name);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_EXT_INST_IMPORT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_ext_inst (GskSpvWriter *writer,
+                         GskSpvWriterSection section,
+                         GskSlType * result_type,
+                         guint32 set,
+                         guint32 instruction,
+                         guint32 *operands,
+                         gsize n_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, set);
+  g_array_append_val (bytes, instruction);
+  g_array_append_vals (bytes, operands, n_operands);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_EXT_INST;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_memory_model (GskSpvWriter *writer,
+                             GskSpvAddressingModel addressing_model,
+                             GskSpvMemoryModel memory_model)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, (guint32) { addressing_model });
+  g_array_append_val (bytes, (guint32) { memory_model });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_MEMORY_MODEL;
+}
+
+static inline void
+gsk_spv_writer_entry_point (GskSpvWriter *writer,
+                            GskSpvExecutionModel execution_model,
+                            guint32 entry_point,
+                            const char * name,
+                            guint32 *interfaces,
+                            gsize n_interfaces)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, (guint32) { execution_model });
+  g_array_append_val (bytes, entry_point);
+  append_string (bytes, name);
+  g_array_append_vals (bytes, interfaces, n_interfaces);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ENTRY_POINT;
+}
+
+static inline void
+gsk_spv_writer_execution_mode (GskSpvWriter *writer,
+                               guint32 entry_point,
+                               GskSpvExecutionMode mode)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, entry_point);
+  g_array_append_val (bytes, (guint32) { mode });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_EXECUTION_MODE;
+}
+
+static inline void
+gsk_spv_writer_capability (GskSpvWriter *writer,
+                           GskSpvCapability capability)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_HEADER);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, (guint32) { capability });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CAPABILITY;
+}
+
+static inline guint32
+gsk_spv_writer_type_void (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_VOID;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_bool (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_BOOL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_int (GskSpvWriter *writer,
+                         guint32 width,
+                         guint32 signedness)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, width);
+  g_array_append_val (bytes, signedness);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_INT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_float (GskSpvWriter *writer,
+                           guint32 width)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, width);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_FLOAT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_vector (GskSpvWriter *writer,
+                            guint32 component_type,
+                            guint32 component_count)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, component_type);
+  g_array_append_val (bytes, component_count);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_VECTOR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_matrix (GskSpvWriter *writer,
+                            guint32 column_type,
+                            guint32 column_count)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, column_type);
+  g_array_append_val (bytes, column_count);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_MATRIX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_image (GskSpvWriter *writer,
+                           guint32 sampled_type,
+                           GskSpvDim dim,
+                           guint32 depth,
+                           guint32 arrayed,
+                           guint32 ms,
+                           guint32 sampled,
+                           GskSpvImageFormat image_format,
+                           GskSpvAccessQualifier opt_access_qualifier)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_type);
+  g_array_append_val (bytes, (guint32) { dim });
+  g_array_append_val (bytes, depth);
+  g_array_append_val (bytes, arrayed);
+  g_array_append_val (bytes, ms);
+  g_array_append_val (bytes, sampled);
+  g_array_append_val (bytes, (guint32) { image_format });
+  g_array_append_val (bytes, (guint32) { opt_access_qualifier });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_IMAGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_sampler (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_SAMPLER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_sampled_image (GskSpvWriter *writer,
+                                   guint32 image_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image_type);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_TYPE_SAMPLED_IMAGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_array (GskSpvWriter *writer,
+                           guint32 element_type,
+                           guint32 length)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, element_type);
+  g_array_append_val (bytes, length);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_ARRAY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_runtime_array (GskSpvWriter *writer,
+                                   guint32 element_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, element_type);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_TYPE_RUNTIME_ARRAY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_struct (GskSpvWriter *writer,
+                            guint32 *member_0_types,
+                            gsize n_member_0_types)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, member_0_types, n_member_0_types);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_STRUCT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_opaque (GskSpvWriter *writer,
+                            const char * name)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  append_string (bytes, name);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_OPAQUE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_pointer (GskSpvWriter *writer,
+                             GskSpvStorageClass storage_class,
+                             guint32 type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, (guint32) { storage_class });
+  g_array_append_val (bytes, type);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_POINTER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_function (GskSpvWriter *writer,
+                              guint32 return_type,
+                              guint32 *parameter_0_types,
+                              gsize n_parameter_0_types)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, return_type);
+  g_array_append_vals (bytes, parameter_0_types, n_parameter_0_types);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_FUNCTION;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_event (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_EVENT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_device_event (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_TYPE_DEVICE_EVENT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_reserve_id (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_TYPE_RESERVE_ID;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_queue (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_QUEUE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_type_pipe (GskSpvWriter *writer,
+                          GskSpvAccessQualifier qualifier)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, (guint32) { qualifier });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TYPE_PIPE;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_type_forward_pointer (GskSpvWriter *writer,
+                                     guint32 pointer_type,
+                                     GskSpvStorageClass storage_class)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer_type);
+  g_array_append_val (bytes, (guint32) { storage_class });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_TYPE_FORWARD_POINTER;
+}
+
+static inline guint32
+gsk_spv_writer_constant_true (GskSpvWriter *writer,
+                              GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONSTANT_TRUE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_constant_false (GskSpvWriter *writer,
+                               GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONSTANT_FALSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_constant (GskSpvWriter *writer,
+                         GskSlType * result_type,
+                         guint32 *values,
+                         gsize n_values)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, values, n_values);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONSTANT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_constant_composite (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 *constituents,
+                                   gsize n_constituents)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, constituents, n_constituents);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CONSTANT_COMPOSITE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_constant_sampler (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 GskSpvSamplerAddressingMode sampler_addressing_mode,
+                                 guint32 param,
+                                 GskSpvSamplerFilterMode sampler_filter_mode)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, (guint32) { sampler_addressing_mode });
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, (guint32) { sampler_filter_mode });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CONSTANT_SAMPLER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_constant_null (GskSpvWriter *writer,
+                              GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONSTANT_NULL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_spec_constant_true (GskSpvWriter *writer,
+                                   GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SPEC_CONSTANT_TRUE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_spec_constant_false (GskSpvWriter *writer,
+                                    GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SPEC_CONSTANT_FALSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_spec_constant (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 *values,
+                              gsize n_values)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, values, n_values);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SPEC_CONSTANT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_spec_constant_composite (GskSpvWriter *writer,
+                                        GskSlType * result_type,
+                                        guint32 *constituents,
+                                        gsize n_constituents)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, constituents, n_constituents);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SPEC_CONSTANT_COMPOSITE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_spec_constant_op (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 *opcodes,
+                                 gsize n_opcodes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DEFINE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, opcodes, n_opcodes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SPEC_CONSTANT_OP;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_function (GskSpvWriter *writer,
+                         GskSlType * result_type,
+                         GskSpvFunctionControl function_control,
+                         guint32 function_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECLARE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, (guint32) { function_control });
+  g_array_append_val (bytes, function_type);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FUNCTION;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_function_parameter (GskSpvWriter *writer,
+                                   GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECLARE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_FUNCTION_PARAMETER;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_function_end (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FUNCTION_END;
+}
+
+static inline guint32
+gsk_spv_writer_function_call (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 function,
+                              guint32 *argument_0s,
+                              gsize n_argument_0s)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, function);
+  g_array_append_vals (bytes, argument_0s, n_argument_0s);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FUNCTION_CALL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_variable (GskSpvWriter *writer,
+                         GskSlPointerType * result_type,
+                         GskSpvStorageClass storage_class,
+                         guint32 opt_initializer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECLARE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, (guint32) { storage_class });
+  if (opt_initializer != 0)
+    g_array_append_val (bytes, opt_initializer);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_VARIABLE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_texel_pointer (GskSpvWriter *writer,
+                                    GskSlPointerType * result_type,
+                                    guint32 image,
+                                    guint32 coordinate,
+                                    guint32 sample)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, sample);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_TEXEL_POINTER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_load (GskSpvWriter *writer,
+                     GskSlType * result_type,
+                     guint32 pointer,
+                     GskSpvMemoryAccess opt_memory_access)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  if (opt_memory_access != 0)
+    g_array_append_val (bytes, (guint32) { opt_memory_access });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOAD;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_store (GskSpvWriter *writer,
+                      guint32 pointer,
+                      guint32 object,
+                      GskSpvMemoryAccess opt_memory_access)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, object);
+  if (opt_memory_access != 0)
+    g_array_append_val (bytes, (guint32) { opt_memory_access });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_STORE;
+}
+
+static inline void
+gsk_spv_writer_copy_memory (GskSpvWriter *writer,
+                            guint32 target,
+                            guint32 source,
+                            GskSpvMemoryAccess opt_memory_access)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, target);
+  g_array_append_val (bytes, source);
+  if (opt_memory_access != 0)
+    g_array_append_val (bytes, (guint32) { opt_memory_access });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_COPY_MEMORY;
+}
+
+static inline void
+gsk_spv_writer_copy_memory_sized (GskSpvWriter *writer,
+                                  guint32 target,
+                                  guint32 source,
+                                  guint32 size,
+                                  GskSpvMemoryAccess opt_memory_access)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, target);
+  g_array_append_val (bytes, source);
+  g_array_append_val (bytes, size);
+  if (opt_memory_access != 0)
+    g_array_append_val (bytes, (guint32) { opt_memory_access });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COPY_MEMORY_SIZED;
+}
+
+static inline guint32
+gsk_spv_writer_access_chain (GskSpvWriter *writer,
+                             GskSlPointerType * result_type,
+                             guint32 base,
+                             guint32 *indexes,
+                             gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ACCESS_CHAIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_in_bounds_access_chain (GskSpvWriter *writer,
+                                       GskSlPointerType * result_type,
+                                       guint32 base,
+                                       guint32 *indexes,
+                                       gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IN_BOUNDS_ACCESS_CHAIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_ptr_access_chain (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 base,
+                                 guint32 element,
+                                 guint32 *indexes,
+                                 gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, element);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_PTR_ACCESS_CHAIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_array_length (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 structure,
+                             guint32 array_member)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, structure);
+  g_array_append_val (bytes, array_member);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ARRAY_LENGTH;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_generic_ptr_mem_semantics (GskSpvWriter *writer,
+                                          GskSpvWriterSection section,
+                                          GskSlType * result_type,
+                                          guint32 pointer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_in_bounds_ptr_access_chain (GskSpvWriter *writer,
+                                           GskSlType * result_type,
+                                           guint32 base,
+                                           guint32 element,
+                                           guint32 *indexes,
+                                           gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, element);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_decorate (GskSpvWriter *writer,
+                         guint32 target,
+                         GskSpvDecoration decoration)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECORATE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, target);
+  g_array_append_val (bytes, (guint32) { decoration });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_DECORATE;
+}
+
+static inline void
+gsk_spv_writer_member_decorate (GskSpvWriter *writer,
+                                guint32 structure_type,
+                                guint32 member,
+                                GskSpvDecoration decoration)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECORATE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, structure_type);
+  g_array_append_val (bytes, member);
+  g_array_append_val (bytes, (guint32) { decoration });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_MEMBER_DECORATE;
+}
+
+static inline guint32
+gsk_spv_writer_decoration_group (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECORATE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_DECORATION_GROUP;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_group_decorate (GskSpvWriter *writer,
+                               guint32 decoration_group,
+                               guint32 *targets,
+                               gsize n_targets)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECORATE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, decoration_group);
+  g_array_append_vals (bytes, targets, n_targets);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_DECORATE;
+}
+
+static inline void
+gsk_spv_writer_group_member_decorate (GskSpvWriter *writer,
+                                      guint32 decoration_group,
+                                      guint32 *targets[2],
+                                      gsize n_targets)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_DECORATE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, decoration_group);
+  g_array_append_vals (bytes, targets, 2 * n_targets);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_MEMBER_DECORATE;
+}
+
+static inline guint32
+gsk_spv_writer_vector_extract_dynamic (GskSpvWriter *writer,
+                                       GskSlType * result_type,
+                                       guint32 vector,
+                                       guint32 index)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_append_val (bytes, index);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_vector_insert_dynamic (GskSpvWriter *writer,
+                                      GskSlType * result_type,
+                                      guint32 vector,
+                                      guint32 component,
+                                      guint32 index)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_append_val (bytes, component);
+  g_array_append_val (bytes, index);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_VECTOR_INSERT_DYNAMIC;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_vector_shuffle (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 vector_1,
+                               guint32 vector_2,
+                               guint32 *components,
+                               gsize n_components)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector_1);
+  g_array_append_val (bytes, vector_2);
+  g_array_append_vals (bytes, components, n_components);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_VECTOR_SHUFFLE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_composite_construct (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 *constituents,
+                                    gsize n_constituents)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, constituents, n_constituents);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COMPOSITE_CONSTRUCT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_composite_extract (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 composite,
+                                  guint32 *indexes,
+                                  gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, composite);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COMPOSITE_EXTRACT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_composite_insert (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 object,
+                                 guint32 composite,
+                                 guint32 *indexes,
+                                 gsize n_indexes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, object);
+  g_array_append_val (bytes, composite);
+  g_array_append_vals (bytes, indexes, n_indexes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COMPOSITE_INSERT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_copy_object (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_COPY_OBJECT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_transpose (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 matrix)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, matrix);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_TRANSPOSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_sampled_image (GskSpvWriter *writer,
+                              GskSpvWriterSection section,
+                              GskSlType * result_type,
+                              guint32 image,
+                              guint32 sampler)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, sampler);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SAMPLED_IMAGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_implicit_lod (GskSpvWriter *writer,
+                                          GskSlType * result_type,
+                                          guint32 sampled_image,
+                                          guint32 coordinate,
+                                          GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_explicit_lod (GskSpvWriter *writer,
+                                          GskSlType * result_type,
+                                          guint32 sampled_image,
+                                          guint32 coordinate,
+                                          GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_dref_implicit_lod (GskSpvWriter *writer,
+                                               GskSlType * result_type,
+                                               guint32 sampled_image,
+                                               guint32 coordinate,
+                                               guint32 d_ref_,
+                                               GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_DREF_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_dref_explicit_lod (GskSpvWriter *writer,
+                                               GskSlType * result_type,
+                                               guint32 sampled_image,
+                                               guint32 coordinate,
+                                               guint32 d_ref_,
+                                               GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_DREF_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_proj_implicit_lod (GskSpvWriter *writer,
+                                               GskSlType * result_type,
+                                               guint32 sampled_image,
+                                               guint32 coordinate,
+                                               GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_proj_explicit_lod (GskSpvWriter *writer,
+                                               GskSlType * result_type,
+                                               guint32 sampled_image,
+                                               guint32 coordinate,
+                                               GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_proj_dref_implicit_lod (GskSpvWriter *writer,
+                                                    GskSlType * result_type,
+                                                    guint32 sampled_image,
+                                                    guint32 coordinate,
+                                                    guint32 d_ref_,
+                                                    GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sample_proj_dref_explicit_lod (GskSpvWriter *writer,
+                                                    GskSlType * result_type,
+                                                    guint32 sampled_image,
+                                                    guint32 coordinate,
+                                                    guint32 d_ref_,
+                                                    GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_fetch (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 image,
+                            guint32 coordinate,
+                            GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IMAGE_FETCH;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_gather (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 sampled_image,
+                             guint32 coordinate,
+                             guint32 component,
+                             GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, component);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IMAGE_GATHER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_dref_gather (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 sampled_image,
+                                  guint32 coordinate,
+                                  guint32 d_ref_,
+                                  GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_DREF_GATHER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_read (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 image,
+                           guint32 coordinate,
+                           GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IMAGE_READ;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_image_write (GskSpvWriter *writer,
+                            guint32 image,
+                            guint32 coordinate,
+                            guint32 texel,
+                            GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, texel);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IMAGE_WRITE;
+}
+
+static inline guint32
+gsk_spv_writer_image (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 sampled_image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IMAGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_format (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_FORMAT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_order (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_ORDER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_size_lod (GskSpvWriter *writer,
+                                     GskSlType * result_type,
+                                     guint32 image,
+                                     guint32 level_of_detail)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, level_of_detail);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_SIZE_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_size (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_SIZE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_lod (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 sampled_image,
+                                guint32 coordinate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_levels (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_LEVELS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_query_samples (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 image)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_QUERY_SAMPLES;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_f_to_u (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 float_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, float_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONVERT_F_TO_U;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_f_to_s (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 float_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, float_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONVERT_F_TO_S;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_s_to_f (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 signed_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, signed_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONVERT_S_TO_F;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_u_to_f (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 unsigned_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, unsigned_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_CONVERT_U_TO_F;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_convert (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 unsigned_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, unsigned_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_CONVERT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_convert (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 signed_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, signed_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_CONVERT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_convert (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 float_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, float_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_CONVERT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_quantize_to_f16 (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_QUANTIZE_TO_F16;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_ptr_to_u (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 pointer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CONVERT_PTR_TO_U;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_sat_convert_s_to_u (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 signed_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, signed_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SAT_CONVERT_S_TO_U;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_sat_convert_u_to_s (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 unsigned_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, unsigned_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SAT_CONVERT_U_TO_S;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_convert_u_to_ptr (GskSpvWriter *writer,
+                                 GskSlPointerType * result_type,
+                                 guint32 integer_value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, integer_value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CONVERT_U_TO_PTR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_ptr_cast_to_generic (GskSpvWriter *writer,
+                                    GskSlPointerType * result_type,
+                                    guint32 pointer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_PTR_CAST_TO_GENERIC;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_generic_cast_to_ptr (GskSpvWriter *writer,
+                                    GskSlPointerType * result_type,
+                                    guint32 pointer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GENERIC_CAST_TO_PTR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_generic_cast_to_ptr_explicit (GskSpvWriter *writer,
+                                             GskSlPointerType * result_type,
+                                             guint32 pointer,
+                                             GskSpvStorageClass storage)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, (guint32) { storage });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bitcast (GskSpvWriter *writer,
+                        GskSlType * result_type,
+                        guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BITCAST;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_negate (GskSpvWriter *writer,
+                         GskSlType * result_type,
+                         guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_NEGATE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_negate (GskSpvWriter *writer,
+                         GskSlType * result_type,
+                         guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_NEGATE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_add (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_ADD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_add (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_ADD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_sub (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_SUB;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_sub (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_SUB;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_mul (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_MUL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_mul (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_MUL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_div (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_DIV;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_div (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_DIV;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_div (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_DIV;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_mod (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_MOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_rem (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_REM;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_mod (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_MOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_rem (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_REM;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_mod (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 operand_1,
+                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_MOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_vector_times_scalar (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 vector,
+                                    guint32 scalar)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_append_val (bytes, scalar);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_VECTOR_TIMES_SCALAR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_matrix_times_scalar (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 matrix,
+                                    guint32 scalar)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, matrix);
+  g_array_append_val (bytes, scalar);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_MATRIX_TIMES_SCALAR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_vector_times_matrix (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 vector,
+                                    guint32 matrix)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_append_val (bytes, matrix);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_VECTOR_TIMES_MATRIX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_matrix_times_vector (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 matrix,
+                                    guint32 vector)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, matrix);
+  g_array_append_val (bytes, vector);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_MATRIX_TIMES_VECTOR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_matrix_times_matrix (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 left_matrix,
+                                    guint32 right_matrix)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, left_matrix);
+  g_array_append_val (bytes, right_matrix);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_MATRIX_TIMES_MATRIX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_outer_product (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 vector_1,
+                              guint32 vector_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector_1);
+  g_array_append_val (bytes, vector_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_OUTER_PRODUCT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_dot (GskSpvWriter *writer,
+                    GskSlType * result_type,
+                    guint32 vector_1,
+                    guint32 vector_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector_1);
+  g_array_append_val (bytes, vector_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_DOT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_add_carry (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_ADD_CARRY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_sub_borrow (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 operand_1,
+                             guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_SUB_BORROW;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_mul_extended (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 operand_1,
+                               guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_MUL_EXTENDED;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_mul_extended (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 operand_1,
+                               guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_MUL_EXTENDED;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_any (GskSpvWriter *writer,
+                    GskSlType * result_type,
+                    guint32 vector)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ANY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_all (GskSpvWriter *writer,
+                    GskSlType * result_type,
+                    guint32 vector)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, vector);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ALL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_is_nan (GskSpvWriter *writer,
+                       GskSlType * result_type,
+                       guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IS_NAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_is_inf (GskSpvWriter *writer,
+                       GskSlType * result_type,
+                       guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IS_INF;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_is_finite (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IS_FINITE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_is_normal (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IS_NORMAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_sign_bit_set (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SIGN_BIT_SET;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_less_or_greater (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 x,
+                                guint32 y)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_append_val (bytes, y);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_LESS_OR_GREATER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_ordered (GskSpvWriter *writer,
+                        GskSlType * result_type,
+                        guint32 x,
+                        guint32 y)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_append_val (bytes, y);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ORDERED;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_unordered (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 x,
+                          guint32 y)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, x);
+  g_array_append_val (bytes, y);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_UNORDERED;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_logical_equal (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 operand_1,
+                              guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOGICAL_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_logical_not_equal (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 operand_1,
+                                  guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_LOGICAL_NOT_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_logical_or (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 operand_1,
+                           guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOGICAL_OR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_logical_and (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOGICAL_AND;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_logical_not (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOGICAL_NOT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_select (GskSpvWriter *writer,
+                       GskSlType * result_type,
+                       guint32 condition,
+                       guint32 object_1,
+                       guint32 object_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, condition);
+  g_array_append_val (bytes, object_1);
+  g_array_append_val (bytes, object_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SELECT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_equal (GskSpvWriter *writer,
+                        GskSlType * result_type,
+                        guint32 operand_1,
+                        guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_i_not_equal (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_I_NOT_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_greater_than (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 operand_1,
+                               guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_GREATER_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_greater_than (GskSpvWriter *writer,
+                               GskSlType * result_type,
+                               guint32 operand_1,
+                               guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_GREATER_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_greater_than_equal (GskSpvWriter *writer,
+                                     GskSlType * result_type,
+                                     guint32 operand_1,
+                                     guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_U_GREATER_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_greater_than_equal (GskSpvWriter *writer,
+                                     GskSlType * result_type,
+                                     guint32 operand_1,
+                                     guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_S_GREATER_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_less_than (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_U_LESS_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_less_than (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_S_LESS_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_u_less_than_equal (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 operand_1,
+                                  guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_U_LESS_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_s_less_than_equal (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 operand_1,
+                                  guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_S_LESS_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_equal (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_ORD_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_equal (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 operand_1,
+                              guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_F_UNORD_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_not_equal (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 operand_1,
+                                guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_ORD_NOT_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_not_equal (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 operand_1,
+                                  guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_UNORD_NOT_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_less_than (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 operand_1,
+                                guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_ORD_LESS_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_less_than (GskSpvWriter *writer,
+                                  GskSlType * result_type,
+                                  guint32 operand_1,
+                                  guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_UNORD_LESS_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_greater_than (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 operand_1,
+                                   guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_ORD_GREATER_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_greater_than (GskSpvWriter *writer,
+                                     GskSlType * result_type,
+                                     guint32 operand_1,
+                                     guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_UNORD_GREATER_THAN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_less_than_equal (GskSpvWriter *writer,
+                                      GskSlType * result_type,
+                                      guint32 operand_1,
+                                      guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_ORD_LESS_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_less_than_equal (GskSpvWriter *writer,
+                                        GskSlType * result_type,
+                                        guint32 operand_1,
+                                        guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_UNORD_LESS_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_ord_greater_than_equal (GskSpvWriter *writer,
+                                         GskSlType * result_type,
+                                         guint32 operand_1,
+                                         guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_ORD_GREATER_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_f_unord_greater_than_equal (GskSpvWriter *writer,
+                                           GskSlType * result_type,
+                                           guint32 operand_1,
+                                           guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_F_UNORD_GREATER_THAN_EQUAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_shift_right_logical (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 base,
+                                    guint32 shift)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, shift);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SHIFT_RIGHT_LOGICAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_shift_right_arithmetic (GskSpvWriter *writer,
+                                       GskSlType * result_type,
+                                       guint32 base,
+                                       guint32 shift)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, shift);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SHIFT_RIGHT_ARITHMETIC;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_shift_left_logical (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 base,
+                                   guint32 shift)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, shift);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SHIFT_LEFT_LOGICAL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bitwise_or (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 operand_1,
+                           guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BITWISE_OR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bitwise_xor (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BITWISE_XOR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bitwise_and (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 operand_1,
+                            guint32 operand_2)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand_1);
+  g_array_append_val (bytes, operand_2);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BITWISE_AND;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_not (GskSpvWriter *writer,
+                    GskSlType * result_type,
+                    guint32 operand)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, operand);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_NOT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bit_field_insert (GskSpvWriter *writer,
+                                 GskSlType * result_type,
+                                 guint32 base,
+                                 guint32 insert,
+                                 guint32 offset,
+                                 guint32 count)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, insert);
+  g_array_append_val (bytes, offset);
+  g_array_append_val (bytes, count);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_BIT_FIELD_INSERT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bit_field_s_extract (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 base,
+                                    guint32 offset,
+                                    guint32 count)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, offset);
+  g_array_append_val (bytes, count);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_BIT_FIELD_S_EXTRACT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bit_field_u_extract (GskSpvWriter *writer,
+                                    GskSlType * result_type,
+                                    guint32 base,
+                                    guint32 offset,
+                                    guint32 count)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_append_val (bytes, offset);
+  g_array_append_val (bytes, count);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_BIT_FIELD_U_EXTRACT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bit_reverse (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 base)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BIT_REVERSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_bit_count (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 base)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, base);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BIT_COUNT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdx (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdy (GskSpvWriter *writer,
+                      GskSlType * result_type,
+                      guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_fwidth (GskSpvWriter *writer,
+                       GskSlType * result_type,
+                       guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FWIDTH;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdx_fine (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDX_FINE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdy_fine (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDY_FINE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_fwidth_fine (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FWIDTH_FINE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdx_coarse (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDX_COARSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_d_pdy_coarse (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_D_PDY_COARSE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_fwidth_coarse (GskSpvWriter *writer,
+                              GskSlType * result_type,
+                              guint32 p)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, p);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_FWIDTH_COARSE;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_emit_vertex (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_EMIT_VERTEX;
+}
+
+static inline void
+gsk_spv_writer_end_primitive (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_END_PRIMITIVE;
+}
+
+static inline void
+gsk_spv_writer_emit_stream_vertex (GskSpvWriter *writer,
+                                   guint32 stream)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, stream);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_EMIT_STREAM_VERTEX;
+}
+
+static inline void
+gsk_spv_writer_end_stream_primitive (GskSpvWriter *writer,
+                                     guint32 stream)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, stream);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_END_STREAM_PRIMITIVE;
+}
+
+static inline void
+gsk_spv_writer_control_barrier (GskSpvWriter *writer,
+                                guint32 execution,
+                                guint32 memory,
+                                guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, memory);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CONTROL_BARRIER;
+}
+
+static inline void
+gsk_spv_writer_memory_barrier (GskSpvWriter *writer,
+                               guint32 memory,
+                               guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, memory);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_MEMORY_BARRIER;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_load (GskSpvWriter *writer,
+                            GskSlType * result_type,
+                            guint32 pointer,
+                            guint32 scope,
+                            guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_LOAD;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_atomic_store (GskSpvWriter *writer,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_STORE;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_exchange (GskSpvWriter *writer,
+                                GskSlType * result_type,
+                                guint32 pointer,
+                                guint32 scope,
+                                guint32 semantics,
+                                guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_EXCHANGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_compare_exchange (GskSpvWriter *writer,
+                                        GskSlType * result_type,
+                                        guint32 pointer,
+                                        guint32 scope,
+                                        guint32 equal,
+                                        guint32 unequal,
+                                        guint32 value,
+                                        guint32 comparator)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, equal);
+  g_array_append_val (bytes, unequal);
+  g_array_append_val (bytes, value);
+  g_array_append_val (bytes, comparator);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_compare_exchange_weak (GskSpvWriter *writer,
+                                             GskSlType * result_type,
+                                             guint32 pointer,
+                                             guint32 scope,
+                                             guint32 equal,
+                                             guint32 unequal,
+                                             guint32 value,
+                                             guint32 comparator)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, equal);
+  g_array_append_val (bytes, unequal);
+  g_array_append_val (bytes, value);
+  g_array_append_val (bytes, comparator);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE_WEAK;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_i_increment (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 pointer,
+                                   guint32 scope,
+                                   guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_I_INCREMENT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_i_decrement (GskSpvWriter *writer,
+                                   GskSlType * result_type,
+                                   guint32 pointer,
+                                   guint32 scope,
+                                   guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_I_DECREMENT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_i_add (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_I_ADD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_i_sub (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_I_SUB;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_s_min (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_S_MIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_u_min (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_U_MIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_s_max (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_S_MAX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_u_max (GskSpvWriter *writer,
+                             GskSlType * result_type,
+                             guint32 pointer,
+                             guint32 scope,
+                             guint32 semantics,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_U_MAX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_and (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 pointer,
+                           guint32 scope,
+                           guint32 semantics,
+                           guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_AND;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_or (GskSpvWriter *writer,
+                          GskSlType * result_type,
+                          guint32 pointer,
+                          guint32 scope,
+                          guint32 semantics,
+                          guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_OR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_xor (GskSpvWriter *writer,
+                           GskSlType * result_type,
+                           guint32 pointer,
+                           guint32 scope,
+                           guint32 semantics,
+                           guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ATOMIC_XOR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_phi (GskSpvWriter *writer,
+                    GskSlType * result_type,
+                    guint32 *variable__parent_____s[2],
+                    gsize n_variable__parent_____s)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_vals (bytes, variable__parent_____s, 2 * n_variable__parent_____s);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_PHI;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_loop_merge (GskSpvWriter *writer,
+                           guint32 merge_block,
+                           guint32 continue_target,
+                           GskSpvLoopControl loop_control)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, merge_block);
+  g_array_append_val (bytes, continue_target);
+  g_array_append_val (bytes, (guint32) { loop_control });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LOOP_MERGE;
+}
+
+static inline void
+gsk_spv_writer_selection_merge (GskSpvWriter *writer,
+                                guint32 merge_block,
+                                GskSpvSelectionControl selection_control)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, merge_block);
+  g_array_append_val (bytes, (guint32) { selection_control });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SELECTION_MERGE;
+}
+
+static inline guint32
+gsk_spv_writer_label (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LABEL;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_branch (GskSpvWriter *writer,
+                       guint32 target_label)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, target_label);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BRANCH;
+}
+
+static inline void
+gsk_spv_writer_branch_conditional (GskSpvWriter *writer,
+                                   guint32 condition,
+                                   guint32 true_label,
+                                   guint32 false_label,
+                                   guint32 *branch_weights,
+                                   gsize n_branch_weights)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, condition);
+  g_array_append_val (bytes, true_label);
+  g_array_append_val (bytes, false_label);
+  g_array_append_vals (bytes, branch_weights, n_branch_weights);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_BRANCH_CONDITIONAL;
+}
+
+static inline void
+gsk_spv_writer_switch (GskSpvWriter *writer,
+                       guint32 selector,
+                       guint32 default_,
+                       guint32 *targets[2],
+                       gsize n_targets)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, selector);
+  g_array_append_val (bytes, default_);
+  g_array_append_vals (bytes, targets, 2 * n_targets);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_SWITCH;
+}
+
+static inline void
+gsk_spv_writer_kill (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_KILL;
+}
+
+static inline void
+gsk_spv_writer_return (GskSpvWriter *writer)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_RETURN;
+}
+
+static inline void
+gsk_spv_writer_return_value (GskSpvWriter *writer,
+                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, GSK_SPV_WRITER_SECTION_CODE);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_RETURN_VALUE;
+}
+
+static inline void
+gsk_spv_writer_unreachable (GskSpvWriter *writer,
+                            GskSpvWriterSection section)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_UNREACHABLE;
+}
+
+static inline void
+gsk_spv_writer_lifetime_start (GskSpvWriter *writer,
+                               GskSpvWriterSection section,
+                               guint32 pointer,
+                               guint32 size)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, size);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LIFETIME_START;
+}
+
+static inline void
+gsk_spv_writer_lifetime_stop (GskSpvWriter *writer,
+                              GskSpvWriterSection section,
+                              guint32 pointer,
+                              guint32 size)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, size);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_LIFETIME_STOP;
+}
+
+static inline guint32
+gsk_spv_writer_group_async_copy (GskSpvWriter *writer,
+                                 GskSpvWriterSection section,
+                                 GskSlType * result_type,
+                                 guint32 execution,
+                                 guint32 destination,
+                                 guint32 source,
+                                 guint32 num_elements,
+                                 guint32 stride,
+                                 guint32 event)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, destination);
+  g_array_append_val (bytes, source);
+  g_array_append_val (bytes, num_elements);
+  g_array_append_val (bytes, stride);
+  g_array_append_val (bytes, event);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_ASYNC_COPY;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_group_wait_events (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  guint32 execution,
+                                  guint32 num_events,
+                                  guint32 events_list)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, num_events);
+  g_array_append_val (bytes, events_list);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_WAIT_EVENTS;
+}
+
+static inline guint32
+gsk_spv_writer_group_all (GskSpvWriter *writer,
+                          GskSpvWriterSection section,
+                          GskSlType * result_type,
+                          guint32 execution,
+                          guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_ALL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_any (GskSpvWriter *writer,
+                          GskSpvWriterSection section,
+                          GskSlType * result_type,
+                          guint32 execution,
+                          guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_ANY;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_broadcast (GskSpvWriter *writer,
+                                GskSpvWriterSection section,
+                                GskSlType * result_type,
+                                guint32 execution,
+                                guint32 value,
+                                guint32 local_id)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, value);
+  g_array_append_val (bytes, local_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_BROADCAST;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_i_add (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_I_ADD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_add (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_F_ADD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_min (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_F_MIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_u_min (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_U_MIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_s_min (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_S_MIN;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_max (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_F_MAX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_u_max (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_U_MAX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_s_max (GskSpvWriter *writer,
+                            GskSpvWriterSection section,
+                            GskSlType * result_type,
+                            guint32 execution,
+                            GskSpvGroupOperation operation,
+                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_GROUP_S_MAX;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_read_pipe (GskSpvWriter *writer,
+                          GskSpvWriterSection section,
+                          GskSlType * result_type,
+                          guint32 pipe,
+                          guint32 pointer,
+                          guint32 packet_size,
+                          guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_READ_PIPE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_write_pipe (GskSpvWriter *writer,
+                           GskSpvWriterSection section,
+                           GskSlType * result_type,
+                           guint32 pipe,
+                           guint32 pointer,
+                           guint32 packet_size,
+                           guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_WRITE_PIPE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_reserved_read_pipe (GskSpvWriter *writer,
+                                   GskSpvWriterSection section,
+                                   GskSlType * result_type,
+                                   guint32 pipe,
+                                   guint32 reserve_id,
+                                   guint32 index,
+                                   guint32 pointer,
+                                   guint32 packet_size,
+                                   guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, index);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_RESERVED_READ_PIPE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_reserved_write_pipe (GskSpvWriter *writer,
+                                    GskSpvWriterSection section,
+                                    GskSlType * result_type,
+                                    guint32 pipe,
+                                    guint32 reserve_id,
+                                    guint32 index,
+                                    guint32 pointer,
+                                    guint32 packet_size,
+                                    guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, index);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_RESERVED_WRITE_PIPE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_reserve_read_pipe_packets (GskSpvWriter *writer,
+                                          GskSpvWriterSection section,
+                                          GskSlType * result_type,
+                                          guint32 pipe,
+                                          guint32 num_packets,
+                                          guint32 packet_size,
+                                          guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, num_packets);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_RESERVE_READ_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_reserve_write_pipe_packets (GskSpvWriter *writer,
+                                           GskSpvWriterSection section,
+                                           GskSlType * result_type,
+                                           guint32 pipe,
+                                           guint32 num_packets,
+                                           guint32 packet_size,
+                                           guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, num_packets);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_RESERVE_WRITE_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_commit_read_pipe (GskSpvWriter *writer,
+                                 GskSpvWriterSection section,
+                                 guint32 pipe,
+                                 guint32 reserve_id,
+                                 guint32 packet_size,
+                                 guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COMMIT_READ_PIPE;
+}
+
+static inline void
+gsk_spv_writer_commit_write_pipe (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  guint32 pipe,
+                                  guint32 reserve_id,
+                                  guint32 packet_size,
+                                  guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_COMMIT_WRITE_PIPE;
+}
+
+static inline guint32
+gsk_spv_writer_is_valid_reserve_id (GskSpvWriter *writer,
+                                    GskSpvWriterSection section,
+                                    GskSlType * result_type,
+                                    guint32 reserve_id)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, reserve_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IS_VALID_RESERVE_ID;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_num_pipe_packets (GskSpvWriter *writer,
+                                     GskSpvWriterSection section,
+                                     GskSlType * result_type,
+                                     guint32 pipe,
+                                     guint32 packet_size,
+                                     guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_NUM_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_max_pipe_packets (GskSpvWriter *writer,
+                                     GskSpvWriterSection section,
+                                     GskSlType * result_type,
+                                     guint32 pipe,
+                                     guint32 packet_size,
+                                     guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_MAX_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_reserve_read_pipe_packets (GskSpvWriter *writer,
+                                                GskSpvWriterSection section,
+                                                GskSlType * result_type,
+                                                guint32 execution,
+                                                guint32 pipe,
+                                                guint32 num_packets,
+                                                guint32 packet_size,
+                                                guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, num_packets);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_RESERVE_READ_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_reserve_write_pipe_packets (GskSpvWriter *writer,
+                                                 GskSpvWriterSection section,
+                                                 GskSlType * result_type,
+                                                 guint32 execution,
+                                                 guint32 pipe,
+                                                 guint32 num_packets,
+                                                 guint32 packet_size,
+                                                 guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, num_packets);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_RESERVE_WRITE_PIPE_PACKETS;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_group_commit_read_pipe (GskSpvWriter *writer,
+                                       GskSpvWriterSection section,
+                                       guint32 execution,
+                                       guint32 pipe,
+                                       guint32 reserve_id,
+                                       guint32 packet_size,
+                                       guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_COMMIT_READ_PIPE;
+}
+
+static inline void
+gsk_spv_writer_group_commit_write_pipe (GskSpvWriter *writer,
+                                        GskSpvWriterSection section,
+                                        guint32 execution,
+                                        guint32 pipe,
+                                        guint32 reserve_id,
+                                        guint32 packet_size,
+                                        guint32 packet_alignment)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, pipe);
+  g_array_append_val (bytes, reserve_id);
+  g_array_append_val (bytes, packet_size);
+  g_array_append_val (bytes, packet_alignment);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_COMMIT_WRITE_PIPE;
+}
+
+static inline guint32
+gsk_spv_writer_enqueue_marker (GskSpvWriter *writer,
+                               GskSpvWriterSection section,
+                               GskSlType * result_type,
+                               guint32 queue,
+                               guint32 num_events,
+                               guint32 wait_events,
+                               guint32 ret_event)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, queue);
+  g_array_append_val (bytes, num_events);
+  g_array_append_val (bytes, wait_events);
+  g_array_append_val (bytes, ret_event);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ENQUEUE_MARKER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_enqueue_kernel (GskSpvWriter *writer,
+                               GskSpvWriterSection section,
+                               GskSlType * result_type,
+                               guint32 queue,
+                               guint32 flags,
+                               guint32 nd_range,
+                               guint32 num_events,
+                               guint32 wait_events,
+                               guint32 ret_event,
+                               guint32 invoke,
+                               guint32 param,
+                               guint32 param_size,
+                               guint32 param_align,
+                               guint32 *local_sizes,
+                               gsize n_local_sizes)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, queue);
+  g_array_append_val (bytes, flags);
+  g_array_append_val (bytes, nd_range);
+  g_array_append_val (bytes, num_events);
+  g_array_append_val (bytes, wait_events);
+  g_array_append_val (bytes, ret_event);
+  g_array_append_val (bytes, invoke);
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, param_size);
+  g_array_append_val (bytes, param_align);
+  g_array_append_vals (bytes, local_sizes, n_local_sizes);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_ENQUEUE_KERNEL;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_kernel_n_drange_sub_group_count (GskSpvWriter *writer,
+                                                    GskSpvWriterSection section,
+                                                    GskSlType * result_type,
+                                                    guint32 nd_range,
+                                                    guint32 invoke,
+                                                    guint32 param,
+                                                    guint32 param_size,
+                                                    guint32 param_align)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, nd_range);
+  g_array_append_val (bytes, invoke);
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, param_size);
+  g_array_append_val (bytes, param_align);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_KERNEL_N_DRANGE_SUB_GROUP_COUNT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_kernel_n_drange_max_sub_group_size (GskSpvWriter *writer,
+                                                       GskSpvWriterSection section,
+                                                       GskSlType * result_type,
+                                                       guint32 nd_range,
+                                                       guint32 invoke,
+                                                       guint32 param,
+                                                       guint32 param_size,
+                                                       guint32 param_align)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, nd_range);
+  g_array_append_val (bytes, invoke);
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, param_size);
+  g_array_append_val (bytes, param_align);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_KERNEL_N_DRANGE_MAX_SUB_GROUP_SIZE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_kernel_work_group_size (GskSpvWriter *writer,
+                                           GskSpvWriterSection section,
+                                           GskSlType * result_type,
+                                           guint32 invoke,
+                                           guint32 param,
+                                           guint32 param_size,
+                                           guint32 param_align)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, invoke);
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, param_size);
+  g_array_append_val (bytes, param_align);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_KERNEL_WORK_GROUP_SIZE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_get_kernel_preferred_work_group_size_multiple (GskSpvWriter *writer,
+                                                              GskSpvWriterSection section,
+                                                              GskSlType * result_type,
+                                                              guint32 invoke,
+                                                              guint32 param,
+                                                              guint32 param_size,
+                                                              guint32 param_align)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, invoke);
+  g_array_append_val (bytes, param);
+  g_array_append_val (bytes, param_size);
+  g_array_append_val (bytes, param_align);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_retain_event (GskSpvWriter *writer,
+                             GskSpvWriterSection section,
+                             guint32 event)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, event);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_RETAIN_EVENT;
+}
+
+static inline void
+gsk_spv_writer_release_event (GskSpvWriter *writer,
+                              GskSpvWriterSection section,
+                              guint32 event)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, event);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_RELEASE_EVENT;
+}
+
+static inline guint32
+gsk_spv_writer_create_user_event (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CREATE_USER_EVENT;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_is_valid_event (GskSpvWriter *writer,
+                               GskSpvWriterSection section,
+                               GskSlType * result_type,
+                               guint32 event)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, event);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_IS_VALID_EVENT;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_set_user_event_status (GskSpvWriter *writer,
+                                      GskSpvWriterSection section,
+                                      guint32 event,
+                                      guint32 status)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, event);
+  g_array_append_val (bytes, status);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SET_USER_EVENT_STATUS;
+}
+
+static inline void
+gsk_spv_writer_capture_event_profiling_info (GskSpvWriter *writer,
+                                             GskSpvWriterSection section,
+                                             guint32 event,
+                                             guint32 profiling_info,
+                                             guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, event);
+  g_array_append_val (bytes, profiling_info);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_CAPTURE_EVENT_PROFILING_INFO;
+}
+
+static inline guint32
+gsk_spv_writer_get_default_queue (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  GskSlType * result_type)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GET_DEFAULT_QUEUE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_build_nd_range (GskSpvWriter *writer,
+                               GskSpvWriterSection section,
+                               GskSlType * result_type,
+                               guint32 global_work_size,
+                               guint32 local_work_size,
+                               guint32 global_work_offset)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, global_work_size);
+  g_array_append_val (bytes, local_work_size);
+  g_array_append_val (bytes, global_work_offset);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_BUILD_ND_RANGE;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_implicit_lod (GskSpvWriter *writer,
+                                                 GskSpvWriterSection section,
+                                                 GskSlType * result_type,
+                                                 guint32 sampled_image,
+                                                 guint32 coordinate,
+                                                 GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_explicit_lod (GskSpvWriter *writer,
+                                                 GskSpvWriterSection section,
+                                                 GskSlType * result_type,
+                                                 guint32 sampled_image,
+                                                 guint32 coordinate,
+                                                 GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_dref_implicit_lod (GskSpvWriter *writer,
+                                                      GskSpvWriterSection section,
+                                                      GskSlType * result_type,
+                                                      guint32 sampled_image,
+                                                      guint32 coordinate,
+                                                      guint32 d_ref_,
+                                                      GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_dref_explicit_lod (GskSpvWriter *writer,
+                                                      GskSpvWriterSection section,
+                                                      GskSlType * result_type,
+                                                      guint32 sampled_image,
+                                                      guint32 coordinate,
+                                                      guint32 d_ref_,
+                                                      GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_proj_implicit_lod (GskSpvWriter *writer,
+                                                      GskSpvWriterSection section,
+                                                      GskSlType * result_type,
+                                                      guint32 sampled_image,
+                                                      guint32 coordinate,
+                                                      GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_proj_explicit_lod (GskSpvWriter *writer,
+                                                      GskSpvWriterSection section,
+                                                      GskSlType * result_type,
+                                                      guint32 sampled_image,
+                                                      guint32 coordinate,
+                                                      GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_proj_dref_implicit_lod (GskSpvWriter *writer,
+                                                           GskSpvWriterSection section,
+                                                           GskSlType * result_type,
+                                                           guint32 sampled_image,
+                                                           guint32 coordinate,
+                                                           guint32 d_ref_,
+                                                           GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_IMPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_sample_proj_dref_explicit_lod (GskSpvWriter *writer,
+                                                           GskSpvWriterSection section,
+                                                           GskSlType * result_type,
+                                                           guint32 sampled_image,
+                                                           guint32 coordinate,
+                                                           guint32 d_ref_,
+                                                           GskSpvImageOperands image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  g_array_append_val (bytes, (guint32) { image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_EXPLICIT_LOD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_fetch (GskSpvWriter *writer,
+                                   GskSpvWriterSection section,
+                                   GskSlType * result_type,
+                                   guint32 image,
+                                   guint32 coordinate,
+                                   GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_FETCH;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_gather (GskSpvWriter *writer,
+                                    GskSpvWriterSection section,
+                                    GskSlType * result_type,
+                                    guint32 sampled_image,
+                                    guint32 coordinate,
+                                    guint32 component,
+                                    GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, component);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_GATHER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_dref_gather (GskSpvWriter *writer,
+                                         GskSpvWriterSection section,
+                                         GskSlType * result_type,
+                                         guint32 sampled_image,
+                                         guint32 coordinate,
+                                         guint32 d_ref_,
+                                         GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, sampled_image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, d_ref_);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_DREF_GATHER;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_texels_resident (GskSpvWriter *writer,
+                                             GskSpvWriterSection section,
+                                             GskSlType * result_type,
+                                             guint32 resident_code)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, resident_code);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_TEXELS_RESIDENT;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_no_line (GskSpvWriter *writer,
+                        GskSpvWriterSection section)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | GSK_SPV_OP_NO_LINE;
+}
+
+static inline guint32
+gsk_spv_writer_atomic_flag_test_and_set (GskSpvWriter *writer,
+                                         GskSpvWriterSection section,
+                                         GskSlType * result_type,
+                                         guint32 pointer,
+                                         guint32 scope,
+                                         guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_FLAG_TEST_AND_SET;
+
+  return result_id;
+}
+
+static inline void
+gsk_spv_writer_atomic_flag_clear (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  guint32 pointer,
+                                  guint32 scope,
+                                  guint32 semantics)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, pointer);
+  g_array_append_val (bytes, scope);
+  g_array_append_val (bytes, semantics);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_ATOMIC_FLAG_CLEAR;
+}
+
+static inline guint32
+gsk_spv_writer_image_sparse_read (GskSpvWriter *writer,
+                                  GskSpvWriterSection section,
+                                  GskSlType * result_type,
+                                  guint32 image,
+                                  guint32 coordinate,
+                                  GskSpvImageOperands opt_image_operands)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  if (opt_image_operands != 0)
+    g_array_append_val (bytes, (guint32) { opt_image_operands });
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_IMAGE_SPARSE_READ;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_ballot_khr (GskSpvWriter *writer,
+                                    GskSpvWriterSection section,
+                                    GskSlType * result_type,
+                                    guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_BALLOT_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_first_invocation_khr (GskSpvWriter *writer,
+                                              GskSpvWriterSection section,
+                                              GskSlType * result_type,
+                                              guint32 value)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, value);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_FIRST_INVOCATION_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_all_khr (GskSpvWriter *writer,
+                                 GskSpvWriterSection section,
+                                 GskSlType * result_type,
+                                 guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_ALL_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_any_khr (GskSpvWriter *writer,
+                                 GskSpvWriterSection section,
+                                 GskSlType * result_type,
+                                 guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_ANY_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_all_equal_khr (GskSpvWriter *writer,
+                                       GskSpvWriterSection section,
+                                       GskSlType * result_type,
+                                       guint32 predicate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, predicate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_ALL_EQUAL_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_subgroup_read_invocation_khr (GskSpvWriter *writer,
+                                             GskSpvWriterSection section,
+                                             GskSlType * result_type,
+                                             guint32 value,
+                                             guint32 index)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, value);
+  g_array_append_val (bytes, index);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_SUBGROUP_READ_INVOCATION_KHR;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_i_add_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_I_ADD_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_add_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_F_ADD_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_min_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_F_MIN_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_u_min_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_U_MIN_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_s_min_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_S_MIN_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_f_max_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_F_MAX_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_u_max_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_U_MAX_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_group_s_max_non_uniform_amd (GskSpvWriter *writer,
+                                            GskSpvWriterSection section,
+                                            GskSlType * result_type,
+                                            guint32 execution,
+                                            GskSpvGroupOperation operation,
+                                            guint32 x)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, execution);
+  g_array_append_val (bytes, (guint32) { operation });
+  g_array_append_val (bytes, x);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_GROUP_S_MAX_NON_UNIFORM_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_fragment_mask_fetch_amd (GskSpvWriter *writer,
+                                        GskSpvWriterSection section,
+                                        GskSlType * result_type,
+                                        guint32 image,
+                                        guint32 coordinate)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_FRAGMENT_MASK_FETCH_AMD;
+
+  return result_id;
+}
+
+static inline guint32
+gsk_spv_writer_fragment_fetch_amd (GskSpvWriter *writer,
+                                   GskSpvWriterSection section,
+                                   GskSlType * result_type,
+                                   guint32 image,
+                                   guint32 coordinate,
+                                   guint32 fragment_index)
+{
+  GArray *bytes = gsk_spv_writer_get_bytes (writer, section);
+  guint32 result_type_id = gsk_spv_writer_get_id_for_type (writer, result_type);
+  guint32 result_id = gsk_spv_writer_make_id (writer);
+  guint start_index = bytes->len;
+
+  g_array_append_val (bytes, (guint32) { 0 });
+  g_array_append_val (bytes, result_type_id);
+  g_array_append_val (bytes, result_id);
+  g_array_append_val (bytes, image);
+  g_array_append_val (bytes, coordinate);
+  g_array_append_val (bytes, fragment_index);
+  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | 
GSK_SPV_OP_FRAGMENT_FETCH_AMD;
+
+  return result_id;
+}
+
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index f749668..6be694b 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -22,6 +22,7 @@
 #include <glib.h>
 
 #include "gsksltypesprivate.h"
+#include "gskspvenumsprivate.h"
 
 G_BEGIN_DECLS
 
@@ -31,256 +32,10 @@ G_BEGIN_DECLS
 #define GSK_SPV_GENERATOR 0
 
 typedef enum {
-  GSK_SPV_OP_NOP = 0,
-  GSK_SPV_OP_UNDEF = 1,
-  GSK_SPV_OP_SOURCE_CONTINUED = 2,
-  GSK_SPV_OP_SOURCE = 3,
-  GSK_SPV_OP_SOURCE_EXTENSION = 4,
-  GSK_SPV_OP_NAME = 5,
-  GSK_SPV_OP_MEMBER_NAME = 6,
-  GSK_SPV_OP_STRING = 7,
-  GSK_SPV_OP_LINE = 8,
-  GSK_SPV_OP_EXTENSION = 10,
-  GSK_SPV_OP_EXT_INST_IMPORT = 11,
-  GSK_SPV_OP_EXT_INST = 12,
-  GSK_SPV_OP_MEMORY_MODEL = 14,
-  GSK_SPV_OP_ENTRY_POINT = 15,
-  GSK_SPV_OP_EXECUTION_MODE = 16,
-  GSK_SPV_OP_CAPABILITY = 17,
-  GSK_SPV_OP_TYPE_VOID = 19,
-  GSK_SPV_OP_TYPE_BOOL = 20,
-  GSK_SPV_OP_TYPE_INT = 21,
-  GSK_SPV_OP_TYPE_FLOAT = 22,
-  GSK_SPV_OP_TYPE_VECTOR = 23,
-  GSK_SPV_OP_TYPE_MATRIX = 24,
-  GSK_SPV_OP_TYPE_IMAGE = 25,
-  GSK_SPV_OP_TYPE_SAMPLER = 26,
-  GSK_SPV_OP_TYPE_SAMPLED_IMAGE = 27,
-  GSK_SPV_OP_TYPE_ARRAY = 28,
-  GSK_SPV_OP_TYPE_RUNTIME_ARRAY = 29,
-  GSK_SPV_OP_TYPE_STRUCT = 30,
-  GSK_SPV_OP_TYPE_OPAQUE = 31,
-  GSK_SPV_OP_TYPE_POINTER = 32,
-  GSK_SPV_OP_TYPE_FUNCTION = 33,
-  GSK_SPV_OP_TYPE_EVENT = 34,
-  GSK_SPV_OP_TYPE_DEVICE_EVENT = 35,
-  GSK_SPV_OP_TYPE_RESERVE_ID = 36,
-  GSK_SPV_OP_TYPE_QUEUE = 37,
-  GSK_SPV_OP_TYPE_PIPE = 38,
-  GSK_SPV_OP_TYPE_FORWARD_POINTER = 39,
-  GSK_SPV_OP_CONSTANT_TRUE = 41,
-  GSK_SPV_OP_CONSTANT_FALSE = 42,
-  GSK_SPV_OP_CONSTANT = 43,
-  GSK_SPV_OP_CONSTANT_COMPOSITE = 44,
-  GSK_SPV_OP_CONSTANT_SAMPLER = 45,
-  GSK_SPV_OP_CONSTANT_NULL = 46,
-  GSK_SPV_OP_SPEC_CONSTANT_TRUE = 48,
-  GSK_SPV_OP_SPEC_CONSTANT_FALSE = 49,
-  GSK_SPV_OP_SPEC_CONSTANT = 50,
-  GSK_SPV_OP_SPEC_CONSTANT_COMPOSITE = 51,
-  GSK_SPV_OP_SPEC_CONSTANT_OP = 52,
-  GSK_SPV_OP_FUNCTION = 54,
-  GSK_SPV_OP_FUNCTION_PARAMETER = 55,
-  GSK_SPV_OP_FUNCTION_END = 56,
-  GSK_SPV_OP_FUNCTION_CALL = 57,
-  GSK_SPV_OP_VARIABLE = 59,
-  GSK_SPV_OP_IMAGE_TEXEL_POINTER = 60,
-  GSK_SPV_OP_LOAD = 61,
-  GSK_SPV_OP_STORE = 62,
-  GSK_SPV_OP_COPY_MEMORY = 63,
-  GSK_SPV_OP_COPY_MEMORY_SIZED = 64,
-  GSK_SPV_OP_ACCESS_CHAIN = 65,
-  GSK_SPV_OP_IN_BOUNDS_ACCESS_CHAIN = 66,
-  GSK_SPV_OP_PTR_ACCESS_CHAIN = 67,
-  GSK_SPV_OP_ARRAY_LENGTH = 68,
-  GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS = 69,
-  GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN = 70,
-  GSK_SPV_OP_DECORATE = 71,
-  GSK_SPV_OP_MEMBER_DECORATE = 72,
-  GSK_SPV_OP_DECORATION_GROUP = 73,
-  GSK_SPV_OP_GROUP_DECORATE = 74,
-  GSK_SPV_OP_GROUP_MEMBER_DECORATE = 75,
-  GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC = 77,
-  GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
-  GSK_SPV_OP_VECTOR_SHUFFLE = 79,
-  GSK_SPV_OP_COMPOSITE_CONSTRUCT = 80,
-  GSK_SPV_OP_COMPOSITE_EXTRACT = 81,
-  GSK_SPV_OP_COMPOSITE_INSERT = 82,
-  GSK_SPV_OP_COPY_OBJECT = 83,
-  GSK_SPV_OP_TRANSPOSE = 84,
-  GSK_SPV_OP_CONVERT_F_TO_U = 109,
-  GSK_SPV_OP_CONVERT_F_TO_S = 110,
-  GSK_SPV_OP_CONVERT_S_TO_F = 111,
-  GSK_SPV_OP_CONVERT_U_TO_F = 112,
-  GSK_SPV_OP_U_CONVERT = 113,
-  GSK_SPV_OP_S_CONVERT = 114,
-  GSK_SPV_OP_F_CONVERT = 115,
-  GSK_SPV_OP_QUANTIZE_TO_F16 = 116,
-  GSK_SPV_OP_CONVERT_PTR_TO_U = 117,
-  GSK_SPV_OP_SAT_CONVERT_S_TO_U = 118,
-  GSK_SPV_OP_SAT_CONVERT_U_TO_S = 119,
-  GSK_SPV_OP_CONVERT_U_TO_PTR = 120,
-  GSK_SPV_OP_PTR_CAST_TO_GENERIC = 121,
-  GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
-  GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
-  GSK_SPV_OP_BITCAST = 124,
-  GSK_SPV_OP_S_NEGATE = 126,
-  GSK_SPV_OP_F_NEGATE = 127,
-  GSK_SPV_OP_I_ADD = 128,
-  GSK_SPV_OP_F_ADD = 129,
-  GSK_SPV_OP_I_SUB = 130,
-  GSK_SPV_OP_F_SUB = 131,
-  GSK_SPV_OP_I_MUL = 132,
-  GSK_SPV_OP_F_MUL = 133,
-  GSK_SPV_OP_U_DIV = 134,
-  GSK_SPV_OP_S_DIV = 135,
-  GSK_SPV_OP_F_DIV = 136,
-  GSK_SPV_OP_U_MOD = 137,
-  GSK_SPV_OP_S_REM = 138,
-  GSK_SPV_OP_S_MOD = 139,
-  GSK_SPV_OP_F_REM = 140,
-  GSK_SPV_OP_F_MOD = 141,
-  GSK_SPV_OP_VECTOR_TIMES_SCALAR = 142,
-  GSK_SPV_OP_MATRIX_TIMES_SCALAR = 143,
-  GSK_SPV_OP_VECTOR_TIMES_MATRIX = 144,
-  GSK_SPV_OP_MATRIX_TIMES_VECTOR = 145,
-  GSK_SPV_OP_MATRIX_TIMES_MATRIX = 146,
-  GSK_SPV_OP_OUTER_PRODUCT = 147,
-  GSK_SPV_OP_DOT = 148,
-  GSK_SPV_OP_I_ADD_CARRY = 149,
-  GSK_SPV_OP_I_SUB_BORROW = 150,
-  GSK_SPV_OP_U_MUL_EXTENDED = 151,
-  GSK_SPV_OP_S_MUL_EXTENDED = 152,
-  GSK_SPV_OP_ANY = 154,
-  GSK_SPV_OP_ALL = 155,
-  GSK_SPV_OP_IS_NAN = 156,
-  GSK_SPV_OP_IS_INF = 157,
-  GSK_SPV_OP_IS_FINITE = 158,
-  GSK_SPV_OP_IS_NORMAL = 159,
-  GSK_SPV_OP_SIGN_BIT_SET = 160,
-  GSK_SPV_OP_LESS_OR_GREATER = 161,
-  GSK_SPV_OP_ORDERED = 162,
-  GSK_SPV_OP_UNORDERED = 163,
-  GSK_SPV_OP_LOGICAL_EQUAL = 164,
-  GSK_SPV_OP_LOGICAL_NOT_EQUAL = 165,
-  GSK_SPV_OP_LOGICAL_OR = 166,
-  GSK_SPV_OP_LOGICAL_AND = 167,
-  GSK_SPV_OP_LOGICAL_NOT = 168,
-  GSK_SPV_OP_SELECT = 169,
-  GSK_SPV_OP_I_EQUAL = 170,
-  GSK_SPV_OP_I_NOT_EQUAL = 171,
-  GSK_SPV_OP_U_GREATER_THAN = 172,
-  GSK_SPV_OP_S_GREATER_THAN = 173,
-  GSK_SPV_OP_U_GREATER_THAN_EQUAL = 174,
-  GSK_SPV_OP_S_GREATER_THAN_EQUAL = 175,
-  GSK_SPV_OP_U_LESS_THAN = 176,
-  GSK_SPV_OP_S_LESS_THAN = 177,
-  GSK_SPV_OP_U_LESS_THAN_EQUAL = 178,
-  GSK_SPV_OP_S_LESS_THAN_EQUAL = 179,
-  GSK_SPV_OP_F_ORD_EQUAL = 180,
-  GSK_SPV_OP_F_UNORD_EQUAL = 181,
-  GSK_SPV_OP_F_ORD_NOT_EQUAL = 182,
-  GSK_SPV_OP_F_UNORD_NOT_EQUAL = 183,
-  GSK_SPV_OP_F_ORD_LESS_THAN = 184,
-  GSK_SPV_OP_F_UNORD_LESS_THAN = 185,
-  GSK_SPV_OP_F_ORD_GREATER_THAN = 186,
-  GSK_SPV_OP_F_UNORD_GREATER_THAN = 187,
-  GSK_SPV_OP_F_ORD_LESS_THAN_EQUAL = 188,
-  GSK_SPV_OP_F_UNORD_LESS_THAN_EQUAL = 189,
-  GSK_SPV_OP_F_ORD_GREATER_THAN_EQUAL = 190,
-  GSK_SPV_OP_F_UNORD_GREATER_THAN_EQUAL = 191,
-  GSK_SPV_OP_PHI = 245,
-  GSK_SPV_OP_LOOP_MERGE = 246,
-  GSK_SPV_OP_SELECTION_MERGE = 247,
-  GSK_SPV_OP_LABEL = 248,
-  GSK_SPV_OP_BRANCH = 249,
-  GSK_SPV_OP_BRANCH_CONDITIONAL = 250,
-  GSK_SPV_OP_SWITCH = 251,
-  GSK_SPV_OP_KILL = 252,
-  GSK_SPV_OP_RETURN = 253,
-  GSK_SPV_OP_RETURN_VALUE = 254,
-  GSK_SPV_OP_UNREACHABLE = 255,
-  GSK_SPV_OP_LIFETIME_START = 256,
-  GSK_SPV_OP_LIFETIME_STOP = 257,
-  GSK_SPV_OP_SIZE_OF = 321,
-  GSK_SPV_OP_TYPE_PIPE_STORAGE = 322,
-  GSK_SPV_OP_TYPE_NAMED_BARRIER = 327,
-  GSK_SPV_OP_DECORATE_ID = 332
-} GskSpvOpcode;
-
-typedef enum {
-  GSK_SPV_CAPABILITY_MATRIX = 0,
-  GSK_SPV_CAPABILITY_SHADER = 1
-} GskSpvCapability;
-
-typedef enum {
-  GSK_SPV_ADDRESSING_LOGICAL = 0,
-  GSK_SPV_ADDRESSING_PHYSICAL32 = 1,
-  GSK_SPV_ADDRESSING_PHYSICAL64 = 2,
-} GskSpvAddressingModel;
-
-typedef enum {
-  GSK_SPV_MEMORY_SIMPLE = 0,
-  GSK_SPV_MEMORY_GLSL450 = 1,
-  GSK_SPV_MEMORY_OPEN_CL = 2
-} GskSpvMemoryModel;
-
-typedef enum {
-  GSK_SPV_EXECUTION_MODEL_VERTEX = 0,
-  GSK_SPV_EXECUTION_MODEL_TESSELATION_CONTROL = 1,
-  GSK_SPV_EXECUTION_MODEL_TESSELATION_EVALUATION = 2,
-  GSK_SPV_EXECUTION_MODEL_GEOMETRY = 3,
-  GSK_SPV_EXECUTION_MODEL_FRAGMENT = 4,
-  GSK_SPV_EXECUTION_MODEL_GL_COMPUTE = 5,
-  GSK_SPV_EXECUTION_MODEL_KERNEL = 6,
-} GskSpvExecutionModel;
-
-typedef enum {
-  GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT = 7
-} GskSpvExecutionMode;
-
-typedef enum {
-  GSK_SPV_STORAGE_CLASS_UNIFORM_CONSTANT = 0,
-  GSK_SPV_STORAGE_CLASS_INPUT = 1,
-  GSK_SPV_STORAGE_CLASS_UNIFORM = 2,
-  GSK_SPV_STORAGE_CLASS_OUTPUT = 3,
-  GSK_SPV_STORAGE_CLASS_WORKGROUP = 4,
-  GSK_SPV_STORAGE_CLASS_CROSS_WORKGROUP = 5,
-  GSK_SPV_STORAGE_CLASS_PRIVATE = 6,
-  GSK_SPV_STORAGE_CLASS_FUNCTION = 7,
-  GSK_SPV_STORAGE_CLASS_GENERIC = 8,
-  GSK_SPV_STORAGE_CLASS_PUSH_CONSTANT = 9,
-  GSK_SPV_STORAGE_CLASS_ATOMIC_COUNTER = 10,
-  GSK_SPV_STORAGE_CLASS_IMAGE = 11,
-  GSK_SPV_STORAGE_CLASS_STORAGE_BUFFER = 12
-} GskSpvStorageClass;
-
-typedef enum {
-  GSK_SPV_DECORATION_RELAXED_PRECISION = 0,
-  GSK_SPV_DECORATION_SPEC_ID = 1,
-  GSK_SPV_DECORATION_BLOCK = 2,
-  GSK_SPV_DECORATION_BUFFER_BLOCK = 3,
-  GSK_SPV_DECORATION_ROW_MAJOR = 4,
-  GSK_SPV_DECORATION_COLUMN_MAJOR = 5,
-  GSK_SPV_DECORATION_ARRAY_STRIDE = 6,
-  GSK_SPV_DECORATION_MATRIX_STRIDE = 7,
-  GSK_SPV_DECORATION_GLSL_SHARED = 8,
-  GSK_SPV_DECORATION_GLSL_PACKED = 9,
-  GSK_SPV_DECORATION_C_PACKED = 10,
-  GSK_SPV_DECORATION_BUILTIN = 11,
-  GSK_SPV_DECORATION_NO_PERSPECTIVE = 13,
-  GSK_SPV_DECORATION_FLAT = 14,
-  GSK_SPV_DECORATION_PATCH = 15,
-  GSK_SPV_DECORATION_CENTROID = 16,
-  GSK_SPV_DECORATION_SAMPLE = 17,
-  GSK_SPV_DECORATION_INVARIANT = 18,
-  GSK_SPV_DECORATION_RESTRICT = 19,
-  GSK_SPV_DECORATION_ALIASED = 20
-} GskSpvDecoration;
-
-typedef enum {
   GSK_SPV_WRITER_SECTION_HEADER,
   GSK_SPV_WRITER_SECTION_DEBUG,
+  GSK_SPV_WRITER_SECTION_DECORATE,
+  GSK_SPV_WRITER_SECTION_DEFINE,
   GSK_SPV_WRITER_SECTION_DECLARE,
   GSK_SPV_WRITER_SECTION_CODE,
   /* add more */
@@ -309,18 +64,17 @@ guint32                 gsk_spv_writer_get_id_for_one           (GskSpvWriter
 guint32                 gsk_spv_writer_get_id_for_variable      (GskSpvWriter           *writer,
                                                                  GskSlVariable          *variable);
 
-guint32                 gsk_spv_writer_next_id                  (GskSpvWriter           *writer);
-void                    gsk_spv_writer_add                      (GskSpvWriter           *writer,
-                                                                 GskSpvWriterSection     section,
-                                                                 guint16                 word_count,
-                                                                 guint16                 opcode,
-                                                                 guint32                *words);
+guint32                 gsk_spv_writer_make_id                  (GskSpvWriter           *writer);
+GArray *                gsk_spv_writer_get_bytes                (GskSpvWriter           *writer,
+                                                                 GskSpvWriterSection     section);
 
-guint32                 gsk_spv_writer_add_conversion           (GskSpvWriter           *writer,
+guint32                 gsk_spv_writer_convert                  (GskSpvWriter           *writer,
                                                                  guint32                 id,
                                                                  GskSlType              *type,
                                                                  GskSlType              *new_type);
 
+#include "gskspvwritergeneratedprivate.h"
+
 G_END_DECLS
 
 #endif /* __GSK_SPV_WRITER_PRIVATE_H__ */
diff --git a/gsk/meson.build b/gsk/meson.build
index 0bb7a1f..889fc65 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -62,6 +62,11 @@ gsk_public_headers = files([
   'gsktypes.h',
 ])
 
+gsk_private_headers = files([
+  'gskspvenumsprivate.h',
+  'gskspvwritergeneratedprivate.h'
+])
+
 install_headers(gsk_public_headers, 'gsk.h', subdir: 'gtk-4.0/gsk')
 
 gsk_private_vulkan_shaders = []
diff --git a/gsk/spirv.core.grammar.json b/gsk/spirv.core.grammar.json
new file mode 100644
index 0000000..36a816d
--- /dev/null
+++ b/gsk/spirv.core.grammar.json
@@ -0,0 +1,5630 @@
+{
+  "copyright" : [
+    "Copyright (c) 2014-2016 The Khronos Group Inc.",
+    "",
+    "Permission is hereby granted, free of charge, to any person obtaining a copy",
+    "of this software and/or associated documentation files (the \"Materials\"),",
+    "to deal in the Materials without restriction, including without limitation",
+    "the rights to use, copy, modify, merge, publish, distribute, sublicense,",
+    "and/or sell copies of the Materials, and to permit persons to whom the",
+    "Materials are furnished to do so, subject to the following conditions:",
+    "",
+    "The above copyright notice and this permission notice shall be included in",
+    "all copies or substantial portions of the Materials.",
+    "",
+    "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS",
+    "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND",
+    "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ",
+    "",
+    "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS",
+    "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
+    "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL",
+    "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
+    "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING",
+    "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS",
+    "IN THE MATERIALS."
+  ],
+  "magic_number" : "0x07230203",
+  "major_version" : 1,
+  "minor_version" : 0,
+  "revision" : 12,
+  "instructions" : [
+    {
+      "opname" : "OpNop",
+      "opcode" : 0
+    },
+    {
+      "opname" : "OpUndef",
+      "opcode" : 1,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSourceContinued",
+      "opcode" : 2,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Continued Source'" }
+      ]
+    },
+    {
+      "opname" : "OpSource",
+      "opcode" : 3,
+      "operands" : [
+        { "kind" : "SourceLanguage" },
+        { "kind" : "LiteralInteger",                     "name" : "'Version'" },
+        { "kind" : "IdRef",          "quantifier" : "?", "name" : "'File'" },
+        { "kind" : "LiteralString",  "quantifier" : "?", "name" : "'Source'" }
+      ]
+    },
+    {
+      "opname" : "OpSourceExtension",
+      "opcode" : 4,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Extension'" }
+      ]
+    },
+    {
+      "opname" : "OpName",
+      "opcode" : 5,
+      "operands" : [
+        { "kind" : "IdRef",         "name" : "'Target'" },
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpMemberName",
+      "opcode" : 6,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Member'" },
+        { "kind" : "LiteralString",  "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpString",
+      "opcode" : 7,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "'String'" }
+      ]
+    },
+    {
+      "opname" : "OpLine",
+      "opcode" : 8,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'File'" },
+        { "kind" : "LiteralInteger", "name" : "'Line'" },
+        { "kind" : "LiteralInteger", "name" : "'Column'" }
+      ]
+    },
+    {
+      "opname" : "OpExtension",
+      "opcode" : 10,
+      "operands" : [
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpExtInstImport",
+      "opcode" : 11,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "'Name'" }
+      ]
+    },
+    {
+      "opname" : "OpExtInst",
+      "opcode" : 12,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                                     "name" : "'Set'" },
+        { "kind" : "LiteralExtInstInteger",                     "name" : "'Instruction'" },
+        { "kind" : "IdRef",                 "quantifier" : "*", "name" : "'Operand 1', +\n'Operand 2', 
+\n..." }
+      ]
+    },
+    {
+      "opname" : "OpMemoryModel",
+      "opcode" : 14,
+      "operands" : [
+        { "kind" : "AddressingModel" },
+        { "kind" : "MemoryModel" }
+      ]
+    },
+    {
+      "opname" : "OpEntryPoint",
+      "opcode" : 15,
+      "operands" : [
+        { "kind" : "ExecutionModel" },
+        { "kind" : "IdRef",                              "name" : "'Entry Point'" },
+        { "kind" : "LiteralString",                      "name" : "'Name'" },
+        { "kind" : "IdRef",          "quantifier" : "*", "name" : "'Interface'" }
+      ]
+    },
+    {
+      "opname" : "OpExecutionMode",
+      "opcode" : 16,
+      "operands" : [
+        { "kind" : "IdRef",         "name" : "'Entry Point'" },
+        { "kind" : "ExecutionMode", "name" : "'Mode'" }
+      ]
+    },
+    {
+      "opname" : "OpCapability",
+      "opcode" : 17,
+      "operands" : [
+        { "kind" : "Capability", "name" : "'Capability'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeVoid",
+      "opcode" : 19,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeBool",
+      "opcode" : 20,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeInt",
+      "opcode" : 21,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralInteger", "name" : "'Width'" },
+        { "kind" : "LiteralInteger", "name" : "'Signedness'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeFloat",
+      "opcode" : 22,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralInteger", "name" : "'Width'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeVector",
+      "opcode" : 23,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Component Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Component Count'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeMatrix",
+      "opcode" : 24,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Column Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Column Count'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpTypeImage",
+      "opcode" : 25,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                               "name" : "'Sampled Type'" },
+        { "kind" : "Dim" },
+        { "kind" : "LiteralInteger",                      "name" : "'Depth'" },
+        { "kind" : "LiteralInteger",                      "name" : "'Arrayed'" },
+        { "kind" : "LiteralInteger",                      "name" : "'MS'" },
+        { "kind" : "LiteralInteger",                      "name" : "'Sampled'" },
+        { "kind" : "ImageFormat" },
+        { "kind" : "AccessQualifier", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpTypeSampler",
+      "opcode" : 26,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpTypeSampledImage",
+      "opcode" : 27,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Image Type'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeArray",
+      "opcode" : 28,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Element Type'" },
+        { "kind" : "IdRef",    "name" : "'Length'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeRuntimeArray",
+      "opcode" : 29,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "name" : "'Element Type'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpTypeStruct",
+      "opcode" : 30,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",    "quantifier" : "*", "name" : "'Member 0 type', +\n'member 1 type', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpTypeOpaque",
+      "opcode" : 31,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "The name of the opaque type." }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpTypePointer",
+      "opcode" : 32,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "StorageClass" },
+        { "kind" : "IdRef",        "name" : "'Type'" }
+      ]
+    },
+    {
+      "opname" : "OpTypeFunction",
+      "opcode" : 33,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                        "name" : "'Return Type'" },
+        { "kind" : "IdRef",    "quantifier" : "*", "name" : "'Parameter 0 Type', +\n'Parameter 1 Type', 
+\n..." }
+      ]
+    },
+    {
+      "opname" : "OpTypeEvent",
+      "opcode" : 34,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpTypeDeviceEvent",
+      "opcode" : 35,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpTypeReserveId",
+      "opcode" : 36,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpTypeQueue",
+      "opcode" : 37,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpTypePipe",
+      "opcode" : 38,
+      "operands" : [
+        { "kind" : "IdResult" },
+        { "kind" : "AccessQualifier", "name" : "'Qualifier'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpTypeForwardPointer",
+      "opcode" : 39,
+      "operands" : [
+        { "kind" : "IdRef",        "name" : "'Pointer Type'" },
+        { "kind" : "StorageClass" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpConstantTrue",
+      "opcode" : 41,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpConstantFalse",
+      "opcode" : 42,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpConstant",
+      "opcode" : 43,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConstantComposite",
+      "opcode" : 44,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpConstantSampler",
+      "opcode" : 45,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "SamplerAddressingMode" },
+        { "kind" : "LiteralInteger",        "name" : "'Param'" },
+        { "kind" : "SamplerFilterMode" }
+      ],
+      "capabilities" : [ "LiteralSampler" ]
+    },
+    {
+      "opname" : "OpConstantNull",
+      "opcode" : 46,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantTrue",
+      "opcode" : 48,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantFalse",
+      "opcode" : 49,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstant",
+      "opcode" : 50,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantComposite",
+      "opcode" : 51,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpSpecConstantOp",
+      "opcode" : 52,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralSpecConstantOpInteger", "name" : "'Opcode'" }
+      ]
+    },
+    {
+      "opname" : "OpFunction",
+      "opcode" : 54,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "FunctionControl" },
+        { "kind" : "IdRef",           "name" : "'Function Type'" }
+      ]
+    },
+    {
+      "opname" : "OpFunctionParameter",
+      "opcode" : 55,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpFunctionEnd",
+      "opcode" : 56
+    },
+    {
+      "opname" : "OpFunctionCall",
+      "opcode" : 57,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Function'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Argument 0', +\n'Argument 1', +\n..." }
+      ]
+    },
+    {
+      "opname" : "OpVariable",
+      "opcode" : 59,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "StorageClass" },
+        { "kind" : "IdRef",        "quantifier" : "?", "name" : "'Initializer'" }
+      ]
+    },
+    {
+      "opname" : "OpImageTexelPointer",
+      "opcode" : 60,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Coordinate'" },
+        { "kind" : "IdRef",        "name" : "'Sample'" }
+      ]
+    },
+    {
+      "opname" : "OpLoad",
+      "opcode" : 61,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Pointer'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpStore",
+      "opcode" : 62,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Pointer'" },
+        { "kind" : "IdRef",                            "name" : "'Object'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpCopyMemory",
+      "opcode" : 63,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Target'" },
+        { "kind" : "IdRef",                            "name" : "'Source'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpCopyMemorySized",
+      "opcode" : 64,
+      "operands" : [
+        { "kind" : "IdRef",                            "name" : "'Target'" },
+        { "kind" : "IdRef",                            "name" : "'Source'" },
+        { "kind" : "IdRef",                            "name" : "'Size'" },
+        { "kind" : "MemoryAccess", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpAccessChain",
+      "opcode" : 65,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpInBoundsAccessChain",
+      "opcode" : 66,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpPtrAccessChain",
+      "opcode" : 67,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",                            "name" : "'Element'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ],
+      "capabilities" : [
+        "Addresses",
+        "VariablePointers",
+        "VariablePointersStorageBuffer"
+      ]
+    },
+    {
+      "opname" : "OpArrayLength",
+      "opcode" : 68,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",          "name" : "'Structure'" },
+        { "kind" : "LiteralInteger", "name" : "'Array member'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpGenericPtrMemSemantics",
+      "opcode" : 69,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpInBoundsPtrAccessChain",
+      "opcode" : 70,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Base'" },
+        { "kind" : "IdRef",                            "name" : "'Element'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Indexes'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpDecorate",
+      "opcode" : 71,
+      "operands" : [
+        { "kind" : "IdRef",      "name" : "'Target'" },
+        { "kind" : "Decoration" }
+      ]
+    },
+    {
+      "opname" : "OpMemberDecorate",
+      "opcode" : 72,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Structure Type'" },
+        { "kind" : "LiteralInteger", "name" : "'Member'" },
+        { "kind" : "Decoration" }
+      ]
+    },
+    {
+      "opname" : "OpDecorationGroup",
+      "opcode" : 73,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpGroupDecorate",
+      "opcode" : 74,
+      "operands" : [
+        { "kind" : "IdRef",                     "name" : "'Decoration Group'" },
+        { "kind" : "IdRef", "quantifier" : "*", "name" : "'Targets'" }
+      ]
+    },
+    {
+      "opname" : "OpGroupMemberDecorate",
+      "opcode" : 75,
+      "operands" : [
+        { "kind" : "IdRef",                                       "name" : "'Decoration Group'" },
+        { "kind" : "PairIdRefLiteralInteger", "quantifier" : "*", "name" : "'Targets'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorExtractDynamic",
+      "opcode" : 77,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Index'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorInsertDynamic",
+      "opcode" : 78,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Component'" },
+        { "kind" : "IdRef",        "name" : "'Index'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorShuffle",
+      "opcode" : 79,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Vector 1'" },
+        { "kind" : "IdRef",                              "name" : "'Vector 2'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Components'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeConstruct",
+      "opcode" : 80,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeExtract",
+      "opcode" : 81,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Composite'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpCompositeInsert",
+      "opcode" : 82,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                              "name" : "'Object'" },
+        { "kind" : "IdRef",                              "name" : "'Composite'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Indexes'" }
+      ]
+    },
+    {
+      "opname" : "OpCopyObject",
+      "opcode" : 83,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpTranspose",
+      "opcode" : 84,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpSampledImage",
+      "opcode" : 86,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Sampler'" }
+      ]
+    },
+    {
+      "opname" : "OpImageSampleImplicitLod",
+      "opcode" : 87,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleExplicitLod",
+      "opcode" : 88,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ]
+    },
+    {
+      "opname" : "OpImageSampleDrefImplicitLod",
+      "opcode" : 89,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleDrefExplicitLod",
+      "opcode" : 90,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjImplicitLod",
+      "opcode" : 91,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjExplicitLod",
+      "opcode" : 92,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjDrefImplicitLod",
+      "opcode" : 93,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageSampleProjDrefExplicitLod",
+      "opcode" : 94,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageFetch",
+      "opcode" : 95,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImageGather",
+      "opcode" : 96,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Component'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageDrefGather",
+      "opcode" : 97,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpImageRead",
+      "opcode" : 98,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImageWrite",
+      "opcode" : 99,
+      "operands" : [
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Texel'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ]
+    },
+    {
+      "opname" : "OpImage",
+      "opcode" : 100,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Sampled Image'" }
+      ]
+    },
+    {
+      "opname" : "OpImageQueryFormat",
+      "opcode" : 101,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageQueryOrder",
+      "opcode" : 102,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageQuerySizeLod",
+      "opcode" : 103,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" },
+        { "kind" : "IdRef",        "name" : "'Level of Detail'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQuerySize",
+      "opcode" : 104,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQueryLod",
+      "opcode" : 105,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",        "name" : "'Coordinate'" }
+      ],
+      "capabilities" : [ "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQueryLevels",
+      "opcode" : 106,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpImageQuerySamples",
+      "opcode" : 107,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Image'" }
+      ],
+      "capabilities" : [ "Kernel", "ImageQuery" ]
+    },
+    {
+      "opname" : "OpConvertFToU",
+      "opcode" : 109,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertFToS",
+      "opcode" : 110,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertSToF",
+      "opcode" : 111,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertUToF",
+      "opcode" : 112,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ]
+    },
+    {
+      "opname" : "OpUConvert",
+      "opcode" : 113,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ]
+    },
+    {
+      "opname" : "OpSConvert",
+      "opcode" : 114,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ]
+    },
+    {
+      "opname" : "OpFConvert",
+      "opcode" : 115,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Float Value'" }
+      ]
+    },
+    {
+      "opname" : "OpQuantizeToF16",
+      "opcode" : 116,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpConvertPtrToU",
+      "opcode" : 117,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpSatConvertSToU",
+      "opcode" : 118,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Signed Value'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpSatConvertUToS",
+      "opcode" : 119,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Unsigned Value'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpConvertUToPtr",
+      "opcode" : 120,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Integer Value'" }
+      ],
+      "capabilities" : [ "Addresses" ]
+    },
+    {
+      "opname" : "OpPtrCastToGeneric",
+      "opcode" : 121,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGenericCastToPtr",
+      "opcode" : 122,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGenericCastToPtrExplicit",
+      "opcode" : 123,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "StorageClass", "name" : "'Storage'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpBitcast",
+      "opcode" : 124,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpSNegate",
+      "opcode" : 126,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpFNegate",
+      "opcode" : 127,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpIAdd",
+      "opcode" : 128,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFAdd",
+      "opcode" : 129,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpISub",
+      "opcode" : 130,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFSub",
+      "opcode" : 131,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIMul",
+      "opcode" : 132,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFMul",
+      "opcode" : 133,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUDiv",
+      "opcode" : 134,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSDiv",
+      "opcode" : 135,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFDiv",
+      "opcode" : 136,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUMod",
+      "opcode" : 137,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSRem",
+      "opcode" : 138,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSMod",
+      "opcode" : 139,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFRem",
+      "opcode" : 140,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFMod",
+      "opcode" : 141,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpVectorTimesScalar",
+      "opcode" : 142,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Scalar'" }
+      ]
+    },
+    {
+      "opname" : "OpMatrixTimesScalar",
+      "opcode" : 143,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" },
+        { "kind" : "IdRef",        "name" : "'Scalar'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpVectorTimesMatrix",
+      "opcode" : 144,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpMatrixTimesVector",
+      "opcode" : 145,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Matrix'" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpMatrixTimesMatrix",
+      "opcode" : 146,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'LeftMatrix'" },
+        { "kind" : "IdRef",        "name" : "'RightMatrix'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpOuterProduct",
+      "opcode" : 147,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector 1'" },
+        { "kind" : "IdRef",        "name" : "'Vector 2'" }
+      ],
+      "capabilities" : [ "Matrix" ]
+    },
+    {
+      "opname" : "OpDot",
+      "opcode" : 148,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector 1'" },
+        { "kind" : "IdRef",        "name" : "'Vector 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIAddCarry",
+      "opcode" : 149,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpISubBorrow",
+      "opcode" : 150,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUMulExtended",
+      "opcode" : 151,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSMulExtended",
+      "opcode" : 152,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpAny",
+      "opcode" : 154,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ]
+    },
+    {
+      "opname" : "OpAll",
+      "opcode" : 155,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Vector'" }
+      ]
+    },
+    {
+      "opname" : "OpIsNan",
+      "opcode" : 156,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ]
+    },
+    {
+      "opname" : "OpIsInf",
+      "opcode" : 157,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ]
+    },
+    {
+      "opname" : "OpIsFinite",
+      "opcode" : 158,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpIsNormal",
+      "opcode" : 159,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpSignBitSet",
+      "opcode" : 160,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLessOrGreater",
+      "opcode" : 161,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpOrdered",
+      "opcode" : 162,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpUnordered",
+      "opcode" : 163,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'x'" },
+        { "kind" : "IdRef",        "name" : "'y'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLogicalEqual",
+      "opcode" : 164,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalNotEqual",
+      "opcode" : 165,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalOr",
+      "opcode" : 166,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalAnd",
+      "opcode" : 167,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpLogicalNot",
+      "opcode" : 168,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpSelect",
+      "opcode" : 169,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Condition'" },
+        { "kind" : "IdRef",        "name" : "'Object 1'" },
+        { "kind" : "IdRef",        "name" : "'Object 2'" }
+      ]
+    },
+    {
+      "opname" : "OpIEqual",
+      "opcode" : 170,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpINotEqual",
+      "opcode" : 171,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUGreaterThan",
+      "opcode" : 172,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSGreaterThan",
+      "opcode" : 173,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpUGreaterThanEqual",
+      "opcode" : 174,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSGreaterThanEqual",
+      "opcode" : 175,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpULessThan",
+      "opcode" : 176,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSLessThan",
+      "opcode" : 177,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpULessThanEqual",
+      "opcode" : 178,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpSLessThanEqual",
+      "opcode" : 179,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdEqual",
+      "opcode" : 180,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordEqual",
+      "opcode" : 181,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdNotEqual",
+      "opcode" : 182,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordNotEqual",
+      "opcode" : 183,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdLessThan",
+      "opcode" : 184,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordLessThan",
+      "opcode" : 185,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdGreaterThan",
+      "opcode" : 186,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordGreaterThan",
+      "opcode" : 187,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdLessThanEqual",
+      "opcode" : 188,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordLessThanEqual",
+      "opcode" : 189,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFOrdGreaterThanEqual",
+      "opcode" : 190,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpFUnordGreaterThanEqual",
+      "opcode" : 191,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftRightLogical",
+      "opcode" : 194,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftRightArithmetic",
+      "opcode" : 195,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpShiftLeftLogical",
+      "opcode" : 196,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Shift'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseOr",
+      "opcode" : 197,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseXor",
+      "opcode" : 198,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpBitwiseAnd",
+      "opcode" : 199,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand 1'" },
+        { "kind" : "IdRef",        "name" : "'Operand 2'" }
+      ]
+    },
+    {
+      "opname" : "OpNot",
+      "opcode" : 200,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Operand'" }
+      ]
+    },
+    {
+      "opname" : "OpBitFieldInsert",
+      "opcode" : 201,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Insert'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitFieldSExtract",
+      "opcode" : 202,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitFieldUExtract",
+      "opcode" : 203,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" },
+        { "kind" : "IdRef",        "name" : "'Offset'" },
+        { "kind" : "IdRef",        "name" : "'Count'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitReverse",
+      "opcode" : 204,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpBitCount",
+      "opcode" : 205,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Base'" }
+      ]
+    },
+    {
+      "opname" : "OpDPdx",
+      "opcode" : 207,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpDPdy",
+      "opcode" : 208,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpFwidth",
+      "opcode" : 209,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpDPdxFine",
+      "opcode" : 210,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdyFine",
+      "opcode" : 211,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpFwidthFine",
+      "opcode" : 212,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdxCoarse",
+      "opcode" : 213,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpDPdyCoarse",
+      "opcode" : 214,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpFwidthCoarse",
+      "opcode" : 215,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'P'" }
+      ],
+      "capabilities" : [ "DerivativeControl" ]
+    },
+    {
+      "opname" : "OpEmitVertex",
+      "opcode" : 218,
+      "capabilities" : [ "Geometry" ]
+    },
+    {
+      "opname" : "OpEndPrimitive",
+      "opcode" : 219,
+      "capabilities" : [ "Geometry" ]
+    },
+    {
+      "opname" : "OpEmitStreamVertex",
+      "opcode" : 220,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Stream'" }
+      ],
+      "capabilities" : [ "GeometryStreams" ]
+    },
+    {
+      "opname" : "OpEndStreamPrimitive",
+      "opcode" : 221,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Stream'" }
+      ],
+      "capabilities" : [ "GeometryStreams" ]
+    },
+    {
+      "opname" : "OpControlBarrier",
+      "opcode" : 224,
+      "operands" : [
+        { "kind" : "IdScope",           "name" : "'Execution'" },
+        { "kind" : "IdScope",           "name" : "'Memory'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpMemoryBarrier",
+      "opcode" : 225,
+      "operands" : [
+        { "kind" : "IdScope",           "name" : "'Memory'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicLoad",
+      "opcode" : 227,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicStore",
+      "opcode" : 228,
+      "operands" : [
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicExchange",
+      "opcode" : 229,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicCompareExchange",
+      "opcode" : 230,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Equal'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Unequal'" },
+        { "kind" : "IdRef",             "name" : "'Value'" },
+        { "kind" : "IdRef",             "name" : "'Comparator'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicCompareExchangeWeak",
+      "opcode" : 231,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Equal'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Unequal'" },
+        { "kind" : "IdRef",             "name" : "'Value'" },
+        { "kind" : "IdRef",             "name" : "'Comparator'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpAtomicIIncrement",
+      "opcode" : 232,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicIDecrement",
+      "opcode" : 233,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicIAdd",
+      "opcode" : 234,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicISub",
+      "opcode" : 235,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicSMin",
+      "opcode" : 236,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicUMin",
+      "opcode" : 237,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicSMax",
+      "opcode" : 238,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicUMax",
+      "opcode" : 239,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicAnd",
+      "opcode" : 240,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicOr",
+      "opcode" : 241,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpAtomicXor",
+      "opcode" : 242,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" },
+        { "kind" : "IdRef",             "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpPhi",
+      "opcode" : 245,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "PairIdRefIdRef", "quantifier" : "*", "name" : "'Variable, Parent, ...'" }
+      ]
+    },
+    {
+      "opname" : "OpLoopMerge",
+      "opcode" : 246,
+      "operands" : [
+        { "kind" : "IdRef",       "name" : "'Merge Block'" },
+        { "kind" : "IdRef",       "name" : "'Continue Target'" },
+        { "kind" : "LoopControl" }
+      ]
+    },
+    {
+      "opname" : "OpSelectionMerge",
+      "opcode" : 247,
+      "operands" : [
+        { "kind" : "IdRef",            "name" : "'Merge Block'" },
+        { "kind" : "SelectionControl" }
+      ]
+    },
+    {
+      "opname" : "OpLabel",
+      "opcode" : 248,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ]
+    },
+    {
+      "opname" : "OpBranch",
+      "opcode" : 249,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Target Label'" }
+      ]
+    },
+    {
+      "opname" : "OpBranchConditional",
+      "opcode" : 250,
+      "operands" : [
+        { "kind" : "IdRef",                              "name" : "'Condition'" },
+        { "kind" : "IdRef",                              "name" : "'True Label'" },
+        { "kind" : "IdRef",                              "name" : "'False Label'" },
+        { "kind" : "LiteralInteger", "quantifier" : "*", "name" : "'Branch weights'" }
+      ]
+    },
+    {
+      "opname" : "OpSwitch",
+      "opcode" : 251,
+      "operands" : [
+        { "kind" : "IdRef",                                       "name" : "'Selector'" },
+        { "kind" : "IdRef",                                       "name" : "'Default'" },
+        { "kind" : "PairLiteralIntegerIdRef", "quantifier" : "*", "name" : "'Target'" }
+      ]
+    },
+    {
+      "opname" : "OpKill",
+      "opcode" : 252,
+      "capabilities" : [ "Shader" ]
+    },
+    {
+      "opname" : "OpReturn",
+      "opcode" : 253
+    },
+    {
+      "opname" : "OpReturnValue",
+      "opcode" : 254,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Value'" }
+      ]
+    },
+    {
+      "opname" : "OpUnreachable",
+      "opcode" : 255
+    },
+    {
+      "opname" : "OpLifetimeStart",
+      "opcode" : 256,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Pointer'" },
+        { "kind" : "LiteralInteger", "name" : "'Size'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpLifetimeStop",
+      "opcode" : 257,
+      "operands" : [
+        { "kind" : "IdRef",          "name" : "'Pointer'" },
+        { "kind" : "LiteralInteger", "name" : "'Size'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupAsyncCopy",
+      "opcode" : 259,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Destination'" },
+        { "kind" : "IdRef",        "name" : "'Source'" },
+        { "kind" : "IdRef",        "name" : "'Num Elements'" },
+        { "kind" : "IdRef",        "name" : "'Stride'" },
+        { "kind" : "IdRef",        "name" : "'Event'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupWaitEvents",
+      "opcode" : 260,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Num Events'" },
+        { "kind" : "IdRef",   "name" : "'Events List'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpGroupAll",
+      "opcode" : 261,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupAny",
+      "opcode" : 262,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupBroadcast",
+      "opcode" : 263,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Value'" },
+        { "kind" : "IdRef",        "name" : "'LocalId'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupIAdd",
+      "opcode" : 264,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFAdd",
+      "opcode" : 265,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMin",
+      "opcode" : 266,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMin",
+      "opcode" : 267,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMin",
+      "opcode" : 268,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMax",
+      "opcode" : 269,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMax",
+      "opcode" : 270,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMax",
+      "opcode" : 271,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpReadPipe",
+      "opcode" : 274,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpWritePipe",
+      "opcode" : 275,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReservedReadPipe",
+      "opcode" : 276,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",        "name" : "'Index'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReservedWritePipe",
+      "opcode" : 277,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",        "name" : "'Index'" },
+        { "kind" : "IdRef",        "name" : "'Pointer'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReserveReadPipePackets",
+      "opcode" : 278,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpReserveWritePipePackets",
+      "opcode" : 279,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpCommitReadPipe",
+      "opcode" : 280,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Pipe'" },
+        { "kind" : "IdRef", "name" : "'Reserve Id'" },
+        { "kind" : "IdRef", "name" : "'Packet Size'" },
+        { "kind" : "IdRef", "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpCommitWritePipe",
+      "opcode" : 281,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Pipe'" },
+        { "kind" : "IdRef", "name" : "'Reserve Id'" },
+        { "kind" : "IdRef", "name" : "'Packet Size'" },
+        { "kind" : "IdRef", "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpIsValidReserveId",
+      "opcode" : 282,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Reserve Id'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGetNumPipePackets",
+      "opcode" : 283,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGetMaxPipePackets",
+      "opcode" : 284,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupReserveReadPipePackets",
+      "opcode" : 285,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupReserveWritePipePackets",
+      "opcode" : 286,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",      "name" : "'Execution'" },
+        { "kind" : "IdRef",        "name" : "'Pipe'" },
+        { "kind" : "IdRef",        "name" : "'Num Packets'" },
+        { "kind" : "IdRef",        "name" : "'Packet Size'" },
+        { "kind" : "IdRef",        "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupCommitReadPipe",
+      "opcode" : 287,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Pipe'" },
+        { "kind" : "IdRef",   "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",   "name" : "'Packet Size'" },
+        { "kind" : "IdRef",   "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpGroupCommitWritePipe",
+      "opcode" : 288,
+      "operands" : [
+        { "kind" : "IdScope", "name" : "'Execution'" },
+        { "kind" : "IdRef",   "name" : "'Pipe'" },
+        { "kind" : "IdRef",   "name" : "'Reserve Id'" },
+        { "kind" : "IdRef",   "name" : "'Packet Size'" },
+        { "kind" : "IdRef",   "name" : "'Packet Alignment'" }
+      ],
+      "capabilities" : [ "Pipes" ]
+    },
+    {
+      "opname" : "OpEnqueueMarker",
+      "opcode" : 291,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Queue'" },
+        { "kind" : "IdRef",        "name" : "'Num Events'" },
+        { "kind" : "IdRef",        "name" : "'Wait Events'" },
+        { "kind" : "IdRef",        "name" : "'Ret Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpEnqueueKernel",
+      "opcode" : 292,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                            "name" : "'Queue'" },
+        { "kind" : "IdRef",                            "name" : "'Flags'" },
+        { "kind" : "IdRef",                            "name" : "'ND Range'" },
+        { "kind" : "IdRef",                            "name" : "'Num Events'" },
+        { "kind" : "IdRef",                            "name" : "'Wait Events'" },
+        { "kind" : "IdRef",                            "name" : "'Ret Event'" },
+        { "kind" : "IdRef",                            "name" : "'Invoke'" },
+        { "kind" : "IdRef",                            "name" : "'Param'" },
+        { "kind" : "IdRef",                            "name" : "'Param Size'" },
+        { "kind" : "IdRef",                            "name" : "'Param Align'" },
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Local Size'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelNDrangeSubGroupCount",
+      "opcode" : 293,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'ND Range'" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelNDrangeMaxSubGroupSize",
+      "opcode" : 294,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'ND Range'" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelWorkGroupSize",
+      "opcode" : 295,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetKernelPreferredWorkGroupSizeMultiple",
+      "opcode" : 296,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Invoke'" },
+        { "kind" : "IdRef",        "name" : "'Param'" },
+        { "kind" : "IdRef",        "name" : "'Param Size'" },
+        { "kind" : "IdRef",        "name" : "'Param Align'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpRetainEvent",
+      "opcode" : 297,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpReleaseEvent",
+      "opcode" : 298,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpCreateUserEvent",
+      "opcode" : 299,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpIsValidEvent",
+      "opcode" : 300,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Event'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpSetUserEventStatus",
+      "opcode" : 301,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" },
+        { "kind" : "IdRef", "name" : "'Status'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpCaptureEventProfilingInfo",
+      "opcode" : 302,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Event'" },
+        { "kind" : "IdRef", "name" : "'Profiling Info'" },
+        { "kind" : "IdRef", "name" : "'Value'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpGetDefaultQueue",
+      "opcode" : 303,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpBuildNDRange",
+      "opcode" : 304,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'GlobalWorkSize'" },
+        { "kind" : "IdRef",        "name" : "'LocalWorkSize'" },
+        { "kind" : "IdRef",        "name" : "'GlobalWorkOffset'" }
+      ],
+      "capabilities" : [ "DeviceEnqueue" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleImplicitLod",
+      "opcode" : 305,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleExplicitLod",
+      "opcode" : 306,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleDrefImplicitLod",
+      "opcode" : 307,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleDrefExplicitLod",
+      "opcode" : 308,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjImplicitLod",
+      "opcode" : 309,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjExplicitLod",
+      "opcode" : 310,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjDrefImplicitLod",
+      "opcode" : 311,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseSampleProjDrefExplicitLod",
+      "opcode" : 312,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",         "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",         "name" : "'Coordinate'" },
+        { "kind" : "IdRef",         "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseFetch",
+      "opcode" : 313,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseGather",
+      "opcode" : 314,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'Component'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseDrefGather",
+      "opcode" : 315,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Sampled Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "IdRef",                             "name" : "'D~ref~'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpImageSparseTexelsResident",
+      "opcode" : 316,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",        "name" : "'Resident Code'" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpNoLine",
+      "opcode" : 317
+    },
+    {
+      "opname" : "OpAtomicFlagTestAndSet",
+      "opcode" : 318,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpAtomicFlagClear",
+      "opcode" : 319,
+      "operands" : [
+        { "kind" : "IdRef",             "name" : "'Pointer'" },
+        { "kind" : "IdScope",           "name" : "'Scope'" },
+        { "kind" : "IdMemorySemantics", "name" : "'Semantics'" }
+      ],
+      "capabilities" : [ "Kernel" ]
+    },
+    {
+      "opname" : "OpImageSparseRead",
+      "opcode" : 320,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef",                             "name" : "'Image'" },
+        { "kind" : "IdRef",                             "name" : "'Coordinate'" },
+        { "kind" : "ImageOperands", "quantifier" : "?" }
+      ],
+      "capabilities" : [ "SparseResidency" ]
+    },
+    {
+      "opname" : "OpSubgroupBallotKHR",
+      "opcode" : 4421,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "SubgroupBallotKHR" ]
+    },
+    {
+      "opname" : "OpSubgroupFirstInvocationKHR",
+      "opcode" : 4422,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Value'" }
+      ],
+      "capabilities" : [ "SubgroupBallotKHR" ]
+    },
+    {
+      "opname" : "OpSubgroupAllKHR",
+      "opcode" : 4428,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "SubgroupVoteKHR" ]
+    },
+    {
+      "opname" : "OpSubgroupAnyKHR",
+      "opcode" : 4429,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "SubgroupVoteKHR" ]
+    },
+    {
+      "opname" : "OpSubgroupAllEqualKHR",
+      "opcode" : 4430,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Predicate'" }
+      ],
+      "capabilities" : [ "SubgroupVoteKHR" ]
+    },
+    {
+      "opname" : "OpSubgroupReadInvocationKHR",
+      "opcode" : 4432,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Value'" },
+        { "kind" : "IdRef", "name" : "'Index'" }
+      ],
+      "capabilities" : [ "SubgroupBallotKHR" ]
+    },
+    {
+      "opname" : "OpGroupIAddNonUniformAMD",
+      "opcode" : 5000,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFAddNonUniformAMD",
+      "opcode" : 5001,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMinNonUniformAMD",
+      "opcode" : 5002,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMinNonUniformAMD",
+      "opcode" : 5003,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMinNonUniformAMD",
+      "opcode" : 5004,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupFMaxNonUniformAMD",
+      "opcode" : 5005,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupUMaxNonUniformAMD",
+      "opcode" : 5006,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpGroupSMaxNonUniformAMD",
+      "opcode" : 5007,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdScope",        "name" : "'Execution'" },
+        { "kind" : "GroupOperation", "name" : "'Operation'" },
+        { "kind" : "IdRef",          "name" : "'X'" }
+      ],
+      "capabilities" : [ "Groups" ]
+    },
+    {
+      "opname" : "OpFragmentMaskFetchAMD",
+      "opcode" : 5011,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Image'" },
+        { "kind" : "IdRef", "name" : "'Coordinate'" }
+      ],
+      "capabilities" : [ "FragmentMaskAMD" ]
+    },
+    {
+      "opname" : "OpFragmentFetchAMD",
+      "opcode" : 5012,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Image'" },
+        { "kind" : "IdRef", "name" : "'Coordinate'" },
+        { "kind" : "IdRef", "name" : "'Fragment Index'" }
+      ],
+      "capabilities" : [ "FragmentMaskAMD" ]
+    }
+  ],
+  "operand_kinds" : [
+    {
+      "category" : "BitEnum",
+      "kind" : "ImageOperands",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Bias",
+          "value" : "0x0001",
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Lod",
+          "value" : "0x0002",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Grad",
+          "value" : "0x0004",
+          "parameters" : [
+            { "kind" : "IdRef" },
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "ConstOffset",
+          "value" : "0x0008",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Offset",
+          "value" : "0x0010",
+          "capabilities" : [ "ImageGatherExtended" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "ConstOffsets",
+          "value" : "0x0020",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "Sample",
+          "value" : "0x0040",
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        },
+        {
+          "enumerant" : "MinLod",
+          "value" : "0x0080",
+          "capabilities" : [ "MinLod" ],
+          "parameters" : [
+            { "kind" : "IdRef" }
+          ]
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "FPFastMathMode",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "NotNaN",
+          "value" : "0x0001",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NotInf",
+          "value" : "0x0002",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NSZ",
+          "value" : "0x0004",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "AllowRecip",
+          "value" : "0x0008",
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Fast",
+          "value" : "0x0010",
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "SelectionControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Flatten",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontFlatten",
+          "value" : "0x0002"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "LoopControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Unroll",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontUnroll",
+          "value" : "0x0002"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "FunctionControl",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Inline",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "DontInline",
+          "value" : "0x0002"
+        },
+        {
+          "enumerant" : "Pure",
+          "value" : "0x0004"
+        },
+        {
+          "enumerant" : "Const",
+          "value" : "0x0008"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "MemorySemantics",
+      "enumerants" : [
+        {
+          "enumerant" : "Relaxed",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Acquire",
+          "value" : "0x0002"
+        },
+        {
+          "enumerant" : "Release",
+          "value" : "0x0004"
+        },
+        {
+          "enumerant" : "AcquireRelease",
+          "value" : "0x0008"
+        },
+        {
+          "enumerant" : "SequentiallyConsistent",
+          "value" : "0x0010"
+        },
+        {
+          "enumerant" : "UniformMemory",
+          "value" : "0x0040",
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SubgroupMemory",
+          "value" : "0x0080"
+        },
+        {
+          "enumerant" : "WorkgroupMemory",
+          "value" : "0x0100"
+        },
+        {
+          "enumerant" : "CrossWorkgroupMemory",
+          "value" : "0x0200"
+        },
+        {
+          "enumerant" : "AtomicCounterMemory",
+          "value" : "0x0400",
+          "capabilities" : [ "AtomicStorage" ]
+        },
+        {
+          "enumerant" : "ImageMemory",
+          "value" : "0x0800"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "MemoryAccess",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "Volatile",
+          "value" : "0x0001"
+        },
+        {
+          "enumerant" : "Aligned",
+          "value" : "0x0002",
+          "parameters" : [
+            { "kind" : "LiteralInteger" }
+          ]
+        },
+        {
+          "enumerant" : "Nontemporal",
+          "value" : "0x0004"
+        }
+      ]
+    },
+    {
+      "category" : "BitEnum",
+      "kind" : "KernelProfilingInfo",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : "0x0000"
+        },
+        {
+          "enumerant" : "CmdExecTime",
+          "value" : "0x0001",
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SourceLanguage",
+      "enumerants" : [
+        {
+          "enumerant" : "Unknown",
+          "value" : 0
+        },
+        {
+          "enumerant" : "ESSL",
+          "value" : 1
+        },
+        {
+          "enumerant" : "GLSL",
+          "value" : 2
+        },
+        {
+          "enumerant" : "OpenCL_C",
+          "value" : 3
+        },
+        {
+          "enumerant" : "OpenCL_CPP",
+          "value" : 4
+        },
+        {
+          "enumerant" : "HLSL",
+          "value" : 5
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ExecutionModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Vertex",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "TessellationControl",
+          "value" : 1,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessellationEvaluation",
+          "value" : 2,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Geometry",
+          "value" : 3,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Fragment",
+          "value" : 4,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLCompute",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Kernel",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "AddressingModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Logical",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Physical32",
+          "value" : 1,
+          "capabilities" : [ "Addresses" ]
+        },
+        {
+          "enumerant" : "Physical64",
+          "value" : 2,
+          "capabilities" : [ "Addresses" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "MemoryModel",
+      "enumerants" : [
+        {
+          "enumerant" : "Simple",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLSL450",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OpenCL",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ExecutionMode",
+      "enumerants" : [
+        {
+          "enumerant" : "Invocations",
+          "value" : 0,
+          "capabilities" : [ "Geometry" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Number of <<Invocation,invocations>>'" }
+          ]
+        },
+        {
+          "enumerant" : "SpacingEqual",
+          "value" : 1,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "SpacingFractionalEven",
+          "value" : 2,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "SpacingFractionalOdd",
+          "value" : 3,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "VertexOrderCw",
+          "value" : 4,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "VertexOrderCcw",
+          "value" : 5,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "PixelCenterInteger",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OriginUpperLeft",
+          "value" : 7,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "OriginLowerLeft",
+          "value" : 8,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "EarlyFragmentTests",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointMode",
+          "value" : 10,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Xfb",
+          "value" : 11,
+          "capabilities" : [ "TransformFeedback" ]
+        },
+        {
+          "enumerant" : "DepthReplacing",
+          "value" : 12,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthGreater",
+          "value" : 14,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthLess",
+          "value" : 15,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DepthUnchanged",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "LocalSize",
+          "value" : 17,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'x size'" },
+            { "kind" : "LiteralInteger", "name" : "'y size'" },
+            { "kind" : "LiteralInteger", "name" : "'z size'" }
+          ]
+        },
+        {
+          "enumerant" : "LocalSizeHint",
+          "value" : 18,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'x size'" },
+            { "kind" : "LiteralInteger", "name" : "'y size'" },
+            { "kind" : "LiteralInteger", "name" : "'z size'" }
+          ]
+        },
+        {
+          "enumerant" : "InputPoints",
+          "value" : 19,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "InputLines",
+          "value" : 20,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "InputLinesAdjacency",
+          "value" : 21,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Triangles",
+          "value" : 22,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "InputTrianglesAdjacency",
+          "value" : 23,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "Quads",
+          "value" : 24,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Isolines",
+          "value" : 25,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "OutputVertices",
+          "value" : 26,
+          "capabilities" : [ "Geometry", "Tessellation" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Vertex count'" }
+          ]
+        },
+        {
+          "enumerant" : "OutputPoints",
+          "value" : 27,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "OutputLineStrip",
+          "value" : 28,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "OutputTriangleStrip",
+          "value" : 29,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "VecTypeHint",
+          "value" : 30,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Vector type'" }
+          ]
+        },
+        {
+          "enumerant" : "ContractionOff",
+          "value" : 31,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "PostDepthCoverage",
+          "value" : 4446,
+          "capabilities" : [ "SampleMaskPostDepthCoverage" ]
+        },
+        {
+          "enumerant" : "StencilRefReplacingEXT",
+          "value" : 5027,
+          "capabilities" : [ "StencilExportEXT" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "StorageClass",
+      "enumerants" : [
+        {
+          "enumerant" : "UniformConstant",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Input",
+          "value" : 1
+        },
+        {
+          "enumerant" : "Uniform",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Output",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Workgroup",
+          "value" : 4
+        },
+        {
+          "enumerant" : "CrossWorkgroup",
+          "value" : 5
+        },
+        {
+          "enumerant" : "Private",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Function",
+          "value" : 7
+        },
+        {
+          "enumerant" : "Generic",
+          "value" : 8,
+          "capabilities" : [ "GenericPointer" ]
+        },
+        {
+          "enumerant" : "PushConstant",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "AtomicCounter",
+          "value" : 10,
+          "capabilities" : [ "AtomicStorage" ]
+        },
+        {
+          "enumerant" : "Image",
+          "value" : 11
+        },
+        {
+          "enumerant" : "StorageBuffer",
+          "value" : 12,
+          "extensions" : [
+            "SPV_KHR_storage_buffer_storage_class",
+            "SPV_KHR_variable_pointers"
+          ],
+          "capabilities" : [ "Shader" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Dim",
+      "enumerants" : [
+        {
+          "enumerant" : "1D",
+          "value" : 0,
+          "capabilities" : [ "Sampled1D" ]
+        },
+        {
+          "enumerant" : "2D",
+          "value" : 1
+        },
+        {
+          "enumerant" : "3D",
+          "value" : 2
+        },
+        {
+          "enumerant" : "Cube",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rect",
+          "value" : 4,
+          "capabilities" : [ "SampledRect" ]
+        },
+        {
+          "enumerant" : "Buffer",
+          "value" : 5,
+          "capabilities" : [ "SampledBuffer" ]
+        },
+        {
+          "enumerant" : "SubpassData",
+          "value" : 6,
+          "capabilities" : [ "InputAttachment" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SamplerAddressingMode",
+      "enumerants" : [
+        {
+          "enumerant" : "None",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ClampToEdge",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Clamp",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Repeat",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RepeatMirrored",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "SamplerFilterMode",
+      "enumerants" : [
+        {
+          "enumerant" : "Nearest",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Linear",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageFormat",
+      "enumerants" : [
+        {
+          "enumerant" : "Unknown",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Rgba32f",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16f",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32f",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8",
+          "value" : 4,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8Snorm",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rg32f",
+          "value" : 6,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16f",
+          "value" : 7,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R11fG11fB10f",
+          "value" : 8,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16f",
+          "value" : 9,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba16",
+          "value" : 10,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgb10A2",
+          "value" : 11,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16",
+          "value" : 12,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8",
+          "value" : 13,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16",
+          "value" : 14,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8",
+          "value" : 15,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba16Snorm",
+          "value" : 16,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16Snorm",
+          "value" : 17,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8Snorm",
+          "value" : 18,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16Snorm",
+          "value" : 19,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8Snorm",
+          "value" : 20,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba32i",
+          "value" : 21,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16i",
+          "value" : 22,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8i",
+          "value" : 23,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32i",
+          "value" : 24,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rg32i",
+          "value" : 25,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16i",
+          "value" : 26,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8i",
+          "value" : 27,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16i",
+          "value" : 28,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8i",
+          "value" : 29,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rgba32ui",
+          "value" : 30,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba16ui",
+          "value" : 31,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgba8ui",
+          "value" : 32,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "R32ui",
+          "value" : 33,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Rgb10a2ui",
+          "value" : 34,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg32ui",
+          "value" : 35,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg16ui",
+          "value" : 36,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "Rg8ui",
+          "value" : 37,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R16ui",
+          "value" : 38,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        },
+        {
+          "enumerant" : "R8ui",
+          "value" : 39,
+          "capabilities" : [ "StorageImageExtendedFormats" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageChannelOrder",
+      "enumerants" : [
+        {
+          "enumerant" : "R",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "A",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RG",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RA",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGB",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGBA",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "BGRA",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ARGB",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Intensity",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Luminance",
+          "value" : 9,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Rx",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGx",
+          "value" : 11,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "RGBx",
+          "value" : 12,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Depth",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "DepthStencil",
+          "value" : 14,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGB",
+          "value" : 15,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGBx",
+          "value" : 16,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sRGBA",
+          "value" : 17,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "sBGRA",
+          "value" : 18,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ABGR",
+          "value" : 19,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "ImageChannelDataType",
+      "enumerants" : [
+        {
+          "enumerant" : "SnormInt8",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SnormInt16",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt8",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt16",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormShort565",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormShort555",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt101010",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt8",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt16",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SignedInt32",
+          "value" : 9,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt8",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt16",
+          "value" : 11,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnsignedInt32",
+          "value" : 12,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "HalfFloat",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float",
+          "value" : 14,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt24",
+          "value" : 15,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "UnormInt101010_2",
+          "value" : 16,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "FPRoundingMode",
+      "enumerants" : [
+        {
+          "enumerant" : "RTE",
+          "value" : 0,
+          "capabilities" : [
+            "Kernel",
+            "StorageUniformBufferBlock16",
+            "StorageUniform16",
+            "StoragePushConstant16",
+            "StorageInputOutput16"
+          ]
+        },
+        {
+          "enumerant" : "RTZ",
+          "value" : 1,
+          "capabilities" : [
+            "Kernel",
+            "StorageUniformBufferBlock16",
+            "StorageUniform16",
+            "StoragePushConstant16",
+            "StorageInputOutput16"
+          ]
+        },
+        {
+          "enumerant" : "RTP",
+          "value" : 2,
+          "capabilities" : [
+            "Kernel",
+            "StorageUniformBufferBlock16",
+            "StorageUniform16",
+            "StoragePushConstant16",
+            "StorageInputOutput16"
+          ]
+        },
+        {
+          "enumerant" : "RTN",
+          "value" : 3,
+          "capabilities" : [
+            "Kernel",
+            "StorageUniformBufferBlock16",
+            "StorageUniform16",
+            "StoragePushConstant16",
+            "StorageInputOutput16"
+          ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "LinkageType",
+      "enumerants" : [
+        {
+          "enumerant" : "Export",
+          "value" : 0,
+          "capabilities" : [ "Linkage" ]
+        },
+        {
+          "enumerant" : "Import",
+          "value" : 1,
+          "capabilities" : [ "Linkage" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "AccessQualifier",
+      "enumerants" : [
+        {
+          "enumerant" : "ReadOnly",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WriteOnly",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ReadWrite",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "FunctionParameterAttribute",
+      "enumerants" : [
+        {
+          "enumerant" : "Zext",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Sext",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ByVal",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Sret",
+          "value" : 3,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoAlias",
+          "value" : 4,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoCapture",
+          "value" : 5,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoWrite",
+          "value" : 6,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NoReadWrite",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Decoration",
+      "enumerants" : [
+        {
+          "enumerant" : "RelaxedPrecision",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SpecId",
+          "value" : 1,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Specialization Constant ID'" }
+          ]
+        },
+        {
+          "enumerant" : "Block",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "BufferBlock",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "RowMajor",
+          "value" : 4,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "ColMajor",
+          "value" : 5,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "ArrayStride",
+          "value" : 6,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Array Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "MatrixStride",
+          "value" : 7,
+          "capabilities" : [ "Matrix" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Matrix Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "GLSLShared",
+          "value" : 8,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GLSLPacked",
+          "value" : 9,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "CPacked",
+          "value" : 10,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "BuiltIn",
+          "value" : 11,
+          "parameters" : [
+            { "kind" : "BuiltIn" }
+          ]
+        },
+        {
+          "enumerant" : "NoPerspective",
+          "value" : 13,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Flat",
+          "value" : 14,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Patch",
+          "value" : 15,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "Centroid",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Sample",
+          "value" : 17,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "Invariant",
+          "value" : 18,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Restrict",
+          "value" : 19
+        },
+        {
+          "enumerant" : "Aliased",
+          "value" : 20
+        },
+        {
+          "enumerant" : "Volatile",
+          "value" : 21
+        },
+        {
+          "enumerant" : "Constant",
+          "value" : 22,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Coherent",
+          "value" : 23
+        },
+        {
+          "enumerant" : "NonWritable",
+          "value" : 24
+        },
+        {
+          "enumerant" : "NonReadable",
+          "value" : 25
+        },
+        {
+          "enumerant" : "Uniform",
+          "value" : 26,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SaturatedConversion",
+          "value" : 28,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Stream",
+          "value" : 29,
+          "capabilities" : [ "GeometryStreams" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Stream Number'" }
+          ]
+        },
+        {
+          "enumerant" : "Location",
+          "value" : 30,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Location'" }
+          ]
+        },
+        {
+          "enumerant" : "Component",
+          "value" : 31,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Component'" }
+          ]
+        },
+        {
+          "enumerant" : "Index",
+          "value" : 32,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Index'" }
+          ]
+        },
+        {
+          "enumerant" : "Binding",
+          "value" : 33,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Binding Point'" }
+          ]
+        },
+        {
+          "enumerant" : "DescriptorSet",
+          "value" : 34,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Descriptor Set'" }
+          ]
+        },
+        {
+          "enumerant" : "Offset",
+          "value" : 35,
+          "capabilities" : [ "Shader" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Byte Offset'" }
+          ]
+        },
+        {
+          "enumerant" : "XfbBuffer",
+          "value" : 36,
+          "capabilities" : [ "TransformFeedback" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'XFB Buffer Number'" }
+          ]
+        },
+        {
+          "enumerant" : "XfbStride",
+          "value" : 37,
+          "capabilities" : [ "TransformFeedback" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'XFB Stride'" }
+          ]
+        },
+        {
+          "enumerant" : "FuncParamAttr",
+          "value" : 38,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "FunctionParameterAttribute", "name" : "'Function Parameter Attribute'" }
+          ]
+        },
+        {
+          "enumerant" : "FPRoundingMode",
+          "value" : 39,
+          "capabilities" : [
+            "Kernel",
+            "StorageUniformBufferBlock16",
+            "StorageUniform16",
+            "StoragePushConstant16",
+            "StorageInputOutput16"
+          ],
+          "parameters" : [
+            { "kind" : "FPRoundingMode", "name" : "'Floating-Point Rounding Mode'" }
+          ]
+        },
+        {
+          "enumerant" : "FPFastMathMode",
+          "value" : 40,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "FPFastMathMode", "name" : "'Fast-Math Mode'" }
+          ]
+        },
+        {
+          "enumerant" : "LinkageAttributes",
+          "value" : 41,
+          "capabilities" : [ "Linkage" ],
+          "parameters" : [
+            { "kind" : "LiteralString", "name" : "'Name'" },
+            { "kind" : "LinkageType",   "name" : "'Linkage Type'" }
+          ]
+        },
+        {
+          "enumerant" : "NoContraction",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InputAttachmentIndex",
+          "value" : 43,
+          "capabilities" : [ "InputAttachment" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Attachment Index'" }
+          ]
+        },
+        {
+          "enumerant" : "Alignment",
+          "value" : 44,
+          "capabilities" : [ "Kernel" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Alignment'" }
+          ]
+        },
+        {
+          "enumerant" : "ExplicitInterpAMD",
+          "value" : 4999
+        },
+        {
+          "enumerant" : "OverrideCoverageNV",
+          "value" : 5248,
+          "capabilities" : [ "SampleMaskOverrideCoverageNV" ]
+        },
+        {
+          "enumerant" : "PassthroughNV",
+          "value" : 5250,
+          "capabilities" : [ "GeometryShaderPassthroughNV" ]
+        },
+        {
+          "enumerant" : "ViewportRelativeNV",
+          "value" : 5252,
+          "capabilities" : [ "ShaderViewportMaskNV" ]
+        },
+        {
+          "enumerant" : "SecondaryViewportRelativeNV",
+          "value" : 5256,
+          "capabilities" : [ "ShaderStereoViewNV" ],
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Offset'" }
+          ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "BuiltIn",
+      "enumerants" : [
+        {
+          "enumerant" : "Position",
+          "value" : 0,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointSize",
+          "value" : 1,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ClipDistance",
+          "value" : 3,
+          "capabilities" : [ "ClipDistance" ]
+        },
+        {
+          "enumerant" : "CullDistance",
+          "value" : 4,
+          "capabilities" : [ "CullDistance" ]
+        },
+        {
+          "enumerant" : "VertexId",
+          "value" : 5,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InstanceId",
+          "value" : 6,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PrimitiveId",
+          "value" : 7,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "InvocationId",
+          "value" : 8,
+          "capabilities" : [ "Geometry", "Tessellation" ]
+        },
+        {
+          "enumerant" : "Layer",
+          "value" : 9,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "ViewportIndex",
+          "value" : 10,
+          "capabilities" : [ "MultiViewport" ]
+        },
+        {
+          "enumerant" : "TessLevelOuter",
+          "value" : 11,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessLevelInner",
+          "value" : 12,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "TessCoord",
+          "value" : 13,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "PatchVertices",
+          "value" : 14,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "FragCoord",
+          "value" : 15,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "PointCoord",
+          "value" : 16,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "FrontFacing",
+          "value" : 17,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampleId",
+          "value" : 18,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "SamplePosition",
+          "value" : 19,
+          "capabilities" : [ "SampleRateShading" ]
+        },
+        {
+          "enumerant" : "SampleMask",
+          "value" : 20,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "FragDepth",
+          "value" : 22,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "HelperInvocation",
+          "value" : 23,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "NumWorkgroups",
+          "value" : 24
+        },
+        {
+          "enumerant" : "WorkgroupSize",
+          "value" : 25
+        },
+        {
+          "enumerant" : "WorkgroupId",
+          "value" : 26
+        },
+        {
+          "enumerant" : "LocalInvocationId",
+          "value" : 27
+        },
+        {
+          "enumerant" : "GlobalInvocationId",
+          "value" : 28
+        },
+        {
+          "enumerant" : "LocalInvocationIndex",
+          "value" : 29
+        },
+        {
+          "enumerant" : "WorkDim",
+          "value" : 30,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalSize",
+          "value" : 31,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "EnqueuedWorkgroupSize",
+          "value" : 32,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalOffset",
+          "value" : 33,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "GlobalLinearId",
+          "value" : 34,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupSize",
+          "value" : 36,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupMaxSize",
+          "value" : 37,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NumSubgroups",
+          "value" : 38,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "NumEnqueuedSubgroups",
+          "value" : 39,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupId",
+          "value" : 40,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "SubgroupLocalInvocationId",
+          "value" : 41,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "VertexIndex",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InstanceIndex",
+          "value" : 43,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SubgroupEqMaskKHR",
+          "value" : 4416,
+          "capabilities" : [ "SubgroupBallotKHR" ]
+        },
+        {
+          "enumerant" : "SubgroupGeMaskKHR",
+          "value" : 4417,
+          "capabilities" : [ "SubgroupBallotKHR" ]
+        },
+        {
+          "enumerant" : "SubgroupGtMaskKHR",
+          "value" : 4418,
+          "capabilities" : [ "SubgroupBallotKHR" ]
+        },
+        {
+          "enumerant" : "SubgroupLeMaskKHR",
+          "value" : 4419,
+          "capabilities" : [ "SubgroupBallotKHR" ]
+        },
+        {
+          "enumerant" : "SubgroupLtMaskKHR",
+          "value" : 4420,
+          "capabilities" : [ "SubgroupBallotKHR" ]
+        },
+        {
+          "enumerant" : "BaseVertex",
+          "value" : 4424,
+          "capabilities" : [ "DrawParameters" ]
+        },
+        {
+          "enumerant" : "BaseInstance",
+          "value" : 4425,
+          "capabilities" : [ "DrawParameters" ]
+        },
+        {
+          "enumerant" : "DrawIndex",
+          "value" : 4426,
+          "capabilities" : [ "DrawParameters" ]
+        },
+        {
+          "enumerant" : "DeviceIndex",
+          "value" : 4438,
+          "capabilities" : [ "DeviceGroup" ]
+        },
+        {
+          "enumerant" : "ViewIndex",
+          "value" : 4440,
+          "capabilities" : [ "MultiView" ]
+        },
+        {
+          "enumerant" : "BaryCoordNoPerspAMD",
+          "value" : 4992
+        },
+        {
+          "enumerant" : "BaryCoordNoPerspCentroidAMD",
+          "value" : 4993
+        },
+        {
+          "enumerant" : "BaryCoordNoPerspSampleAMD",
+          "value" : 4994
+        },
+        {
+          "enumerant" : "BaryCoordSmoothAMD",
+          "value" : 4995
+        },
+        {
+          "enumerant" : "BaryCoordSmoothCentroidAMD",
+          "value" : 4996
+        },
+        {
+          "enumerant" : "BaryCoordSmoothSampleAMD",
+          "value" : 4997
+        },
+        {
+          "enumerant" : "BaryCoordPullModelAMD",
+          "value" : 4998
+        },
+        {
+          "enumerant" : "FragStencilRefEXT",
+          "value" : 5014,
+          "capabilities" : [ "StencilExportEXT" ]
+        },
+        {
+          "enumerant" : "ViewportMaskNV",
+          "value" : 5253,
+          "capabilities" : [ "ShaderViewportMaskNV" ]
+        },
+        {
+          "enumerant" : "SecondaryPositionNV",
+          "value" : 5257,
+          "capabilities" : [ "ShaderStereoViewNV" ]
+        },
+        {
+          "enumerant" : "SecondaryViewportMaskNV",
+          "value" : 5258,
+          "capabilities" : [ "ShaderStereoViewNV" ]
+        },
+        {
+          "enumerant" : "PositionPerViewNV",
+          "value" : 5261,
+          "capabilities" : [ "PerViewAttributesNV" ]
+        },
+        {
+          "enumerant" : "ViewportMaskPerViewNV",
+          "value" : 5262,
+          "capabilities" : [ "PerViewAttributesNV" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Scope",
+      "enumerants" : [
+        {
+          "enumerant" : "CrossDevice",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Device",
+          "value" : 1
+        },
+        {
+          "enumerant" : "Workgroup",
+          "value" : 2
+        },
+        {
+          "enumerant" : "Subgroup",
+          "value" : 3
+        },
+        {
+          "enumerant" : "Invocation",
+          "value" : 4
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "GroupOperation",
+      "enumerants" : [
+        {
+          "enumerant" : "Reduce",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "InclusiveScan",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ExclusiveScan",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "KernelEnqueueFlags",
+      "enumerants" : [
+        {
+          "enumerant" : "NoWait",
+          "value" : 0,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WaitKernel",
+          "value" : 1,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "WaitWorkGroup",
+          "value" : 2,
+          "capabilities" : [ "Kernel" ]
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "Capability",
+      "enumerants" : [
+        {
+          "enumerant" : "Matrix",
+          "value" : 0
+        },
+        {
+          "enumerant" : "Shader",
+          "value" : 1,
+          "capabilities" : [ "Matrix" ]
+        },
+        {
+          "enumerant" : "Geometry",
+          "value" : 2,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Tessellation",
+          "value" : 3,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Addresses",
+          "value" : 4
+        },
+        {
+          "enumerant" : "Linkage",
+          "value" : 5
+        },
+        {
+          "enumerant" : "Kernel",
+          "value" : 6
+        },
+        {
+          "enumerant" : "Vector16",
+          "value" : 7,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float16Buffer",
+          "value" : 8,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Float16",
+          "value" : 9
+        },
+        {
+          "enumerant" : "Float64",
+          "value" : 10
+        },
+        {
+          "enumerant" : "Int64",
+          "value" : 11
+        },
+        {
+          "enumerant" : "Int64Atomics",
+          "value" : 12,
+          "capabilities" : [ "Int64" ]
+        },
+        {
+          "enumerant" : "ImageBasic",
+          "value" : 13,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "ImageReadWrite",
+          "value" : 14,
+          "capabilities" : [ "ImageBasic" ]
+        },
+        {
+          "enumerant" : "ImageMipmap",
+          "value" : 15,
+          "capabilities" : [ "ImageBasic" ]
+        },
+        {
+          "enumerant" : "Pipes",
+          "value" : 17,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "Groups",
+          "value" : 18
+        },
+        {
+          "enumerant" : "DeviceEnqueue",
+          "value" : 19,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "LiteralSampler",
+          "value" : 20,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "AtomicStorage",
+          "value" : 21,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Int16",
+          "value" : 22
+        },
+        {
+          "enumerant" : "TessellationPointSize",
+          "value" : 23,
+          "capabilities" : [ "Tessellation" ]
+        },
+        {
+          "enumerant" : "GeometryPointSize",
+          "value" : 24,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "ImageGatherExtended",
+          "value" : 25,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageMultisample",
+          "value" : 27,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "UniformBufferArrayDynamicIndexing",
+          "value" : 28,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampledImageArrayDynamicIndexing",
+          "value" : 29,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageBufferArrayDynamicIndexing",
+          "value" : 30,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageArrayDynamicIndexing",
+          "value" : 31,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ClipDistance",
+          "value" : 32,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "CullDistance",
+          "value" : 33,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageCubeArray",
+          "value" : 34,
+          "capabilities" : [ "SampledCubeArray" ]
+        },
+        {
+          "enumerant" : "SampleRateShading",
+          "value" : 35,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageRect",
+          "value" : 36,
+          "capabilities" : [ "SampledRect" ]
+        },
+        {
+          "enumerant" : "SampledRect",
+          "value" : 37,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GenericPointer",
+          "value" : 38,
+          "capabilities" : [ "Addresses" ]
+        },
+        {
+          "enumerant" : "Int8",
+          "value" : 39,
+          "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "InputAttachment",
+          "value" : 40,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SparseResidency",
+          "value" : 41,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "MinLod",
+          "value" : 42,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "Sampled1D",
+          "value" : 43
+        },
+        {
+          "enumerant" : "Image1D",
+          "value" : 44,
+          "capabilities" : [ "Sampled1D" ]
+        },
+        {
+          "enumerant" : "SampledCubeArray",
+          "value" : 45,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "SampledBuffer",
+          "value" : 46
+        },
+        {
+          "enumerant" : "ImageBuffer",
+          "value" : 47,
+          "capabilities" : [ "SampledBuffer" ]
+        },
+        {
+          "enumerant" : "ImageMSArray",
+          "value" : 48,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageExtendedFormats",
+          "value" : 49,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "ImageQuery",
+          "value" : 50,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "DerivativeControl",
+          "value" : 51,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "InterpolationFunction",
+          "value" : 52,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "TransformFeedback",
+          "value" : 53,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "GeometryStreams",
+          "value" : 54,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "StorageImageReadWithoutFormat",
+          "value" : 55,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "StorageImageWriteWithoutFormat",
+          "value" : 56,
+          "capabilities" : [ "Shader" ]
+        },
+        {
+          "enumerant" : "MultiViewport",
+          "value" : 57,
+          "capabilities" : [ "Geometry" ]
+        },
+        {
+          "enumerant" : "SubgroupBallotKHR",
+          "value" : 4423,
+          "extensions" : [ "SPV_KHR_shader_ballot" ]
+        },
+        {
+          "enumerant" : "DrawParameters",
+          "value" : 4427,
+          "extensions" : [ "SPV_KHR_shader_draw_parameters" ]
+        },
+        {
+          "enumerant" : "SubgroupVoteKHR",
+          "value" : 4431,
+          "extensions" : [ "SPV_KHR_subgroup_vote" ]
+        },
+        {
+          "enumerant" : "StorageBuffer16BitAccess",
+          "value" : 4433,
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "StorageUniformBufferBlock16",
+          "value" : 4433,
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "UniformAndStorageBuffer16BitAccess",
+          "value" : 4434,
+          "capabilities" : [
+            "StorageBuffer16BitAccess",
+            "StorageUniformBufferBlock16"
+          ],
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "StorageUniform16",
+          "value" : 4434,
+          "capabilities" : [
+            "StorageBuffer16BitAccess",
+            "StorageUniformBufferBlock16"
+          ],
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "StoragePushConstant16",
+          "value" : 4435,
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "StorageInputOutput16",
+          "value" : 4436,
+          "extensions" : [ "SPV_KHR_16bit_storage" ]
+        },
+        {
+          "enumerant" : "DeviceGroup",
+          "value" : 4437,
+          "extensions" : [ "SPV_KHR_device_group" ]
+        },
+        {
+          "enumerant" : "MultiView",
+          "value" : 4439,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_KHR_multiview" ]
+        },
+        {
+          "enumerant" : "VariablePointersStorageBuffer",
+          "value" : 4441,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_KHR_variable_pointers" ]
+        },
+        {
+          "enumerant" : "VariablePointers",
+          "value" : 4442,
+          "capabilities" : [ "VariablePointersStorageBuffer" ],
+          "extensions" : [ "SPV_KHR_variable_pointers" ]
+        },
+        {
+            "enumerant": "AtomicStorageOps",
+            "value": 4445,
+            "extensions": [ "SPV_KHR_shader_atomic_counter_ops" ]
+        },
+        {
+          "enumerant" : "SampleMaskPostDepthCoverage",
+          "value" : 4447,
+          "extensions" : [ "SPV_KHR_post_depth_coverage" ]
+        },
+        {
+          "enumerant" : "ImageGatherBiasLodAMD",
+          "value" : 5009,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_AMD_texture_gather_bias_lod" ]
+        },
+        {
+          "enumerant" : "FragmentMaskAMD",
+          "value" : 5010,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_AMD_shader_fragment_mask" ]
+        },
+        {
+          "enumerant" : "StencilExportEXT",
+          "value" : 5013,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_EXT_shader_stencil_export" ]
+        },
+        {
+          "enumerant" : "ImageReadWriteLodAMD",
+          "value" : 5015,
+          "capabilities" : [ "Shader" ],
+          "extensions" : [ "SPV_AMD_shader_image_load_store_lod" ]
+        },
+        {
+          "enumerant" : "SampleMaskOverrideCoverageNV",
+          "value" : 5249,
+          "capabilities" : [ "SampleRateShading" ],
+          "extensions" : [ "SPV_NV_sample_mask_override_coverage" ]
+        },
+        {
+          "enumerant" : "GeometryShaderPassthroughNV",
+          "value" : 5251,
+          "capabilities" : [ "Geometry" ],
+          "extensions" : [ "SPV_NV_geometry_shader_passthrough" ]
+        },
+        {
+          "enumerant" : "ShaderViewportIndexLayerEXT",
+          "value" : 5254,
+          "capabilities" : [ "MultiViewport" ],
+          "extensions" : [ "SPV_EXT_shader_viewport_index_layer" ]
+        },
+        {
+          "enumerant" : "ShaderViewportIndexLayerNV",
+          "value" : 5254,
+          "capabilities" : [ "MultiViewport" ],
+          "extensions" : [ "SPV_NV_viewport_array2" ]
+        },
+        {
+          "enumerant" : "ShaderViewportMaskNV",
+          "value" : 5255,
+          "capabilities" : [ "ShaderViewportIndexLayerNV" ],
+          "extensions" : [ "SPV_NV_viewport_array2" ]
+        },
+        {
+          "enumerant" : "ShaderStereoViewNV",
+          "value" : 5259,
+          "capabilities" : [ "ShaderViewportMaskNV" ],
+          "extensions" : [ "SPV_NV_stereo_view_rendering" ]
+        },
+        {
+          "enumerant" : "PerViewAttributesNV",
+          "value" : 5260,
+          "capabilities" : [ "MultiView" ],
+          "extensions" : [ "SPV_NVX_multiview_per_view_attributes" ]
+        }
+      ]
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdResultType",
+      "doc" : "Reference to an <id> representing the result's type of the enclosing instruction"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdResult",
+      "doc" : "Definition of an <id> representing the result of the enclosing instruction"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdMemorySemantics",
+      "doc" : "Reference to an <id> representing a 32-bit integer that is a mask from the MemorySemantics 
operand kind"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdScope",
+      "doc" : "Reference to an <id> representing a 32-bit integer that is a mask from the Scope operand kind"
+    },
+    {
+      "category" : "Id",
+      "kind" : "IdRef",
+      "doc" : "Reference to an <id>"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralInteger",
+      "doc" : "An integer consuming one or more words"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralString",
+      "doc" : "A null-terminated stream of characters consuming an integral number of words"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralContextDependentNumber",
+      "doc" : "A literal number whose size and format are determined by a previous operand in the enclosing 
instruction"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralExtInstInteger",
+      "doc" : "A 32-bit unsigned integer indicating which instruction to use and determining the layout of 
following operands (for OpExtInst)"
+    },
+    {
+      "category" : "Literal",
+      "kind" : "LiteralSpecConstantOpInteger",
+      "doc" : "An opcode indicating the operation to be performed and determining the layout of following 
operands (for OpSpecConstantOp)"
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairLiteralIntegerIdRef",
+      "bases" : [ "LiteralInteger", "IdRef" ]
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairIdRefLiteralInteger",
+      "bases" : [ "IdRef", "LiteralInteger" ]
+    },
+    {
+      "category" : "Composite",
+      "kind" : "PairIdRefIdRef",
+      "bases" : [ "IdRef", "IdRef" ]
+    }
+  ]
+}
diff --git a/gsk/spirv.js b/gsk/spirv.js
new file mode 100644
index 0000000..849fd80
--- /dev/null
+++ b/gsk/spirv.js
@@ -0,0 +1,715 @@
+function usage() 
+{
+  print ("usage: gjs spirv.js enums|functions SPIRV_GRAMMAR_FILE");
+}
+
+if (ARGV.length != 2)
+  {
+    usage();
+    throw new SyntaxError ("Script needs 2 arguments but got " + ARGV.length);
+  }
+
+var contents = imports.gi.Gio.File.new_for_path(ARGV[1]).load_contents(null);
+var spirv = JSON.parse(contents[1]);
+
+if (!String.prototype.format) {
+  String.prototype.format = function() {
+    var args = arguments;
+    return this.replace(/{(\d+)}/g, function(match, number) {
+      return typeof args[number] != 'undefined'
+        ? args[number]
+        : match
+      ;
+    });
+  };
+}
+
+function all_lower(s)
+{
+  let result = "";
+  let needs_underscore = false;
+  let had_caps = false;
+  for (let i = 0; i < s.length; i++)
+    {
+      if (s[i] >= 'a' && s[i] <= 'z')
+        {
+          needs_underscore = true;
+          had_caps = false;
+          result += s[i];
+        }
+      else if (s[i] >= "A" && s[i] <= "Z")
+        {
+          if (needs_underscore)
+            result += "_";
+          else if (s[i+1] && s[i+1] >= "a" && s[i+1] <= "z" && had_caps)
+            result += "_";
+          needs_underscore = false;
+          had_caps = true;
+          result += s[i].toLowerCase();
+        }
+      else if (s[i] >= '0' && s[i] <= '9')
+        {
+          needs_underscore = true
+          had_caps = false;
+          result += s[i]
+        }
+      else
+        {
+          needs_underscore = false
+          had_caps = false;
+          result += "_";
+        }
+    }
+  return result;
+}
+
+function all_upper(s)
+{
+  return all_lower(s).toUpperCase();
+}
+
+function sanitize_name (name)
+{
+  name = name.substr(1);
+  return all_lower(name.substr(0, name.indexOf("'")));
+}
+
+var SpecialTypes = {
+  "OpVariable": { "result_type": "IdResultPointerType" },
+  "OpImageTexelPointer": { "result_type": "IdResultPointerType" },
+  "OpAccessChain": { "result_type": "IdResultPointerType" },
+  "OpInBoundsAccessChain": { "result_type": "IdResultPointerType" },
+  "OpConvertUToPtr": { "result_type": "IdResultPointerType" },
+  "OpPtrCastToGeneric": { "result_type": "IdResultPointerType" },
+  "OpGenericCastToPtr": { "result_type": "IdResultPointerType" },
+  "OpGenericCastToPtrExplicit": { "result_type": "IdResultPointerType" }
+};
+
+/* maps opcodes to section in file they appear in */
+var Sections = {
+  "OpNop": "",
+  "OpUndef": "",
+  "OpSourceContinued": "",
+  "OpSource": "debug",
+  "OpSourceExtension": "debug",
+  "OpName": "debug",
+  "OpMemberName": "debug",
+  "OpString": "",
+  "OpLine": "",
+  "OpExtension": "header",
+  "OpExtInstImport": "header",
+  "OpExtInst": "",
+  "OpMemoryModel": "header",
+  "OpEntryPoint": "header",
+  "OpExecutionMode": "header",
+  "OpCapability": "header",
+  "OpTypeVoid": "define",
+  "OpTypeBool": "define",
+  "OpTypeInt": "define",
+  "OpTypeFloat": "define",
+  "OpTypeVector": "define",
+  "OpTypeMatrix": "define",
+  "OpTypeImage": "define",
+  "OpTypeSampler": "define",
+  "OpTypeSampledImage": "define",
+  "OpTypeArray": "define",
+  "OpTypeRuntimeArray": "define",
+  "OpTypeStruct": "define",
+  "OpTypeOpaque": "define",
+  "OpTypePointer": "define",
+  "OpTypeFunction": "define",
+  "OpTypeEvent": "define",
+  "OpTypeDeviceEvent": "define",
+  "OpTypeReserveId": "define",
+  "OpTypeQueue": "define",
+  "OpTypePipe": "define",
+  "OpTypeForwardPointer": "define",
+  "OpConstantTrue": "define",
+  "OpConstantFalse": "define",
+  "OpConstant": "define",
+  "OpConstantComposite": "define",
+  "OpConstantSampler": "define",
+  "OpConstantNull": "define",
+  "OpSpecConstantTrue": "define",
+  "OpSpecConstantFalse": "define",
+  "OpSpecConstant": "define",
+  "OpSpecConstantComposite": "define",
+  "OpSpecConstantOp": "define",
+  "OpFunction": "declare",
+  "OpFunctionParameter": "declare",
+  "OpFunctionEnd": "code",
+  "OpFunctionCall": "code",
+  "OpVariable": "declare",
+  "OpImageTexelPointer": "code",
+  "OpLoad": "code",
+  "OpStore": "code",
+  "OpCopyMemory": "code",
+  "OpCopyMemorySized": "code",
+  "OpAccessChain": "code",
+  "OpInBoundsAccessChain": "code",
+  "OpPtrAccessChain": "code",
+  "OpArrayLength": "code",
+  "OpGenericPtrMemSemantics": "",
+  "OpInBoundsPtrAccessChain": "code",
+  "OpDecorate": "decorate",
+  "OpMemberDecorate": "decorate",
+  "OpDecorationGroup": "decorate",
+  "OpGroupDecorate": "decorate",
+  "OpGroupMemberDecorate": "decorate",
+  "OpVectorExtractDynamic": "code",
+  "OpVectorInsertDynamic": "code",
+  "OpVectorShuffle": "code",
+  "OpCompositeConstruct": "code",
+  "OpCompositeExtract": "code",
+  "OpCompositeInsert": "code",
+  "OpCopyObject": "",
+  "OpTranspose": "code",
+  "OpSampledImage": "",
+  "OpImageSampleImplicitLod": "code",
+  "OpImageSampleExplicitLod": "code",
+  "OpImageSampleDrefImplicitLod": "code",
+  "OpImageSampleDrefExplicitLod": "code",
+  "OpImageSampleProjImplicitLod": "code",
+  "OpImageSampleProjExplicitLod": "code",
+  "OpImageSampleProjDrefImplicitLod": "code",
+  "OpImageSampleProjDrefExplicitLod": "code",
+  "OpImageFetch": "code",
+  "OpImageGather": "code",
+  "OpImageDrefGather": "code",
+  "OpImageRead": "code",
+  "OpImageWrite": "code",
+  "OpImage": "code",
+  "OpImageQueryFormat": "code",
+  "OpImageQueryOrder": "code",
+  "OpImageQuerySizeLod": "code",
+  "OpImageQuerySize": "code",
+  "OpImageQueryLod": "code",
+  "OpImageQueryLevels": "code",
+  "OpImageQuerySamples": "code",
+  "OpConvertFToU": "code",
+  "OpConvertFToS": "code",
+  "OpConvertSToF": "code",
+  "OpConvertUToF": "code",
+  "OpUConvert": "code",
+  "OpSConvert": "code",
+  "OpFConvert": "code",
+  "OpQuantizeToF16": "code",
+  "OpConvertPtrToU": "code",
+  "OpSatConvertSToU": "code",
+  "OpSatConvertUToS": "code",
+  "OpConvertUToPtr": "code",
+  "OpPtrCastToGeneric": "code",
+  "OpGenericCastToPtr": "code",
+  "OpGenericCastToPtrExplicit": "code",
+  "OpBitcast": "code",
+  "OpSNegate": "code",
+  "OpFNegate": "code",
+  "OpIAdd": "code",
+  "OpFAdd": "code",
+  "OpISub": "code",
+  "OpFSub": "code",
+  "OpIMul": "code",
+  "OpFMul": "code",
+  "OpUDiv": "code",
+  "OpSDiv": "code",
+  "OpFDiv": "code",
+  "OpUMod": "code",
+  "OpSRem": "code",
+  "OpSMod": "code",
+  "OpFRem": "code",
+  "OpFMod": "code",
+  "OpVectorTimesScalar": "code",
+  "OpMatrixTimesScalar": "code",
+  "OpVectorTimesMatrix": "code",
+  "OpMatrixTimesVector": "code",
+  "OpMatrixTimesMatrix": "code",
+  "OpOuterProduct": "code",
+  "OpDot": "code",
+  "OpIAddCarry": "code",
+  "OpISubBorrow": "code",
+  "OpUMulExtended": "code",
+  "OpSMulExtended": "code",
+  "OpAny": "code",
+  "OpAll": "code",
+  "OpIsNan": "code",
+  "OpIsInf": "code",
+  "OpIsFinite": "code",
+  "OpIsNormal": "code",
+  "OpSignBitSet": "code",
+  "OpLessOrGreater": "code",
+  "OpOrdered": "code",
+  "OpUnordered": "code",
+  "OpLogicalEqual": "code",
+  "OpLogicalNotEqual": "code",
+  "OpLogicalOr": "code",
+  "OpLogicalAnd": "code",
+  "OpLogicalNot": "code",
+  "OpSelect": "code",
+  "OpIEqual": "code",
+  "OpINotEqual": "code",
+  "OpUGreaterThan": "code",
+  "OpSGreaterThan": "code",
+  "OpUGreaterThanEqual": "code",
+  "OpSGreaterThanEqual": "code",
+  "OpULessThan": "code",
+  "OpSLessThan": "code",
+  "OpULessThanEqual": "code",
+  "OpSLessThanEqual": "code",
+  "OpFOrdEqual": "code",
+  "OpFUnordEqual": "code",
+  "OpFOrdNotEqual": "code",
+  "OpFUnordNotEqual": "code",
+  "OpFOrdLessThan": "code",
+  "OpFUnordLessThan": "code",
+  "OpFOrdGreaterThan": "code",
+  "OpFUnordGreaterThan": "code",
+  "OpFOrdLessThanEqual": "code",
+  "OpFUnordLessThanEqual": "code",
+  "OpFOrdGreaterThanEqual": "code",
+  "OpFUnordGreaterThanEqual": "code",
+  "OpShiftRightLogical": "code",
+  "OpShiftRightArithmetic": "code",
+  "OpShiftLeftLogical": "code",
+  "OpBitwiseOr": "code",
+  "OpBitwiseXor": "code",
+  "OpBitwiseAnd": "code",
+  "OpNot": "code",
+  "OpBitFieldInsert": "code",
+  "OpBitFieldSExtract": "code",
+  "OpBitFieldUExtract": "code",
+  "OpBitReverse": "code",
+  "OpBitCount": "code",
+  "OpDPdx": "code",
+  "OpDPdy": "code",
+  "OpFwidth": "code",
+  "OpDPdxFine": "code",
+  "OpDPdyFine": "code",
+  "OpFwidthFine": "code",
+  "OpDPdxCoarse": "code",
+  "OpDPdyCoarse": "code",
+  "OpFwidthCoarse": "code",
+  "OpEmitVertex": "code",
+  "OpEndPrimitive": "code",
+  "OpEmitStreamVertex": "code",
+  "OpEndStreamPrimitive": "code",
+  "OpControlBarrier": "code",
+  "OpMemoryBarrier": "code",
+  "OpAtomicLoad": "code",
+  "OpAtomicStore": "code",
+  "OpAtomicExchange": "code",
+  "OpAtomicCompareExchange": "code",
+  "OpAtomicCompareExchangeWeak": "code",
+  "OpAtomicIIncrement": "code",
+  "OpAtomicIDecrement": "code",
+  "OpAtomicIAdd": "code",
+  "OpAtomicISub": "code",
+  "OpAtomicSMin": "code",
+  "OpAtomicUMin": "code",
+  "OpAtomicSMax": "code",
+  "OpAtomicUMax": "code",
+  "OpAtomicAnd": "code",
+  "OpAtomicOr": "code",
+  "OpAtomicXor": "code",
+  "OpPhi": "code",
+  "OpLoopMerge": "code",
+  "OpSelectionMerge": "code",
+  "OpLabel": "code",
+  "OpBranch": "code",
+  "OpBranchConditional": "code",
+  "OpSwitch": "code",
+  "OpKill": "code",
+  "OpReturn": "code",
+  "OpReturnValue": "code",
+  "OpUnreachable": "",
+  "OpLifetimeStart": "",
+  "OpLifetimeStop": "",
+  "OpGroupAsyncCopy": "",
+  "OpGroupWaitEvents": "",
+  "OpGroupAll": "",
+  "OpGroupAny": "",
+  "OpGroupBroadcast": "",
+  "OpGroupIAdd": "",
+  "OpGroupFAdd": "",
+  "OpGroupFMin": "",
+  "OpGroupUMin": "",
+  "OpGroupSMin": "",
+  "OpGroupFMax": "",
+  "OpGroupUMax": "",
+  "OpGroupSMax": "",
+  "OpReadPipe": "",
+  "OpWritePipe": "",
+  "OpReservedReadPipe": "",
+  "OpReservedWritePipe": "",
+  "OpReserveReadPipePackets": "",
+  "OpReserveWritePipePackets": "",
+  "OpCommitReadPipe": "",
+  "OpCommitWritePipe": "",
+  "OpIsValidReserveId": "",
+  "OpGetNumPipePackets": "",
+  "OpGetMaxPipePackets": "",
+  "OpGroupReserveReadPipePackets": "",
+  "OpGroupReserveWritePipePackets": "",
+  "OpGroupCommitReadPipe": "",
+  "OpGroupCommitWritePipe": "",
+  "OpEnqueueMarker": "",
+  "OpEnqueueKernel": "",
+  "OpGetKernelNDrangeSubGroupCount": "",
+  "OpGetKernelNDrangeMaxSubGroupSize": "",
+  "OpGetKernelWorkGroupSize": "",
+  "OpGetKernelPreferredWorkGroupSizeMultiple": "",
+  "OpRetainEvent": "",
+  "OpReleaseEvent": "",
+  "OpCreateUserEvent": "",
+  "OpIsValidEvent": "",
+  "OpSetUserEventStatus": "",
+  "OpCaptureEventProfilingInfo": "",
+  "OpGetDefaultQueue": "",
+  "OpBuildNDRange": "",
+  "OpImageSparseSampleImplicitLod": "",
+  "OpImageSparseSampleExplicitLod": "",
+  "OpImageSparseSampleDrefImplicitLod": "",
+  "OpImageSparseSampleDrefExplicitLod": "",
+  "OpImageSparseSampleProjImplicitLod": "",
+  "OpImageSparseSampleProjExplicitLod": "",
+  "OpImageSparseSampleProjDrefImplicitLod": "",
+  "OpImageSparseSampleProjDrefExplicitLod": "",
+  "OpImageSparseFetch": "",
+  "OpImageSparseGather": "",
+  "OpImageSparseDrefGather": "",
+  "OpImageSparseTexelsResident": "",
+  "OpNoLine": "",
+  "OpAtomicFlagTestAndSet": "",
+  "OpAtomicFlagClear": "",
+  "OpImageSparseRead": "",
+  "OpSubgroupBallotKHR": "",
+  "OpSubgroupFirstInvocationKHR": "",
+  "OpSubgroupAllKHR": "",
+  "OpSubgroupAnyKHR": "",
+  "OpSubgroupAllEqualKHR": "",
+  "OpSubgroupReadInvocationKHR": "",
+  "OpGroupIAddNonUniformAMD": "",
+  "OpGroupFAddNonUniformAMD": "",
+  "OpGroupFMinNonUniformAMD": "",
+  "OpGroupUMinNonUniformAMD": "",
+  "OpGroupSMinNonUniformAMD": "",
+  "OpGroupFMaxNonUniformAMD": "",
+  "OpGroupUMaxNonUniformAMD": "",
+  "OpGroupSMaxNonUniformAMD": "",
+  "OpFragmentMaskFetchAMD": "",
+  "OpFragmentFetchAMD": ""
+};
+
+var Operands = {
+  "IdMemorySemantics": { ctype: "guint32", ctype_suffix: "",
+                         optional_unset: "0",
+                         append_many: "g_array_append_vals ({0}, {1}, {2})",
+                         append_one: "g_array_append_val ({0}, {1})" },
+  "IdRef": { ctype: "guint32", ctype_suffix: "",
+             optional_unset: "0",
+             append_many: "g_array_append_vals ({0}, {1}, {2})",
+             append_one: "g_array_append_val ({0}, {1})" },
+  "IdResult": { ctype: "guint32", ctype_suffix: "",
+                optional_unset: "0",
+                declare_local: "guint32 {0}_id = gsk_spv_writer_make_id (writer);",
+                append_one: "g_array_append_val ({0}, {1}_id)" },
+  "IdResultType": { ctype: "GskSlType *", ctype_suffix: "",
+                    optional_unset: "NULL",
+                    declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_type (writer, {0});",
+                    append_one: "g_array_append_val ({0}, {1}_id)" },
+  "IdResultPointerType" : { ctype: "GskSlPointerType *", ctype_suffix: "",
+                            optional_unset: "NULL",
+                            declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_pointer_type (writer, 
{0});",
+                            append_one: "g_array_append_val ({0}, {1}_id)" },
+  "IdScope": { ctype: "guint32", ctype_suffix: "",
+               optional_unset: "0",
+               append_many: "g_array_append_vals ({0}, {1}, {2})",
+               append_one: "g_array_append_val ({0}, {1})" },
+  "LiteralContextDependentNumber": { ctype: "guint32", ctype_suffix: "",
+                                     is_many: true,
+                                     append_many: "g_array_append_vals ({0}, {1}, {2})" },
+  "LiteralExtInstInteger": { ctype: "guint32", ctype_suffix: "",
+                             append_many: "g_array_append_vals ({0}, {1}, {2})",
+                             append_one: "g_array_append_val ({0}, {1})" },
+  "LiteralInteger": { ctype: "guint32", ctype_suffix: "",
+                      append_many: "g_array_append_vals ({0}, {1}, {2})",
+                      append_one: "g_array_append_val ({0}, {1})" },
+  "LiteralString": { ctype: "const char *", ctype_suffix: "",
+                     optional_unset: "NULL",
+                     append_one: "append_string ({0}, {1})" },
+  "LiteralSpecConstantOpInteger": { ctype: "guint32", ctype_suffix: "",
+                                    is_many: true,
+                                    append_many: "g_array_append_vals ({0}, {1}, {2})" },
+  "PairIdRefLiteralInteger": { ctype: "guint32", ctype_suffix: "[2]",
+                               append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
+                               append_one: "g_array_append_vals ({0}, {1}, 2)" },
+  "PairIdRefIdRef": { ctype: "guint32", ctype_suffix: "[2]",
+                      append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
+                      append_one: "g_array_append_vals ({0}, {1}, 2)" },
+  "PairLiteralIntegerIdRef": { ctype: "guint32", ctype_suffix: "[2]",
+                               append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
+                               append_one: "g_array_append_vals ({0}, {1}, 2)" }
+};
+
+for (let kind in spirv.operand_kinds)
+  {
+    kind = spirv.operand_kinds[kind];
+    if (kind.category == "BitEnum" ||
+        kind.category == "ValueEnum")
+      {
+        Operands[kind.kind] = { ctype: "GskSpv" + kind.kind, ctype_suffix: "",
+                                append_one: "g_array_append_val ({0}, (guint32) { {1} })" };
+        if (kind.category == "BitEnum")
+          Operands[kind.kind].optional_unset = "0";
+      }
+  }
+
+function fix_operand (ins, o)
+{
+  if (o.name)
+    {
+      if (o.name == "The name of the opaque type.")
+        o.varname = "name"
+      else
+      o.varname = sanitize_name (o.name);
+    }
+  else
+    {
+      if (o.kind == "IdResultType")
+        o.varname = "result_type"
+      else if (o.kind == "IdResult")
+        o.varname = "result"
+      else if (Operands[o.kind])
+        o.varname = all_lower (o.kind);
+    }
+  if (!o.varname)
+    throw new TypeError (o.name + " of type " + o.kind + " has no variable name");
+  if (o.varname == "default")
+    o.varname += "_";
+  if (o.kind == "IdResult")
+    ins.result = true;
+
+  let operand;
+  if (SpecialTypes[ins.opname] &&
+      SpecialTypes[ins.opname][o.varname])
+    operand = Operands[SpecialTypes[ins.opname][o.varname]];
+  else
+    operand = Operands[o.kind];
+
+  o.ctype = operand.ctype;
+  o.ctype_suffix = operand.ctype_suffix;
+  if (operand.append_one)
+    o.append_one = operand.append_one;
+  if (operand.append_many)
+    o.append_many = operand.append_many;
+  if (operand.declare_local)
+    o.declare_local = operand.declare_local;
+  if (operand.is_many)
+    {
+      if (o.quantifier)
+        throw new SyntaxError ("Can't deal with lists of " + o.kind);
+      else
+        o.quantifier = "*";
+    }
+  if (!o.quantifier)
+    o.quantifier = "";
+  if (o.quantifier == "?")
+    {
+      o.varname = "opt_" + o.varname;
+      if (operand.optional_unset)
+        o.unset = operand.optional_unset;
+    }
+  if (o.quantifier == "*")
+    {
+      if (o.varname[o.varname.length - 1] == "1")
+        o.varname = o.varname.substr(0, o.varname.length - 2);
+      if (o.varname[o.varname.length - 1] != "s")
+        o.varname += "s";
+    }
+}
+
+for (let i in spirv.instructions)
+  {
+    let ins = spirv.instructions[i];
+    ins.result = false;
+    ins.enum_value = "GSK_SPV_OP_" + all_upper (ins.opname.substr(2));
+    if (ins.operands)
+      {
+        for (let o in ins.operands)
+          {
+            o = ins.operands[o];
+            fix_operand (ins, o);
+          }
+      }
+    else
+      ins.operands = [];
+    if (Sections[ins.opname])
+      {
+        ins.section = Sections[ins.opname];
+        ins.section_enum = "GSK_SPV_WRITER_SECTION_" + ins.section.toUpperCase();
+      }
+  }
+
+function header()
+{
+  print ("/* GTK - The GIMP Toolkit");
+  print (" *   ");
+  print (" * Copyright © 2017 Benjamin Otte <otte gnome org>");
+  print (" *");
+  print (" * This library is free software; you can redistribute it and/or");
+  print (" * modify it under the terms of the GNU Lesser General Public");
+  print (" * License as published by the Free Software Foundation; either");
+  print (" * version 2 of the License, or (at your option) any later version.");
+  print (" *");
+  print (" * This library is distributed in the hope that it will be useful,");
+  print (" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
+  print (" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU");
+  print (" * Lesser General Public License for more details.");
+  print (" *");
+  print (" * You should have received a copy of the GNU Lesser General Public");
+  print (" * License along with this library. If not, see <http://www.gnu.org/licenses/>.");
+  print (" */");
+  print ("");
+  print ("/*");
+  print (" * !!! THIS FILE WAS AUTOGENERATED !!!");
+  print (" * ");
+  print (" * This file was created using the command");
+  print (" *   gjs spirv.js " + ARGV.join (" "));
+  print (" * Apply any changes to those files and then regenerate using above command.");
+  print (" */");
+  print ();
+}
+
+if (ARGV[0] == "enums")
+  {
+    header ();
+    print ("#ifndef __GSK_SPV_ENUMS_H__");
+    print ("#define __GSK_SPV_ENUMS_H__");
+    print ();
+
+    for (let kind in spirv.operand_kinds)
+      {
+        kind = spirv.operand_kinds[kind];
+        if (kind.category == "BitEnum" ||
+            kind.category == "ValueEnum")
+          {
+            print ("typedef enum {");
+            for (let i = 0; i < kind.enumerants.length; i++)
+              {
+                let e = kind.enumerants[i];
+                //print (Object.keys(e));
+                print ("  GSK_SPV_" + all_upper(kind.kind) + "_" + all_upper (e.enumerant) + " = " + e.value 
+ (i + 1 < kind.enumerants.length ? "," : ""));
+              }
+            print ("} GskSpv" + kind.kind + ";");
+            print ();
+          }
+      }
+
+    print ("typedef enum {");
+    for (let i =0; i < spirv.instructions.length; i++)
+      {
+        let ins = spirv.instructions[i];
+        print ("  " + ins.enum_value + " = " + ins.opcode + (i + 1 < spirv.instructions.length ? "," : ""));
+      }
+    print ("} GskSpvOpcode;");
+    print ();
+    print ("#endif /* __GSK_SPV_ENUMS_H__ */");
+  }
+else if (ARGV[0] == "functions")
+  {
+    header ();
+    print ("#include <string.h>");
+    print ();
+    print ("static inline void");
+    print ("append_string (GArray     *bytes,");
+    print ("               const char *str)");
+    print ("{");
+    print ("  gsize len = strlen (str);");
+    print ("  guint size = bytes->len;");
+    print ("  g_array_set_size (bytes, size + len / 4 + 1);");
+    print ("  memcpy (&g_array_index (bytes, guint32, size), str, len);");
+    print ("}");
+    print ();
+    for (let i in spirv.instructions)
+      {
+        let ins = spirv.instructions[i];
+        let prefix = "gsk_spv_writer_" + all_lower(ins.opname.substr(2)) + " (";
+        let len = prefix.length;
+        if (ins.result)
+          print ("static inline guint32");
+        else
+          print ("static inline void");
+        if (ins.operands.length > 1 ||
+            ins.operands.length == 1 && !ins.result)
+          {
+            let seen_result = !ins.result;
+            print (prefix + "GskSpvWriter *writer,");
+            if (!ins.section)
+              print (Array(len+1).join(" ") + "GskSpvWriterSection section,");
+            for (let i = 0; i < ins.operands.length; i++)
+              {
+                let o = ins.operands[i];
+                if (o.kind == "IdResult")
+                  {
+                    seen_result = true;
+                    continue;
+                  }
+                if (o.quantifier == "*")
+                  {
+                    print (Array(len+1).join(" ") + o.ctype + " *" + o.varname + o.ctype_suffix + ",")
+                    print (Array(len+1).join(" ") + "gsize n_" + o.varname + (i + 2 - seen_result < 
ins.operands.length ? "," : ")"));
+                  }
+                else
+                  {
+                    print (Array(len+1).join(" ") + o.ctype + " " + o.varname +  o.ctype_suffix + (i + 2 - 
seen_result < ins.operands.length ? "," : ")"));
+                  }
+              }
+          }
+        else
+          {
+            if (ins.section)
+              print ("gsk_spv_writer_" + all_lower(ins.opname.substr(2)) + " (GskSpvWriter *writer)");
+            else
+              {
+                print ("gsk_spv_writer_" + all_lower(ins.opname.substr(2)) + " (GskSpvWriter *writer,");
+                print (Array(len+1).join(" ") + "GskSpvWriterSection section)");
+              }
+          }
+        print ("{");
+        print ("  GArray *bytes = gsk_spv_writer_get_bytes (writer, " + (ins.section_enum ? ins.section_enum 
: "section" ) + ");");
+        for (let i = 0; i < ins.operands.length; i++)
+          {
+            let o = ins.operands[i];
+            if (o.declare_local)
+              print ("  " + o.declare_local.format (o.varname));
+          }
+        print ("  guint start_index = bytes->len;");
+        print ("");
+        print ("  g_array_append_val (bytes, (guint32) { 0 });");
+        for (let i = 0; i < ins.operands.length; i++)
+          {
+            let o = ins.operands[i];
+            let indent = "  ";
+            if (o.unset)
+              {
+                print (indent + "if (" + o.varname + " != " + o.unset + ")");
+                indent += "  ";
+              }
+            if (o.quantifier == "*")
+              print (indent + o.append_many.format ("bytes", o.varname, "n_" + o.varname) + ";");
+            else
+              print (indent + o.append_one.format ("bytes", o.varname) + ";");
+          }
+        print ("  g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | " + 
ins.enum_value + ";");
+        if (ins.result)
+          {
+            print ("");
+            print ("  return result_id;");
+          }
+        print ("}");
+        print ("");
+      }
+  }
+else
+  {
+    usage ()
+  }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]