spirv: Hand-roll fewer vtn_ssa_value creations
[mesa.git] / src / compiler / spirv / vtn_variables.c
index aad07d7556ddee3cf3ebdc734f8d576f8478f23d..d2e9f07ebfe06d8c5171d6cc070cced0ffa87d50 100644 (file)
@@ -68,51 +68,14 @@ vtn_decorate_pointer(struct vtn_builder *b, struct vtn_value *val,
 }
 
 struct vtn_value *
-vtn_push_value_pointer(struct vtn_builder *b, uint32_t value_id,
-                       struct vtn_pointer *ptr)
+vtn_push_pointer(struct vtn_builder *b, uint32_t value_id,
+                 struct vtn_pointer *ptr)
 {
    struct vtn_value *val = vtn_push_value(b, value_id, vtn_value_type_pointer);
    val->pointer = vtn_decorate_pointer(b, val, ptr);
    return val;
 }
 
-static void
-ssa_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
-                  const struct vtn_decoration *dec, void *void_ctx)
-{
-   switch (dec->decoration) {
-   case SpvDecorationNonUniformEXT:
-      if (val->value_type == vtn_value_type_ssa) {
-         val->ssa->access |= ACCESS_NON_UNIFORM;
-      } else if (val->value_type == vtn_value_type_pointer) {
-         val->pointer->access |= ACCESS_NON_UNIFORM;
-      } else if (val->value_type == vtn_value_type_sampled_image) {
-         val->sampled_image->image->access |= ACCESS_NON_UNIFORM;
-      } else if (val->value_type == vtn_value_type_image_pointer) {
-         val->image->image->access |= ACCESS_NON_UNIFORM;
-      }
-      break;
-
-   default:
-      break;
-   }
-}
-
-struct vtn_value *
-vtn_push_ssa(struct vtn_builder *b, uint32_t value_id,
-             struct vtn_type *type, struct vtn_ssa_value *ssa)
-{
-   struct vtn_value *val;
-   if (type->base_type == vtn_base_type_pointer) {
-      val = vtn_push_value_pointer(b, value_id, vtn_pointer_from_ssa(b, ssa->def, type));
-   } else {
-      val = vtn_push_value(b, value_id, vtn_value_type_ssa);
-      val->ssa = ssa;
-      vtn_foreach_decoration(b, val, ssa_decoration_cb, NULL);
-   }
-   return val;
-}
-
 void
 vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,
                uint32_t dst_value_id)
@@ -129,7 +92,8 @@ vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,
    src_copy.type = dst->type;
    *dst = src_copy;
 
-   vtn_foreach_decoration(b, dst, ssa_decoration_cb, NULL);
+   if (dst->value_type == vtn_value_type_pointer)
+      dst->pointer = vtn_decorate_pointer(b, dst, dst->pointer);
 }
 
 static struct vtn_access_chain *
@@ -908,9 +872,6 @@ _vtn_block_load_store(struct vtn_builder *b, nir_intrinsic_op op, bool load,
                       struct vtn_type *type, enum gl_access_qualifier access,
                       struct vtn_ssa_value **inout)
 {
-   if (load && *inout == NULL)
-      *inout = vtn_create_ssa_value(b, type->type);
-
    enum glsl_base_type base_type = glsl_get_base_type(type->type);
    switch (base_type) {
    case GLSL_TYPE_UINT:
@@ -1065,7 +1026,7 @@ vtn_block_load(struct vtn_builder *b, struct vtn_pointer *src)
    nir_ssa_def *offset, *index = NULL;
    offset = vtn_pointer_to_offset(b, src, &index);
 
-   struct vtn_ssa_value *value = NULL;
+   struct vtn_ssa_value *value = vtn_create_ssa_value(b, src->type->type);
    _vtn_block_load_store(b, op, true, index, offset,
                          access_offset, access_size,
                          src->type, src->access, &value);
@@ -1129,7 +1090,6 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load,
              * deref.
              */
             if (load) {
-               *inout = vtn_create_ssa_value(b, ptr->type->type);
                (*inout)->def = nir_load_deref_with_access(&b->nb, deref,
                                                           ptr->type->access | access);
             } else {
@@ -1151,13 +1111,6 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load,
    case GLSL_TYPE_ARRAY:
    case GLSL_TYPE_STRUCT: {
       unsigned elems = glsl_get_length(ptr->type->type);
-      if (load) {
-         vtn_assert(*inout == NULL);
-         *inout = rzalloc(b, struct vtn_ssa_value);
-         (*inout)->type = ptr->type->type;
-         (*inout)->elems = rzalloc_array(b, struct vtn_ssa_value *, elems);
-      }
-
       struct vtn_access_chain chain = {
          .length = 1,
          .link = {
@@ -1184,7 +1137,7 @@ vtn_variable_load(struct vtn_builder *b, struct vtn_pointer *src)
    if (vtn_pointer_uses_ssa_offset(b, src)) {
       return vtn_block_load(b, src);
    } else {
-      struct vtn_ssa_value *val = NULL;
+      struct vtn_ssa_value *val = vtn_create_ssa_value(b, src->type->type);
       _vtn_variable_load_store(b, true, src, src->access, &val);
       return val;
    }
@@ -1354,22 +1307,10 @@ vtn_get_builtin_location(struct vtn_builder *b,
          vtn_fail("invalid stage for SpvBuiltInViewportIndex");
       break;
    case SpvBuiltInTessLevelOuter:
-      if (b->options && b->options->tess_levels_are_sysvals &&
-          *mode == nir_var_shader_in) {
-         *location = SYSTEM_VALUE_TESS_LEVEL_OUTER;
-         set_mode_system_value(b, mode);
-      } else {
-         *location = VARYING_SLOT_TESS_LEVEL_OUTER;
-      }
+      *location = VARYING_SLOT_TESS_LEVEL_OUTER;
       break;
    case SpvBuiltInTessLevelInner:
-      if (b->options && b->options->tess_levels_are_sysvals &&
-          *mode == nir_var_shader_in) {
-         *location = SYSTEM_VALUE_TESS_LEVEL_INNER;
-         set_mode_system_value(b, mode);
-      } else {
-         *location = VARYING_SLOT_TESS_LEVEL_INNER;
-      }
+      *location = VARYING_SLOT_TESS_LEVEL_INNER;
       break;
    case SpvBuiltInTessCoord:
       *location = SYSTEM_VALUE_TESS_COORD;
@@ -1595,6 +1536,9 @@ apply_var_decoration(struct vtn_builder *b,
    case SpvDecorationRestrict:
       var_data->access |= ACCESS_RESTRICT;
       break;
+   case SpvDecorationAliased:
+      var_data->access &= ~ACCESS_RESTRICT;
+      break;
    case SpvDecorationVolatile:
       var_data->access |= ACCESS_VOLATILE;
       break;
@@ -1617,11 +1561,6 @@ apply_var_decoration(struct vtn_builder *b,
       switch (builtin) {
       case SpvBuiltInTessLevelOuter:
       case SpvBuiltInTessLevelInner:
-         /* Since the compact flag is only valid on arrays, don't set it if
-          * we are lowering TessLevelInner/Outer to vec4/vec2. */
-         if (!b->options || !b->options->lower_tess_levels_to_vec)
-            var_data->compact = true;
-         break;
       case SpvBuiltInClipDistance:
       case SpvBuiltInCullDistance:
          var_data->compact = true;
@@ -1635,7 +1574,6 @@ apply_var_decoration(struct vtn_builder *b,
    case SpvDecorationRowMajor:
    case SpvDecorationColMajor:
    case SpvDecorationMatrixStride:
-   case SpvDecorationAliased:
    case SpvDecorationUniform:
    case SpvDecorationUniformId:
    case SpvDecorationLinkageAttributes:
@@ -1833,22 +1771,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    }
 }
 
-static void
-var_decoration_tess_level_vec_cb(
-      struct vtn_builder *b, struct vtn_value *val, int member,
-      const struct vtn_decoration *dec, void *void_var)
-{
-   struct vtn_variable *vtn_var = void_var;
-   if (dec->decoration == SpvDecorationBuiltIn) {
-      SpvBuiltIn builtin = dec->operands[0];
-      if (builtin == SpvBuiltInTessLevelOuter) {
-         vtn_var->var->type = glsl_vector_type(GLSL_TYPE_FLOAT, 4);
-      } else if (builtin == SpvBuiltInTessLevelInner) {
-         vtn_var->var->type = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
-      }
-   }
-}
-
 enum vtn_variable_mode
 vtn_storage_class_to_mode(struct vtn_builder *b,
                           SpvStorageClass class,
@@ -2425,12 +2347,15 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
    if (var_initializer)
       var->var->pointer_initializer = var_initializer;
 
+   if (var->mode == vtn_variable_mode_uniform ||
+       var->mode == vtn_variable_mode_ssbo) {
+      /* SSBOs and images are assumed to not alias in the Simple, GLSL and Vulkan memory models */
+      var->var->data.access |= b->mem_model != SpvMemoryModelOpenCL ? ACCESS_RESTRICT : 0;
+   }
+
    vtn_foreach_decoration(b, val, var_decoration_cb, var);
    vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
 
-   if (b->options && b->options->lower_tess_levels_to_vec)
-      vtn_foreach_decoration(b, val, var_decoration_tess_level_vec_cb, var);
-
    /* Propagate access flags from the OpVariable decorations. */
    val->pointer->access |= var->access;
 
@@ -2541,12 +2466,12 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
    switch (opcode) {
    case SpvOpUndef: {
       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);
-      val->type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      val->type = vtn_get_type(b, w[1]);
       break;
    }
 
    case SpvOpVariable: {
-      struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      struct vtn_type *ptr_type = vtn_get_type(b, w[1]);
 
       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);
 
@@ -2591,11 +2516,10 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
             chain->link[idx].mode = vtn_access_mode_id;
             chain->link[idx].id = w[i];
          }
-         access |= vtn_value_access(link_val);
          idx++;
       }
 
-      struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      struct vtn_type *ptr_type = vtn_get_type(b, w[1]);
       struct vtn_value *base_val = vtn_untyped_value(b, w[3]);
       if (base_val->value_type == vtn_value_type_sampled_image) {
          /* This is rather insane.  SPIR-V allows you to use OpSampledImage
@@ -2621,7 +2545,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
             vtn_pointer_dereference(b, base_val->pointer, chain);
          ptr->ptr_type = ptr_type;
          ptr->access |= access;
-         vtn_push_value_pointer(b, w[2], ptr);
+         vtn_push_pointer(b, w[2], ptr);
       }
       break;
    }
@@ -2637,8 +2561,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
    }
 
    case SpvOpLoad: {
-      struct vtn_type *res_type =
-         vtn_value(b, w[1], vtn_value_type_type)->type;
+      struct vtn_type *res_type = vtn_get_type(b, w[1]);
       struct vtn_value *src_val = vtn_value(b, w[3], vtn_value_type_pointer);
       struct vtn_pointer *src = src_val->pointer;
 
@@ -2646,7 +2569,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
 
       if (res_type->base_type == vtn_base_type_image ||
           res_type->base_type == vtn_base_type_sampler) {
-         vtn_push_value_pointer(b, w[2], src);
+         vtn_push_pointer(b, w[2], src);
          return;
       } else if (res_type->base_type == vtn_base_type_sampled_image) {
          struct vtn_value *val =
@@ -2673,7 +2596,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
          }
       }
 
-      vtn_push_ssa(b, w[2], res_type, vtn_variable_load(b, src));
+      vtn_push_ssa_value(b, w[2], vtn_variable_load(b, src));
       break;
    }
 
@@ -2787,48 +2710,46 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
                            nir_imm_int(&b->nb, 0u)),
                   nir_imm_int(&b->nb, stride));
 
-      struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
-      val->ssa = vtn_create_ssa_value(b, glsl_uint_type());
-      val->ssa->def = array_length;
+      vtn_push_nir_ssa(b, w[2], array_length);
       break;
    }
 
    case SpvOpConvertPtrToU: {
-      struct vtn_value *u_val = vtn_push_value(b, w[2], vtn_value_type_ssa);
+      struct vtn_type *u_type = vtn_get_type(b, w[1]);
+      struct vtn_type *ptr_type = vtn_get_value_type(b, w[3]);
+
+      vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer ||
+                  ptr_type->type == NULL,
+                  "OpConvertPtrToU can only be used on physical pointers");
 
-      vtn_fail_if(u_val->type->base_type != vtn_base_type_vector &&
-                  u_val->type->base_type != vtn_base_type_scalar,
+      vtn_fail_if(u_type->base_type != vtn_base_type_vector &&
+                  u_type->base_type != vtn_base_type_scalar,
                   "OpConvertPtrToU can only be used to cast to a vector or "
                   "scalar type");
 
       /* The pointer will be converted to an SSA value automatically */
-      struct vtn_ssa_value *ptr_ssa = vtn_ssa_value(b, w[3]);
-
-      u_val->ssa = vtn_create_ssa_value(b, u_val->type->type);
-      u_val->ssa->def = nir_sloppy_bitcast(&b->nb, ptr_ssa->def, u_val->type->type);
-      u_val->ssa->access |= ptr_ssa->access;
+      nir_ssa_def *ptr = vtn_get_nir_ssa(b, w[3]);
+      nir_ssa_def *u = nir_sloppy_bitcast(&b->nb, ptr, u_type->type);
+      vtn_push_nir_ssa(b, w[2], u);
       break;
    }
 
    case SpvOpConvertUToPtr: {
-      struct vtn_value *ptr_val =
-         vtn_push_value(b, w[2], vtn_value_type_pointer);
-      struct vtn_value *u_val = vtn_untyped_value(b, w[3]);
+      struct vtn_type *ptr_type = vtn_get_type(b, w[1]);
+      struct vtn_type *u_type = vtn_get_value_type(b, w[3]);
 
-      vtn_fail_if(ptr_val->type->type == NULL,
+      vtn_fail_if(ptr_type->base_type != vtn_base_type_pointer ||
+                  ptr_type->type == NULL,
                   "OpConvertUToPtr can only be used on physical pointers");
 
-      vtn_fail_if(u_val->type->base_type != vtn_base_type_vector &&
-                  u_val->type->base_type != vtn_base_type_scalar,
+      vtn_fail_if(u_type->base_type != vtn_base_type_vector &&
+                  u_type->base_type != vtn_base_type_scalar,
                   "OpConvertUToPtr can only be used to cast from a vector or "
                   "scalar type");
 
-      struct vtn_ssa_value *u_ssa = vtn_ssa_value(b, w[3]);
-      nir_ssa_def *ptr_ssa = nir_sloppy_bitcast(&b->nb, u_ssa->def,
-                                                ptr_val->type->type);
-      ptr_val->pointer = vtn_pointer_from_ssa(b, ptr_ssa, ptr_val->type);
-      vtn_foreach_decoration(b, ptr_val, ptr_decoration_cb, ptr_val->pointer);
-      ptr_val->pointer->access |= u_val->ssa->access;
+      nir_ssa_def *u = vtn_get_nir_ssa(b, w[3]);
+      nir_ssa_def *ptr = nir_sloppy_bitcast(&b->nb, u, ptr_type->type);
+      vtn_push_pointer(b, w[2], vtn_pointer_from_ssa(b, ptr, ptr_type));
       break;
    }