From 659f333b3a4ff92ff985b168728ad37fe3d7e437 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 4 Mar 2018 19:06:24 +0100 Subject: [PATCH] glsl: add packed for struct types 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 Reviewed-by: Erik Faye-Lund --- 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 | 17 ++++++++++++++++- src/compiler/spirv/vtn_private.h | 7 +++++++ 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index e370598663d..899dd16878e 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/glsl_types.cpp @@ -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); diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index fc2266bb738..fb46c67b84e 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) { @@ -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, diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp index 9101d49ffbb..96b824e5141 100644 --- a/src/compiler/nir_types.cpp +++ b/src/compiler/nir_types.cpp @@ -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 * diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h index 4d8aada5f27..1e8fa33a9aa 100644 --- a/src/compiler/nir_types.h +++ b/src/compiler/nir_types.h @@ -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, diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 3b7f8d8a9ac..5becd3418da 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -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; } diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index bdf326c26f7..20aedc170d9 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.30.2