glsl: add support for ARB_blend_func_extended (v3)
authorDave Airlie <airlied@redhat.com>
Sat, 24 Mar 2012 13:33:41 +0000 (13:33 +0000)
committerDave Airlie <airlied@redhat.com>
Fri, 13 Apr 2012 16:19:01 +0000 (17:19 +0100)
This adds index support to the GLSL compiler.

I'm not 100% sure of my approach here, esp without how output ordering
happens wrt location, index pairs, in the "mark" function.

Since current hw doesn't ever have a location > 0 with an index > 0,
we don't have to work out if the output ordering the hw requires is
location, index, location, index or location, location, index, index.
But we have no hw to know, so punt on it for now.

v2: index requires layout - catch and error
    setup explicit index properly.

v3: drop idx_offset stuff, assume index follow location

Signed-off-by: Dave Airlie <airlied@redhat.com>
src/glsl/ast.h
src/glsl/ast_to_hir.cpp
src/glsl/builtin_variables.cpp
src/glsl/glsl_parser.yy
src/glsl/ir.h
src/glsl/ir_clone.cpp
src/glsl/ir_set_program_inouts.cpp
src/glsl/linker.cpp

index 9b1e0b192099fe5ff9e2f74599b1c1cdbf303ed0..b096c838c06d45276da019091f5191791d9b8db4 100644 (file)
@@ -363,6 +363,11 @@ struct ast_type_qualifier {
          * qualifier is used.
          */
         unsigned explicit_location:1;
+        /**
+         * Flag set if GL_ARB_explicit_attrib_location "index" layout
+         * qualifier is used.
+         */
+        unsigned explicit_index:1;
 
          /** \name Layout qualifiers for GL_AMD_conservative_depth */
          /** \{ */
@@ -386,6 +391,13 @@ struct ast_type_qualifier {
     * This field is only valid if \c explicit_location is set.
     */
    int location;
+   /**
+    * Index specified via GL_ARB_explicit_attrib_location layout
+    *
+    * \note
+    * This field is only valid if \c explicit_index is set.
+    */
+   int index;
 
    /**
     * Return true if and only if an interpolation qualifier is present.
index f4dfc4ce34cf11fd066e44cda45d3806ffd305bb..820c86c5e6bff196833febb2ebec521f6f3ff742 100644 (file)
@@ -2092,14 +2092,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
         } else {
            var->location = qual->location;
         }
+        if (qual->flags.q.explicit_index) {
+           var->explicit_index = true;
+           var->index = qual->index;
+        }
       }
+   } else if (qual->flags.q.explicit_index) {
+        _mesa_glsl_error(loc, state,
+                         "explicit index requires explicit location\n");
    }
 
    /* Does the declaration use the 'layout' keyword?
     */
    const bool uses_layout = qual->flags.q.pixel_center_integer
       || qual->flags.q.origin_upper_left
-      || qual->flags.q.explicit_location;
+      || qual->flags.q.explicit_location; /* no need for index since it relies on location */
 
    /* Does the declaration use the deprecated 'attribute' or 'varying'
     * keywords?
index 516a69caff937cd4dc12b157642308892758abff..03b64c931a4f691d1db2960556beb101d16db0d5 100644 (file)
@@ -408,6 +408,7 @@ add_variable(exec_list *instructions, glsl_symbol_table *symtab,
 
    var->location = slot;
    var->explicit_location = (slot >= 0);
+   var->explicit_index = 0;
 
    /* Once the variable is created an initialized, add it to the symbol table
     * and add the declaration to the IR stream.
index 920213c3035c404faf657ce0f241ecc844984646..5753acf3cd1c430f13abb0cf6eeb0127d0c25a0e 100644 (file)
@@ -1103,8 +1103,14 @@ layout_qualifier_id_list:
           if ($1.flags.q.explicit_location)
              $$.location = $1.location;
 
+          if ($1.flags.q.explicit_index)
+             $$.index = $1.index;
+
           if ($3.flags.q.explicit_location)
              $$.location = $3.location;
+
+          if ($3.flags.q.explicit_index)
+             $$.index = $3.index;
        }
        ;
 
@@ -1191,6 +1197,20 @@ layout_qualifier_id:
                    YYERROR;
                 }
              }
+
+             if (strcmp("index", $1) == 0) {
+                got_one = true;
+
+                $$.flags.q.explicit_index = 1;
+
+                if ($3 >= 0) {
+                   $$.index = $3;
+                } else {
+                   _mesa_glsl_error(& @3, state,
+                                    "invalid index %d specified\n", $3);
+                    YYERROR;
+                 }
+              }
           }
 
           /* If the identifier didn't match any known layout identifiers,
index 9450e8f843042169990563263ffb6ffe5d9de53c..d6c6a607ae8696ea1965cf11e502ce918a57827a 100644 (file)
@@ -386,6 +386,7 @@ public:
     * no effect).
     */
    unsigned explicit_location:1;
+   unsigned explicit_index:1;
 
    /**
     * Does this variable have an initializer?
index 26b0d8f5f3f40798d87f52b37fb72617c3fb9e39..5a7a71cf6bade3a6392c07c2a155056eeb768a78 100644 (file)
@@ -57,6 +57,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    var->origin_upper_left = this->origin_upper_left;
    var->pixel_center_integer = this->pixel_center_integer;
    var->explicit_location = this->explicit_location;
+   var->explicit_index = this->explicit_index;
    var->has_initializer = this->has_initializer;
    var->depth_layout = this->depth_layout;
 
@@ -74,6 +75,9 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    if (this->explicit_location)
       var->location = this->location;
 
+   if (this->explicit_index)
+      var->index = this->index;
+
    if (this->constant_value)
       var->constant_value = this->constant_value->clone(mem_ctx, ht);
 
index 8c2bc30d614a96f3192d571717b14b30e746f257..8f3edb96936da51caea0e63f4fb9aab3d0b31b43 100644 (file)
@@ -81,12 +81,12 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
     */
 
    for (int i = 0; i < len; i++) {
-      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i);
+      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i);
       if (var->mode == ir_var_in) {
         prog->InputsRead |= bitfield;
          if (is_fragment_shader) {
             gl_fragment_program *fprog = (gl_fragment_program *) prog;
-            fprog->InterpQualifier[var->location + offset + i] =
+            fprog->InterpQualifier[var->location + var->index + offset + i] =
                (glsl_interp_qualifier) var->interpolation;
          }
       } else if (var->mode == ir_var_system_value) {
index 49b6b8f4a5e84ece80fa5fcb3c3ec7e074e6ad9e..6ba297237c74438336d122a45cf11a8268998ff0 100644 (file)
@@ -1274,10 +1274,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
         }
       } else if (target_index == MESA_SHADER_FRAGMENT) {
         unsigned binding;
+        unsigned index;
 
         if (prog->FragDataBindings->get(binding, var->name)) {
            assert(binding >= FRAG_RESULT_DATA0);
            var->location = binding;
+
+           if (prog->FragDataIndexBindings->get(index, var->name)) {
+              var->index = index;
+           }
         }
       }
 
@@ -1288,7 +1293,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
        */
       const unsigned slots = count_attribute_slots(var->type);
       if (var->location != -1) {
-        if (var->location >= generic_base) {
+        if (var->location >= generic_base && var->index < 1) {
            /* From page 61 of the OpenGL 4.0 spec:
             *
             *     "LinkProgram will fail if the attribute bindings assigned
@@ -1333,8 +1338,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
                  ? "vertex shader input" : "fragment shader output";
               linker_error(prog,
                            "insufficient contiguous locations "
-                           "available for %s `%s'", string,
-                           var->name);
+                           "available for %s `%s' %d %d %d", string,
+                           var->name, used_locations, use_mask, attr);
               return false;
            }
 
@@ -2321,7 +2326,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       goto done;
    }
 
-   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) {
+   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) {
       goto done;
    }