glsl: Fix conversions in array constructors
authorChad Versace <chad@chad-versace.us>
Wed, 27 Jul 2011 20:00:02 +0000 (13:00 -0700)
committerChad Versace <chad@chad-versace.us>
Sat, 30 Jul 2011 14:27:30 +0000 (07:27 -0700)
Array constructors obey narrower conversion rules than other constructors
[1] --- they use the implicit conversion rules [2] instead of the scalar
constructor conversions [3].  But process_array_constructor() was
incorrectly applying the broader rules.

[1] GLSL 1.50 spec, Section 5.4.4 Array Constructors, page 52 (58 of pdf)
[2] GLSL 1.50 spec, Section 4.1.10 Implicit Conversions, page 25 (31 of pdf)
[3] GLSL 1.50 spec, Section 5.4.1 Conversion, page 48 (54 of pdf)

To fix this, first check (with glsl_type::can_be_implicitly_converted_to)
if an implicit conversion is legal before performing the conversion.

Fixes:
piglit:spec/glsl-1.20/compiler/structure-and-array-operations/array-ctor-implicit-conversion-bool-float.vert
piglit:spec/glsl-1.20/compiler/structure-and-array-operations/array-ctor-implicit-conversion-bvec*-vec*.vert

Note: This is a candidate for the 7.10 and 7.11 branches.
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Chad Versace <chad@chad-versace.us>
src/glsl/ast_function.cpp

index bdb73f487068930af565ad072077cf1b20518076..8bcf48dfd91a585d8b2ef0cffa3e15e60c95bf7c 100644 (file)
@@ -442,13 +442,21 @@ process_array_constructor(exec_list *instructions,
       ir_rvalue *ir = (ir_rvalue *) n;
       ir_rvalue *result = ir;
 
-      /* Apply implicit conversions (not the scalar constructor rules!) */
+      /* Apply implicit conversions (not the scalar constructor rules!). See
+       * the spec quote above. */
       if (constructor_type->element_type()->is_float()) {
         const glsl_type *desired_type =
            glsl_type::get_instance(GLSL_TYPE_FLOAT,
                                    ir->type->vector_elements,
                                    ir->type->matrix_columns);
-        result = convert_component(ir, desired_type);
+        if (result->type->can_implicitly_convert_to(desired_type)) {
+           /* Even though convert_component() implements the constructor
+            * conversion rules (not the implicit conversion rules), its safe
+            * to use it here because we already checked that the implicit
+            * conversion is legal.
+            */
+           result = convert_component(ir, desired_type);
+        }
       }
 
       if (result->type != constructor_type->element_type()) {