From 0019d6152749fab000c12daf4d3c7b0d4fba2caf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alejandro=20Pi=C3=B1eiro?= Date: Wed, 16 Jan 2019 16:50:29 +0100 Subject: [PATCH] glsl/nir: add glsl_types::explicit_size plus nir C wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit While using SPIR-V shaders (ARB_gl_spirv), layout data is not implicit to a specific value (std140, std430, etc) but explicitly included on the type (explicit values for offset, stride and row_major). So this method is equivalent to the existing std140_size and std430_size, but using such explicit values. Note that the value returned by this method is only valid if such data is set, so when dealing with SPIR-V shaders. v2: (all changes suggested by Jason Ekstrand) * Iterate through all struct members, instead of assume that fields are ordered by offset * Use else if * Take into account the case that explicit_stride > elem_size, to fine graine the final size on arrays and matrices * Handle different bit-sizes in general, not just 32 and 64. v3: (change suggested by Caio Marcelo de Oliveira Filho) * fix up explicit_size() to consider interface types Signed-off-by: Alejandro Piñeiro Signed-off-by: Antia Puentes Signed-off-by: Neil Roberts Reviewed-by: Timothy Arceri Reviewed-by: Caio Marcelo de Oliveira Filho --- src/compiler/glsl_types.cpp | 68 +++++++++++++++++++++++++++++++++++++ src/compiler/glsl_types.h | 13 +++++++ src/compiler/nir_types.cpp | 6 ++++ src/compiler/nir_types.h | 2 ++ 4 files changed, 89 insertions(+) diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index ded355ee308..123a8e40255 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/glsl_types.cpp @@ -2124,6 +2124,74 @@ glsl_type::std430_array_stride(bool row_major) const return stride; } +/* Note that the value returned by this method is only correct if the + * explit offset, and stride values are set, so only with SPIR-V shaders. + * Should not be used with GLSL shaders. + */ + +unsigned +glsl_type::explicit_size(bool align_to_stride) const +{ + if (this->is_struct() || this->is_interface()) { + if (this->length > 0) { + unsigned size = 0; + + for (unsigned i = 0; i < this->length; i++) { + assert(this->fields.structure[i].offset >= 0); + unsigned last_byte = this->fields.structure[i].offset + + this->fields.structure[i].type->explicit_size(); + size = MAX2(size, last_byte); + } + + return size; + } else { + return 0; + } + } else if (this->is_array()) { + /* From ARB_program_interface_query spec: + * + * "For the property of BUFFER_DATA_SIZE, then the implementation-dependent + * minimum total buffer object size, in basic machine units, required to + * hold all active variables associated with an active uniform block, shader + * storage block, or atomic counter buffer is written to . If the + * final member of an active shader storage block is array with no declared + * size, the minimum buffer size is computed assuming the array was declared + * as an array with one element." + * + */ + if (this->is_unsized_array()) + return this->explicit_stride; + + assert(this->length > 0); + unsigned elem_size = align_to_stride ? this->explicit_stride : this->fields.array->explicit_size(); + assert(this->explicit_stride >= elem_size); + + return this->explicit_stride * (this->length - 1) + elem_size; + } else if (this->is_matrix()) { + const struct glsl_type *elem_type; + unsigned length; + + if (this->interface_row_major) { + elem_type = get_instance(this->base_type, + this->matrix_columns, 1); + length = this->vector_elements; + } else { + elem_type = get_instance(this->base_type, + this->vector_elements, 1); + length = this->matrix_columns; + } + + unsigned elem_size = align_to_stride ? this->explicit_stride : elem_type->explicit_size(); + + assert(this->explicit_stride); + return this->explicit_stride * (length - 1) + elem_size; + } + + unsigned N = this->bit_size() / 8; + + return this->vector_elements * N; +} + unsigned glsl_type::std430_size(bool row_major) const { diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index 1e550986e47..3fd49a759c6 100644 --- a/src/compiler/glsl_types.h +++ b/src/compiler/glsl_types.h @@ -543,6 +543,19 @@ public: */ unsigned cl_size() const; + /** + * Size in bytes of this type based on its explicit data. + * + * When using SPIR-V shaders (ARB_gl_spirv), memory layouts are expressed + * through explicit offset, stride and matrix layout, so the size + * can/should be computed used those values. + * + * Note that the value returned by this method is only correct if such + * values are set, so only with SPIR-V shaders. Should not be used with + * GLSL shaders. + */ + unsigned explicit_size(bool align_to_stride=false) const; + /** * \brief Can this type be implicitly converted to another? * diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp index e2dfc40ff0b..69f89a7fd74 100644 --- a/src/compiler/nir_types.cpp +++ b/src/compiler/nir_types.cpp @@ -721,3 +721,9 @@ glsl_type_get_image_count(const struct glsl_type *type) return 0; } + +unsigned +glsl_get_explicit_size(const struct glsl_type *type, bool align_to_stride) +{ + return type->explicit_size(align_to_stride); +} diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h index 7bcf4c08f4c..806ba824084 100644 --- a/src/compiler/nir_types.h +++ b/src/compiler/nir_types.h @@ -102,6 +102,8 @@ int glsl_get_cl_size(const struct glsl_type *type); int glsl_get_cl_alignment(const struct glsl_type *type); +unsigned glsl_get_explicit_size(const struct glsl_type *type, bool align_to_stride); + static inline unsigned glsl_get_bit_size(const struct glsl_type *type) { -- 2.30.2