glsl: add packed for struct types
authorKarol Herbst <kherbst@redhat.com>
Sun, 4 Mar 2018 18:06:24 +0000 (19:06 +0100)
committerKarol Herbst <karolherbst@gmail.com>
Tue, 19 Mar 2019 04:08:07 +0000 (04:08 +0000)
We need this for OpenCL kernels because we have to apply C rules for alignment
and padding inside structs and for this we also have to know if a struct is
packed or not.

v2: fix for kernel params

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
src/compiler/glsl_types.cpp
src/compiler/glsl_types.h
src/compiler/nir_types.cpp
src/compiler/nir_types.h
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_private.h

index e370598663d696007b671f34fc27e3339da07893..899dd16878e76586649dc8d47a9da0f7f7310b34 100644 (file)
@@ -94,11 +94,11 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
 }
 
 glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-                     const char *name) :
+                     const char *name, bool packed) :
    gl_type(0),
    base_type(GLSL_TYPE_STRUCT), sampled_type(GLSL_TYPE_VOID),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   interface_packing(0), interface_row_major(0),
+   interface_packing(0), interface_row_major(0), packed(packed),
    vector_elements(0), matrix_columns(0),
    length(num_fields), explicit_stride(0)
 {
@@ -1129,9 +1129,10 @@ glsl_type::record_key_hash(const void *a)
 const glsl_type *
 glsl_type::get_struct_instance(const glsl_struct_field *fields,
                                unsigned num_fields,
-                               const char *name)
+                               const char *name,
+                               bool packed)
 {
-   const glsl_type key(fields, num_fields, name);
+   const glsl_type key(fields, num_fields, name, packed);
 
    mtx_lock(&glsl_type::hash_mutex);
 
@@ -1143,7 +1144,7 @@ glsl_type::get_struct_instance(const glsl_struct_field *fields,
    const struct hash_entry *entry = _mesa_hash_table_search(struct_types,
                                                             &key);
    if (entry == NULL) {
-      const glsl_type *t = new glsl_type(fields, num_fields, name);
+      const glsl_type *t = new glsl_type(fields, num_fields, name, packed);
 
       entry = _mesa_hash_table_insert(struct_types, t, (void *) t);
    }
@@ -1151,6 +1152,7 @@ glsl_type::get_struct_instance(const glsl_struct_field *fields,
    assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_STRUCT);
    assert(((glsl_type *) entry->data)->length == num_fields);
    assert(strcmp(((glsl_type *) entry->data)->name, name) == 0);
+   assert(((glsl_type *) entry->data)->packed == packed);
 
    mtx_unlock(&glsl_type::hash_mutex);
 
@@ -2447,6 +2449,8 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type)
       if (type->is_interface()) {
          blob_write_uint32(blob, type->interface_packing);
          blob_write_uint32(blob, type->interface_row_major);
+      } else {
+         blob_write_uint32(blob, type->packed);
       }
       return;
    case GLSL_TYPE_VOID:
@@ -2535,7 +2539,8 @@ decode_type_from_blob(struct blob_reader *blob)
          t = glsl_type::get_interface_instance(fields, num_fields, packing,
                                                row_major, name);
       } else {
-         t = glsl_type::get_struct_instance(fields, num_fields, name);
+         unsigned packed = blob_read_uint32(blob);
+         t = glsl_type::get_struct_instance(fields, num_fields, name, packed);
       }
 
       free(fields);
index fc2266bb7389bdd3d2ecbf62c20a41d4f96e1314..fb46c67b84e26c3c5e2daeef88586c9007f7e384 100644 (file)
@@ -176,6 +176,13 @@ struct glsl_type {
    unsigned interface_packing:2;
    unsigned interface_row_major:1;
 
+   /**
+    * For \c GLSL_TYPE_STRUCT this specifies if the struct is packed or not.
+    *
+    * Only used for Compute kernels
+    */
+   unsigned packed:1;
+
 private:
    glsl_type() : mem_ctx(NULL)
    {
@@ -314,7 +321,8 @@ public:
     */
    static const glsl_type *get_struct_instance(const glsl_struct_field *fields,
                                               unsigned num_fields,
-                                              const char *name);
+                                              const char *name,
+                                              bool packed = false);
 
    /**
     * Get the instance of an interface block type
@@ -946,7 +954,7 @@ private:
 
    /** Constructor for record types */
    glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-            const char *name);
+            const char *name, bool packed = false);
 
    /** Constructor for interface types */
    glsl_type(const glsl_struct_field *fields, unsigned num_fields,
index 9101d49ffbb07b019b689efa89b65ec5319441bb..96b824e5141f8f94547e19240096702ada83cc34 100644 (file)
@@ -510,9 +510,10 @@ glsl_array_type(const glsl_type *base, unsigned elements,
 
 const glsl_type *
 glsl_struct_type(const glsl_struct_field *fields,
-                 unsigned num_fields, const char *name)
+                 unsigned num_fields, const char *name,
+                 bool packed)
 {
-   return glsl_type::get_struct_instance(fields, num_fields, name);
+   return glsl_type::get_struct_instance(fields, num_fields, name, packed);
 }
 
 const glsl_type *
index 4d8aada5f27280ad96f98ad8d9a04dcabd82d809..1e8fa33a9aabf87934c09edd679d94f1c9160b72 100644 (file)
@@ -193,7 +193,8 @@ const struct glsl_type *glsl_array_type(const struct glsl_type *base,
                                         unsigned explicit_stride);
 
 const struct glsl_type *glsl_struct_type(const struct glsl_struct_field *fields,
-                                         unsigned num_fields, const char *name);
+                                         unsigned num_fields, const char *name,
+                                         bool packed);
 const struct glsl_type *glsl_interface_type(const struct glsl_struct_field *fields,
                                             unsigned num_fields,
                                             enum glsl_interface_packing packing,
index 3b7f8d8a9ac0f1941975a3b8e4ec00b57b8cd58f..5becd3418da6a9d59529f8aed30dd79d9313b890 100644 (file)
@@ -819,6 +819,13 @@ struct_member_decoration_cb(struct vtn_builder *b,
       break;
 
    case SpvDecorationCPacked:
+      if (b->shader->info.stage != MESA_SHADER_KERNEL)
+         vtn_warn("Decoration only allowed for CL-style kernels: %s",
+                  spirv_decoration_to_string(dec->decoration));
+      else
+         ctx->type->packed = true;
+      break;
+
    case SpvDecorationSaturatedConversion:
    case SpvDecorationFuncParamAttr:
    case SpvDecorationFPRoundingMode:
@@ -979,6 +986,13 @@ type_decoration_cb(struct vtn_builder *b,
       break;
 
    case SpvDecorationCPacked:
+      if (b->shader->info.stage != MESA_SHADER_KERNEL)
+         vtn_warn("Decoration only allowed for CL-style kernels: %s",
+                  spirv_decoration_to_string(dec->decoration));
+      else
+         type->packed = true;
+      break;
+
    case SpvDecorationSaturatedConversion:
    case SpvDecorationFuncParamAttr:
    case SpvDecorationFPRoundingMode:
@@ -1242,6 +1256,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
       val->type->length = num_fields;
       val->type->members = ralloc_array(b, struct vtn_type *, num_fields);
       val->type->offsets = ralloc_array(b, unsigned, num_fields);
+      val->type->packed = false;
 
       NIR_VLA(struct glsl_struct_field, fields, count);
       for (unsigned i = 0; i < num_fields; i++) {
@@ -1266,7 +1281,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
 
       const char *name = val->name ? val->name : "struct";
 
-      val->type->type = glsl_struct_type(fields, num_fields, name);
+      val->type->type = glsl_struct_type(fields, num_fields, name, false);
       break;
    }
 
index bdf326c26f73018b119b56645f87a3189a9aff2e..20aedc170d91a928627a8b4f482aef4c2c1e8f39 100644 (file)
@@ -335,6 +335,13 @@ struct vtn_type {
           * (i.e. a block that contains only builtins).
           */
          bool builtin_block:1;
+
+         /* for structs and unions it specifies the minimum alignment of the
+          * members. 0 means packed.
+          *
+          * Set by CPacked and Alignment Decorations in kernels.
+          */
+         bool packed:1;
       };
 
       /* Members for pointer types */