[Mesa-dev] [PATCH 12/22] nir: add type alignment support to lower_io

Karol Herbst kherbst at redhat.com
Tue Nov 13 15:48:16 UTC 2018


From: Rob Clark <robdclark at gmail.com>

For cl we can have structs with 8/16/32/64 bit scalar types (as well as,
ofc, arrays/structs/etc), which are padded according to 'C' rules.  So
for lowering struct deref's we need to not just consider a field's size,
but also it's alignment.

Signed-off-by: Karol Herbst <kherbst at redhat.com>
---
 src/compiler/nir/nir.h          | 10 +++++++
 src/compiler/nir/nir_lower_io.c | 52 ++++++++++++++++++++++++---------
 2 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index c469e111b2c..11e3d18320a 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2825,10 +2825,20 @@ typedef enum {
     */
    nir_lower_io_force_sample_interpolation = (1 << 1),
 } nir_lower_io_options;
+typedef struct nir_memory_model {
+   int (*type_size)(const struct glsl_type *);
+   int (*type_align)(const struct glsl_type *);
+} nir_memory_model;
 bool nir_lower_io(nir_shader *shader,
                   nir_variable_mode modes,
                   int (*type_size)(const struct glsl_type *),
                   nir_lower_io_options);
+// TEMP use different name to avoid fixing all the callers yet:
+bool nir_lower_io2(nir_shader *shader,
+                  nir_variable_mode modes,
+                  const nir_memory_model *mm,
+                  nir_lower_io_options);
+
 nir_src *nir_get_io_offset_src(nir_intrinsic_instr *instr);
 nir_src *nir_get_io_vertex_index_src(nir_intrinsic_instr *instr);
 
diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c
index 2a6c284de2b..292baf9e4fc 100644
--- a/src/compiler/nir/nir_lower_io.c
+++ b/src/compiler/nir/nir_lower_io.c
@@ -38,7 +38,7 @@
 struct lower_io_state {
    void *dead_ctx;
    nir_builder builder;
-   int (*type_size)(const struct glsl_type *type);
+   const nir_memory_model *mm;
    nir_variable_mode modes;
    nir_lower_io_options options;
 };
@@ -86,12 +86,26 @@ nir_is_per_vertex_io(const nir_variable *var, gl_shader_stage stage)
    return false;
 }
 
+static int
+default_type_align(const struct glsl_type *type)
+{
+   return 1;
+}
+
+static inline int
+align(int value, int alignment)
+{
+   return (value + alignment - 1) & ~(alignment - 1);
+}
+
 static nir_ssa_def *
 get_io_offset(nir_deref_instr *deref, nir_ssa_def **vertex_index,
               struct lower_io_state *state, unsigned *component)
 {
    nir_builder *b = &state->builder;
-   int (*type_size)(const struct glsl_type *) = state->type_size;
+   int (*type_size)(const struct glsl_type *) = state->mm->type_size;
+   int (*type_align)(const struct glsl_type *) = state->mm->type_align ?
+      state->mm->type_align : default_type_align;
    nir_deref_path path;
    nir_deref_path_init(&path, deref, NULL);
 
@@ -137,7 +151,10 @@ get_io_offset(nir_deref_instr *deref, nir_ssa_def **vertex_index,
 
          unsigned field_offset = 0;
          for (unsigned i = 0; i < (*p)->strct.index; i++) {
-            field_offset += type_size(glsl_get_struct_field(parent->type, i));
+            const struct glsl_type *field_type =
+               glsl_get_struct_field(parent->type, i);
+            field_offset = align(field_offset, type_align(field_type));
+            field_offset += type_size(field_type);
          }
          offset = nir_iadd(b, offset, nir_imm_int(b, field_offset));
       } else {
@@ -207,7 +224,7 @@ lower_load(nir_intrinsic_instr *intrin, struct lower_io_state *state,
       nir_intrinsic_set_component(load, component);
 
    if (load->intrinsic == nir_intrinsic_load_uniform)
-      nir_intrinsic_set_range(load, state->type_size(var->type));
+      nir_intrinsic_set_range(load, state->mm->type_size(var->type));
 
    if (vertex_index) {
       load->src[0] = nir_src_for_ssa(vertex_index);
@@ -488,10 +505,8 @@ nir_lower_io_block(nir_block *block,
 }
 
 static bool
-nir_lower_io_impl(nir_function_impl *impl,
-                  nir_variable_mode modes,
-                  int (*type_size)(const struct glsl_type *),
-                  nir_lower_io_options options)
+nir_lower_io_impl(nir_function_impl *impl, nir_variable_mode modes,
+                  const nir_memory_model *mm, nir_lower_io_options options)
 {
    struct lower_io_state state;
    bool progress = false;
@@ -499,7 +514,7 @@ nir_lower_io_impl(nir_function_impl *impl,
    nir_builder_init(&state.builder, impl);
    state.dead_ctx = ralloc_context(NULL);
    state.modes = modes;
-   state.type_size = type_size;
+   state.mm = mm;
    state.options = options;
 
    nir_foreach_block(block, impl) {
@@ -514,22 +529,33 @@ nir_lower_io_impl(nir_function_impl *impl,
 }
 
 bool
-nir_lower_io(nir_shader *shader, nir_variable_mode modes,
-             int (*type_size)(const struct glsl_type *),
-             nir_lower_io_options options)
+nir_lower_io2(nir_shader *shader, nir_variable_mode modes,
+             const nir_memory_model *mm, nir_lower_io_options options)
 {
    bool progress = false;
 
    nir_foreach_function(function, shader) {
       if (function->impl) {
          progress |= nir_lower_io_impl(function->impl, modes,
-                                       type_size, options);
+                                       mm, options);
       }
    }
 
    return progress;
 }
 
+
+bool
+nir_lower_io(nir_shader *shader, nir_variable_mode modes,
+             int (*type_size)(const struct glsl_type *),
+             nir_lower_io_options options)
+{
+   nir_memory_model mm = {
+         .type_size = type_size,
+   };
+   return nir_lower_io2(shader, modes, &mm, options);
+}
+
 /**
  * Return the offset source for a load/store intrinsic.
  */
-- 
2.19.1



More information about the mesa-dev mailing list