[Mesa-dev] [PATCH 07/11] glsl: add double support

Pohjolainen, Topi topi.pohjolainen at intel.com
Tue Aug 19 09:38:37 PDT 2014


On Thu, Aug 14, 2014 at 08:52:38PM +1000, Dave Airlie wrote:
> This adds the guts of the fp64 implementation to the GLSL compiler.
> 
> - builtin double types
> - double constant support
> - lexer parsing for double types (lf, LF)
> - enforcing flat on double fs inputs
> - double operations (d2f,f2d, pack/unpack, frexp - in 2 parts)
> - ir builder bits.
> - double constant expression handling
> 
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/glsl/ast.h                         |   2 +
>  src/glsl/ast_function.cpp              |  36 ++++++
>  src/glsl/ast_to_hir.cpp                |  28 ++++-
>  src/glsl/builtin_type_macros.h         |  16 +++
>  src/glsl/builtin_types.cpp             |  30 +++++
>  src/glsl/glsl_lexer.ll                 |  42 ++++++-
>  src/glsl/glsl_parser.yy                |  33 +++++-
>  src/glsl/glsl_parser_extras.cpp        |   4 +
>  src/glsl/glsl_types.cpp                |  74 ++++++++++--
>  src/glsl/glsl_types.h                  |  18 ++-
>  src/glsl/ir.cpp                        |  90 +++++++++++++-
>  src/glsl/ir.h                          |  17 +++
>  src/glsl/ir_builder.cpp                |  11 ++
>  src/glsl/ir_builder.h                  |   3 +
>  src/glsl/ir_clone.cpp                  |   1 +
>  src/glsl/ir_constant_expression.cpp    | 207 ++++++++++++++++++++++++++++-----
>  src/glsl/ir_print_visitor.cpp          |  11 ++
>  src/glsl/ir_set_program_inouts.cpp     |  24 +++-
>  src/glsl/ir_validate.cpp               |  45 ++++++-
>  src/glsl/link_uniform_initializers.cpp |   4 +
>  src/glsl/link_uniforms.cpp             |   2 +
>  src/glsl/link_varyings.cpp             |   3 +-
>  src/mesa/program/ir_to_mesa.cpp        |   6 +
>  23 files changed, 641 insertions(+), 66 deletions(-)
> 
> diff --git a/src/glsl/ast.h b/src/glsl/ast.h
> index 15bf086..99274ed 100644
> --- a/src/glsl/ast.h
> +++ b/src/glsl/ast.h
> @@ -189,6 +189,7 @@ enum ast_operators {
>     ast_uint_constant,
>     ast_float_constant,
>     ast_bool_constant,
> +   ast_double_constant,
>  
>     ast_sequence,
>     ast_aggregate
> @@ -236,6 +237,7 @@ public:
>        float float_constant;
>        unsigned uint_constant;
>        int bool_constant;
> +      double double_constant;
>     } primary_expression;
>  
>  
> diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
> index 39c7bee..6169ae6 100644
> --- a/src/glsl/ast_function.cpp
> +++ b/src/glsl/ast_function.cpp
> @@ -570,6 +570,10 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
>  	 result = new(ctx) ir_expression(ir_unop_i2u,
>  		  new(ctx) ir_expression(ir_unop_b2i, src));
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 result = new(ctx) ir_expression(ir_unop_f2u,
> +                  new(ctx) ir_expression(ir_unop_d2f, src));
> +	 break;
>        }
>        break;
>     case GLSL_TYPE_INT:
> @@ -583,6 +587,10 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
>        case GLSL_TYPE_BOOL:
>  	 result = new(ctx) ir_expression(ir_unop_b2i, src);
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 result = new(ctx) ir_expression(ir_unop_f2i,
> +                  new(ctx) ir_expression(ir_unop_d2f, src));
> +	 break;
>        }
>        break;
>     case GLSL_TYPE_FLOAT:
> @@ -596,6 +604,9 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
>        case GLSL_TYPE_BOOL:
>  	 result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL);
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 result = new(ctx) ir_expression(ir_unop_d2f, desired_type, src, NULL);
> +	 break;
>        }
>        break;
>     case GLSL_TYPE_BOOL:
> @@ -610,8 +621,30 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
>        case GLSL_TYPE_FLOAT:
>  	 result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL);
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 result = new(ctx) ir_expression(ir_unop_f2b,
> +                  new(ctx) ir_expression(ir_unop_d2f, src));
> +	 break;
>        }
>        break;
> +   case GLSL_TYPE_DOUBLE:
> +      switch (b) {
> +      case GLSL_TYPE_INT:
> +         result = new(ctx) ir_expression(ir_unop_f2d,
> +                  new(ctx) ir_expression(ir_unop_i2f, src));
> +	 break;
> +      case GLSL_TYPE_UINT:
> +         result = new(ctx) ir_expression(ir_unop_f2d,
> +                  new(ctx) ir_expression(ir_unop_u2f, src));
> +	 break;
> +      case GLSL_TYPE_BOOL:
> +         result = new(ctx) ir_expression(ir_unop_f2d,
> +                  new(ctx) ir_expression(ir_unop_b2f, src));
> +	 break;
> +      case GLSL_TYPE_FLOAT:
> +	 result = new(ctx) ir_expression(ir_unop_f2d, desired_type, src, NULL);
> +	 break;
> +      }
>     }
>  
>     assert(result != NULL);
> @@ -1009,6 +1042,9 @@ emit_inline_vector_constructor(const glsl_type *type,
>  	       case GLSL_TYPE_FLOAT:
>  		  data.f[i + base_component] = c->get_float_component(i);
>  		  break;
> +	       case GLSL_TYPE_DOUBLE:
> +		  data.d[i + base_component] = c->get_double_component(i);
> +		  break;
>  	       case GLSL_TYPE_BOOL:
>  		  data.b[i + base_component] = c->get_bool_component(i);
>  		  break;
> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
> index 30b02d0..d1aae69 100644
> --- a/src/glsl/ast_to_hir.cpp
> +++ b/src/glsl/ast_to_hir.cpp
> @@ -172,6 +172,7 @@ get_conversion_operation(const glsl_type *to, const glsl_type *from,
>        switch (from->base_type) {
>        case GLSL_TYPE_INT: return ir_unop_i2f;
>        case GLSL_TYPE_UINT: return ir_unop_u2f;
> +      case GLSL_TYPE_DOUBLE: return ir_unop_d2f;

This is to support implicit conversion (only called by
apply_implicit_conversion()), right? Isn't this now allowing a conversion
from higher to lower precision (double to float) which is specifically
prohibited. Quoting the spec:

    "Modify Section 4.1.10, Implicit Conversions, p. 27

     (modify table of implicit conversions)

                                Can be implicitly
        Type of expression        converted to
        ---------------------   -------------------
        int                     uint(*), float, double
        ivec2                   uvec2(*), vec2, dvec2
        ivec3                   uvec3(*), vec3, dvec3
        ivec4                   uvec4(*), vec4, dvec4

        uint                    float, double
        uvec2                   vec2, dvec2
        uvec3                   vec3, dvec3
        uvec4                   vec4, dvec4

        float                   double
        vec2                    dvec2
        vec3                    dvec3
        vec4                    dvec4

        mat2                    dmat2
        mat3                    dmat3
        mat4                    dmat4
        mat2x3                  dmat2x3
        mat2x4                  dmat2x4
        mat3x2                  dmat3x2
        mat3x4                  dmat3x4
        mat4x2                  dmat4x2
        mat4x3                  dmat4x3

        (*) if ARB_gpu_shader5 or NV_gpu_shader5 is supported

    (modify second paragraph of the section) No implicit conversions are
    provided to convert from unsigned to signed integer types, from
    floating-point to integer types, or from higher-precision to
    lower-precision types."

And aren't we now missing the conversions into double? Or are these handled
somewhere else?

>        default: return (ir_expression_operation)0;
>        }
>  
> @@ -340,8 +341,8 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
>      * type of both operands must be float.
>      */
>     assert(type_a->is_matrix() || type_b->is_matrix());
> -   assert(type_a->base_type == GLSL_TYPE_FLOAT);
> -   assert(type_b->base_type == GLSL_TYPE_FLOAT);
> +   assert(type_a->base_type == GLSL_TYPE_FLOAT || type_a->base_type == GLSL_TYPE_DOUBLE);
> +   assert(type_b->base_type == GLSL_TYPE_FLOAT || type_b->base_type == GLSL_TYPE_DOUBLE);
>  
>     /*   "* The operator is add (+), subtract (-), or divide (/), and the
>      *      operands are matrices with the same number of rows and the same
> @@ -960,6 +961,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
>     case GLSL_TYPE_UINT:
>     case GLSL_TYPE_INT:
>     case GLSL_TYPE_BOOL:
> +   case GLSL_TYPE_DOUBLE:
>        return new(mem_ctx) ir_expression(operation, op0, op1);
>  
>     case GLSL_TYPE_ARRAY: {
> @@ -1749,6 +1751,10 @@ ast_expression::do_hir(exec_list *instructions,
>        result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
>        break;
>  
> +   case ast_double_constant:
> +      result = new(ctx) ir_constant(this->primary_expression.double_constant);
> +      break;
> +
>     case ast_sequence: {
>        /* It should not be possible to generate a sequence in the AST without
>         * any expressions in it.
> @@ -2562,6 +2568,12 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>           _mesa_glsl_error(loc, state,
>                            "varying variables may not be of type struct");
>           break;
> +      case GLSL_TYPE_DOUBLE:
> +         if (state->is_version(400, 0) || state->ARB_gpu_shader_fp64_enable)
> +            break;
> +         _mesa_glsl_error(loc, state,
> +                          "varying variables may not be of type double");
> +         break;
>        default:
>           _mesa_glsl_error(loc, state, "illegal type for a varying variable");
>           break;
> @@ -3612,6 +3624,18 @@ ast_declarator_list::hir(exec_list *instructions,
>                            var_type);
>        }
>  
> +      /* Double fragment inputs must be qualified with 'flat'. */
> +      if ((state->is_version(400, 0) || state->ARB_gpu_shader_fp64_enable) &&
> +          var->type->contains_double() &&
> +          var->data.interpolation != INTERP_QUALIFIER_FLAT &&
> +          ((state->stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in)
> +             )) {
> +         const char *var_type = (state->stage == MESA_SHADER_VERTEX) ?
> +            "vertex output" : "fragment input";
> +         _mesa_glsl_error(&loc, state, "if a %s is (or contains) "
> +                          "a double, then it must be qualified with 'flat'",
> +                          var_type);
> +      }
>  
>        /* Interpolation qualifiers cannot be applied to 'centroid' and
>         * 'centroid varying'.
> diff --git a/src/glsl/builtin_type_macros.h b/src/glsl/builtin_type_macros.h
> index 236e1ce..bf74eb3 100644
> --- a/src/glsl/builtin_type_macros.h
> +++ b/src/glsl/builtin_type_macros.h
> @@ -64,6 +64,22 @@ DECL_TYPE(mat3x4, GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3)
>  DECL_TYPE(mat4x2, GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4)
>  DECL_TYPE(mat4x3, GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4)
>  
> +DECL_TYPE(double,  GL_DOUBLE,        GLSL_TYPE_DOUBLE, 1, 1)
> +DECL_TYPE(dvec2,   GL_DOUBLE_VEC2,   GLSL_TYPE_DOUBLE, 2, 1)
> +DECL_TYPE(dvec3,   GL_DOUBLE_VEC3,   GLSL_TYPE_DOUBLE, 3, 1)
> +DECL_TYPE(dvec4,   GL_DOUBLE_VEC4,   GLSL_TYPE_DOUBLE, 4, 1)
> +
> +DECL_TYPE(dmat2,   GL_DOUBLE_MAT2,   GLSL_TYPE_DOUBLE, 2, 2)
> +DECL_TYPE(dmat3,   GL_DOUBLE_MAT3,   GLSL_TYPE_DOUBLE, 3, 3)
> +DECL_TYPE(dmat4,   GL_DOUBLE_MAT4,   GLSL_TYPE_DOUBLE, 4, 4)
> +
> +DECL_TYPE(dmat2x3, GL_DOUBLE_MAT2x3, GLSL_TYPE_DOUBLE, 3, 2)
> +DECL_TYPE(dmat2x4, GL_DOUBLE_MAT2x4, GLSL_TYPE_DOUBLE, 4, 2)
> +DECL_TYPE(dmat3x2, GL_DOUBLE_MAT3x2, GLSL_TYPE_DOUBLE, 2, 3)
> +DECL_TYPE(dmat3x4, GL_DOUBLE_MAT3x4, GLSL_TYPE_DOUBLE, 4, 3)
> +DECL_TYPE(dmat4x2, GL_DOUBLE_MAT4x2, GLSL_TYPE_DOUBLE, 2, 4)
> +DECL_TYPE(dmat4x3, GL_DOUBLE_MAT4x3, GLSL_TYPE_DOUBLE, 3, 4)
> +
>  DECL_TYPE(sampler1D,         GL_SAMPLER_1D,                   GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D,   0, 0, GLSL_TYPE_FLOAT)
>  DECL_TYPE(sampler2D,         GL_SAMPLER_2D,                   GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D,   0, 0, GLSL_TYPE_FLOAT)
>  DECL_TYPE(sampler3D,         GL_SAMPLER_3D,                   GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D,   0, 0, GLSL_TYPE_FLOAT)
> diff --git a/src/glsl/builtin_types.cpp b/src/glsl/builtin_types.cpp
> index 10fac0f..fef86df 100644
> --- a/src/glsl/builtin_types.cpp
> +++ b/src/glsl/builtin_types.cpp
> @@ -159,6 +159,20 @@ const static struct builtin_type_versions {
>     T(mat4x2,                          120, 300)
>     T(mat4x3,                          120, 300)
>  
> +   T(double,                          400, 999)
> +   T(dvec2,                           400, 999)
> +   T(dvec3,                           400, 999)
> +   T(dvec4,                           400, 999)
> +   T(dmat2,                           400, 999)
> +   T(dmat3,                           400, 999)
> +   T(dmat4,                           400, 999)
> +   T(dmat2x3,                         400, 999)
> +   T(dmat2x4,                         400, 999)
> +   T(dmat3x2,                         400, 999)
> +   T(dmat3x4,                         400, 999)
> +   T(dmat4x2,                         400, 999)
> +   T(dmat4x3,                         400, 999)
> +
>     T(sampler1D,                       110, 999)
>     T(sampler2D,                       110, 100)
>     T(sampler3D,                       110, 300)
> @@ -361,5 +375,21 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
>     if (state->ARB_shader_atomic_counters_enable) {
>        add_type(symbols, glsl_type::atomic_uint_type);
>     }
> +
> +   if (state->ARB_gpu_shader_fp64_enable) {
> +      add_type(symbols, glsl_type::double_type);
> +      add_type(symbols, glsl_type::dvec2_type);
> +      add_type(symbols, glsl_type::dvec3_type);
> +      add_type(symbols, glsl_type::dvec4_type);
> +      add_type(symbols, glsl_type::dmat2_type);
> +      add_type(symbols, glsl_type::dmat3_type);
> +      add_type(symbols, glsl_type::dmat4_type);
> +      add_type(symbols, glsl_type::dmat2x3_type);
> +      add_type(symbols, glsl_type::dmat2x4_type);
> +      add_type(symbols, glsl_type::dmat3x2_type);
> +      add_type(symbols, glsl_type::dmat3x4_type);
> +      add_type(symbols, glsl_type::dmat4x2_type);
> +      add_type(symbols, glsl_type::dmat4x3_type);
> +   }
>  }
>  /** @} */
> diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
> index b7c4aad..7d72a0e 100644
> --- a/src/glsl/glsl_lexer.ll
> +++ b/src/glsl/glsl_lexer.ll
> @@ -468,6 +468,27 @@ layout		{
>  			    return FLOATCONSTANT;
>  			}
>  
> +[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?(lf|LF)	{
> +			    yylval->dreal = glsl_strtod(yytext, NULL);
> +			    return DOUBLECONSTANT;
> +			}
> +\.[0-9]+([eE][+-]?[0-9]+)?(lf|LF)		{
> +			    yylval->dreal = glsl_strtod(yytext, NULL);
> +			    return DOUBLECONSTANT;
> +			}
> +[0-9]+\.([eE][+-]?[0-9]+)?(lf|LF)		{
> +			    yylval->dreal = glsl_strtod(yytext, NULL);
> +			    return DOUBLECONSTANT;
> +			}
> +[0-9]+[eE][+-]?[0-9]+(lf|LF)	{
> +			    yylval->dreal = glsl_strtod(yytext, NULL);
> +			    return DOUBLECONSTANT;
> +			}
> +[0-9]+(lf|LF)		{
> +			    yylval->dreal = glsl_strtod(yytext, NULL);
> +			    return DOUBLECONSTANT;
> +			}
> +
>  true			{
>  			    yylval->n = 1;
>  			    return BOOLCONSTANT;
> @@ -499,7 +520,7 @@ external	KEYWORD(110, 100, 0, 0, EXTERNAL);
>  interface	KEYWORD(110, 100, 0, 0, INTERFACE);
>  long		KEYWORD(110, 100, 0, 0, LONG_TOK);
>  short		KEYWORD(110, 100, 0, 0, SHORT_TOK);
> -double		KEYWORD(110, 100, 400, 0, DOUBLE_TOK);
> +double		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DOUBLE_TOK);
>  half		KEYWORD(110, 100, 0, 0, HALF);
>  fixed		KEYWORD(110, 100, 0, 0, FIXED_TOK);
>  unsigned	KEYWORD(110, 100, 0, 0, UNSIGNED);
> @@ -508,9 +529,22 @@ output		KEYWORD(110, 100, 0, 0, OUTPUT);
>  hvec2		KEYWORD(110, 100, 0, 0, HVEC2);
>  hvec3		KEYWORD(110, 100, 0, 0, HVEC3);
>  hvec4		KEYWORD(110, 100, 0, 0, HVEC4);
> -dvec2		KEYWORD(110, 100, 400, 0, DVEC2);
> -dvec3		KEYWORD(110, 100, 400, 0, DVEC3);
> -dvec4		KEYWORD(110, 100, 400, 0, DVEC4);
> +dvec2		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DVEC2);
> +dvec3		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DVEC3);
> +dvec4		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DVEC4);
> +dmat2		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT2X2);
> +dmat3		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT3X3);
> +dmat4		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT4X4);
> +dmat2x2		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT2X2);
> +dmat2x3		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT2X3);
> +dmat2x4		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT2X4);
> +dmat3x2		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT3X2);
> +dmat3x3		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT3X3);
> +dmat3x4		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT3X4);
> +dmat4x2		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT4X2);
> +dmat4x3		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT4X3);
> +dmat4x4		KEYWORD_WITH_ALT(110, 100, 400, 0, yyextra->ARB_gpu_shader_fp64_enable, DMAT4X4);
> +
>  fvec2		KEYWORD(110, 100, 0, 0, FVEC2);
>  fvec3		KEYWORD(110, 100, 0, 0, FVEC3);
>  fvec4		KEYWORD(110, 100, 0, 0, FVEC4);
> diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
> index 4c87163..00d4bca 100644
> --- a/src/glsl/glsl_parser.yy
> +++ b/src/glsl/glsl_parser.yy
> @@ -91,6 +91,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>  %union {
>     int n;
>     float real;
> +   double dreal;
>     const char *identifier;
>  
>     struct ast_type_qualifier type_qualifier;
> @@ -125,14 +126,17 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>     } selection_rest_statement;
>  }
>  
> -%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK
> +%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK DOUBLE_TOK
>  %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
> -%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4
> +%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4 DVEC2 DVEC3 DVEC4
>  %token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
>  %token NOPERSPECTIVE FLAT SMOOTH
>  %token MAT2X2 MAT2X3 MAT2X4
>  %token MAT3X2 MAT3X3 MAT3X4
>  %token MAT4X2 MAT4X3 MAT4X4
> +%token DMAT2X2 DMAT2X3 DMAT2X4
> +%token DMAT3X2 DMAT3X3 DMAT3X4
> +%token DMAT4X2 DMAT4X3 DMAT4X4
>  %token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
>  %token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW
>  %token SAMPLER2DARRAYSHADOW SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW
> @@ -159,6 +163,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>  %type <identifier> any_identifier
>  %type <interface_block> instance_name_opt
>  %token <real> FLOATCONSTANT
> +%token <dreal> DOUBLECONSTANT
>  %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
>  %token <identifier> FIELD_SELECTION
>  %token LEFT_OP RIGHT_OP
> @@ -179,8 +184,8 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>      */
>  %token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
>  %token INLINE_TOK NOINLINE PUBLIC_TOK STATIC EXTERN EXTERNAL
> -%token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT
> -%token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
> +%token LONG_TOK SHORT_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT
> +%token HVEC2 HVEC3 HVEC4 FVEC2 FVEC3 FVEC4
>  %token SAMPLER3DRECT
>  %token SIZEOF CAST NAMESPACE USING
>  %token RESOURCE PATCH
> @@ -420,6 +425,13 @@ primary_expression:
>        $$->set_location(@1);
>        $$->primary_expression.float_constant = $1;
>     }
> +   | DOUBLECONSTANT
> +   {
> +      void *ctx = state;
> +      $$ = new(ctx) ast_expression(ast_double_constant, NULL, NULL, NULL);
> +      $$->set_location(@1);
> +      $$->primary_expression.double_constant = $1;
> +   }
>     | BOOLCONSTANT
>     {
>        void *ctx = state;
> @@ -1839,6 +1851,7 @@ type_specifier_nonarray:
>  basic_type_specifier_nonarray:
>     VOID_TOK                 { $$ = "void"; }
>     | FLOAT_TOK              { $$ = "float"; }
> +   | DOUBLE_TOK             { $$ = "double"; }
>     | INT_TOK                { $$ = "int"; }
>     | UINT_TOK               { $$ = "uint"; }
>     | BOOL_TOK               { $$ = "bool"; }
> @@ -1854,6 +1867,9 @@ basic_type_specifier_nonarray:
>     | UVEC2                  { $$ = "uvec2"; }
>     | UVEC3                  { $$ = "uvec3"; }
>     | UVEC4                  { $$ = "uvec4"; }
> +   | DVEC2                  { $$ = "dvec2"; }
> +   | DVEC3                  { $$ = "dvec3"; }
> +   | DVEC4                  { $$ = "dvec4"; }
>     | MAT2X2                 { $$ = "mat2"; }
>     | MAT2X3                 { $$ = "mat2x3"; }
>     | MAT2X4                 { $$ = "mat2x4"; }
> @@ -1863,6 +1879,15 @@ basic_type_specifier_nonarray:
>     | MAT4X2                 { $$ = "mat4x2"; }
>     | MAT4X3                 { $$ = "mat4x3"; }
>     | MAT4X4                 { $$ = "mat4"; }
> +   | DMAT2X2                { $$ = "dmat2"; }
> +   | DMAT2X3                { $$ = "dmat2x3"; }
> +   | DMAT2X4                { $$ = "dmat2x4"; }
> +   | DMAT3X2                { $$ = "dmat3x2"; }
> +   | DMAT3X3                { $$ = "dmat3"; }
> +   | DMAT3X4                { $$ = "dmat3x4"; }
> +   | DMAT4X2                { $$ = "dmat4x2"; }
> +   | DMAT4X3                { $$ = "dmat4x3"; }
> +   | DMAT4X4                { $$ = "dmat4"; }
>     | SAMPLER1D              { $$ = "sampler1D"; }
>     | SAMPLER2D              { $$ = "sampler2D"; }
>     | SAMPLER2DRECT          { $$ = "sampler2DRect"; }
> diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
> index 53fbb25..6af242a 100644
> --- a/src/glsl/glsl_parser_extras.cpp
> +++ b/src/glsl/glsl_parser_extras.cpp
> @@ -954,6 +954,10 @@ ast_expression::print(void) const
>        printf("%f ", primary_expression.float_constant);
>        break;
>  
> +   case ast_double_constant:
> +      printf("%lf ", primary_expression.double_constant);
> +      break;
> +
>     case ast_bool_constant:
>        printf("%s ",
>  	     primary_expression.bool_constant
> diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
> index 66e9b13..649dbc4 100644
> --- a/src/glsl/glsl_types.cpp
> +++ b/src/glsl/glsl_types.cpp
> @@ -175,6 +175,22 @@ glsl_type::contains_integer() const
>  }
>  
>  bool
> +glsl_type::contains_double() const
> +{
> +   if (this->is_array()) {
> +      return this->fields.array->contains_double();
> +   } else if (this->is_record()) {
> +      for (unsigned int i = 0; i < this->length; i++) {
> +	 if (this->fields.structure[i].type->contains_double())
> +	    return true;
> +      }
> +      return false;
> +   } else {
> +      return this->is_double();
> +   }
> +}
> +
> +bool
>  glsl_type::contains_opaque() const {
>     switch (base_type) {
>     case GLSL_TYPE_SAMPLER:
> @@ -249,6 +265,8 @@ const glsl_type *glsl_type::get_base_type() const
>        return int_type;
>     case GLSL_TYPE_FLOAT:
>        return float_type;
> +   case GLSL_TYPE_DOUBLE:
> +      return double_type;
>     case GLSL_TYPE_BOOL:
>        return bool_type;
>     default:
> @@ -273,6 +291,8 @@ const glsl_type *glsl_type::get_scalar_type() const
>        return int_type;
>     case GLSL_TYPE_FLOAT:
>        return float_type;
> +   case GLSL_TYPE_DOUBLE:
> +      return double_type;
>     case GLSL_TYPE_BOOL:
>        return bool_type;
>     default:
> @@ -351,6 +371,17 @@ glsl_type::vec(unsigned components)
>     return ts[components - 1];
>  }
>  
> +const glsl_type *
> +glsl_type::dvec(unsigned components)
> +{
> +   if (components == 0 || components > 4)
> +      return error_type;
> +
> +   static const glsl_type *const ts[] = {
> +      double_type, dvec2_type, dvec3_type, dvec4_type
> +   };
> +   return ts[components - 1];
> +}
>  
>  const glsl_type *
>  glsl_type::ivec(unsigned components)
> @@ -410,13 +441,15 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
>  	 return ivec(rows);
>        case GLSL_TYPE_FLOAT:
>  	 return vec(rows);
> +      case GLSL_TYPE_DOUBLE:
> +	 return dvec(rows);
>        case GLSL_TYPE_BOOL:
>  	 return bvec(rows);
>        default:
>  	 return error_type;
>        }
>     } else {
> -      if ((base_type != GLSL_TYPE_FLOAT) || (rows == 1))
> +      if ((base_type != GLSL_TYPE_FLOAT && base_type != GLSL_TYPE_DOUBLE) || (rows == 1))
>  	 return error_type;
>  
>        /* GLSL matrix types are named mat{COLUMNS}x{ROWS}.  Only the following
> @@ -430,17 +463,32 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
>         */
>  #define IDX(c,r) (((c-1)*3) + (r-1))
>  
> -      switch (IDX(columns, rows)) {
> -      case IDX(2,2): return mat2_type;
> -      case IDX(2,3): return mat2x3_type;
> -      case IDX(2,4): return mat2x4_type;
> -      case IDX(3,2): return mat3x2_type;
> -      case IDX(3,3): return mat3_type;
> -      case IDX(3,4): return mat3x4_type;
> -      case IDX(4,2): return mat4x2_type;
> -      case IDX(4,3): return mat4x3_type;
> -      case IDX(4,4): return mat4_type;
> -      default: return error_type;
> +      if (base_type == GLSL_TYPE_DOUBLE) {
> +         switch (IDX(columns, rows)) {
> +         case IDX(2,2): return dmat2_type;
> +         case IDX(2,3): return dmat2x3_type;
> +         case IDX(2,4): return dmat2x4_type;
> +         case IDX(3,2): return dmat3x2_type;
> +         case IDX(3,3): return dmat3_type;
> +         case IDX(3,4): return dmat3x4_type;
> +         case IDX(4,2): return dmat4x2_type;
> +         case IDX(4,3): return dmat4x3_type;
> +         case IDX(4,4): return dmat4_type;
> +         default: return error_type;
> +         }
> +      } else {
> +         switch (IDX(columns, rows)) {
> +         case IDX(2,2): return mat2_type;
> +         case IDX(2,3): return mat2x3_type;
> +         case IDX(2,4): return mat2x4_type;
> +         case IDX(3,2): return mat3x2_type;
> +         case IDX(3,3): return mat3_type;
> +         case IDX(3,4): return mat3x4_type;
> +         case IDX(4,2): return mat4x2_type;
> +         case IDX(4,3): return mat4x3_type;
> +         case IDX(4,4): return mat4_type;
> +         default: return error_type;
> +         }
>        }
>     }
>  
> @@ -646,6 +694,7 @@ glsl_type::component_slots() const
>     case GLSL_TYPE_UINT:
>     case GLSL_TYPE_INT:
>     case GLSL_TYPE_FLOAT:
> +   case GLSL_TYPE_DOUBLE:
>     case GLSL_TYPE_BOOL:
>        return this->components();
>  
> @@ -1002,6 +1051,7 @@ glsl_type::count_attribute_slots() const
>     case GLSL_TYPE_INT:
>     case GLSL_TYPE_FLOAT:
>     case GLSL_TYPE_BOOL:
> +   case GLSL_TYPE_DOUBLE:
>        return this->matrix_columns;
>  
>     case GLSL_TYPE_STRUCT:
> diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
> index e00a3e0..4b2b7b1 100644
> --- a/src/glsl/glsl_types.h
> +++ b/src/glsl/glsl_types.h
> @@ -196,6 +196,7 @@ struct glsl_type {
>      * @{
>      */
>     static const glsl_type *vec(unsigned components);
> +   static const glsl_type *dvec(unsigned components);
>     static const glsl_type *ivec(unsigned components);
>     static const glsl_type *uvec(unsigned components);
>     static const glsl_type *bvec(unsigned components);
> @@ -372,7 +373,7 @@ struct glsl_type {
>     bool is_matrix() const
>     {
>        /* GLSL only has float matrices. */
> -      return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT);
> +      return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT || base_type == GLSL_TYPE_DOUBLE);
>     }
>  
>     /**
> @@ -380,7 +381,7 @@ struct glsl_type {
>      */
>     bool is_numeric() const
>     {
> -      return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT);
> +      return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_DOUBLE);
>     }
>  
>     /**
> @@ -398,6 +399,12 @@ struct glsl_type {
>     bool contains_integer() const;
>  
>     /**
> +    * Query whether or not type is a double type, or for struct and array
> +    * types, contains a double type.
> +    */
> +   bool contains_double() const;
> +
> +   /**
>      * Query whether or not a type is a float type
>      */
>     bool is_float() const
> @@ -406,6 +413,13 @@ struct glsl_type {
>     }
>  
>     /**
> +    * Query whether or not a type is a double type
> +    */
> +   bool is_double() const
> +   {
> +      return base_type == GLSL_TYPE_DOUBLE;
> +   }
> +   /**
>      * Query whether or not a type is a non-array boolean type
>      */
>     bool is_boolean() const
> diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
> index 28fd94b..6616e44 100644
> --- a/src/glsl/ir.cpp
> +++ b/src/glsl/ir.cpp
> @@ -268,6 +268,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>     case ir_unop_b2f:
>     case ir_unop_i2f:
>     case ir_unop_u2f:
> +   case ir_unop_d2f:
>     case ir_unop_bitcast_i2f:
>     case ir_unop_bitcast_u2f:
>        this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
> @@ -280,6 +281,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>  					   op0->type->vector_elements, 1);
>        break;
>  
> +   case ir_unop_f2d:
> +      this->type = glsl_type::get_instance(GLSL_TYPE_DOUBLE,
> +					   op0->type->vector_elements, 1);
> +      break;
> +
>     case ir_unop_i2u:
>     case ir_unop_f2u:
>     case ir_unop_bitcast_f2u:
> @@ -293,6 +299,10 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>        this->type = glsl_type::float_type;
>        break;
>  
> +   case ir_unop_unpack_double_2x32:
> +      this->type = glsl_type::uvec2_type;
> +      break;
> +
>     case ir_unop_any:
>        this->type = glsl_type::bool_type;
>        break;
> @@ -305,6 +315,10 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>        this->type = glsl_type::uint_type;
>        break;
>  
> +   case ir_unop_pack_double_2x32:
> +      this->type = glsl_type::double_type;
> +      break;
> +
>     case ir_unop_unpack_snorm_2x16:
>     case ir_unop_unpack_unorm_2x16:
>     case ir_unop_unpack_half_2x16:
> @@ -316,6 +330,14 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>        this->type = glsl_type::vec4_type;
>        break;
>  
> +   case ir_unop_frexp_sig:
> +      this->type = op0->type;
> +      break;
> +   case ir_unop_frexp_exp:
> +      this->type = glsl_type::get_instance(GLSL_TYPE_INT,
> +					   op0->type->vector_elements, 1);
> +      break;
> +
>     default:
>        assert(!"not reached: missing automatic type setup for ir_expression");
>        this->type = op0->type;
> @@ -390,7 +412,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
>        break;
>  
>     case ir_binop_dot:
> -      this->type = glsl_type::float_type;
> +      this->type = op0->type->get_base_type();
>        break;
>  
>     case ir_binop_pack_half_2x16_split:
> @@ -499,6 +521,8 @@ static const char *const operator_strs[] = {
>     "bitcast_u2f",
>     "bitcast_f2u",
>     "any",
> +   "d2f",
> +   "f2d",
>     "trunc",
>     "ceil",
>     "floor",
> @@ -526,6 +550,10 @@ static const char *const operator_strs[] = {
>     "bit_count",
>     "find_msb",
>     "find_lsb",
> +   "packDouble2x32",
> +   "unpackDouble2x32",
> +   "frexp_sig",
> +   "frexp_exp",
>     "noise",
>     "interpolate_at_centroid",
>     "+",
> @@ -641,6 +669,20 @@ ir_constant::ir_constant(float f, unsigned vector_elements)
>     }
>  }
>  
> +ir_constant::ir_constant(double d, unsigned vector_elements)
> +   : ir_rvalue(ir_type_constant)
> +{
> +   assert(vector_elements <= 4);
> +   this->ir_type = ir_type_constant;
> +   this->type = glsl_type::get_instance(GLSL_TYPE_DOUBLE, vector_elements, 1);
> +   for (unsigned i = 0; i < vector_elements; i++) {
> +      this->value.d[i] = d;
> +   }
> +   for (unsigned i = vector_elements; i < 16; i++)  {
> +      this->value.d[i] = 0;
> +   }
> +}
> +
>  ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
>     : ir_rvalue(ir_type_constant)
>  {
> @@ -756,6 +798,10 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
>  	    for (unsigned i = 0; i < type->components(); i++)
>  	       this->value.f[i] = value->value.f[0];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    for (unsigned i = 0; i < type->components(); i++)
> +	       this->value.d[i] = value->value.d[0];
> +	    break;
>  	 case GLSL_TYPE_BOOL:
>  	    for (unsigned i = 0; i < type->components(); i++)
>  	       this->value.b[i] = value->value.b[0];
> @@ -814,6 +860,9 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
>  	 case GLSL_TYPE_BOOL:
>  	    this->value.b[i] = value->get_bool_component(j);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    this->value.d[i] = value->get_double_component(j);
> +	    break;
>  	 default:
>  	    /* FINISHME: What to do?  Exceptions are not the answer.
>  	     */
> @@ -890,6 +939,24 @@ ir_constant::get_float_component(unsigned i) const
>     return 0.0;
>  }
>  
> +double
> +ir_constant::get_double_component(unsigned i) const
> +{
> +   switch (this->type->base_type) {
> +   case GLSL_TYPE_UINT:  return (double) this->value.u[i];
> +   case GLSL_TYPE_INT:   return (double) this->value.i[i];
> +   case GLSL_TYPE_FLOAT: return (double) this->value.f[i];
> +   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1.0 : 0.0;
> +   case GLSL_TYPE_DOUBLE: return this->value.d[i];
> +   default:              assert(!"Should not get here."); break;
> +   }
> +
> +   /* Must return something to make the compiler happy.  This is clearly an
> +    * error case.
> +    */
> +   return 0.0;
> +}
> +
>  int
>  ir_constant::get_int_component(unsigned i) const
>  {
> @@ -979,6 +1046,7 @@ ir_constant::copy_offset(ir_constant *src, int offset)
>     case GLSL_TYPE_UINT:
>     case GLSL_TYPE_INT:
>     case GLSL_TYPE_FLOAT:
> +   case GLSL_TYPE_DOUBLE:
>     case GLSL_TYPE_BOOL: {
>        unsigned int size = src->type->components();
>        assert (size <= this->type->components() - offset);
> @@ -996,6 +1064,9 @@ ir_constant::copy_offset(ir_constant *src, int offset)
>  	 case GLSL_TYPE_BOOL:
>  	    value.b[i+offset] = src->get_bool_component(i);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    value.d[i+offset] = src->get_double_component(i);
> +	    break;
>  	 default: // Shut up the compiler
>  	    break;
>  	 }
> @@ -1052,6 +1123,9 @@ ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
>  	 case GLSL_TYPE_BOOL:
>  	    value.b[i+offset] = src->get_bool_component(id++);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    value.d[i+offset] = src->get_double_component(id++);
> +	    break;
>  	 default:
>  	    assert(!"Should not get here.");
>  	    return;
> @@ -1112,6 +1186,10 @@ ir_constant::has_value(const ir_constant *c) const
>  	 if (this->value.b[i] != c->value.b[i])
>  	    return false;
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 if (this->value.d[i] != c->value.d[i])
> +	    return false;
> +	 break;
>        default:
>  	 assert(!"Should not get here.");
>  	 return false;
> @@ -1149,6 +1227,10 @@ ir_constant::is_value(float f, int i) const
>  	 if (this->value.b[c] != bool(i))
>  	    return false;
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 if (this->value.d[c] != double(i))
> +	    return false;
> +	 break;
>        default:
>  	 /* The only other base types are structures, arrays, and samplers.
>  	  * Samplers cannot be constants, and the others should have been
> @@ -1198,6 +1280,12 @@ ir_constant::is_basis() const
>  	 else if (this->value.f[c] != 0.0)
>  	    return false;
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 if (this->value.d[c] == 1.0)
> +	    ones++;
> +	 else if (this->value.d[c] != 0.0)
> +	    return false;
> +	 break;
>        case GLSL_TYPE_INT:
>  	 if (this->value.i[c] == 1)
>  	    ones++;
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index 31c3545..ad42f66 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -1179,6 +1179,9 @@ enum ir_expression_operation {
>     ir_unop_bitcast_f2u, /**< Bit-identical float-to-uint "conversion" */
>     ir_unop_any,
>  
> +   ir_unop_d2f,         /**< Double-to-float conversion. */
> +   ir_unop_f2d,         /**< Float-to-double conversion. */
> +
>     /**
>      * \name Unary floating-point rounding operations.
>      */
> @@ -1244,6 +1247,17 @@ enum ir_expression_operation {
>     ir_unop_find_lsb,
>     /*@}*/
>  
> +   /**
> +    * \name Double packing, part of ARB_gpu_shader_fp64.
> +    */
> +   /*@{*/
> +   ir_unop_pack_double_2x32,
> +   ir_unop_unpack_double_2x32,
> +   /*@}*/
> +
> +   ir_unop_frexp_sig,
> +   ir_unop_frexp_exp,
> +
>     ir_unop_noise,
>  
>     /**
> @@ -2052,6 +2066,7 @@ union ir_constant_data {
>        int i[16];
>        float f[16];
>        bool b[16];
> +      double d[16];
>  };
>  
>  
> @@ -2062,6 +2077,7 @@ public:
>     ir_constant(unsigned int u, unsigned vector_elements=1);
>     ir_constant(int i, unsigned vector_elements=1);
>     ir_constant(float f, unsigned vector_elements=1);
> +   ir_constant(double d, unsigned vector_elements=1);
>  
>     /**
>      * Construct an ir_constant from a list of ir_constant values
> @@ -2108,6 +2124,7 @@ public:
>     /*@{*/
>     bool get_bool_component(unsigned i) const;
>     float get_float_component(unsigned i) const;
> +   double get_double_component(unsigned i) const;
>     int get_int_component(unsigned i) const;
>     unsigned get_uint_component(unsigned i) const;
>     /*@}*/
> diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp
> index f039414..6ebdab2 100644
> --- a/src/glsl/ir_builder.cpp
> +++ b/src/glsl/ir_builder.cpp
> @@ -251,6 +251,11 @@ ir_expression *round_even(operand a)
>     return expr(ir_unop_round_even, a);
>  }
>  
> +ir_expression *fract(operand a)
> +{
> +   return expr(ir_unop_fract, a);
> +}
> +
>  /* dot for vectors, mul for scalars */
>  ir_expression *dot(operand a, operand b)
>  {
> @@ -519,6 +524,12 @@ interpolate_at_sample(operand a, operand b)
>  }
>  
>  ir_expression *
> +f2d(operand a)
> +{
> +   return expr(ir_unop_f2d, a);
> +}
> +
> +ir_expression *
>  fma(operand a, operand b, operand c)
>  {
>     return expr(ir_triop_fma, a, b, c);
> diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h
> index 573596c..7881288 100644
> --- a/src/glsl/ir_builder.h
> +++ b/src/glsl/ir_builder.h
> @@ -138,6 +138,7 @@ ir_expression *div(operand a, operand b);
>  ir_expression *carry(operand a, operand b);
>  ir_expression *borrow(operand a, operand b);
>  ir_expression *round_even(operand a);
> +ir_expression *fract(operand a);
>  ir_expression *dot(operand a, operand b);
>  ir_expression *clamp(operand a, operand b, operand c);
>  ir_expression *saturate(operand a);
> @@ -183,6 +184,8 @@ ir_expression *i2b(operand a);
>  ir_expression *f2b(operand a);
>  ir_expression *b2f(operand a);
>  
> +ir_expression *f2d(operand a);
> +
>  ir_expression *min2(operand a, operand b);
>  ir_expression *max2(operand a, operand b);
>  
> diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
> index 4b444d4..1a583a0 100644
> --- a/src/glsl/ir_clone.cpp
> +++ b/src/glsl/ir_clone.cpp
> @@ -334,6 +334,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
>     case GLSL_TYPE_UINT:
>     case GLSL_TYPE_INT:
>     case GLSL_TYPE_FLOAT:
> +   case GLSL_TYPE_DOUBLE:
>     case GLSL_TYPE_BOOL:
>        return new(mem_ctx) ir_constant(this->type, &this->value);
>  
> diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
> index 5570ed4..6b22086 100644
> --- a/src/glsl/ir_constant_expression.cpp
> +++ b/src/glsl/ir_constant_expression.cpp
> @@ -60,7 +60,7 @@ static double copysign(double x, double y)
>  #endif
>  
>  static float
> -dot(ir_constant *op0, ir_constant *op1)
> +dot_f(ir_constant *op0, ir_constant *op1)
>  {
>     assert(op0->type->is_float() && op1->type->is_float());
>  
> @@ -71,6 +71,18 @@ dot(ir_constant *op0, ir_constant *op1)
>     return result;
>  }
>  
> +static double
> +dot_d(ir_constant *op0, ir_constant *op1)
> +{
> +   assert(op0->type->is_double() && op1->type->is_double());
> +
> +   double result = 0;
> +   for (unsigned c = 0; c < op0->type->components(); c++)
> +      result += op0->value.d[c] * op1->value.d[c];
> +
> +   return result;
> +}
> +
>  /* This method is the only one supported by gcc.  Unions in particular
>   * are iffy, and read-through-converted-pointer is killed by strict
>   * aliasing.  OTOH, the compiler sees through the memcpy, so the
> @@ -667,32 +679,52 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	    data.b[0] = true;
>        }
>        break;
> +   case ir_unop_d2f:
> +      assert(op[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      for (unsigned c = 0; c < op[0]->type->components(); c++) {
> +	 data.f[c] = op[0]->value.d[c];
> +      }
> +      break;
> +   case ir_unop_f2d:
> +      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
> +      for (unsigned c = 0; c < op[0]->type->components(); c++) {
> +	 data.d[c] = op[0]->value.f[c];
> +      }
> +      break;
>  
>     case ir_unop_trunc:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = truncf(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = trunc(op[0]->value.d[c]);
> +         else
> +            data.f[c] = truncf(op[0]->value.f[c]);
>        }
>        break;
>  
>     case ir_unop_round_even:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = _mesa_round_to_even(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = _mesa_round_to_even(op[0]->value.d[c]);
> +         else
> +            data.f[c] = _mesa_round_to_even(op[0]->value.f[c]);
>        }
>        break;
>  
>     case ir_unop_ceil:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = ceilf(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = ceil(op[0]->value.d[c]);
> +         else
> +            data.f[c] = ceilf(op[0]->value.f[c]);
>        }
>        break;
>  
>     case ir_unop_floor:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = floorf(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = floor(op[0]->value.d[c]);
> +         else
> +            data.f[c] = floorf(op[0]->value.f[c]);
>        }
>        break;
>  
> @@ -708,6 +740,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = op[0]->value.d[c] - floor(op[0]->value.d[c]);
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -742,6 +777,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = -op[0]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = -op[0]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -762,6 +800,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = fabs(op[0]->value.f[c]);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = fabs(op[0]->value.d[c]);
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -780,6 +821,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = float((op[0]->value.f[c] > 0)-(op[0]->value.f[c] < 0));
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = double((op[0]->value.d[c] > 0)-(op[0]->value.d[c] < 0));
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -787,7 +831,6 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>        break;
>  
>     case ir_unop_rcp:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
>  	 switch (this->type->base_type) {
>  	 case GLSL_TYPE_UINT:
> @@ -802,6 +845,10 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	    if (op[0]->value.f[c] != 0.0)
>  	       data.f[c] = 1.0F / op[0]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    if (op[0]->value.d[c] != 0.0)
> +	       data.d[c] = 1.0 / op[0]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -809,16 +856,20 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>        break;
>  
>     case ir_unop_rsq:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = 1.0F / sqrtf(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = 1.0 / sqrt(op[0]->value.d[c]);
> +         else
> +            data.f[c] = 1.0F / sqrtf(op[0]->value.f[c]);
>        }
>        break;
>  
>     case ir_unop_sqrt:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
>        for (unsigned c = 0; c < op[0]->type->components(); c++) {
> -	 data.f[c] = sqrtf(op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = sqrt(op[0]->value.d[c]);
> +         else
> +            data.f[c] = sqrtf(op[0]->value.f[c]);
>        }
>        break;
>  
> @@ -930,7 +981,10 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>        break;
>  
>     case ir_binop_dot:
> -      data.f[0] = dot(op[0], op[1]);
> +      if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +         data.d[0] = dot_d(op[0], op[1]);
> +      else
> +         data.f[0] = dot_f(op[0], op[1]);
>        break;
>  
>     case ir_binop_min:
> @@ -949,6 +1003,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = MIN2(op[0]->value.f[c0], op[1]->value.f[c1]);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = MIN2(op[0]->value.d[c0], op[1]->value.d[c1]);
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -971,6 +1028,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = MAX2(op[0]->value.f[c0], op[1]->value.f[c1]);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = MAX2(op[0]->value.d[c0], op[1]->value.d[c1]);
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -993,6 +1053,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = op[0]->value.f[c0] + op[1]->value.f[c1];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = op[0]->value.d[c0] + op[1]->value.d[c1];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1015,6 +1078,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = op[0]->value.d[c0] - op[1]->value.d[c1];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1039,6 +1105,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	    case GLSL_TYPE_FLOAT:
>  	       data.f[c] = op[0]->value.f[c0] * op[1]->value.f[c1];
>  	       break;
> +	    case GLSL_TYPE_DOUBLE:
> +	       data.d[c] = op[0]->value.d[c0] * op[1]->value.d[c1];
> +	       break;
>  	    default:
>  	       assert(0);
>  	    }
> @@ -1062,7 +1131,10 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 for (unsigned j = 0; j < p; j++) {
>  	    for (unsigned i = 0; i < n; i++) {
>  	       for (unsigned k = 0; k < m; k++) {
> -		  data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
> +                  if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +                     data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
> +                  else
> +                     data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
>  	       }
>  	    }
>  	 }
> @@ -1094,6 +1166,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = op[0]->value.d[c0] / op[1]->value.d[c1];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1129,6 +1204,13 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	    data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1]
>  	       * floorf(op[0]->value.f[c0] / op[1]->value.f[c1]);
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    /* We don't use fmod because it rounds toward zero; GLSL specifies
> +	     * the use of floor.
> +	     */
> +	    data.d[c] = op[0]->value.d[c0] - op[1]->value.d[c1]
> +	       * floor(op[0]->value.d[c0] / op[1]->value.d[c1]);
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1165,6 +1247,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] < op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1183,6 +1268,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] > op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1201,6 +1289,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] <= op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1219,6 +1310,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] >= op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1240,6 +1334,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_BOOL:
>  	    data.b[c] = op[0]->value.b[c] == op[1]->value.b[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] == op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1261,6 +1358,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_BOOL:
>  	    data.b[c] = op[0]->value.b[c] != op[1]->value.b[c];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.b[c] = op[0]->value.d[c] != op[1]->value.d[c];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1465,6 +1565,18 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>        }
>        break;
>  
> +   case ir_unop_pack_double_2x32: {
> +      uint64_t temp;
> +      temp = (uint64_t)op[0]->value.u[0] | ((uint64_t)op[0]->value.u[1] << 32);
> +      data.d[0] = *(double *)&temp;
> +
> +      break;
> +   }
> +   case ir_unop_unpack_double_2x32:
> +      data.u[0] = *(uint32_t *)&op[0]->value.d[0];
> +      data.u[1] = *((uint32_t *)&op[0]->value.d[0] + 1);
> +      break;
> +
>     case ir_triop_bitfield_extract: {
>        int offset = op[1]->value.i[0];
>        int bits = op[2]->value.i[0];
> @@ -1513,40 +1625,60 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  
>     case ir_binop_ldexp:
>        for (unsigned c = 0; c < components; c++) {
> -         data.f[c] = ldexp(op[0]->value.f[c], op[1]->value.i[c]);
> -         /* Flush subnormal values to zero. */
> -         if (!isnormal(data.f[c]))
> -            data.f[c] = copysign(0.0f, op[0]->value.f[c]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE) {
> +            data.d[c] = ldexp(op[0]->value.d[c], op[1]->value.i[c]);
> +            /* Flush subnormal values to zero. */
> +            if (!isnormal(data.d[c]))
> +               data.d[c] = copysign(0.0, op[0]->value.d[c]);
> +
> +         } else {
> +            data.f[c] = ldexp(op[0]->value.f[c], op[1]->value.i[c]);
> +            /* Flush subnormal values to zero. */
> +            if (!isnormal(data.f[c]))
> +               data.f[c] = copysign(0.0f, op[0]->value.f[c]);
> +         }
>        }
>        break;
>  
>     case ir_triop_fma:
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
> -      assert(op[1]->type->base_type == GLSL_TYPE_FLOAT);
> -      assert(op[2]->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT || op[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(op[1]->type->base_type == GLSL_TYPE_FLOAT || op[1]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(op[2]->type->base_type == GLSL_TYPE_FLOAT || op[2]->type->base_type == GLSL_TYPE_DOUBLE);
>  
>        for (unsigned c = 0; c < components; c++) {
> -         data.f[c] = op[0]->value.f[c] * op[1]->value.f[c]
> -                                       + op[2]->value.f[c];
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = op[0]->value.d[c] * op[1]->value.d[c]
> +                                          + op[2]->value.d[c];
> +         else
> +            data.f[c] = op[0]->value.f[c] * op[1]->value.f[c]
> +                                          + op[2]->value.f[c];
>        }
>        break;
>  
>     case ir_triop_lrp: {
> -      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
> -      assert(op[1]->type->base_type == GLSL_TYPE_FLOAT);
> -      assert(op[2]->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT || op[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(op[1]->type->base_type == GLSL_TYPE_FLOAT || op[1]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(op[2]->type->base_type == GLSL_TYPE_FLOAT || op[2]->type->base_type == GLSL_TYPE_DOUBLE);
>  
>        unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
>        for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
> -         data.f[c] = op[0]->value.f[c] * (1.0f - op[2]->value.f[c2]) +
> -                     (op[1]->value.f[c] * op[2]->value.f[c2]);
> +         if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = op[0]->value.d[c] * (1.0 - op[2]->value.d[c2]) +
> +               (op[1]->value.d[c] * op[2]->value.d[c2]);
> +         else
> +            data.f[c] = op[0]->value.f[c] * (1.0f - op[2]->value.f[c2]) +
> +               (op[1]->value.f[c] * op[2]->value.f[c2]);
>        }
>        break;
>     }
>  
>     case ir_triop_csel:
>        for (unsigned c = 0; c < components; c++) {
> -         data.u[c] = op[0]->value.b[c] ? op[1]->value.u[c]
> +         if (op[1]->type->base_type == GLSL_TYPE_DOUBLE)
> +            data.d[c] = op[0]->value.b[c] ? op[1]->value.d[c]
> +                                       : op[2]->value.d[c];
> +         else
> +            data.u[c] = op[0]->value.b[c] ? op[1]->value.u[c]
>                                         : op[2]->value.u[c];
>        }
>        break;
> @@ -1569,6 +1701,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>        case GLSL_TYPE_BOOL:
>  	 data.b[idx] = op[1]->value.b[0];
>  	 break;
> +      case GLSL_TYPE_DOUBLE:
> +	 data.d[idx] = op[1]->value.d[0];
> +	 break;
>        default:
>  	 assert(!"Should not get here.");
>  	 break;
> @@ -1615,6 +1750,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_FLOAT:
>  	    data.f[c] = op[c]->value.f[0];
>  	    break;
> +	 case GLSL_TYPE_DOUBLE:
> +	    data.d[c] = op[c]->value.d[0];
> +	    break;
>  	 default:
>  	    assert(0);
>  	 }
> @@ -1656,6 +1794,7 @@ ir_swizzle::constant_expression_value(struct hash_table *variable_context)
>  	 case GLSL_TYPE_INT:   data.u[i] = v->value.u[swiz_idx[i]]; break;
>  	 case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
>  	 case GLSL_TYPE_BOOL:  data.b[i] = v->value.b[swiz_idx[i]]; break;
> +	 case GLSL_TYPE_DOUBLE:data.d[i] = v->value.d[swiz_idx[i]]; break;
>  	 default:              assert(!"Should not get here."); break;
>  	 }
>        }
> @@ -1730,6 +1869,12 @@ ir_dereference_array::constant_expression_value(struct hash_table *variable_cont
>  
>  	    break;
>  
> +	 case GLSL_TYPE_DOUBLE:
> +	    for (unsigned i = 0; i < column_type->vector_elements; i++)
> +	       data.d[i] = array->value.d[mat_idx + i];
> +
> +	    break;
> +
>  	 default:
>  	    assert(!"Should not get here.");
>  	    break;
> diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
> index bd39805..3600827 100644
> --- a/src/glsl/ir_print_visitor.cpp
> +++ b/src/glsl/ir_print_visitor.cpp
> @@ -436,6 +436,17 @@ void ir_print_visitor::visit(ir_constant *ir)
>                 fprintf(f, "%f", ir->value.f[i]);
>              break;
>  	 case GLSL_TYPE_BOOL:  fprintf(f, "%d", ir->value.b[i]); break;
> +	 case GLSL_TYPE_DOUBLE:
> +            if (ir->value.d[i] == 0.0)
> +               /* 0.0 == -0.0, so print with %f to get the proper sign. */
> +               fprintf(f, "%.1f", ir->value.d[i]);
> +            else if (fabs(ir->value.d[i]) < 0.000001)
> +               fprintf(f, "%a", ir->value.f[i]);
> +            else if (fabs(ir->value.d[i]) > 1000000.0)
> +               fprintf(f, "%e", ir->value.d[i]);
> +            else
> +               fprintf(f, "%f", ir->value.d[i]);
> +            break;
>  	 default: assert(0);
>  	 }
>        }
> diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
> index 5163eb2..dfd09d5 100644
> --- a/src/glsl/ir_set_program_inouts.cpp
> +++ b/src/glsl/ir_set_program_inouts.cpp
> @@ -81,6 +81,17 @@ is_shader_inout(ir_variable *var)
>            var->data.mode == ir_var_system_value;
>  }
>  
> +static inline bool
> +is_dvec34_inout(ir_variable *var)
> +{
> +   if (var->type == glsl_type::dvec4_type || var->type == glsl_type::dvec3_type)
> +      return true;
> +
> +   if (var->type->is_array() && (var->type->element_type() == glsl_type::dvec4_type || var->type->element_type() == glsl_type::dvec3_type))
> +      return true;
> +   return false;
> +}
> +
>  static void
>  mark(struct gl_program *prog, ir_variable *var, int offset, int len,
>       bool is_fragment_shader)
> @@ -94,19 +105,26 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
>      */
>  
>     for (int i = 0; i < len; i++) {
> +      int idx = var->data.location + var->data.index + offset + i;
>        GLbitfield64 bitfield =
> -         BITFIELD64_BIT(var->data.location + var->data.index + offset + i);
> +         BITFIELD64_BIT(idx);
> +
> +      if (is_dvec34_inout(var))
> +         bitfield |= bitfield << 1;
>        if (var->data.mode == ir_var_shader_in) {
>  	 prog->InputsRead |= bitfield;
>           if (is_fragment_shader) {
>              gl_fragment_program *fprog = (gl_fragment_program *) prog;
> -            fprog->InterpQualifier[var->data.location +
> -                                   var->data.index + offset + i] =
> +            fprog->InterpQualifier[idx] =
>                 (glsl_interp_qualifier) var->data.interpolation;
>              if (var->data.centroid)
>                 fprog->IsCentroid |= bitfield;
>              if (var->data.sample)
>                 fprog->IsSample |= bitfield;
> +
> +            if (is_dvec34_inout(var))
> +               fprog->InterpQualifier[idx + 1] =
> +                  (glsl_interp_qualifier) var->data.interpolation;
>           }
>        } else if (var->data.mode == ir_var_system_value) {
>           prog->SystemValuesRead |= bitfield;
> diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
> index 4f85b7d..ab78d51 100644
> --- a/src/glsl/ir_validate.cpp
> +++ b/src/glsl/ir_validate.cpp
> @@ -312,6 +312,9 @@ ir_validate::visit_leave(ir_expression *ir)
>     case ir_unop_ceil:
>     case ir_unop_floor:
>     case ir_unop_fract:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT || ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->operands[0]->type == ir->type);
> +      break;
>     case ir_unop_sin:
>     case ir_unop_cos:
>     case ir_unop_sin_reduced:
> @@ -335,6 +338,11 @@ ir_validate::visit_leave(ir_expression *ir)
>        assert(ir->operands[0]->type == glsl_type::vec4_type);
>        break;
>  
> +   case ir_unop_pack_double_2x32:
> +      assert(ir->type == glsl_type::double_type);
> +      assert(ir->operands[0]->type == glsl_type::uvec2_type);
> +      break;
> +
>     case ir_unop_unpack_snorm_2x16:
>     case ir_unop_unpack_unorm_2x16:
>     case ir_unop_unpack_half_2x16:
> @@ -354,6 +362,11 @@ ir_validate::visit_leave(ir_expression *ir)
>        assert(ir->operands[0]->type == glsl_type::uint_type);
>        break;
>  
> +   case ir_unop_unpack_double_2x32:
> +      assert(ir->type == glsl_type::uvec2_type);
> +      assert(ir->operands[0]->type == glsl_type::double_type);
> +      break;
> +
>     case ir_unop_bitfield_reverse:
>        assert(ir->operands[0]->type == ir->type);
>        assert(ir->type->is_integer());
> @@ -376,6 +389,25 @@ ir_validate::visit_leave(ir_expression *ir)
>        assert(ir->operands[0]->type->is_float());
>        break;
>  
> +   case ir_unop_d2f:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
> +      break;
> +   case ir_unop_f2d:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
> +      break;
> +
> +   case ir_unop_frexp_sig:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
> +             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
> +      break;
> +   case ir_unop_frexp_exp:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
> +             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->type->base_type == GLSL_TYPE_INT);
> +      break;
>     case ir_binop_add:
>     case ir_binop_sub:
>     case ir_binop_mul:
> @@ -476,8 +508,8 @@ ir_validate::visit_leave(ir_expression *ir)
>        break;
>  
>     case ir_binop_dot:
> -      assert(ir->type == glsl_type::float_type);
> -      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(ir->type == glsl_type::float_type || ir->type == glsl_type::double_type);
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT || ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
>        assert(ir->operands[0]->type->is_vector());
>        assert(ir->operands[0]->type == ir->operands[1]->type);
>        break;
> @@ -502,7 +534,8 @@ ir_validate::visit_leave(ir_expression *ir)
>  
>     case ir_binop_ldexp:
>        assert(ir->operands[0]->type == ir->type);
> -      assert(ir->operands[0]->type->is_float());
> +      assert(ir->operands[0]->type->is_float() ||
> +             ir->operands[0]->type->is_double());
>        assert(ir->operands[1]->type->base_type == GLSL_TYPE_INT);
>        assert(ir->operands[0]->type->components() ==
>               ir->operands[1]->type->components());
> @@ -528,16 +561,16 @@ ir_validate::visit_leave(ir_expression *ir)
>        break;
>  
>     case ir_triop_fma:
> -      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(ir->type->base_type == GLSL_TYPE_FLOAT || ir->type->base_type == GLSL_TYPE_DOUBLE);
>        assert(ir->type == ir->operands[0]->type);
>        assert(ir->type == ir->operands[1]->type);
>        assert(ir->type == ir->operands[2]->type);
>        break;
>  
>     case ir_triop_lrp:
> -      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT || ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
>        assert(ir->operands[0]->type == ir->operands[1]->type);
> -      assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type);
> +      assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type || ir->operands[2]->type == glsl_type::double_type);
>        break;
>  
>     case ir_triop_csel:
> diff --git a/src/glsl/link_uniform_initializers.cpp b/src/glsl/link_uniform_initializers.cpp
> index c6fe6a9..43a672d 100644
> --- a/src/glsl/link_uniform_initializers.cpp
> +++ b/src/glsl/link_uniform_initializers.cpp
> @@ -74,6 +74,10 @@ 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:
> +	 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 = int(val->value.b[i]);
>  	 break;
> diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
> index 3251097..d0c52d3 100644
> --- a/src/glsl/link_uniforms.cpp
> +++ b/src/glsl/link_uniforms.cpp
> @@ -51,6 +51,8 @@ values_for_type(const glsl_type *type)
>        return 1;
>     } else if (type->is_array() && type->fields.array->is_sampler()) {
>        return type->array_size();
> +   } else if (type->is_double()) {
> +      return 2 * type->component_slots();
>     } else {
>        return type->component_slots();
>     }
> diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp
> index 54ceae1..c5e6af4 100644
> --- a/src/glsl/link_varyings.cpp
> +++ b/src/glsl/link_varyings.cpp
> @@ -861,8 +861,9 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
>           : var->type->matrix_columns;
>        this->matches[this->num_matches].num_components = 4 * slots;
>     } else {
> +      unsigned slot_mul = var->type->is_double() ? 2 : 1;
>        this->matches[this->num_matches].num_components
> -         = var->type->component_slots();
> +         = var->type->component_slots() * slot_mul;
>     }
>     this->matches[this->num_matches].producer_var = producer_var;
>     this->matches[this->num_matches].consumer_var = consumer_var;
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index f7eb87d..93c4b15 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -1399,6 +1399,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
>     case ir_unop_pack_unorm_2x16:
>     case ir_unop_pack_unorm_4x8:
>     case ir_unop_pack_half_2x16:
> +   case ir_unop_pack_double_2x32:
>     case ir_unop_unpack_snorm_2x16:
>     case ir_unop_unpack_snorm_4x8:
>     case ir_unop_unpack_unorm_2x16:
> @@ -1406,11 +1407,16 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
>     case ir_unop_unpack_half_2x16:
>     case ir_unop_unpack_half_2x16_split_x:
>     case ir_unop_unpack_half_2x16_split_y:
> +   case ir_unop_unpack_double_2x32:
>     case ir_binop_pack_half_2x16_split:
>     case ir_unop_bitfield_reverse:
>     case ir_unop_bit_count:
>     case ir_unop_find_msb:
>     case ir_unop_find_lsb:
> +   case ir_unop_d2f:
> +   case ir_unop_f2d:
> +   case ir_unop_frexp_sig:
> +   case ir_unop_frexp_exp:
>        assert(!"not supported");
>        break;
>     case ir_binop_min:
> -- 
> 1.9.3
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list