glsl/nir: add glsl_types::explicit_size plus nir C wrapper
authorAlejandro Piñeiro <apinheiro@igalia.com>
Wed, 16 Jan 2019 15:50:29 +0000 (16:50 +0100)
committerArcady Goldmints-Orlov <agoldmints@igalia.com>
Sun, 30 Jun 2019 21:58:26 +0000 (16:58 -0500)
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 <apinheiro@igalia.com>
Signed-off-by: Antia Puentes <apuentes@igalia.com>
Signed-off-by: Neil Roberts <nroberts@igalia.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/compiler/glsl_types.cpp
src/compiler/glsl_types.h
src/compiler/nir_types.cpp
src/compiler/nir_types.h

index ded355ee308106d6f94e26218a383139a5932a43..123a8e402553caeea01dd7f3d2ac2064645d0a51 100644 (file)
@@ -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
 {
index 1e550986e478a7bbefe76ac402800bac8b30690f..3fd49a759c69fb3a473bdc8e4d54575719ddd1a4 100644 (file)
@@ -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?
     *
index e2dfc40ff0b0c37ab6c4ac7c26a5c6e42691f973..69f89a7fd74ffa28afc714ef3dce7c626d13146e 100644 (file)
@@ -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);
+}
index 7bcf4c08f4c0bfcdc5b498ae1be799e774d1923f..806ba824084e752e98c8a501dec80a2dca379c3b 100644 (file)
@@ -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)
 {