[Mesa-dev] [PATCH 04/17] glsl/ir: Add builtin function support for doubles (was: add double support)

Matt Turner mattst88 at gmail.com
Thu Feb 5 10:37:35 PST 2015


On Thu, Feb 5, 2015 at 3:05 AM, Topi Pohjolainen
<topi.pohjolainen at intel.com> wrote:
> From: Dave Airlie <airlied at gmail.com>
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/glsl/ir.cpp                 | 104 ++++++++++++++++++++++++++++++++++++++--
>  src/glsl/ir.h                   |  21 ++++++++
>  src/glsl/ir_validate.cpp        |  61 ++++++++++++++++++++---
>  src/mesa/program/ir_to_mesa.cpp |  10 ++++
>  4 files changed, 186 insertions(+), 10 deletions(-)
>
> diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
> index fe5601a..9da4a44 100644
> --- a/src/glsl/ir.cpp
> +++ b/src/glsl/ir.cpp
> @@ -257,6 +257,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>     case ir_unop_f2i:
>     case ir_unop_b2i:
>     case ir_unop_u2i:
> +   case ir_unop_d2i:
>     case ir_unop_bitcast_f2i:
>     case ir_unop_bit_count:
>     case ir_unop_find_msb:
> @@ -268,6 +269,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,8 +282,16 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>                                            op0->type->vector_elements, 1);
>        break;
>
> +   case ir_unop_f2d:
> +   case ir_unop_i2d:
> +   case ir_unop_u2d:
> +      this->type = glsl_type::get_instance(GLSL_TYPE_DOUBLE,
> +                                          op0->type->vector_elements, 1);

I think there's a tab here.

> +      break;
> +
>     case ir_unop_i2u:
>     case ir_unop_f2u:
> +   case ir_unop_d2u:
>     case ir_unop_bitcast_f2u:
>        this->type = glsl_type::get_instance(GLSL_TYPE_UINT,
>                                            op0->type->vector_elements, 1);
> @@ -293,6 +303,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 +319,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 +334,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 +416,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 +525,12 @@ static const char *const operator_strs[] = {
>     "bitcast_u2f",
>     "bitcast_f2u",
>     "any",
> +   "d2f",
> +   "f2d",
> +   "d2i",
> +   "i2d",
> +   "d2u",
> +   "u2d",

I see in the spec that you can convert double <-> bool, but I don't
see operations for these.

>     "trunc",
>     "ceil",
>     "floor",
> @@ -531,6 +563,10 @@ static const char *const operator_strs[] = {
>     "find_msb",
>     "find_lsb",
>     "sat",
> +   "packDouble2x32",
> +   "unpackDouble2x32",
> +   "frexp_sig",
> +   "frexp_exp",
>     "noise",
>     "interpolate_at_centroid",
>     "+",
> @@ -646,6 +682,19 @@ 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->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;

I'd write 0.0 here.

> +   }
> +}
> +
>  ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
>     : ir_rvalue(ir_type_constant)
>  {
> @@ -746,9 +795,16 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
>     if (value->type->is_scalar() && value->next->is_tail_sentinel()) {
>        if (type->is_matrix()) {
>          /* Matrix - fill diagonal (rest is already set to 0) */
> -        assert(type->base_type == GLSL_TYPE_FLOAT);
> -        for (unsigned i = 0; i < type->matrix_columns; i++)
> -           this->value.f[i * type->vector_elements + i] = value->value.f[0];
> +         assert(type->base_type == GLSL_TYPE_FLOAT ||
> +                type->base_type == GLSL_TYPE_DOUBLE);
> +         for (unsigned i = 0; i < type->matrix_columns; i++) {
> +            if (type->base_type == GLSL_TYPE_FLOAT)
> +               this->value.f[i * type->vector_elements + i] =
> +                  value->value.f[0];
> +            else
> +               this->value.d[i * type->vector_elements + i] =
> +                  value->value.d[0];
> +         }
>        } else {
>          /* Vector or scalar - fill all components */
>          switch (type->base_type) {
> @@ -761,6 +817,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];
> @@ -819,6 +879,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.
>              */
> @@ -895,6 +958,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
>  {
> @@ -984,6 +1065,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);
> @@ -1001,6 +1083,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;
>          }
> @@ -1057,6 +1142,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;
> @@ -1117,6 +1205,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;
> @@ -1154,6 +1246,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
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index a0f48b2..6e7c654 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -1275,6 +1275,13 @@ 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. */
> +   ir_unop_d2i,         /**< Double-to-integer conversion. */
> +   ir_unop_i2d,         /**< Integer-to-double conversion. */
> +   ir_unop_d2u,         /**< Double-to-unsigned conversion. */
> +   ir_unop_u2d,         /**< Unsigned-to-double conversion. */
> +
>     /**
>      * \name Unary floating-point rounding operations.
>      */
> @@ -1345,6 +1352,17 @@ enum ir_expression_operation {
>     /*@}*/
>
>     ir_unop_saturate,
> +   /**
> +    * \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,
>
>     /**
> @@ -2153,6 +2171,7 @@ union ir_constant_data {
>        int i[16];
>        float f[16];
>        bool b[16];
> +      double d[16];
>  };
>
>
> @@ -2163,6 +2182,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
> @@ -2209,6 +2229,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_validate.cpp b/src/glsl/ir_validate.cpp
> index 6d56339..73a694c 100644
> --- a/src/glsl/ir_validate.cpp
> +++ b/src/glsl/ir_validate.cpp
> @@ -313,6 +313,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);

I'd line wrap this.

> +      assert(ir->operands[0]->type == ir->type);
> +      break;
>     case ir_unop_sin:
>     case ir_unop_cos:
>     case ir_unop_sin_reduced:
> @@ -340,6 +343,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:
> @@ -359,6 +367,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());
> @@ -381,6 +394,41 @@ 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_d2i:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->type->base_type == GLSL_TYPE_INT);
> +      break;
> +   case ir_unop_i2d:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
> +      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
> +      break;
> +   case ir_unop_d2u:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
> +      assert(ir->type->base_type == GLSL_TYPE_UINT);
> +      break;
> +   case ir_unop_u2d:
> +      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
> +      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:
> @@ -481,8 +529,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);

Line wrap.

>        assert(ir->operands[0]->type->is_vector());
>        assert(ir->operands[0]->type == ir->operands[1]->type);
>        break;
> @@ -507,7 +555,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());
> @@ -533,16 +582,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);

Probably line wrap.

>        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);

Here.

>        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);

And here.

>        break;
>
>     case ir_triop_csel:
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index 54413cd..4bcdbc3 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -1356,6 +1356,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:
> @@ -1363,11 +1364,20 @@ 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_d2i:
> +   case ir_unop_i2d:
> +   case ir_unop_d2u:
> +   case ir_unop_u2d:
> +   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