nir/linker: Fill TOP_LEVEL_ARRAY_SIZE and STRIDE
authorAntia Puentes <apuentes@igalia.com>
Sun, 30 Jun 2019 23:27:59 +0000 (18:27 -0500)
committerAlejandro Piñeiro <apinheiro@igalia.com>
Fri, 12 Jul 2019 21:42:41 +0000 (23:42 +0200)
From the ARB_program_interface_query specification:

    "For the property TOP_LEVEL_ARRAY_SIZE, a single integer
    identifying the number of active array elements of the top-level
    shader storage block member containing to the active variable is
    written to <params>.  If the top-level block member is not
    declared as an array, the value one is written to <params>.  If
    the top-level block member is an array with no declared size, the
    value zero is written to <params>."

    "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer
    identifying the stride between array elements of the top-level
    shader storage block member containing the active variable is
    written to <params>.  For top-level block members declared as
    arrays, the value written is the difference, in basic machine
    units, between the offsets of the active variable for consecutive
    elements in the top-level array.  For top-level block members not
    declared as an array, zero is written to <params>."

v2: move top_level_array_size and stride into nir_link_uniforms_state
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/compiler/glsl/gl_nir_link_uniforms.c

index 4a19ad81d75b01bd46990e91c11772f04c58cbf5..1478046c183b9f704f2476bbb13fed77f0761167 100644 (file)
@@ -246,9 +246,12 @@ struct nir_link_uniforms_state {
    unsigned shader_samplers_used;
    unsigned shader_shadow_samplers;
 
+   /* per-variable */
    nir_variable *current_var;
    int offset;
    bool var_is_in_block;
+   int top_level_array_size;
+   int top_level_array_stride;
 
    struct type_tree_entry *current_type;
 };
@@ -353,6 +356,21 @@ nir_link_uniform(struct gl_context *ctx,
 {
    struct gl_uniform_storage *uniform = NULL;
 
+   if (parent_type == state->current_var->type &&
+       nir_variable_is_in_ssbo(state->current_var)) {
+      /* Type is the top level SSBO member */
+      if (glsl_type_is_array(type) &&
+          (glsl_type_is_array(glsl_get_array_element(type)) ||
+           glsl_type_is_struct_or_ifc(glsl_get_array_element(type)))) {
+         /* Type is a top-level array (array of aggregate types) */
+         state->top_level_array_size = glsl_get_length(type);
+         state->top_level_array_stride = glsl_get_explicit_stride(type);
+      } else {
+         state->top_level_array_size = 1;
+         state->top_level_array_stride = 0;
+      }
+   }
+
    /* gl_uniform_storage can cope with one level of array, so if the type is a
     * composite type or an array where each element occupies more than one
     * location than we need to recursively process it.
@@ -432,6 +450,9 @@ nir_link_uniform(struct gl_context *ctx,
          uniform->type = type;
          uniform->array_elements = 0;
       }
+      uniform->top_level_array_size = state->top_level_array_size;
+      uniform->top_level_array_stride = state->top_level_array_stride;
+
       uniform->active_shader_mask |= 1 << stage;
 
       if (location >= 0) {
@@ -518,8 +539,6 @@ nir_link_uniform(struct gl_context *ctx,
        */
       uniform->builtin = false;
       uniform->atomic_buffer_index = -1;
-      uniform->top_level_array_size = 0;
-      uniform->top_level_array_stride = 0;
       uniform->is_bindless = false;
 
       /* The following are not for features not supported by ARB_gl_spirv */
@@ -634,6 +653,8 @@ gl_nir_link_uniforms(struct gl_context *ctx,
          state.current_var = var;
          state.offset = 0;
          state.var_is_in_block = nir_variable_is_in_block(var);
+         state.top_level_array_size = 0;
+         state.top_level_array_stride = 0;
 
          /*
           * From ARB_program_interface spec, issue (16):
@@ -680,7 +701,8 @@ gl_nir_link_uniforms(struct gl_context *ctx,
 
          int res = nir_link_uniform(ctx, prog, sh->Program, shader_type, type,
                                     NULL, 0,
-                                    location, &state);
+                                    location,
+                                    &state);
 
          free_type_tree(type_tree);