ralloc: use rzalloc where it's necessary
[mesa.git] / src / compiler / glsl / link_uniform_blocks.cpp
index 58f22fd61c5d3d582f5a00c629edebdb37e8cd61..1fc0e2d5109f2d20e57a66982c54990d157b04eb 100644 (file)
@@ -34,9 +34,10 @@ namespace {
 class ubo_visitor : public program_resource_visitor {
 public:
    ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables,
-               unsigned num_variables)
+               unsigned num_variables, struct gl_shader_program *prog)
       : index(0), offset(0), buffer_size(0), variables(variables),
-        num_variables(num_variables), mem_ctx(mem_ctx), is_array_instance(false)
+        num_variables(num_variables), mem_ctx(mem_ctx), is_array_instance(false),
+        prog(prog)
    {
       /* empty */
    }
@@ -56,6 +57,7 @@ public:
    unsigned num_variables;
    void *mem_ctx;
    bool is_array_instance;
+   struct gl_shader_program *prog;
 
 private:
    virtual void visit_field(const glsl_type *type, const char *name,
@@ -68,7 +70,7 @@ private:
    }
 
    virtual void enter_record(const glsl_type *type, const char *,
-                             bool row_major, const unsigned packing) {
+                             bool row_major, const enum glsl_interface_packing packing) {
       assert(type->is_record());
       if (packing == GLSL_INTERFACE_PACKING_STD430)
          this->offset = glsl_align(
@@ -79,7 +81,7 @@ private:
    }
 
    virtual void leave_record(const glsl_type *type, const char *,
-                             bool row_major, const unsigned packing) {
+                             bool row_major, const enum glsl_interface_packing packing) {
       assert(type->is_record());
 
       /* If this is the last field of a structure, apply rule #9.  The
@@ -104,7 +106,7 @@ private:
 
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major, const glsl_type *,
-                            const unsigned packing,
+                            const enum glsl_interface_packing packing,
                             bool last_field)
    {
       assert(this->index < this->num_variables);
@@ -245,6 +247,7 @@ process_block_array(struct uniform_block_array_elements *ub_array, char **name,
 
       blocks[i].UniformBufferSize = 0;
       blocks[i]._Packing = gl_uniform_block_packing(type->interface_packing);
+      blocks[i]._RowMajor = type->get_interface_row_major();
 
       parcel->process(type, blocks[i].Name);
 
@@ -307,14 +310,14 @@ create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
    /* Allocate storage to hold all of the information related to uniform
     * blocks that can be queried through the API.
     */
-   struct gl_uniform_block *blocks = ralloc_array(mem_ctx, gl_uniform_block, num_blocks);
+   struct gl_uniform_block *blocks = rzalloc_array(mem_ctx, gl_uniform_block, num_blocks);
    gl_uniform_buffer_variable *variables =
       ralloc_array(blocks, gl_uniform_buffer_variable, num_variables);
 
    /* Add each variable from each uniform block to the API tracking
     * structures.
     */
-   ubo_visitor parcel(blocks, variables, num_variables);
+   ubo_visitor parcel(blocks, variables, num_variables, prog);
 
    STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140)
                  == unsigned(ubo_packing_std140));
@@ -352,6 +355,7 @@ create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
             blocks[i].UniformBufferSize = 0;
             blocks[i]._Packing =
                gl_uniform_block_packing(block_type->interface_packing);
+            blocks[i]._RowMajor = block_type->get_interface_row_major();
 
             parcel.process(block_type,
                            b->has_instance_name ? block_type->name : "");
@@ -383,8 +387,7 @@ void
 link_uniform_blocks(void *mem_ctx,
                     struct gl_context *ctx,
                     struct gl_shader_program *prog,
-                    struct gl_shader **shader_list,
-                    unsigned num_shaders,
+                    struct gl_linked_shader *shader,
                     struct gl_uniform_block **ubo_blocks,
                     unsigned *num_ubo_blocks,
                     struct gl_uniform_block **ssbo_blocks,
@@ -407,9 +410,7 @@ link_uniform_blocks(void *mem_ctx,
    /* Determine which uniform blocks are active.
     */
    link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
-   for (unsigned i = 0; i < num_shaders; i++) {
-      visit_list_elements(&v, shader_list[i]->ir);
-   }
+   visit_list_elements(&v, shader->ir);
 
    /* Count the number of active uniform blocks.  Count the total number of
     * active slots in those uniform blocks.
@@ -464,7 +465,7 @@ link_uniform_blocks(void *mem_ctx,
    _mesa_hash_table_destroy(block_hash, NULL);
 }
 
-bool
+static bool
 link_uniform_blocks_are_compatible(const gl_uniform_block *a,
                                    const gl_uniform_block *b)
 {
@@ -487,6 +488,9 @@ link_uniform_blocks_are_compatible(const gl_uniform_block *a,
    if (a->_Packing != b->_Packing)
       return false;
 
+   if (a->_RowMajor != b->_RowMajor)
+      return false;
+
    for (unsigned i = 0; i < a->NumUniforms; i++) {
       if (strcmp(a->Uniforms[i].Name, b->Uniforms[i].Name) != 0)
          return false;
@@ -500,3 +504,56 @@ link_uniform_blocks_are_compatible(const gl_uniform_block *a,
 
    return true;
 }
+
+/**
+ * Merges a uniform block into an array of uniform blocks that may or
+ * may not already contain a copy of it.
+ *
+ * Returns the index of the new block in the array.
+ */
+int
+link_cross_validate_uniform_block(void *mem_ctx,
+                                  struct gl_uniform_block **linked_blocks,
+                                  unsigned int *num_linked_blocks,
+                                  struct gl_uniform_block *new_block)
+{
+   for (unsigned int i = 0; i < *num_linked_blocks; i++) {
+      struct gl_uniform_block *old_block = &(*linked_blocks)[i];
+
+      if (strcmp(old_block->Name, new_block->Name) == 0)
+         return link_uniform_blocks_are_compatible(old_block, new_block)
+            ? i : -1;
+   }
+
+   *linked_blocks = reralloc(mem_ctx, *linked_blocks,
+                             struct gl_uniform_block,
+                             *num_linked_blocks + 1);
+   int linked_block_index = (*num_linked_blocks)++;
+   struct gl_uniform_block *linked_block = &(*linked_blocks)[linked_block_index];
+
+   memcpy(linked_block, new_block, sizeof(*new_block));
+   linked_block->Uniforms = ralloc_array(*linked_blocks,
+                                         struct gl_uniform_buffer_variable,
+                                         linked_block->NumUniforms);
+
+   memcpy(linked_block->Uniforms,
+          new_block->Uniforms,
+          sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);
+
+   linked_block->Name = ralloc_strdup(*linked_blocks, linked_block->Name);
+
+   for (unsigned int i = 0; i < linked_block->NumUniforms; i++) {
+      struct gl_uniform_buffer_variable *ubo_var =
+         &linked_block->Uniforms[i];
+
+      if (ubo_var->Name == ubo_var->IndexName) {
+         ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name);
+         ubo_var->IndexName = ubo_var->Name;
+      } else {
+         ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name);
+         ubo_var->IndexName = ralloc_strdup(*linked_blocks, ubo_var->IndexName);
+      }
+   }
+
+   return linked_block_index;
+}