mesa, glsl_to_tgsi: add native support for integers in shaders
authorBryan Cain <bryancain3@gmail.com>
Mon, 13 Jun 2011 23:12:56 +0000 (18:12 -0500)
committerBryan Cain <bryancain3@gmail.com>
Mon, 1 Aug 2011 22:59:08 +0000 (17:59 -0500)
Disabled by default on all drivers.  To enable it, change ctx->GLSLVersion to 130
in st_extensions.c.  Currently, softpipe is the only driver with integer support.

src/glsl/glsl_types.h
src/mesa/main/uniforms.c
src/mesa/program/prog_parameter.c
src/mesa/program/prog_parameter.h
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 1b069df..eb9d501 100644 (file)
@@ -165,6 +165,21 @@ struct glsl_type {
    static const glsl_type *const mat4x3_type;
    static const glsl_type *const mat4_type;
    /*@}*/
+   
+   /**
+    * Get the built-in instance of the vec4 type for a specific base type
+    */
+   static const glsl_type *get_vec4_type(glsl_base_type base_type)
+   {
+      if (base_type == GLSL_TYPE_FLOAT)
+         return vec4_type;
+      else if (base_type == GLSL_TYPE_INT)
+         return ivec4_type;
+      else if (base_type == GLSL_TYPE_UINT)
+         return uvec4_type;
+      else
+         return NULL;
+   }
 
 
    /**
index 07d46c6..ce4863f 100644 (file)
@@ -454,8 +454,9 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location,
             for (i = 0; i < rows; i++) {
                const int base = paramPos + offset + i;
                for (j = 0; j < cols; j++ ) {
-                  params[k++] = (GLint)
-                     prog->Parameters->ParameterValues[base][j].f;
+                  params[k++] = ctx->Const.GLSLVersion <= 120 ? 
+                     (GLint) prog->Parameters->ParameterValues[base][j].f : 
+                     prog->Parameters->ParameterValues[base][j].i;
                }
             }
          }
@@ -467,8 +468,9 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location,
             for (i = 0; i < rows; i++) {
                const int base = paramPos + offset + i;
                for (j = 0; j < cols; j++ ) {
-                  params[k++] = (GLuint)
-                     prog->Parameters->ParameterValues[base][j].f;
+                  params[k++] = ctx->Const.GLSLVersion <= 120 ? 
+                     (GLuint) prog->Parameters->ParameterValues[base][j].f : 
+                     prog->Parameters->ParameterValues[base][j].u;
                }
             }
          }
@@ -735,42 +737,52 @@ set_program_uniform(struct gl_context *ctx, struct gl_program *program,
 
       /* loop over number of array elements */
       for (k = 0; k < count; k++) {
-         GLfloat *uniformVal;
+         gl_constant_value *uniformVal;
 
          if (offset + k >= slots) {
             /* Extra array data is ignored */
             break;
          }
 
-         /* uniformVal (the destination) is always float[4] */
+         /* uniformVal (the destination) is always gl_constant_value[4] */
          uniformVal = program->Parameters->ParameterValues[index + offset + k];
 
          if (basicType == GL_INT) {
-            /* convert user's ints to floats */
             const GLint *iValues = ((const GLint *) values) + k * elems;
             for (i = 0; i < elems; i++) {
-               uniformVal[i] = (GLfloat) iValues[i];
+               if (ctx->Const.GLSLVersion <= 120)
+                  uniformVal[i].f = (GLfloat) iValues[i];
+               else
+                  uniformVal[i].i = iValues[i];
             }
          }
          else if (basicType == GL_UNSIGNED_INT) {
-            /* convert user's uints to floats */
             const GLuint *iValues = ((const GLuint *) values) + k * elems;
             for (i = 0; i < elems; i++) {
-               uniformVal[i] = (GLfloat) iValues[i];
+               if (ctx->Const.GLSLVersion <= 120)
+                  uniformVal[i].f = (GLfloat)(GLuint) iValues[i];
+               else
+                  uniformVal[i].u = iValues[i];
             }
          }
          else {
             const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
             assert(basicType == GL_FLOAT);
             for (i = 0; i < elems; i++) {
-               uniformVal[i] = fValues[i];
+               uniformVal[i].f = fValues[i];
             }
          }
 
-         /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
+         /* if the uniform is bool-valued, convert to 1 or 0 */
          if (isUniformBool) {
             for (i = 0; i < elems; i++) {
-               uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
+               if (basicType == GL_FLOAT)
+                  uniformVal[i].b = uniformVal[i].f != 0.0f ? 1 : 0;
+               else
+                  uniformVal[i].b = uniformVal[i].u ? 1 : 0;
+               
+               if (ctx->Const.GLSLVersion <= 120)
+                  uniformVal[i].f = uniformVal[i].b ? 1.0f : 0.0f;
             }
          }
       }
index b1cdf8b..49b3ffb 100644 (file)
@@ -241,9 +241,9 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
  * \return index/position of the new parameter in the parameter list.
  */
 GLint
-_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+_mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
                            const gl_constant_value values[4], GLuint size,
-                           GLuint *swizzleOut)
+                           GLenum datatype, GLuint *swizzleOut)
 {
    GLint pos;
    ASSERT(size >= 1);
@@ -276,7 +276,7 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
 
    /* add a new parameter to store this constant */
    pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
-                             size, GL_NONE, values, NULL, 0x0);
+                             size, datatype, values, NULL, 0x0);
    if (pos >= 0 && swizzleOut) {
       if (size == 1)
          *swizzleOut = SWIZZLE_XXXX;
@@ -287,6 +287,28 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
 }
 
 /**
+ * Add a new unnamed constant to the parameter list.  This will be used
+ * when a fragment/vertex program contains something like this:
+ *    MOV r, { 0, 1, 2, 3 };
+ * If swizzleOut is non-null we'll search the parameter list for an
+ * existing instance of the constant which matches with a swizzle.
+ *
+ * \param paramList  the parameter list
+ * \param values  four float values
+ * \param swizzleOut  returns swizzle mask for accessing the constant
+ * \return index/position of the new parameter in the parameter list.
+ * \sa _mesa_add_typed_unnamed_constant
+ */
+GLint
+_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+                           const gl_constant_value values[4], GLuint size,
+                           GLuint *swizzleOut)
+{
+   return _mesa_add_typed_unnamed_constant(paramList, values, size, GL_NONE,
+                                           swizzleOut);
+}
+
+/**
  * Add parameter representing a varying variable.
  */
 GLint
index dcc171e..f858cf0 100644 (file)
@@ -135,6 +135,11 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
                          GLuint size);
 
 extern GLint
+_mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
+                           const gl_constant_value values[4], GLuint size,
+                           GLenum datatype, GLuint *swizzleOut);
+
+extern GLint
 _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
                            const gl_constant_value values[4], GLuint size,
                            GLuint *swizzleOut);
index 881b9e0..3f5c0c6 100644 (file)
@@ -96,11 +96,13 @@ public:
       else
          this->swizzle = SWIZZLE_XYZW;
       this->negate = 0;
+      this->type = type ? type->base_type : GLSL_TYPE_ERROR;
       this->reladdr = NULL;
    }
 
-   st_src_reg(gl_register_file file, int index)
+   st_src_reg(gl_register_file file, int index, int type)
    {
+      this->type = type;
       this->file = file;
       this->index = index;
       this->swizzle = SWIZZLE_XYZW;
@@ -110,6 +112,7 @@ public:
 
    st_src_reg()
    {
+      this->type = GLSL_TYPE_ERROR;
       this->file = PROGRAM_UNDEFINED;
       this->index = 0;
       this->swizzle = 0;
@@ -123,23 +126,26 @@ public:
    int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
    GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
    int negate; /**< NEGATE_XYZW mask from mesa */
+   int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
    /** Register index should be offset by the integer in this reg. */
    st_src_reg *reladdr;
 };
 
 class st_dst_reg {
 public:
-   st_dst_reg(gl_register_file file, int writemask)
+   st_dst_reg(gl_register_file file, int writemask, int type)
    {
       this->file = file;
       this->index = 0;
       this->writemask = writemask;
       this->cond_mask = COND_TR;
       this->reladdr = NULL;
+      this->type = type;
    }
 
    st_dst_reg()
    {
+      this->type = GLSL_TYPE_ERROR;
       this->file = PROGRAM_UNDEFINED;
       this->index = 0;
       this->writemask = 0;
@@ -153,12 +159,14 @@ public:
    int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
    int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
    GLuint cond_mask:4;
+   int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
    /** Register index should be offset by the integer in this reg. */
    st_src_reg *reladdr;
 };
 
 st_src_reg::st_src_reg(st_dst_reg reg)
 {
+   this->type = reg.type;
    this->file = reg.file;
    this->index = reg.index;
    this->swizzle = SWIZZLE_XYZW;
@@ -168,6 +176,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
 
 st_dst_reg::st_dst_reg(st_src_reg reg)
 {
+   this->type = reg.type;
    this->file = reg.file;
    this->index = reg.index;
    this->writemask = WRITEMASK_XYZW;
@@ -267,6 +276,8 @@ public:
    int samplers_used;
    bool indirect_addr_temps;
    bool indirect_addr_consts;
+   
+   int glsl_version;
 
    variable_storage *find_variable_storage(ir_variable *var);
 
@@ -276,6 +287,8 @@ public:
    void reladdr_to_temp(ir_instruction *ir, st_src_reg *reg, int *num_reladdr);
 
    st_src_reg st_src_reg_for_float(float val);
+   st_src_reg st_src_reg_for_int(int val);
+   st_src_reg st_src_reg_for_type(int type, int val);
 
    /**
     * \name Visit methods
@@ -327,6 +340,10 @@ public:
    glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op,
                                st_dst_reg dst,
                                st_src_reg src0, st_src_reg src1, st_src_reg src2);
+   
+   unsigned get_opcode(ir_instruction *ir, unsigned op,
+                    st_dst_reg dst,
+                    st_src_reg src0, st_src_reg src1);
 
    /**
     * Emit the correct dot-product instruction for the type of arguments
@@ -343,6 +360,8 @@ public:
    void emit_scalar(ir_instruction *ir, unsigned op,
                    st_dst_reg dst, st_src_reg src0, st_src_reg src1);
 
+   void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0);
+
    void emit_scs(ir_instruction *ir, unsigned op,
                 st_dst_reg dst, const st_src_reg &src);
 
@@ -372,9 +391,9 @@ public:
 
 static st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, NULL);
 
-static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP);
+static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_TYPE_ERROR);
 
-static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X);
+static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT);
 
 static void
 fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
@@ -432,6 +451,8 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
 {
    glsl_to_tgsi_instruction *inst = new(mem_ctx) glsl_to_tgsi_instruction();
    int num_reladdr = 0, i;
+   
+   op = get_opcode(ir, op, dst, src0, src1);
 
    /* If we have to do relative addressing, we want to load the ARL
     * reg directly for one of the regs, and preload the other reladdr
@@ -447,7 +468,7 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
    reladdr_to_temp(ir, &src0, &num_reladdr);
 
    if (dst.reladdr) {
-      emit(ir, TGSI_OPCODE_ARL, address_reg, *dst.reladdr);
+      emit_arl(ir, address_reg, *dst.reladdr);
       num_reladdr--;
    }
    assert(num_reladdr == 0);
@@ -531,6 +552,62 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op)
    return emit(ir, op, undef_dst, undef_src, undef_src, undef_src);
 }
 
+/**
+ * Determines whether to use an integer, unsigned integer, or float opcode 
+ * based on the operands and input opcode, then emits the result.
+ * 
+ * TODO: type checking for remaining TGSI opcodes
+ */
+unsigned
+glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op,
+                        st_dst_reg dst,
+                        st_src_reg src0, st_src_reg src1)
+{
+   int type = GLSL_TYPE_FLOAT;
+   
+   if (src0.type == GLSL_TYPE_FLOAT || src1.type == GLSL_TYPE_FLOAT)
+      type = GLSL_TYPE_FLOAT;
+   else if (glsl_version >= 130)
+      type = src0.type;
+
+#define case4(c, f, i, u) \
+   case TGSI_OPCODE_##c: \
+      if (type == GLSL_TYPE_INT) op = TGSI_OPCODE_##i; \
+      else if (type == GLSL_TYPE_UINT) op = TGSI_OPCODE_##u; \
+      else op = TGSI_OPCODE_##f; \
+      break;
+#define case3(f, i, u)  case4(f, f, i, u)
+#define case2fi(f, i)   case4(f, f, i, i)
+#define case2iu(i, u)   case4(i, LAST, i, u)
+   
+   switch(op) {
+      case2fi(ADD, UADD);
+      case2fi(MUL, UMUL);
+      case2fi(MAD, UMAD);
+      case3(DIV, IDIV, UDIV);
+      case3(MAX, IMAX, UMAX);
+      case3(MIN, IMIN, UMIN);
+      case2iu(MOD, UMOD);
+      
+      case2fi(SEQ, USEQ);
+      case2fi(SNE, USNE);
+      case3(SGE, ISGE, USGE);
+      case3(SLT, ISLT, USLT);
+      
+      case2iu(SHL, SHL);
+      case2iu(ISHR, USHR);
+      case2iu(NOT, NOT);
+      case2iu(AND, AND);
+      case2iu(OR, OR);
+      case2iu(XOR, XOR);
+      
+      default: break;
+   }
+   
+   assert(op != TGSI_OPCODE_LAST);
+   return op;
+}
+
 void
 glsl_to_tgsi_visitor::emit_dp(ir_instruction *ir,
                            st_dst_reg dst, st_src_reg src0, st_src_reg src1,
@@ -607,6 +684,22 @@ glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op,
    emit_scalar(ir, op, dst, src0, undef);
 }
 
+void
+glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
+                               st_dst_reg dst, st_src_reg src0)
+{
+   st_src_reg tmp = get_temp(glsl_type::float_type);
+
+   if (src0.type == GLSL_TYPE_INT)
+      emit(ir, TGSI_OPCODE_I2F, st_dst_reg(tmp), src0);
+   else if (src0.type == GLSL_TYPE_UINT)
+      emit(ir, TGSI_OPCODE_U2F, st_dst_reg(tmp), src0);
+   else
+      tmp = src0;
+   
+   emit(ir, TGSI_OPCODE_ARL, dst, tmp);
+}
+
 /**
  * Emit an TGSI_OPCODE_SCS instruction
  *
@@ -705,16 +798,41 @@ glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op,
 struct st_src_reg
 glsl_to_tgsi_visitor::st_src_reg_for_float(float val)
 {
-   st_src_reg src(PROGRAM_CONSTANT, -1, NULL);
+   st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_FLOAT);
    union gl_constant_value uval;
 
    uval.f = val;
-   src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
-                                         &uval, 1, &src.swizzle);
+   src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
+                                         &uval, 1, GL_FLOAT, &src.swizzle);
+
+   return src;
+}
+
+struct st_src_reg
+glsl_to_tgsi_visitor::st_src_reg_for_int(int val)
+{
+   st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_INT);
+   union gl_constant_value uval;
+   
+   assert(glsl_version >= 130);
+
+   uval.i = val;
+   src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
+                                         &uval, 1, GL_INT, &src.swizzle);
 
    return src;
 }
 
+struct st_src_reg
+glsl_to_tgsi_visitor::st_src_reg_for_type(int type, int val)
+{
+   if (glsl_version >= 130)
+      return type == GLSL_TYPE_FLOAT ? st_src_reg_for_float(val) : 
+                                       st_src_reg_for_int(val);
+   else
+      return st_src_reg_for_float(val);
+}
+
 static int
 type_size(const struct glsl_type *type)
 {
@@ -759,8 +877,7 @@ type_size(const struct glsl_type *type)
 /**
  * In the initial pass of codegen, we assign temporary numbers to
  * intermediate results.  (not SSA -- variable assignments will reuse
- * storage).  Actual register allocation for the Mesa VM occurs in a
- * pass over the Mesa IR later.
+ * storage).
  */
 st_src_reg
 glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
@@ -769,6 +886,7 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
    int swizzle[4];
    int i;
 
+   src.type = type->base_type;
    src.file = PROGRAM_TEMPORARY;
    src.index = next_temp;
    src.reladdr = NULL;
@@ -875,7 +993,8 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
          this->variables.push_tail(storage);
          this->next_temp += type_size(ir->type);
 
-         dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index, NULL));
+         dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,
+               glsl_version >= 130 ? ir->type->base_type : GLSL_TYPE_FLOAT));
       }
 
 
@@ -890,7 +1009,8 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
                assert(index == storage->index + (int)i);
             }
          } else {
-            st_src_reg src(PROGRAM_STATE_VAR, index, NULL);
+            st_src_reg src(PROGRAM_STATE_VAR, index,
+                  glsl_version >= 130 ? ir->type->base_type : GLSL_TYPE_FLOAT);
             src.swizzle = slots[i].swizzle;
             emit(ir, TGSI_OPCODE_MOV, dst, src);
             /* even a float takes up a whole vec4 reg in a struct/array. */
@@ -1058,7 +1178,7 @@ glsl_to_tgsi_visitor::reladdr_to_temp(ir_instruction *ir,
    if (!reg->reladdr)
       return;
 
-   emit(ir, TGSI_OPCODE_ARL, address_reg, *reg->reladdr);
+   emit_arl(ir, address_reg, *reg->reladdr);
 
    if (*num_reladdr != 1) {
       st_src_reg temp = get_temp(glsl_type::vec4_type);
@@ -1131,13 +1251,19 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
 
    switch (ir->operation) {
    case ir_unop_logic_not:
-      emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], st_src_reg_for_float(0.0));
+      emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], st_src_reg_for_type(result_dst.type, 0));
       break;
    case ir_unop_neg:
-      op[0].negate = ~op[0].negate;
-      result_src = op[0];
+      assert(result_dst.type == GLSL_TYPE_FLOAT || result_dst.type == GLSL_TYPE_INT);
+      if (result_dst.type == GLSL_TYPE_INT)
+         emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]);
+      else {
+         op[0].negate = ~op[0].negate;
+         result_src = op[0];
+      }
       break;
    case ir_unop_abs:
+      assert(result_dst.type == GLSL_TYPE_FLOAT);
       emit(ir, TGSI_OPCODE_ABS, result_dst, op[0]);
       break;
    case ir_unop_sign:
@@ -1200,9 +1326,16 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       emit(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]);
       break;
    case ir_binop_div:
-      assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+      if (result_dst.type == GLSL_TYPE_FLOAT)
+         assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+      else
+         emit(ir, TGSI_OPCODE_DIV, result_dst, op[0], op[1]);
+      break;
    case ir_binop_mod:
-      assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+      if (result_dst.type == GLSL_TYPE_FLOAT)
+         assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+      else
+         emit(ir, TGSI_OPCODE_MOD, result_dst, op[0], op[1]);
       break;
 
    case ir_binop_less:
@@ -1227,7 +1360,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       /* "==" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
           ir->operands[1]->type->is_vector()) {
-         st_src_reg temp = get_temp(glsl_type::vec4_type);
+         st_src_reg temp = get_temp(glsl_version >= 130 ? 
+               glsl_type::get_vec4_type(ir->operands[0]->type->base_type) : 
+               glsl_type::vec4_type);
+         assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
          emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
          emit_dp(ir, result_dst, temp, temp, vector_elements);
          emit(ir, TGSI_OPCODE_SEQ, result_dst, result_src, st_src_reg_for_float(0.0));
@@ -1239,7 +1375,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       /* "!=" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
           ir->operands[1]->type->is_vector()) {
-         st_src_reg temp = get_temp(glsl_type::vec4_type);
+         st_src_reg temp = get_temp(glsl_version >= 130 ? 
+               glsl_type::get_vec4_type(ir->operands[0]->type->base_type) : 
+               glsl_type::vec4_type);
+         assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
          emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
          emit_dp(ir, result_dst, temp, temp, vector_elements);
          emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_float(0.0));
@@ -1291,17 +1430,24 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       break;
    case ir_unop_i2f:
    case ir_unop_b2f:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_I2F, result_dst, op[0]);
+         break;
+      }
    case ir_unop_b2i:
-      /* Mesa IR lacks types, ints are stored as truncated floats. */
+      /* Booleans are stored as integers (or floats in GLSL 1.20 and lower). */
       result_src = op[0];
       break;
    case ir_unop_f2i:
-      emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
+      if (glsl_version >= 130)
+         emit(ir, TGSI_OPCODE_F2I, result_dst, op[0]);
+      else
+         emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
       break;
    case ir_unop_f2b:
    case ir_unop_i2b:
-      emit(ir, TGSI_OPCODE_SNE, result_dst,
-                         op[0], st_src_reg_for_float(0.0));
+      emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], 
+            st_src_reg_for_type(result_dst.type, 0));
       break;
    case ir_unop_trunc:
       emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]);
@@ -1329,12 +1475,40 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       break;
 
    case ir_unop_bit_not:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_NOT, result_dst, op[0]);
+         break;
+      }
    case ir_unop_u2f:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_U2F, result_dst, op[0]);
+         break;
+      }
    case ir_binop_lshift:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_SHL, result_dst, op[0]);
+         break;
+      }
    case ir_binop_rshift:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_ISHR, result_dst, op[0]);
+         break;
+      }
    case ir_binop_bit_and:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_AND, result_dst, op[0]);
+         break;
+      }
    case ir_binop_bit_xor:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_XOR, result_dst, op[0]);
+         break;
+      }
    case ir_binop_bit_or:
+      if (glsl_version >= 130) {
+         emit(ir, TGSI_OPCODE_OR, result_dst, op[0]);
+         break;
+      }
    case ir_unop_round_even:
       assert(!"GLSL 1.30 features unsupported");
       break;
@@ -1729,7 +1903,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
 {
    st_src_reg src;
    GLfloat stack_vals[4] = { 0 };
-   GLfloat *values = stack_vals;
+   gl_constant_value *values = (gl_constant_value *) stack_vals;
+   GLenum gl_type = GL_NONE;
    unsigned int i;
 
    /* Unfortunately, 4 floats is all we can get into
@@ -1737,7 +1912,6 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
     * aggregate constant and move each constant value into it.  If we
     * get lucky, copy propagation will eliminate the extra moves.
     */
-
    if (ir->type->base_type == GLSL_TYPE_STRUCT) {
       st_src_reg temp_base = get_temp(ir->type);
       st_dst_reg temp = st_dst_reg(temp_base);
@@ -1789,13 +1963,13 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
 
       for (i = 0; i < ir->type->matrix_columns; i++) {
          assert(ir->type->base_type == GLSL_TYPE_FLOAT);
-         values = &ir->value.f[i * ir->type->vector_elements];
+         values = (gl_constant_value *) &ir->value.f[i * ir->type->vector_elements];
 
-         src = st_src_reg(PROGRAM_CONSTANT, -1, NULL);
+         src = st_src_reg(PROGRAM_CONSTANT, -1, ir->type->base_type);
          src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
-                                               (gl_constant_value *) values,
-                                               ir->type->vector_elements,
-                                               &src.swizzle);
+                                                values,
+                                                ir->type->vector_elements,
+                                                &src.swizzle);
          emit(ir, TGSI_OPCODE_MOV, mat_column, src);
 
          mat_column.index++;
@@ -1808,21 +1982,36 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
    src.file = PROGRAM_CONSTANT;
    switch (ir->type->base_type) {
    case GLSL_TYPE_FLOAT:
-      values = &ir->value.f[0];
+      gl_type = GL_FLOAT;
+      for (i = 0; i < ir->type->vector_elements; i++) {
+         values[i].f = ir->value.f[i];
+      }
       break;
    case GLSL_TYPE_UINT:
+      gl_type = glsl_version >= 130 ? GL_UNSIGNED_INT : GL_FLOAT;
       for (i = 0; i < ir->type->vector_elements; i++) {
-         values[i] = ir->value.u[i];
+         if (glsl_version >= 130)
+            values[i].u = ir->value.u[i];
+         else
+            values[i].f = ir->value.u[i];
       }
       break;
    case GLSL_TYPE_INT:
+      gl_type = glsl_version >= 130 ? GL_INT : GL_FLOAT;
       for (i = 0; i < ir->type->vector_elements; i++) {
-         values[i] = ir->value.i[i];
+         if (glsl_version >= 130)
+            values[i].i = ir->value.i[i];
+         else
+            values[i].f = ir->value.i[i];
       }
       break;
    case GLSL_TYPE_BOOL:
+      gl_type = glsl_version >= 130 ? GL_BOOL : GL_FLOAT;
       for (i = 0; i < ir->type->vector_elements; i++) {
-         values[i] = ir->value.b[i];
+         if (glsl_version >= 130)
+            values[i].b = ir->value.b[i];
+         else
+            values[i].f = ir->value.b[i];
       }
       break;
    default:
@@ -1830,9 +2019,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
    }
 
    this->result = st_src_reg(PROGRAM_CONSTANT, -1, ir->type);
-   this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
-                                                  (gl_constant_value *) values,
-                                                  ir->type->vector_elements,
+   this->result.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters,
+                                                  values, ir->type->vector_elements, gl_type,
                                                   &this->result.swizzle);
 }
 
@@ -2535,6 +2723,7 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
 {
    GLuint i;
    GLint outputMap[VERT_RESULT_MAX];
+   GLint outputTypes[VERT_RESULT_MAX];
    GLuint numVaryingReads = 0;
    GLboolean usedTemps[MAX_PROGRAM_TEMPS];
    GLuint firstTemp = 0;
@@ -2562,6 +2751,7 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
                outputMap[var] = _mesa_find_free_register(usedTemps,
                                                          MAX_PROGRAM_TEMPS,
                                                          firstTemp);
+               outputTypes[var] = inst->src[j].type;
                firstTemp = outputMap[var] + 1;
             }
             inst->src[j].file = PROGRAM_TEMPORARY;
@@ -2587,8 +2777,8 @@ glsl_to_tgsi_visitor::remove_output_reads(gl_register_file type)
    for (i = 0; i < VERT_RESULT_MAX; i++) {
       if (outputMap[i] >= 0) {
          /* MOV VAR[i], TEMP[tmp]; */
-         st_src_reg src = st_src_reg(PROGRAM_TEMPORARY, outputMap[i]);
-         st_dst_reg dst = st_dst_reg(type, WRITEMASK_XYZW);
+         st_src_reg src = st_src_reg(PROGRAM_TEMPORARY, outputMap[i], outputTypes[i]);
+         st_dst_reg dst = st_dst_reg(type, WRITEMASK_XYZW, outputTypes[i]);
          dst.index = i;
          this->emit(NULL, TGSI_OPCODE_MOV, dst, src);
       }
@@ -3762,10 +3952,33 @@ st_translate_program(
             if (program->indirect_addr_consts)
                t->constants[i] = ureg_DECL_constant( ureg, i );
             else
-               t->constants[i] = 
-                  ureg_DECL_immediate( ureg,
-                                       (GLfloat *) proginfo->Parameters->ParameterValues[i],
-                                       4 );
+               switch(proginfo->Parameters->Parameters[i].DataType)
+               {
+               case GL_FLOAT:
+               case GL_FLOAT_VEC2:
+               case GL_FLOAT_VEC3:
+               case GL_FLOAT_VEC4:
+                  t->constants[i] = ureg_DECL_immediate(ureg, (float *)proginfo->Parameters->ParameterValues[i], 4);
+                  break;
+               case GL_INT:
+               case GL_INT_VEC2:
+               case GL_INT_VEC3:
+               case GL_INT_VEC4:
+                  t->constants[i] = ureg_DECL_immediate_int(ureg, (int *)proginfo->Parameters->ParameterValues[i], 4);
+                  break;
+               case GL_UNSIGNED_INT:
+               case GL_UNSIGNED_INT_VEC2:
+               case GL_UNSIGNED_INT_VEC3:
+               case GL_UNSIGNED_INT_VEC4:
+               case GL_BOOL:
+               case GL_BOOL_VEC2:
+               case GL_BOOL_VEC3:
+               case GL_BOOL_VEC4:
+                  t->constants[i] = ureg_DECL_immediate_uint(ureg, (unsigned *)proginfo->Parameters->ParameterValues[i], 4);
+                  break;
+               default:
+                  assert(!"should not get here");
+               }
             break;
          default:
             break;
@@ -3874,6 +4087,7 @@ get_mesa_program(struct gl_context *ctx,
    v->prog = prog;
    v->shader_program = shader_program;
    v->options = options;
+   v->glsl_version = ctx->Const.GLSLVersion;
 
    add_uniforms_to_parameters_list(shader_program, shader, prog);