glsl: Only set ir_variable::constant_value for const-decorated variables
[mesa.git] / src / glsl / link_uniform_initializers.cpp
index f6a60bce99337637eb1501056a31a44e37fb7b79..065257b5a0ea80763d32eb9a3009fcd69751c578 100644 (file)
@@ -48,7 +48,7 @@ static unsigned
 get_uniform_block_index(const gl_shader_program *shProg,
                         const char *uniformBlockName)
 {
-   for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
+   for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
       if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
         return i;
    }
@@ -75,6 +75,11 @@ copy_constant_to_storage(union gl_constant_value *storage,
       case GLSL_TYPE_FLOAT:
         storage[i].f = val->value.f[i];
         break;
+      case GLSL_TYPE_DOUBLE:
+         /* XXX need to check on big-endian */
+         storage[i * 2].u = *(uint32_t *)&val->value.d[i];
+         storage[i * 2 + 1].u = *(((uint32_t *)&val->value.d[i]) + 1);
+         break;
       case GLSL_TYPE_BOOL:
         storage[i].b = val->value.b[i] ? boolean_true : 0;
         break;
@@ -84,6 +89,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
       case GLSL_TYPE_ATOMIC_UINT:
       case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_VOID:
+      case GLSL_TYPE_SUBROUTINE:
       case GLSL_TYPE_ERROR:
         /* All other types should have already been filtered by other
          * paths in the caller.
@@ -94,11 +100,16 @@ copy_constant_to_storage(union gl_constant_value *storage,
    }
 }
 
+/**
+ * Initialize an opaque uniform from the value of an explicit binding
+ * qualifier specified in the shader.  Atomic counters are different because
+ * they have no storage and should be handled elsewhere.
+ */
 void
-set_sampler_binding(gl_shader_program *prog, const char *name, int binding)
+set_opaque_binding(gl_shader_program *prog, const char *name, int binding)
 {
    struct gl_uniform_storage *const storage =
-      get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);
+      get_storage(prog->UniformStorage, prog->NumUniformStorage, name);
 
    if (storage == NULL) {
       assert(storage != NULL);
@@ -121,11 +132,20 @@ set_sampler_binding(gl_shader_program *prog, const char *name, int binding)
    for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
       gl_shader *shader = prog->_LinkedShaders[sh];
 
-      if (shader && storage->sampler[sh].active) {
-         for (unsigned i = 0; i < elements; i++) {
-            unsigned index = storage->sampler[sh].index + i;
+      if (shader) {
+         if (storage->type->base_type == GLSL_TYPE_SAMPLER &&
+             storage->opaque[sh].active) {
+            for (unsigned i = 0; i < elements; i++) {
+               const unsigned index = storage->opaque[sh].index + i;
+               shader->SamplerUnits[index] = storage->storage[i].i;
+            }
 
-            shader->SamplerUnits[index] = storage->storage[i].i;
+         } else if (storage->type->base_type == GLSL_TYPE_IMAGE &&
+                    storage->opaque[sh].active) {
+            for (unsigned i = 0; i < elements; i++) {
+               const unsigned index = storage->opaque[sh].index + i;
+               shader->ImageUnits[index] = storage->storage[i].i;
+            }
          }
       }
    }
@@ -188,7 +208,7 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
 
    struct gl_uniform_storage *const storage =
       get_storage(prog->UniformStorage,
-                 prog->NumUserUniformStorage,
+                  prog->NumUniformStorage,
                  name);
    if (storage == NULL) {
       assert(storage != NULL);
@@ -200,6 +220,7 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
         val->array_elements[0]->type->base_type;
       const unsigned int elements = val->array_elements[0]->type->components();
       unsigned int idx = 0;
+      unsigned dmul = (base_type == GLSL_TYPE_DOUBLE) ? 2 : 1;
 
       assert(val->type->length >= storage->array_elements);
       for (unsigned int i = 0; i < storage->array_elements; i++) {
@@ -209,7 +230,7 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
                                   elements,
                                   boolean_true);
 
-        idx += elements;
+        idx += elements * dmul;
       }
    } else {
       copy_constant_to_storage(storage->storage,
@@ -222,8 +243,8 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
          for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
             gl_shader *shader = prog->_LinkedShaders[sh];
 
-            if (shader && storage->sampler[sh].active) {
-               unsigned index = storage->sampler[sh].index;
+            if (shader && storage->opaque[sh].active) {
+               unsigned index = storage->opaque[sh].index;
 
                shader->SamplerUnits[index] = storage->storage[0].i;
             }
@@ -250,7 +271,8 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
       foreach_in_list(ir_instruction, node, shader->ir) {
         ir_variable *const var = node->as_variable();
 
-        if (!var || var->data.mode != ir_var_uniform)
+        if (!var || (var->data.mode != ir_var_uniform &&
+            var->data.mode != ir_var_shader_storage))
            continue;
 
         if (!mem_ctx)
@@ -259,9 +281,10 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
          if (var->data.explicit_binding) {
             const glsl_type *const type = var->type;
 
-            if (type->without_array()->is_sampler()) {
-               linker::set_sampler_binding(prog, var->name, var->data.binding);
-            } else if (var->is_in_uniform_block()) {
+            if (type->without_array()->is_sampler() ||
+                type->without_array()->is_image()) {
+               linker::set_opaque_binding(prog, var->name, var->data.binding);
+            } else if (var->is_in_buffer_block()) {
                const glsl_type *const iface_type = var->get_interface_type();
 
                /* If the variable is an array and it is an interface instance,
@@ -274,7 +297,7 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
                 *         float f[4];
                 *     };
                 *
-                * In this case "f" would pass is_in_uniform_block (above) and
+                * In this case "f" would pass is_in_buffer_block (above) and
                 * type->is_array(), but it will fail is_interface_instance().
                 */
                if (var->is_interface_instance() && var->type->is_array()) {
@@ -303,9 +326,9 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
             } else {
                assert(!"Explicit binding not on a sampler, UBO or atomic.");
             }
-         } else if (var->constant_value) {
+         } else if (var->constant_initializer) {
             linker::set_uniform_initializer(mem_ctx, prog, var->name,
-                                            var->type, var->constant_value,
+                                            var->type, var->constant_initializer,
                                             boolean_true);
          }
       }