diff options
author | Alejandro Piñeiro <[email protected]> | 2019-01-16 16:50:29 +0100 |
---|---|---|
committer | Arcady Goldmints-Orlov <[email protected]> | 2019-06-30 16:58:26 -0500 |
commit | 0019d6152749fab000c12daf4d3c7b0d4fba2caf (patch) | |
tree | 2823fd65795032fe1cdba076ef92906c3f2f14b0 | |
parent | c23522add233301f10cd7ca2d2570f10b1184815 (diff) |
glsl/nir: add glsl_types::explicit_size plus nir C wrapper
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 <[email protected]>
Signed-off-by: Antia Puentes <[email protected]>
Signed-off-by: Neil Roberts <[email protected]>
Reviewed-by: Timothy Arceri <[email protected]>
Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]>
-rw-r--r-- | src/compiler/glsl_types.cpp | 68 | ||||
-rw-r--r-- | src/compiler/glsl_types.h | 13 | ||||
-rw-r--r-- | src/compiler/nir_types.cpp | 6 | ||||
-rw-r--r-- | src/compiler/nir_types.h | 2 |
4 files changed, 89 insertions, 0 deletions
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 <params>. 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 @@ -544,6 +544,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? * * \return True if the types are identical or if this type can be converted 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) { |