[Mesa-dev] [PATCH v3 03/19] glsl: add packed for struct types
Karol Herbst
kherbst at redhat.com
Fri Mar 23 19:33:40 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 a73caa908bf..12a8a546938 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -90,11 +90,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)
{
@@ -1131,9 +1131,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);
@@ -1145,7 +1146,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);
}
@@ -1153,6 +1154,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);
@@ -2262,6 +2264,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:
@@ -2341,7 +2345,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 6982d52e392..34d03505ae8 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -164,6 +164,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)
{
@@ -286,7 +293,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
@@ -867,7 +875,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 ee6b06aea63..76a9cf2fde7 100644
--- a/src/compiler/nir_types.cpp
+++ b/src/compiler/nir_types.cpp
@@ -385,9 +385,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 5b441af1486..8687d4f1336 100644
--- a/src/compiler/nir_types.h
+++ b/src/compiler/nir_types.h
@@ -161,7 +161,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 edf02db584b..334bcab9a82 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -739,6 +739,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:
@@ -1107,6 +1114,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++) {
@@ -1130,7 +1138,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 9f5a22905f1..bd273122703 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -322,6 +322,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.14.3
More information about the mesa-dev
mailing list