[Mesa-dev] [PATCH 07/22] glsl: add packed for struct types

Karol Herbst kherbst at redhat.com
Tue Nov 13 15:48:11 UTC 2018


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.

Signed-off-by: Karol Herbst <kherbst at redhat.com>
---
 src/compiler/glsl_types.cpp       | 17 +++++++++++------
 src/compiler/glsl_types.h         | 12 ++++++++++--
 src/compiler/nir_types.cpp        |  5 +++--
 src/compiler/nir_types.h          |  3 ++-
 src/compiler/spirv/spirv_to_nir.c | 10 +++++++++-
 src/compiler/spirv/vtn_private.h  |  7 +++++++
 6 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp
index e6262371bd0..9b1fd809b41 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -91,11 +91,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)
 {
@@ -1004,9 +1004,10 @@ glsl_type::record_key_hash(const void *a)
 const glsl_type *
 glsl_type::get_record_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);
 
@@ -1018,7 +1019,7 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
    const struct hash_entry *entry = _mesa_hash_table_search(record_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(record_types, t, (void *) t);
    }
@@ -1026,6 +1027,7 @@ glsl_type::get_record_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);
 
@@ -2138,6 +2140,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:
@@ -2217,7 +2221,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_record_instance(fields, num_fields, name);
+         unsigned packed = blob_read_uint32(blob);
+         t = glsl_type::get_record_instance(fields, num_fields, name, packed);
       }
 
       free(fields);
diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h
index d32b580acc1..f2163728610 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -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)
    {
@@ -299,7 +306,8 @@ public:
     */
    static const glsl_type *get_record_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
@@ -888,7 +896,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,
diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp
index 3cd61f66056..506dabdeb1d 100644
--- a/src/compiler/nir_types.cpp
+++ b/src/compiler/nir_types.cpp
@@ -439,9 +439,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_record_instance(fields, num_fields, name);
+   return glsl_type::get_record_instance(fields, num_fields, name, packed);
 }
 
 const glsl_type *
diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h
index 70d593b96ab..7080a23e1cc 100644
--- a/src/compiler/nir_types.h
+++ b/src/compiler/nir_types.h
@@ -173,7 +173,8 @@ const struct glsl_type *glsl_matrix_type(enum glsl_base_type base_type,
 const struct glsl_type *glsl_array_type(const struct glsl_type *base,
                                         unsigned elements);
 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,
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index 650eb6a977c..d7dd5a67cc4 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -780,6 +780,13 @@ struct_member_decoration_cb(struct vtn_builder *b,
       break;
 
    case SpvDecorationCPacked:
+      if (!b->kernel_mode)
+         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:
@@ -1159,6 +1166,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++) {
@@ -1182,7 +1190,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;
    }
 
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index df6356f50fe..d7d5b8db198 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -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 */
-- 
2.19.1



More information about the mesa-dev mailing list