glsl: fix xfb_offset unsized array validation
authorTimothy Arceri <timothy.arceri@collabora.com>
Fri, 27 May 2016 09:07:19 +0000 (19:07 +1000)
committerTimothy Arceri <timothy.arceri@collabora.com>
Mon, 30 May 2016 05:11:47 +0000 (15:11 +1000)
This partially fixes CTS test:
GL44-CTS.enhanced_layouts.xfb_get_program_resource_api

The test now fails at a tes evaluation shader with unsized output arrays.

The ARB_enhanced_layouts spec says:

   "It is a compile-time error to apply xfb_offset to the declaration of an
   unsized array."

So this seems like a bug in the CTS.

Reviewed-by: Dave Airlie <airlied@redhat.com>
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/ir.cpp
src/compiler/glsl/ir.h
src/compiler/glsl/link_varyings.cpp

index 400d3c4e90857dfb285e792f2322e80d43392463..c0cb3d68191b52242b22fcf071d894c51dc4c959 100644 (file)
@@ -3442,11 +3442,11 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
    if (qual->flags.q.explicit_xfb_offset) {
       unsigned qual_xfb_offset;
       unsigned component_size = var->type->contains_double() ? 8 : 4;
-
+      const glsl_type *t = get_varying_type(var, state->stage);
       if (process_qualifier_constant(state, loc, "xfb_offset",
                                      qual->offset, &qual_xfb_offset) &&
           validate_xfb_offset_qualifier(loc, state, (int) qual_xfb_offset,
-                                        var->type, component_size)) {
+                                        t, component_size)) {
          var->data.offset = qual_xfb_offset;
          var->data.explicit_xfb_offset = true;
       }
@@ -7336,12 +7336,6 @@ ast_interface_block::hir(exec_list *instructions,
                                         packing,
                                         this->block_name);
 
-   unsigned component_size = block_type->contains_double() ? 8 : 4;
-   int xfb_offset =
-      layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
-   validate_xfb_offset_qualifier(&loc, state, xfb_offset, block_type,
-                                 component_size);
-
    if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) {
       YYLTYPE loc = this->get_location();
       _mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' "
@@ -7480,6 +7474,13 @@ ast_interface_block::hir(exec_list *instructions,
                                       var_mode);
       }
 
+      unsigned component_size = block_type->contains_double() ? 8 : 4;
+      int xfb_offset =
+         layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
+      const glsl_type *t = get_varying_type(var, state->stage);
+      validate_xfb_offset_qualifier(&loc, state, xfb_offset, t,
+                                    component_size);
+
       var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
          ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
 
@@ -7530,6 +7531,12 @@ ast_interface_block::hir(exec_list *instructions,
        */
       assert(this->array_specifier == NULL);
 
+      unsigned component_size = block_type->contains_double() ? 8 : 4;
+      int xfb_offset =
+         layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
+      validate_xfb_offset_qualifier(&loc, state, xfb_offset, block_type,
+                                    component_size);
+
       for (unsigned i = 0; i < num_variables; i++) {
          ir_variable *var =
             new(state) ir_variable(fields[i].type,
index 5bb3ac3c214f8e7caf12153378bca34eb083a212..70859a7bd9d88d61e71402c735b1d3ba39681002 100644 (file)
@@ -2021,3 +2021,26 @@ mode_string(const ir_variable *var)
    assert(!"Should not get here.");
    return "invalid variable";
 }
+
+/**
+ * Get the varying type stripped of the outermost array if we're processing
+ * a stage whose varyings are arrays indexed by a vertex number (such as
+ * geometry shader inputs).
+ */
+const glsl_type *
+get_varying_type(const ir_variable *var, gl_shader_stage stage)
+{
+   const glsl_type *type = var->type;
+
+   if (!var->data.patch &&
+       ((var->data.mode == ir_var_shader_out &&
+         stage == MESA_SHADER_TESS_CTRL) ||
+        (var->data.mode == ir_var_shader_in &&
+         (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL ||
+          stage == MESA_SHADER_GEOMETRY)))) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
+   return type;
+}
index e8efd27112f3e317279c274bbf5535bfc24ae3f2..b1cfd526fefca05f678905f171c91078e5fbd8c0 100644 (file)
@@ -2621,6 +2621,9 @@ is_gl_identifier(const char *s)
    return s && s[0] == 'g' && s[1] == 'l' && s[2] == '_';
 }
 
+const glsl_type *
+get_varying_type(const ir_variable *var, gl_shader_stage stage);
+
 extern "C" {
 #endif /* __cplusplus */
 
index 7c3bedf3574cc7307727ca9d6aceeeefca0e7af3..34c8906db2f76b37ca3b2c480fb967afdd270926 100644 (file)
 #include "program.h"
 
 
-/**
- * Get the varying type stripped of the outermost array if we're processing
- * a stage whose varyings are arrays indexed by a vertex number (such as
- * geometry shader inputs).
- */
-static const glsl_type *
-get_varying_type(const ir_variable *var, gl_shader_stage stage)
-{
-   const glsl_type *type = var->type;
-
-   if (!var->data.patch &&
-       ((var->data.mode == ir_var_shader_out &&
-         stage == MESA_SHADER_TESS_CTRL) ||
-        (var->data.mode == ir_var_shader_in &&
-         (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL ||
-          stage == MESA_SHADER_GEOMETRY)))) {
-      assert(type->is_array());
-      type = type->fields.array;
-   }
-
-   return type;
-}
-
 static void
 create_xfb_varying_names(void *mem_ctx, const glsl_type *t, char **name,
                          size_t name_length, unsigned *count,