nir: Allow var_mem_global in nir_lower_vars_to_explicit_types
[mesa.git] / src / compiler / glsl / link_uniform_blocks.cpp
index 249a767636c27c8cf3f5a8235aac21d23d3e6875..1603cbd59afec5b516a05c2bd841a2a758e5f8f0 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include "main/core.h"
 #include "ir.h"
 #include "linker.h"
 #include "ir_uniform.h"
 #include "link_uniform_block_active_visitor.h"
 #include "util/hash_table.h"
 #include "program.h"
+#include "main/errors.h"
+#include "main/mtypes.h"
 
 namespace {
 
 class ubo_visitor : public program_resource_visitor {
 public:
    ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables,
-               unsigned num_variables, struct gl_shader_program *prog)
+               unsigned num_variables, struct gl_shader_program *prog,
+               bool use_std430_as_default)
       : index(0), offset(0), buffer_size(0), variables(variables),
         num_variables(num_variables), mem_ctx(mem_ctx),
-        is_array_instance(false), prog(prog)
+        is_array_instance(false), prog(prog),
+        use_std430_as_default(use_std430_as_default)
    {
       /* empty */
    }
@@ -47,7 +50,8 @@ public:
       this->offset = 0;
       this->buffer_size = 0;
       this->is_array_instance = strchr(name, ']') != NULL;
-      this->program_resource_visitor::process(type, name);
+      this->program_resource_visitor::process(type, name,
+                                              use_std430_as_default);
    }
 
    unsigned index;
@@ -64,7 +68,7 @@ private:
                              bool row_major,
                              const enum glsl_interface_packing packing)
    {
-      assert(type->is_record());
+      assert(type->is_struct());
       if (packing == GLSL_INTERFACE_PACKING_STD430)
          this->offset = glsl_align(
             this->offset, type->std430_base_alignment(row_major));
@@ -77,7 +81,7 @@ private:
                              bool row_major,
                              const enum glsl_interface_packing packing)
    {
-      assert(type->is_record());
+      assert(type->is_struct());
 
       /* If this is the last field of a structure, apply rule #9.  The
        * ARB_uniform_buffer_object spec says:
@@ -181,6 +185,8 @@ private:
        */
       this->buffer_size = glsl_align(this->offset, 16);
    }
+
+   bool use_std430_as_default;
 };
 
 class count_block_size : public program_resource_visitor {
@@ -216,7 +222,7 @@ static void process_block_array_leaf(const char *name, gl_uniform_block *blocks,
                                      gl_uniform_buffer_variable *variables,
                                      const struct link_uniform_block_active *const b,
                                      unsigned *block_index,
-                                     unsigned *binding_offset,
+                                     unsigned binding_offset,
                                      unsigned linearized_index,
                                      struct gl_context *ctx,
                                      struct gl_shader_program *prog);
@@ -231,26 +237,28 @@ process_block_array(struct uniform_block_array_elements *ub_array, char **name,
                     size_t name_length, gl_uniform_block *blocks,
                     ubo_visitor *parcel, gl_uniform_buffer_variable *variables,
                     const struct link_uniform_block_active *const b,
-                    unsigned *block_index, unsigned *binding_offset,
+                    unsigned *block_index, unsigned binding_offset,
                     struct gl_context *ctx, struct gl_shader_program *prog,
                     unsigned first_index)
 {
    for (unsigned j = 0; j < ub_array->num_array_elements; j++) {
       size_t new_length = name_length;
 
+      unsigned int element_idx = ub_array->array_elements[j];
       /* Append the subscript to the current variable name */
-      ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]",
-                                   ub_array->array_elements[j]);
+      ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", element_idx);
 
       if (ub_array->array) {
+         unsigned binding_stride = binding_offset + (element_idx *
+                                   ub_array->array->aoa_size);
          process_block_array(ub_array->array, name, new_length, blocks,
                              parcel, variables, b, block_index,
-                             binding_offset, ctx, prog, first_index);
+                             binding_stride, ctx, prog, first_index);
       } else {
          process_block_array_leaf(*name, blocks,
                                   parcel, variables, b, block_index,
-                                  binding_offset, *block_index - first_index,
-                                  ctx, prog);
+                                  binding_offset + element_idx,
+                                  *block_index - first_index, ctx, prog);
       }
    }
 }
@@ -260,7 +268,7 @@ process_block_array_leaf(const char *name,
                          gl_uniform_block *blocks,
                          ubo_visitor *parcel, gl_uniform_buffer_variable *variables,
                          const struct link_uniform_block_active *const b,
-                         unsigned *block_index, unsigned *binding_offset,
+                         unsigned *block_index, unsigned binding_offset,
                          unsigned linearized_index,
                          struct gl_context *ctx, struct gl_shader_program *prog)
 {
@@ -277,10 +285,10 @@ process_block_array_leaf(const char *name,
     *    block binding and each subsequent element takes the next consecutive
     *    uniform block binding point.
     */
-   blocks[i].Binding = (b->has_binding) ? b->binding + *binding_offset : 0;
+   blocks[i].Binding = (b->has_binding) ? b->binding + binding_offset : 0;
 
    blocks[i].UniformBufferSize = 0;
-   blocks[i]._Packing = gl_uniform_block_packing(type->interface_packing);
+   blocks[i]._Packing = glsl_interface_packing(type->interface_packing);
    blocks[i]._RowMajor = type->get_interface_row_major();
    blocks[i].linearized_array_index = linearized_index;
 
@@ -292,7 +300,7 @@ process_block_array_leaf(const char *name,
    if (b->is_shader_storage &&
        parcel->buffer_size > ctx->Const.MaxShaderStorageBlockSize) {
       linker_error(prog, "shader storage block `%s' has size %d, "
-                   "which is larger than than the maximum allowed (%d)",
+                   "which is larger than the maximum allowed (%d)",
                    b->type->name,
                    parcel->buffer_size,
                    ctx->Const.MaxShaderStorageBlockSize);
@@ -301,7 +309,6 @@ process_block_array_leaf(const char *name,
       (unsigned)(ptrdiff_t)(&variables[parcel->index] - blocks[i].Uniforms);
 
    *block_index = *block_index + 1;
-   *binding_offset = *binding_offset + 1;
 }
 
 /* This function resizes the array types of the block so that later we can use
@@ -352,19 +359,10 @@ create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
    /* Add each variable from each uniform block to the API tracking
     * structures.
     */
-   ubo_visitor parcel(blocks, variables, num_variables, prog);
-
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140)
-                 == unsigned(ubo_packing_std140));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED)
-                 == unsigned(ubo_packing_shared));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED)
-                 == unsigned(ubo_packing_packed));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430)
-                 == unsigned(ubo_packing_std430));
+   ubo_visitor parcel(blocks, variables, num_variables, prog,
+                      ctx->Const.UseSTD430AsDefaultPacking);
 
    unsigned i = 0;
-   struct hash_entry *entry;
    hash_table_foreach (block_hash, entry) {
       const struct link_uniform_block_active *const b =
          (const struct link_uniform_block_active *) entry->data;
@@ -373,7 +371,6 @@ create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
       if ((create_ubo_blocks && !b->is_shader_storage) ||
           (!create_ubo_blocks && b->is_shader_storage)) {
 
-         unsigned binding_offset = 0;
          if (b->array != NULL) {
             char *name = ralloc_strdup(NULL,
                                        block_type->without_array()->name);
@@ -381,12 +378,12 @@ create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
 
             assert(b->has_instance_name);
             process_block_array(b->array, &name, name_length, blocks, &parcel,
-                                variables, b, &i, &binding_offset, ctx, prog,
+                                variables, b, &i, 0, ctx, prog,
                                 i);
             ralloc_free(name);
          } else {
             process_block_array_leaf(block_type->name, blocks, &parcel,
-                                     variables, b, &i, &binding_offset,
+                                     variables, b, &i, 0,
                                      0, ctx, prog);
          }
       }
@@ -412,7 +409,7 @@ link_uniform_blocks(void *mem_ctx,
     * the hash is organized by block-name.
     */
    struct hash_table *block_hash =
-      _mesa_hash_table_create(mem_ctx, _mesa_key_hash_string,
+      _mesa_hash_table_create(mem_ctx, _mesa_hash_string,
                               _mesa_key_string_equal);
 
    if (block_hash == NULL) {
@@ -431,7 +428,6 @@ link_uniform_blocks(void *mem_ctx,
    unsigned num_ubo_variables = 0;
    unsigned num_ssbo_variables = 0;
    count_block_size block_size;
-   struct hash_entry *entry;
 
    hash_table_foreach (block_hash, entry) {
       struct link_uniform_block_active *const b =
@@ -444,10 +440,12 @@ link_uniform_blocks(void *mem_ctx,
            GLSL_INTERFACE_PACKING_PACKED)) {
          b->type = resize_block_array(b->type, b->array);
          b->var->type = b->type;
+         b->var->data.max_array_access = b->type->length - 1;
       }
 
       block_size.num_active_uniforms = 0;
-      block_size.process(b->type->without_array(), "");
+      block_size.process(b->type->without_array(), "",
+                         ctx->Const.UseSTD430AsDefaultPacking);
 
       if (b->array != NULL) {
          unsigned aoa_size = b->type->arrays_of_arrays_size();