glsl: fix the type of ir_constant_data::u16
[mesa.git] / src / compiler / glsl / link_atomics.cpp
index fa845e9d1eb4c42096eb843283119e4b0bfe2c7b..bc03d64633be24e833836bc47f6ca5de7b850693 100644 (file)
 #include "ir.h"
 #include "ir_uniform.h"
 #include "linker.h"
-#include "program/hash_table.h"
+#include "main/errors.h"
 #include "main/macros.h"
+#include "main/mtypes.h"
 
 namespace {
    /*
-    * Atomic counter as seen by the program.
+    * Atomic counter uniform as seen by the program.
     */
-   struct active_atomic_counter {
+   struct active_atomic_counter_uniform {
       unsigned uniform_loc;
       ir_variable *var;
    };
@@ -44,44 +45,44 @@ namespace {
     */
    struct active_atomic_buffer {
       active_atomic_buffer()
-         : counters(0), num_counters(0), stage_references(), size(0)
+         : uniforms(0), num_uniforms(0), stage_counter_references(), size(0)
       {}
 
       ~active_atomic_buffer()
       {
-         free(counters);
+         free(uniforms);
       }
 
       void push_back(unsigned uniform_loc, ir_variable *var)
       {
-         active_atomic_counter *new_counters;
+         active_atomic_counter_uniform *new_uniforms;
 
-         new_counters = (active_atomic_counter *)
-            realloc(counters, sizeof(active_atomic_counter) *
-                    (num_counters + 1));
+         new_uniforms = (active_atomic_counter_uniform *)
+            realloc(uniforms, sizeof(active_atomic_counter_uniform) *
+                    (num_uniforms + 1));
 
-         if (new_counters == NULL) {
+         if (new_uniforms == NULL) {
             _mesa_error_no_memory(__func__);
             return;
          }
 
-         counters = new_counters;
-         counters[num_counters].uniform_loc = uniform_loc;
-         counters[num_counters].var = var;
-         num_counters++;
+         uniforms = new_uniforms;
+         uniforms[num_uniforms].uniform_loc = uniform_loc;
+         uniforms[num_uniforms].var = var;
+         num_uniforms++;
       }
 
-      active_atomic_counter *counters;
-      unsigned num_counters;
-      unsigned stage_references[MESA_SHADER_STAGES];
+      active_atomic_counter_uniform *uniforms;
+      unsigned num_uniforms;
+      unsigned stage_counter_references[MESA_SHADER_STAGES];
       unsigned size;
    };
 
    int
    cmp_actives(const void *a, const void *b)
    {
-      const active_atomic_counter *const first = (active_atomic_counter *) a;
-      const active_atomic_counter *const second = (active_atomic_counter *) b;
+      const active_atomic_counter_uniform *const first = (active_atomic_counter_uniform *) a;
+      const active_atomic_counter_uniform *const second = (active_atomic_counter_uniform *) b;
 
       return int(first->var->data.offset) - int(second->var->data.offset);
    }
@@ -103,9 +104,9 @@ namespace {
                            const unsigned shader_stage)
    {
       /* FIXME: Arrays of arrays get counted separately. For example:
-       * x1[3][3][2] = 9 counters
-       * x2[3][2]    = 3 counters
-       * x3[2]       = 1 counter
+       * x1[3][3][2] = 9 uniforms, 18 atomic counters
+       * x2[3][2]    = 3 uniforms, 6 atomic counters
+       * x3[2]       = 1 uniform, 2 atomic counters
        *
        * However this code marks all the counters as active even when they
        * might not be used.
@@ -119,7 +120,7 @@ namespace {
       } else {
          active_atomic_buffer *buf = &buffers[var->data.binding];
          gl_uniform_storage *const storage =
-            &prog->UniformStorage[*uniform_loc];
+            &prog->data->UniformStorage[*uniform_loc];
 
          /* If this is the first time the buffer is used, increment
           * the counter of buffers used.
@@ -129,7 +130,13 @@ namespace {
 
          buf->push_back(*uniform_loc, var);
 
-         buf->stage_references[shader_stage]++;
+         /* When checking for atomic counters we should count every member in
+          * an array as an atomic counter reference.
+          */
+         if (t->is_array())
+            buf->stage_counter_references[shader_stage] += t->length;
+         else
+            buf->stage_counter_references[shader_stage]++;
          buf->size = MAX2(buf->size, *offset + t->atomic_size());
 
          storage->offset = *offset;
@@ -170,22 +177,22 @@ namespace {
          if (buffers[i].size == 0)
             continue;
 
-         qsort(buffers[i].counters, buffers[i].num_counters,
-               sizeof(active_atomic_counter),
+         qsort(buffers[i].uniforms, buffers[i].num_uniforms,
+               sizeof(active_atomic_counter_uniform),
                cmp_actives);
 
-         for (unsigned j = 1; j < buffers[i].num_counters; j++) {
+         for (unsigned j = 1; j < buffers[i].num_uniforms; j++) {
             /* If an overlapping counter found, it must be a reference to the
              * same counter from a different shader stage.
              */
-            if (check_atomic_counters_overlap(buffers[i].counters[j-1].var,
-                                              buffers[i].counters[j].var)
-                && strcmp(buffers[i].counters[j-1].var->name,
-                          buffers[i].counters[j].var->name) != 0) {
+            if (check_atomic_counters_overlap(buffers[i].uniforms[j-1].var,
+                                              buffers[i].uniforms[j].var)
+                && strcmp(buffers[i].uniforms[j-1].var->name,
+                          buffers[i].uniforms[j].var->name) != 0) {
                linker_error(prog, "Atomic counter %s declared at offset %d "
                             "which is already in use.",
-                            buffers[i].counters[j].var->name,
-                            buffers[i].counters[j].var->data.offset);
+                            buffers[i].uniforms[j].var->name,
+                            buffers[i].uniforms[j].var->data.offset);
             }
          }
       }
@@ -202,9 +209,9 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
    active_atomic_buffer *abs =
       find_active_atomic_counters(ctx, prog, &num_buffers);
 
-   prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer,
-                                       num_buffers);
-   prog->NumAtomicBuffers = num_buffers;
+   prog->data->AtomicBuffers = rzalloc_array(prog->data, gl_active_atomic_buffer,
+                                             num_buffers);
+   prog->data->NumAtomicBuffers = num_buffers;
 
    unsigned i = 0;
    for (unsigned binding = 0;
@@ -217,22 +224,22 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
          continue;
 
       active_atomic_buffer &ab = abs[binding];
-      gl_active_atomic_buffer &mab = prog->AtomicBuffers[i];
+      gl_active_atomic_buffer &mab = prog->data->AtomicBuffers[i];
 
       /* Assign buffer-specific fields. */
       mab.Binding = binding;
       mab.MinimumSize = ab.size;
-      mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint,
-                                   ab.num_counters);
-      mab.NumUniforms = ab.num_counters;
+      mab.Uniforms = rzalloc_array(prog->data->AtomicBuffers, GLuint,
+                                   ab.num_uniforms);
+      mab.NumUniforms = ab.num_uniforms;
 
       /* Assign counter-specific fields. */
-      for (unsigned j = 0; j < ab.num_counters; j++) {
-         ir_variable *const var = ab.counters[j].var;
+      for (unsigned j = 0; j < ab.num_uniforms; j++) {
+         ir_variable *const var = ab.uniforms[j].var;
          gl_uniform_storage *const storage =
-            &prog->UniformStorage[ab.counters[j].uniform_loc];
+            &prog->data->UniformStorage[ab.uniforms[j].uniform_loc];
 
-         mab.Uniforms[j] = ab.counters[j].uniform_loc;
+         mab.Uniforms[j] = ab.uniforms[j].uniform_loc;
          if (!var->data.explicit_binding)
             var->data.binding = i;
 
@@ -246,7 +253,7 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
 
       /* Assign stage-specific fields. */
       for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) {
-         if (ab.stage_references[j]) {
+         if (ab.stage_counter_references[j]) {
             mab.StageReferences[j] = GL_TRUE;
             num_atomic_buffers[j]++;
          } else {
@@ -262,23 +269,23 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
     */
    for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) {
       if (prog->_LinkedShaders[j] && num_atomic_buffers[j] > 0) {
-         prog->_LinkedShaders[j]->NumAtomicBuffers = num_atomic_buffers[j];
-         prog->_LinkedShaders[j]->AtomicBuffers =
-            rzalloc_array(prog, gl_active_atomic_buffer *,
+         struct gl_program *gl_prog = prog->_LinkedShaders[j]->Program;
+         gl_prog->info.num_abos = num_atomic_buffers[j];
+         gl_prog->sh.AtomicBuffers =
+            rzalloc_array(gl_prog, gl_active_atomic_buffer *,
                           num_atomic_buffers[j]);
 
          unsigned intra_stage_idx = 0;
          for (unsigned i = 0; i < num_buffers; i++) {
             struct gl_active_atomic_buffer *atomic_buffer =
-               &prog->AtomicBuffers[i];
+               &prog->data->AtomicBuffers[i];
             if (atomic_buffer->StageReferences[j]) {
-               prog->_LinkedShaders[j]->AtomicBuffers[intra_stage_idx] =
-                  atomic_buffer;
+               gl_prog->sh.AtomicBuffers[intra_stage_idx] = atomic_buffer;
 
                for (unsigned u = 0; u < atomic_buffer->NumUniforms; u++) {
-                  prog->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].index =
+                  prog->data->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].index =
                      intra_stage_idx;
-                  prog->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].active =
+                  prog->data->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].active =
                      true;
                }
 
@@ -314,7 +321,7 @@ link_check_atomic_counter_resources(struct gl_context *ctx,
          continue;
 
       for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) {
-         const unsigned n = abs[i].stage_references[j];
+         const unsigned n = abs[i].stage_counter_references[j];
 
          if (n) {
             atomic_counters[j] += n;