Mesa (master): nir: Add a size_align helper function for aligning elements to 16 bytes.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Nov 16 22:33:02 UTC 2020


Module: Mesa
Branch: master
Commit: 51f2b11b043da05e12f26d8466e68e55f0d17c3b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=51f2b11b043da05e12f26d8466e68e55f0d17c3b

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Aug  4 16:09:25 2020 -0700

nir: Add a size_align helper function for aligning elements to 16 bytes.

This is useful for freedreno's intrinsic opt_large_constant lowering,
where we want arrays and struct elements aligned to 16 to avoid generating
lots of extra instructions to extract from the right component.

Reviewed-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5810>

---

 src/compiler/nir_types.cpp | 100 +++++++++++++++++++++++++++++++++++++--------
 src/compiler/nir_types.h   |   2 +
 2 files changed, 84 insertions(+), 18 deletions(-)

diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp
index 54814ccdd8e..448e962b399 100644
--- a/src/compiler/nir_types.cpp
+++ b/src/compiler/nir_types.cpp
@@ -701,6 +701,31 @@ glsl_uint16_type(const struct glsl_type *type)
    return type->get_uint16_type();
 }
 
+static void
+glsl_size_align_handle_array_and_structs(const struct glsl_type *type,
+                                         glsl_type_size_align_func size_align,
+                                         unsigned *size, unsigned *align)
+{
+   if (type->base_type == GLSL_TYPE_ARRAY) {
+      unsigned elem_size = 0, elem_align = 0;
+      size_align(type->fields.array, &elem_size, &elem_align);
+      *align = elem_align;
+      *size = type->length * ALIGN_POT(elem_size, elem_align);
+   } else {
+      assert(type->base_type == GLSL_TYPE_STRUCT ||
+             type->base_type == GLSL_TYPE_INTERFACE);
+
+      *size = 0;
+      *align = 0;
+      for (unsigned i = 0; i < type->length; i++) {
+         unsigned elem_size = 0, elem_align = 0;
+         size_align(type->fields.structure[i].type, &elem_size, &elem_align);
+         *align = MAX2(*align, elem_align);
+         *size = ALIGN_POT(*size, elem_align) + elem_size;
+      }
+   }
+}
+
 void
 glsl_get_natural_size_align_bytes(const struct glsl_type *type,
                                   unsigned *size, unsigned *align)
@@ -731,26 +756,12 @@ glsl_get_natural_size_align_bytes(const struct glsl_type *type,
       break;
    }
 
-   case GLSL_TYPE_ARRAY: {
-      unsigned elem_size = 0, elem_align = 0;
-      glsl_get_natural_size_align_bytes(type->fields.array,
-                                        &elem_size, &elem_align);
-      *align = elem_align;
-      *size = type->length * ALIGN_POT(elem_size, elem_align);
-      break;
-   }
-
+   case GLSL_TYPE_ARRAY:
    case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_STRUCT:
-      *size = 0;
-      *align = 0;
-      for (unsigned i = 0; i < type->length; i++) {
-         unsigned elem_size = 0, elem_align = 0;
-         glsl_get_natural_size_align_bytes(type->fields.structure[i].type,
-                                           &elem_size, &elem_align);
-         *align = MAX2(*align, elem_align);
-         *size = ALIGN_POT(*size, elem_align) + elem_size;
-      }
+      glsl_size_align_handle_array_and_structs(type,
+                                               glsl_get_natural_size_align_bytes,
+                                               size, align);
       break;
 
    case GLSL_TYPE_SAMPLER:
@@ -769,6 +780,59 @@ glsl_get_natural_size_align_bytes(const struct glsl_type *type,
    }
 }
 
+/**
+ * Returns a byte size/alignment for a type where each array element or struct
+ * field is aligned to 16 bytes.
+ */
+void
+glsl_get_vec4_size_align_bytes(const struct glsl_type *type,
+                               unsigned *size, unsigned *align)
+{
+   switch (type->base_type) {
+   case GLSL_TYPE_BOOL:
+      /* We special-case Booleans to 32 bits to not cause heartburn for
+       * drivers that suddenly get an 8-bit load.
+       */
+      *size = 4 * type->components();
+      *align = 16;
+      break;
+
+   case GLSL_TYPE_UINT8:
+   case GLSL_TYPE_INT8:
+   case GLSL_TYPE_UINT16:
+   case GLSL_TYPE_INT16:
+   case GLSL_TYPE_FLOAT16:
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64: {
+      unsigned N = glsl_get_bit_size(type) / 8;
+      *size = 16 * (type->matrix_columns - 1) + N * type->vector_elements;
+      *align = 16;
+      break;
+   }
+
+   case GLSL_TYPE_ARRAY:
+   case GLSL_TYPE_INTERFACE:
+   case GLSL_TYPE_STRUCT:
+      glsl_size_align_handle_array_and_structs(type,
+                                               glsl_get_vec4_size_align_bytes,
+                                               size, align);
+      break;
+
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_ATOMIC_UINT:
+   case GLSL_TYPE_SUBROUTINE:
+   case GLSL_TYPE_VOID:
+   case GLSL_TYPE_ERROR:
+   case GLSL_TYPE_FUNCTION:
+      unreachable("type does not make sense for glsl_get_vec4_size_align_bytes()");
+   }
+}
+
 const glsl_type *
 glsl_atomic_uint_type(void)
 {
diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h
index b4bd9bcc7c9..82c268b98bc 100644
--- a/src/compiler/nir_types.h
+++ b/src/compiler/nir_types.h
@@ -228,6 +228,8 @@ const struct glsl_type *glsl_uint16_type(const struct glsl_type *type);
 
 void glsl_get_natural_size_align_bytes(const struct glsl_type *type,
                                        unsigned *size, unsigned *align);
+void glsl_get_vec4_size_align_bytes(const struct glsl_type *type,
+                                    unsigned *size, unsigned *align);
 
 const struct glsl_type *glsl_atomic_uint_type(void);
 



More information about the mesa-commit mailing list