nir/spirv: Use real pointer types
authorJason Ekstrand <jason@jlekstrand.net>
Thu, 29 Jun 2017 17:33:39 +0000 (10:33 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 5 Jul 2017 22:26:55 +0000 (15:26 -0700)
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_cfg.c
src/compiler/spirv/vtn_private.h
src/compiler/spirv/vtn_variables.c

index cc3ba0d003a4264b4038283ce9e0e8b14facf374..462b0494f96beddab6684baf3404b787e03c6525 100644 (file)
@@ -421,6 +421,7 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
    case vtn_base_type_vector:
    case vtn_base_type_matrix:
    case vtn_base_type_array:
+   case vtn_base_type_pointer:
    case vtn_base_type_image:
    case vtn_base_type_sampler:
       /* Nothing more to do */
@@ -858,13 +859,17 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
       break;
    }
 
-   case SpvOpTypePointer:
-      /* FIXME:  For now, we'll just do the really lame thing and return
-       * the same type.  The validator should ensure that the proper number
-       * of dereferences happen
-       */
-      val->type = vtn_value(b, w[3], vtn_value_type_type)->type;
+   case SpvOpTypePointer: {
+      SpvStorageClass storage_class = w[2];
+      struct vtn_type *deref_type =
+         vtn_value(b, w[3], vtn_value_type_type)->type;
+
+      val->type->base_type = vtn_base_type_pointer;
+      val->type->type = NULL;
+      val->type->storage_class = storage_class;
+      val->type->deref = deref_type;
       break;
+   }
 
    case SpvOpTypeImage: {
       val->type->base_type = vtn_base_type_image;
@@ -956,6 +961,12 @@ vtn_null_constant(struct vtn_builder *b, const struct glsl_type *type)
 {
    nir_constant *c = rzalloc(b, nir_constant);
 
+   /* For pointers and other typeless things, we have to return something but
+    * it doesn't matter what.
+    */
+   if (!type)
+      return c;
+
    switch (glsl_get_base_type(type)) {
    case GLSL_TYPE_INT:
    case GLSL_TYPE_UINT:
index 7158b32cf98fcd8eff67b1ae23ab4bd533983994..c1677b49aaa560c29ebeddbfd25d0beb75fcce23 100644 (file)
@@ -52,7 +52,11 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
       func->num_params = func_type->length;
       func->params = ralloc_array(b->shader, nir_parameter, func->num_params);
       for (unsigned i = 0; i < func->num_params; i++) {
-         func->params[i].type = func_type->params[i]->type;
+         if (func_type->params[i]->base_type == vtn_base_type_pointer) {
+            func->params[i].type = func_type->params[i]->deref->type;
+         } else {
+            func->params[i].type = func_type->params[i]->type;
+         }
 
          /* TODO: We could do something smarter here. */
          func->params[i].param_type = nir_parameter_inout;
@@ -73,11 +77,15 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
 
    case SpvOpFunctionParameter: {
       struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      if (type->base_type == vtn_base_type_pointer) {
+         type = type->deref;
+         assert(type->base_type != vtn_base_type_pointer);
+      }
 
       assert(b->func_param_idx < b->func->impl->num_params);
       nir_variable *param = b->func->impl->params[b->func_param_idx++];
 
-      assert(param->type == type->type);
+      assert(type->type == param->type);
 
       struct vtn_variable *vtn_var = rzalloc(b, struct vtn_variable);
       vtn_var->type = type;
@@ -102,7 +110,7 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
       /* Name the parameter so it shows up nicely in NIR */
       param->name = ralloc_strdup(param, val->name);
 
-      val->pointer = vtn_pointer_for_variable(b, vtn_var);
+      val->pointer = vtn_pointer_for_variable(b, vtn_var, NULL);
       break;
    }
 
index b43b013d523a97e5170bef74462ecdf18a90c912..7cb503568fe99e399175a6d5cb30cc32ba7aef68 100644 (file)
@@ -203,6 +203,7 @@ enum vtn_base_type {
    vtn_base_type_matrix,
    vtn_base_type_array,
    vtn_base_type_struct,
+   vtn_base_type_pointer,
    vtn_base_type_image,
    vtn_base_type_sampler,
    vtn_base_type_function,
@@ -260,6 +261,15 @@ struct vtn_type {
          bool builtin_block:1;
       };
 
+      /* Members for pointer types */
+      struct {
+         /* For pointers, the vtn_type for dereferenced type */
+         struct vtn_type *deref;
+
+         /* Storage class for pointers */
+         SpvStorageClass storage_class;
+      };
+
       /* Members for image types */
       struct {
          /* For images, indicates whether it's sampled or storage */
@@ -327,6 +337,14 @@ struct vtn_pointer {
    /** The dereferenced type of this pointer */
    struct vtn_type *type;
 
+   /** The pointer type of this pointer
+    *
+    * This may be NULL for some temporary pointers constructed as part of a
+    * large load, store, or copy.  It MUST be valid for all pointers which are
+    * stored as SPIR-V SSA values.
+    */
+   struct vtn_type *ptr_type;
+
    /** The referenced variable, if known
     *
     * This field may be NULL if the pointer uses a (block_index, offset) pair
@@ -529,7 +547,8 @@ nir_ssa_def *vtn_vector_insert_dynamic(struct vtn_builder *b, nir_ssa_def *src,
 nir_deref_var *vtn_nir_deref(struct vtn_builder *b, uint32_t id);
 
 struct vtn_pointer *vtn_pointer_for_variable(struct vtn_builder *b,
-                                             struct vtn_variable *var);
+                                             struct vtn_variable *var,
+                                             struct vtn_type *ptr_type);
 
 nir_deref_var *vtn_pointer_to_deref(struct vtn_builder *b,
                                     struct vtn_pointer *ptr);
index 1d13c779babf87dd8d6bb7b343c4008bb506fbac..1ff7427ffb9c4737f389223a59dfe757df1d95fa 100644 (file)
@@ -227,12 +227,13 @@ rewrite_deref_types(nir_deref *deref, const struct glsl_type *type)
 
 struct vtn_pointer *
 vtn_pointer_for_variable(struct vtn_builder *b,
-                         struct vtn_variable *var)
+                         struct vtn_variable *var, struct vtn_type *ptr_type)
 {
    struct vtn_pointer *pointer = rzalloc(b, struct vtn_pointer);
 
    pointer->mode = var->mode;
    pointer->type = var->type;
+   pointer->ptr_type = ptr_type;
    pointer->var = var;
 
    return pointer;
@@ -1470,9 +1471,13 @@ is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage stage)
 
 static void
 vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
-                    struct vtn_type *type, SpvStorageClass storage_class,
+                    struct vtn_type *ptr_type, SpvStorageClass storage_class,
                     nir_constant *initializer)
 {
+   assert(ptr_type->base_type == vtn_base_type_pointer);
+   struct vtn_type *type = ptr_type->deref;
+   assert(type->base_type != vtn_base_type_pointer);
+
    struct vtn_type *without_array = type;
    while(glsl_type_is_array(without_array->type))
       without_array = without_array->array_element;
@@ -1507,7 +1512,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
    var->mode = mode;
 
    assert(val->value_type == vtn_value_type_pointer);
-   val->pointer = vtn_pointer_for_variable(b, var);
+   val->pointer = vtn_pointer_for_variable(b, var, ptr_type);
 
    switch (var->mode) {
    case vtn_variable_mode_local:
@@ -1674,7 +1679,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
    }
 
    case SpvOpVariable: {
-      struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
 
       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);
 
@@ -1683,7 +1688,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
       if (count > 4)
          initializer = vtn_value(b, w[4], vtn_value_type_constant)->constant;
 
-      vtn_create_variable(b, val, type, storage_class, initializer);
+      vtn_create_variable(b, val, ptr_type, storage_class, initializer);
       break;
    }
 
@@ -1705,6 +1710,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
          idx++;
       }
 
+      struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
       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
@@ -1725,6 +1731,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
          struct vtn_value *val =
             vtn_push_value(b, w[2], vtn_value_type_pointer);
          val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain);
+         val->pointer->ptr_type = ptr_type;
       }
       break;
    }