swrast: replace __FUNCTION__ with __func__
[mesa.git] / src / glsl / link_uniform_blocks.cpp
index 72d6c5323a6ebe90a4117bf4e8ac56eaa88d4df6..6ca41107e53880c2a5edffb68475b09d55b08851 100644 (file)
@@ -26,7 +26,7 @@
 #include "linker.h"
 #include "ir_uniform.h"
 #include "link_uniform_block_active_visitor.h"
-#include "main/hash_table.h"
+#include "util/hash_table.h"
 #include "program.h"
 
 namespace {
@@ -67,8 +67,31 @@ private:
       assert(!"Should not get here.");
    }
 
+   virtual void enter_record(const glsl_type *type, const char *name,
+                             bool row_major) {
+      assert(type->is_record());
+      this->offset = glsl_align(
+            this->offset, type->std140_base_alignment(row_major));
+   }
+
+   virtual void leave_record(const glsl_type *type, const char *name,
+                             bool row_major) {
+      assert(type->is_record());
+
+      /* If this is the last field of a structure, apply rule #9.  The
+       * GL_ARB_uniform_buffer_object spec says:
+       *
+       *     "The structure may have padding at the end; the base offset of
+       *     the member following the sub-structure is rounded up to the next
+       *     multiple of the base alignment of the structure."
+       */
+      this->offset = glsl_align(
+            this->offset, type->std140_base_alignment(row_major));
+   }
+
    virtual void visit_field(const glsl_type *type, const char *name,
-                            bool row_major, const glsl_type *record_type)
+                            bool row_major, const glsl_type *record_type,
+                            bool last_field)
    {
       assert(this->index < this->num_variables);
 
@@ -76,7 +99,7 @@ private:
 
       v->Name = ralloc_strdup(mem_ctx, name);
       v->Type = type;
-      v->RowMajor = row_major;
+      v->RowMajor = type->without_array()->is_matrix() && row_major;
 
       if (this->is_array_instance) {
          v->IndexName = ralloc_strdup(mem_ctx, name);
@@ -92,17 +115,16 @@ private:
          unsigned len = strlen(close_bracket + 1) + 1;
 
          memmove(open_bracket, close_bracket + 1, len);
-     } else {
+      } else {
          v->IndexName = v->Name;
       }
 
-      const unsigned alignment = record_type
-        ? record_type->std140_base_alignment(v->RowMajor)
-        : type->std140_base_alignment(v->RowMajor);
+      const unsigned alignment = type->std140_base_alignment(v->RowMajor);
       unsigned size = type->std140_size(v->RowMajor);
 
       this->offset = glsl_align(this->offset, alignment);
       v->Offset = this->offset;
+
       this->offset += size;
 
       /* From the GL_ARB_uniform_buffer_object spec:
@@ -117,16 +139,6 @@ private:
        */
       this->buffer_size = glsl_align(this->offset, 16);
    }
-
-   virtual void visit_field(const glsl_struct_field *field)
-   {
-      /* FINISHME: When support for doubles (dvec4, etc.) is added to the
-       * FINISHME: compiler, this may be incorrect for a structure in a UBO
-       * FINISHME: like struct s { struct { float f } s1; dvec4 v; };.
-       */
-      this->offset = glsl_align(this->offset,
-                                field->type->std140_base_alignment(false));
-   }
 };
 
 class count_block_size : public program_resource_visitor {
@@ -168,7 +180,14 @@ 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_string_equal);
+      _mesa_hash_table_create(mem_ctx, _mesa_key_hash_string,
+                              _mesa_key_string_equal);
+
+   if (block_hash == NULL) {
+      _mesa_error_no_memory(__func__);
+      linker_error(prog, "out of memory\n");
+      return 0;
+   }
 
    /* Determine which uniform blocks are active.
     */
@@ -251,7 +270,17 @@ link_uniform_blocks(void *mem_ctx,
             blocks[i].Name = ralloc_asprintf(blocks, "%s[%u]", name,
                                              b->array_elements[j]);
             blocks[i].Uniforms = &variables[parcel.index];
-            blocks[i].Binding = 0;
+
+            /* The GL_ARB_shading_language_420pack spec says:
+             *
+             *     "If the binding identifier is used with a uniform block
+             *     instanced as an array then the first element of the array
+             *     takes the specified block binding and each subsequent
+             *     element takes the next consecutive uniform block binding
+             *     point."
+             */
+            blocks[i].Binding = (b->has_binding) ? b->binding + j : 0;
+
             blocks[i].UniformBufferSize = 0;
             blocks[i]._Packing =
                gl_uniform_block_packing(block_type->interface_packing);
@@ -269,7 +298,7 @@ link_uniform_blocks(void *mem_ctx,
       } else {
          blocks[i].Name = ralloc_strdup(blocks, block_type->name);
          blocks[i].Uniforms = &variables[parcel.index];
-         blocks[i].Binding = 0;
+         blocks[i].Binding = (b->has_binding) ? b->binding : 0;
          blocks[i].UniformBufferSize = 0;
          blocks[i]._Packing =
             gl_uniform_block_packing(block_type->interface_packing);