glsl_to_tgsi: Remove st_new_shader
[mesa.git] / src / mesa / state_tracker / st_glsl_to_tgsi.cpp
index 3c8aceef9ae82ec18852afd7c09cacc427135537..a4e2c8da58697e6da6366c2284409d86af06e40b 100644 (file)
@@ -74,14 +74,6 @@ extern "C" {
                            (1 << PROGRAM_CONSTANT) |     \
                            (1 << PROGRAM_UNIFORM))
 
-/**
- * Maximum number of temporary registers.
- *
- * It is too big for stack allocated arrays -- it will cause stack overflow on
- * Windows and likely Mac OS X.
- */
-#define MAX_TEMPS         4096
-
 /**
  * Maximum number of arrays
  */
@@ -245,7 +237,8 @@ public:
    ir_instruction *ir;
    GLboolean cond_update;
    bool saturate;
-   int sampler; /**< sampler index */
+   st_src_reg sampler; /**< sampler register */
+   int sampler_array_size; /**< 1-based size of sampler array, 1 if not array */
    int tex_target; /**< One of TEXTURE_*_INDEX */
    GLboolean tex_shadow;
 
@@ -445,7 +438,6 @@ public:
               int mul_operand);
    bool try_emit_mad_for_and_not(ir_expression *ir,
               int mul_operand);
-   bool try_emit_sat(ir_expression *ir);
 
    void emit_swz(ir_expression *ir);
 
@@ -476,6 +468,7 @@ static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_T
 
 static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 0);
 static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 1);
+static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 2);
 
 static void
 fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
@@ -1079,8 +1072,8 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
 
    if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
       unsigned int i;
-      const ir_state_slot *const slots = ir->state_slots;
-      assert(ir->state_slots != NULL);
+      const ir_state_slot *const slots = ir->get_state_slots();
+      assert(slots != NULL);
 
       /* Check if this statevar's setup in the STATE file exactly
        * matches how we'll want to reference it as a
@@ -1088,7 +1081,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
        * temporary storage and hope that it'll get copy-propagated
        * out.
        */
-      for (i = 0; i < ir->num_state_slots; i++) {
+      for (i = 0; i < ir->get_num_state_slots(); i++) {
          if (slots[i].swizzle != SWIZZLE_XYZW) {
             break;
          }
@@ -1096,7 +1089,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
 
       variable_storage *storage;
       st_dst_reg dst;
-      if (i == ir->num_state_slots) {
+      if (i == ir->get_num_state_slots()) {
          /* We'll set the index later. */
          storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
          this->variables.push_tail(storage);
@@ -1107,7 +1100,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
           * of the type.  However, this had better match the number of state
           * elements that we're going to copy into the new temporary.
           */
-         assert((int) ir->num_state_slots == type_size(ir->type));
+         assert((int) ir->get_num_state_slots() == type_size(ir->type));
 
          dst = st_dst_reg(get_temp(ir->type));
 
@@ -1117,7 +1110,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
       }
 
 
-      for (unsigned int i = 0; i < ir->num_state_slots; i++) {
+      for (unsigned int i = 0; i < ir->get_num_state_slots(); i++) {
          int index = _mesa_add_state_reference(this->prog->Parameters,
                                               (gl_state_index *)slots[i].tokens);
 
@@ -1142,7 +1135,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
       }
 
       if (storage->file == PROGRAM_TEMPORARY &&
-          dst.index != storage->index + (int) ir->num_state_slots) {
+          dst.index != storage->index + (int) ir->get_num_state_slots()) {
          fail_link(this->shader_program,
                   "failed to load builtin uniform `%s'  (%d/%d regs loaded)\n",
                   ir->name, dst.index - storage->index,
@@ -1268,53 +1261,6 @@ glsl_to_tgsi_visitor::try_emit_mad_for_and_not(ir_expression *ir, int try_operan
    return true;
 }
 
-bool
-glsl_to_tgsi_visitor::try_emit_sat(ir_expression *ir)
-{
-   /* Emit saturates in the vertex shader only if SM 3.0 is supported.
-    */
-   if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
-       !st_context(this->ctx)->has_shader_model3) {
-      return false;
-   }
-
-   ir_rvalue *sat_src = ir->as_rvalue_to_saturate();
-   if (!sat_src)
-      return false;
-
-   sat_src->accept(this);
-   st_src_reg src = this->result;
-
-   /* If we generated an expression instruction into a temporary in
-    * processing the saturate's operand, apply the saturate to that
-    * instruction.  Otherwise, generate a MOV to do the saturate.
-    *
-    * Note that we have to be careful to only do this optimization if
-    * the instruction in question was what generated src->result.  For
-    * example, ir_dereference_array might generate a MUL instruction
-    * to create the reladdr, and return us a src reg using that
-    * reladdr.  That MUL result is not the value we're trying to
-    * saturate.
-    */
-   ir_expression *sat_src_expr = sat_src->as_expression();
-   if (sat_src_expr && (sat_src_expr->operation == ir_binop_mul ||
-                       sat_src_expr->operation == ir_binop_add ||
-                       sat_src_expr->operation == ir_binop_dot)) {
-      glsl_to_tgsi_instruction *new_inst;
-      new_inst = (glsl_to_tgsi_instruction *)this->instructions.get_tail();
-      new_inst->saturate = true;
-   } else {
-      this->result = get_temp(ir->type);
-      st_dst_reg result_dst = st_dst_reg(this->result);
-      result_dst.writemask = (1 << ir->type->vector_elements) - 1;
-      glsl_to_tgsi_instruction *inst;
-      inst = emit(ir, TGSI_OPCODE_MOV, result_dst, src);
-      inst->saturate = true;
-   }
-
-   return true;
-}
-
 void
 glsl_to_tgsi_visitor::reladdr_to_temp(ir_instruction *ir,
                                    st_src_reg *reg, int *num_reladdr)
@@ -1361,9 +1307,6 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
         return;
    }
 
-   if (try_emit_sat(ir))
-      return;
-
    if (ir->operation == ir_quadop_vector)
       assert(!"ir_quadop_vector should have been lowered");
 
@@ -1458,11 +1401,23 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
    case ir_unop_cos_reduced:
       emit_scs(ir, TGSI_OPCODE_COS, result_dst, op[0]);
       break;
+   case ir_unop_saturate: {
+      glsl_to_tgsi_instruction *inst;
+      inst = emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
+      inst->saturate = true;
+      break;
+   }
 
    case ir_unop_dFdx:
+   case ir_unop_dFdx_coarse:
       emit(ir, TGSI_OPCODE_DDX, result_dst, op[0]);
       break;
+   case ir_unop_dFdx_fine:
+      emit(ir, TGSI_OPCODE_DDX_FINE, result_dst, op[0]);
+      break;
    case ir_unop_dFdy:
+   case ir_unop_dFdy_coarse:
+   case ir_unop_dFdy_fine:
    {
       /* The X component contains 1 or -1 depending on whether the framebuffer
        * is a FBO or the window system buffer, respectively.
@@ -1483,7 +1438,8 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       st_src_reg temp = get_temp(glsl_type::vec4_type);
 
       emit(ir, TGSI_OPCODE_MUL, st_dst_reg(temp), transform_y, op[0]);
-      emit(ir, TGSI_OPCODE_DDY, result_dst, temp);
+      emit(ir, ir->operation == ir_unop_dFdy_fine ?
+           TGSI_OPCODE_DDY_FINE : TGSI_OPCODE_DDY, result_dst, temp);
       break;
    }
 
@@ -2661,10 +2617,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir)
    case GLSL_TYPE_BOOL:
       gl_type = native_integers ? GL_BOOL : GL_FLOAT;
       for (i = 0; i < ir->type->vector_elements; i++) {
-         if (native_integers)
-            values[i].u = ir->value.b[i] ? ~0 : 0;
-         else
-            values[i].f = ir->value.b[i];
+         values[i].u = ir->value.b[i] ? ctx->Const.UniformBooleanTrue : 0;
       }
       break;
    default:
@@ -2799,6 +2752,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
    glsl_to_tgsi_instruction *inst = NULL;
    unsigned opcode = TGSI_OPCODE_NOP;
    const glsl_type *sampler_type = ir->sampler->type;
+   ir_rvalue *sampler_index =
+      _mesa_get_sampler_array_nonconst_index(ir->sampler);
    bool is_cube_array = false;
    unsigned i;
 
@@ -3016,6 +2971,11 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
       coord_dst.writemask = WRITEMASK_XYZW;
    }
 
+   if (sampler_index) {
+      sampler_index->accept(this);
+      emit_arl(ir, sampler_reladdr, this->result);
+   }
+
    if (opcode == TGSI_OPCODE_TXD)
       inst = emit(ir, opcode, result_dst, coord, dx, dy);
    else if (opcode == TGSI_OPCODE_TXQ) {
@@ -3045,9 +3005,17 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
    if (ir->shadow_comparitor)
       inst->tex_shadow = GL_TRUE;
 
-   inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler,
-                                                  this->shader_program,
-                                                  this->prog);
+   inst->sampler.index = _mesa_get_sampler_uniform_value(ir->sampler,
+                                                         this->shader_program,
+                                                         this->prog);
+   if (sampler_index) {
+      inst->sampler.reladdr = ralloc(mem_ctx, st_src_reg);
+      memcpy(inst->sampler.reladdr, &sampler_reladdr, sizeof(sampler_reladdr));
+      inst->sampler_array_size =
+         ir->sampler->as_dereference_array()->array->type->array_size();
+   } else {
+      inst->sampler_array_size = 1;
+   }
 
    if (ir->offset) {
       for (i = 0; i < MAX_GLSL_TEXTURE_OFFSET && offset[i].file != PROGRAM_UNDEFINED; i++)
@@ -3120,8 +3088,18 @@ glsl_to_tgsi_visitor::visit(ir_discard *ir)
 {
    if (ir->condition) {
       ir->condition->accept(this);
-      this->result.negate = ~this->result.negate;
-      emit(ir, TGSI_OPCODE_KILL_IF, undef_dst, this->result);
+      st_src_reg condition = this->result;
+
+      /* Convert the bool condition to a float so we can negate. */
+      if (native_integers) {
+         st_src_reg temp = get_temp(ir->condition->type);
+         emit(ir, TGSI_OPCODE_AND, st_dst_reg(temp),
+              condition, st_src_reg_for_float(1.0));
+         condition = temp;
+      }
+
+      condition.negate = ~condition.negate;
+      emit(ir, TGSI_OPCODE_KILL_IF, undef_dst, condition);
    } else {
       /* unconditional kil */
       emit(ir, TGSI_OPCODE_KILL);
@@ -3191,6 +3169,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
    shader_program = NULL;
    shader = NULL;
    options = NULL;
+   have_sqrt = false;
 }
 
 glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()
@@ -3215,10 +3194,12 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog)
 
    foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) {
       if (is_tex_instruction(inst->op)) {
-         v->samplers_used |= 1 << inst->sampler;
+         for (int i = 0; i < inst->sampler_array_size; i++) {
+            v->samplers_used |= 1 << (inst->sampler.index + i);
 
-         if (inst->tex_shadow) {
-            prog->ShadowSamplers |= 1 << inst->sampler;
+            if (inst->tex_shadow) {
+               prog->ShadowSamplers |= 1 << (inst->sampler.index + i);
+            }
          }
       }
    }
@@ -3229,78 +3210,6 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog)
       _mesa_update_shader_textures_used(v->shader_program, prog);
 }
 
-static void
-set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
-                       struct gl_shader_program *shader_program,
-                       const char *name, const glsl_type *type,
-                       ir_constant *val)
-{
-   if (type->is_record()) {
-      ir_constant *field_constant;
-
-      field_constant = (ir_constant *)val->components.get_head();
-
-      for (unsigned int i = 0; i < type->length; i++) {
-         const glsl_type *field_type = type->fields.structure[i].type;
-         const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
-                                           type->fields.structure[i].name);
-         set_uniform_initializer(ctx, mem_ctx, shader_program, field_name,
-                                field_type, field_constant);
-         field_constant = (ir_constant *)field_constant->next;
-      }
-      return;
-   }
-
-   unsigned offset;
-   unsigned index = _mesa_get_uniform_location(ctx, shader_program, name,
-                                              &offset);
-   if (offset == GL_INVALID_INDEX) {
-      fail_link(shader_program,
-               "Couldn't find uniform for initializer %s\n", name);
-      return;
-   }
-   int loc = _mesa_uniform_merge_location_offset(shader_program, index, offset);
-
-   for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
-      ir_constant *element;
-      const glsl_type *element_type;
-      if (type->is_array()) {
-         element = val->array_elements[i];
-         element_type = type->fields.array;
-      } else {
-         element = val;
-         element_type = type;
-      }
-
-      void *values;
-
-      if (element_type->base_type == GLSL_TYPE_BOOL) {
-         int *conv = ralloc_array(mem_ctx, int, element_type->components());
-         for (unsigned int j = 0; j < element_type->components(); j++) {
-            conv[j] = element->value.b[j];
-         }
-         values = (void *)conv;
-         element_type = glsl_type::get_instance(GLSL_TYPE_INT,
-                                               element_type->vector_elements,
-                                               1);
-      } else {
-         values = &element->value;
-      }
-
-      if (element_type->is_matrix()) {
-         _mesa_uniform_matrix(ctx, shader_program,
-                             element_type->matrix_columns,
-                             element_type->vector_elements,
-                             loc, 1, GL_FALSE, (GLfloat *)values);
-      } else {
-         _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns,
-                      values, element_type->gl_type);
-      }
-
-      loc++;
-   }
-}
-
 /**
  * Returns the mask of channels (bitmask of WRITEMASK_X,Y,Z,W) which
  * are read from the given src in this instruction
@@ -3347,14 +3256,10 @@ get_src_arg_mask(st_dst_reg dst, st_src_reg src)
 void
 glsl_to_tgsi_visitor::simplify_cmp(void)
 {
-   unsigned *tempWrites;
+   int tempWritesSize = 0;
+   unsigned *tempWrites = NULL;
    unsigned outputWrites[MAX_PROGRAM_OUTPUTS];
 
-   tempWrites = new unsigned[MAX_TEMPS];
-   if (!tempWrites) {
-      return;
-   }
-   memset(tempWrites, 0, sizeof(unsigned) * MAX_TEMPS);
    memset(outputWrites, 0, sizeof(outputWrites));
 
    foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
@@ -3376,7 +3281,19 @@ glsl_to_tgsi_visitor::simplify_cmp(void)
          prevWriteMask = outputWrites[inst->dst.index];
          outputWrites[inst->dst.index] |= inst->dst.writemask;
       } else if (inst->dst.file == PROGRAM_TEMPORARY) {
-         assert(inst->dst.index < MAX_TEMPS);
+         if (inst->dst.index >= tempWritesSize) {
+            const int inc = 4096;
+
+            tempWrites = (unsigned*)
+                         realloc(tempWrites,
+                                 (tempWritesSize + inc) * sizeof(unsigned));
+            if (!tempWrites)
+               return;
+
+            memset(tempWrites + tempWritesSize, 0, inc * sizeof(unsigned));
+            tempWritesSize += inc;
+         }
+
          prevWriteMask = tempWrites[inst->dst.index];
          tempWrites[inst->dst.index] |= inst->dst.writemask;
       } else
@@ -3395,7 +3312,7 @@ glsl_to_tgsi_visitor::simplify_cmp(void)
       }
    }
 
-   delete [] tempWrites;
+   free(tempWrites);
 }
 
 /* Replaces all references to a temporary register index with another index. */
@@ -4024,7 +3941,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
    src0 = v->get_temp(glsl_type::vec4_type);
    dst0 = st_dst_reg(src0);
    inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
-   inst->sampler = 0;
+   inst->sampler_array_size = 1;
    inst->tex_target = TEXTURE_2D_INDEX;
 
    prog->InputsRead |= VARYING_BIT_TEX0;
@@ -4063,14 +3980,16 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
       /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
       temp_dst.writemask = WRITEMASK_XY; /* write R,G */
       inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
-      inst->sampler = 1;
+      inst->sampler.index = 1;
+      inst->sampler_array_size = 1;
       inst->tex_target = TEXTURE_2D_INDEX;
 
       /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
       src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
       temp_dst.writemask = WRITEMASK_ZW; /* write B,A */
       inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
-      inst->sampler = 1;
+      inst->sampler.index = 1;
+      inst->sampler_array_size = 1;
       inst->tex_target = TEXTURE_2D_INDEX;
 
       prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */
@@ -4151,7 +4070,8 @@ get_bitmap_visitor(struct st_fragment_program *fp,
    src0 = v->get_temp(glsl_type::vec4_type);
    dst0 = st_dst_reg(src0);
    inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord);
-   inst->sampler = samplerIndex;
+   inst->sampler.index = samplerIndex;
+   inst->sampler_array_size = 1;
    inst->tex_target = TEXTURE_2D_INDEX;
 
    prog->InputsRead |= VARYING_BIT_TEX0;
@@ -4201,13 +4121,15 @@ struct label {
 struct st_translate {
    struct ureg_program *ureg;
 
-   struct ureg_dst temps[MAX_TEMPS];
+   unsigned temps_size;
+   struct ureg_dst *temps;
+
    struct ureg_dst arrays[MAX_ARRAYS];
    struct ureg_src *constants;
    struct ureg_src *immediates;
    struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
    struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
-   struct ureg_dst address[2];
+   struct ureg_dst address[3];
    struct ureg_src samplers[PIPE_MAX_SAMPLERS];
    struct ureg_src systemValues[SYSTEM_VALUE_MAX];
    struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET];
@@ -4239,13 +4161,23 @@ struct st_translate {
 
 /** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */
 const unsigned _mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = {
-   TGSI_SEMANTIC_FACE,
+   /* Vertex shader
+    */
    TGSI_SEMANTIC_VERTEXID,
    TGSI_SEMANTIC_INSTANCEID,
+   0,
+   0,
+
+   /* Geometry shader
+    */
+   TGSI_SEMANTIC_INVOCATIONID,
+
+   /* Fragment shader
+    */
+   TGSI_SEMANTIC_FACE,
    TGSI_SEMANTIC_SAMPLEID,
    TGSI_SEMANTIC_SAMPLEPOS,
    TGSI_SEMANTIC_SAMPLEMASK,
-   TGSI_SEMANTIC_INVOCATIONID,
 };
 
 /**
@@ -4334,7 +4266,19 @@ dst_register(struct st_translate *t,
       return ureg_dst_undef();
 
    case PROGRAM_TEMPORARY:
-      assert(index < Elements(t->temps));
+      /* Allocate space for temporaries on demand. */
+      if (index >= t->temps_size) {
+         const int inc = 4096;
+
+         t->temps = (struct ureg_dst*)
+                    realloc(t->temps,
+                            (t->temps_size + inc) * sizeof(struct ureg_dst));
+         if (!t->temps)
+            return ureg_dst_undef();
+
+         memset(t->temps + t->temps_size, 0, inc * sizeof(struct ureg_dst));
+         t->temps_size += inc;
+      }
 
       if (ureg_dst_is_undef(t->temps[index]))
          t->temps[index] = ureg_DECL_local_temporary(t->ureg);
@@ -4610,7 +4554,11 @@ compile_tgsi_instruction(struct st_translate *t,
    case TGSI_OPCODE_TXL2:
    case TGSI_OPCODE_TG4:
    case TGSI_OPCODE_LODQ:
-      src[num_src++] = t->samplers[inst->sampler];
+      src[num_src] = t->samplers[inst->sampler.index];
+      if (inst->sampler.reladdr)
+         src[num_src] =
+            ureg_src_indirect(src[num_src], ureg_src(t->address[2]));
+      num_src++;
       for (i = 0; i < inst->tex_offset_num_offset; i++) {
          texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i], i);
       }
@@ -4833,15 +4781,19 @@ emit_wpos(struct st_context *st,
  * saturating the value to [0,1] does the job.
  */
 static void
-emit_face_var(struct st_translate *t)
+emit_face_var(struct gl_context *ctx, struct st_translate *t)
 {
    struct ureg_program *ureg = t->ureg;
    struct ureg_dst face_temp = ureg_DECL_temporary(ureg);
    struct ureg_src face_input = t->inputs[t->inputMapping[VARYING_SLOT_FACE]];
 
-   /* MOV_SAT face_temp, input[face] */
-   face_temp = ureg_saturate(face_temp);
-   ureg_MOV(ureg, face_temp, face_input);
+   if (ctx->Const.NativeIntegers) {
+      ureg_FSGE(ureg, face_temp, face_input, ureg_imm1f(ureg, 0));
+   }
+   else {
+      /* MOV_SAT face_temp, input[face] */
+      ureg_MOV(ureg, ureg_saturate(face_temp), face_input);
+   }
 
    /* Use face_temp as face input from here on: */
    t->inputs[t->inputMapping[VARYING_SLOT_FACE]] = ureg_src(face_temp);
@@ -4904,6 +4856,21 @@ st_translate_program(
    assert(numInputs <= Elements(t->inputs));
    assert(numOutputs <= Elements(t->outputs));
 
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_FRONT_FACE] ==
+          TGSI_SEMANTIC_FACE);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_VERTEX_ID] ==
+          TGSI_SEMANTIC_VERTEXID);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_INSTANCE_ID] ==
+          TGSI_SEMANTIC_INSTANCEID);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_ID] ==
+          TGSI_SEMANTIC_SAMPLEID);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_POS] ==
+          TGSI_SEMANTIC_SAMPLEPOS);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_MASK_IN] ==
+          TGSI_SEMANTIC_SAMPLEMASK);
+   assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_INVOCATION_ID] ==
+          TGSI_SEMANTIC_INVOCATIONID);
+
    t = CALLOC_STRUCT(st_translate);
    if (!t) {
       ret = PIPE_ERROR_OUT_OF_MEMORY;
@@ -4946,7 +4913,7 @@ st_translate_program(
       }
 
       if (proginfo->InputsRead & VARYING_BIT_FACE)
-         emit_face_var(t);
+         emit_face_var(ctx, t);
 
       /*
        * Declare output attributes.
@@ -5026,10 +4993,9 @@ st_translate_program(
    /* Declare address register.
     */
    if (program->num_address_regs > 0) {
-      assert(program->num_address_regs <= 2);
-      t->address[0] = ureg_DECL_address(ureg);
-      if (program->num_address_regs == 2)
-         t->address[1] = ureg_DECL_address(ureg);
+      assert(program->num_address_regs <= 3);
+      for (int i = 0; i < program->num_address_regs; i++)
+         t->address[i] = ureg_DECL_address(ureg);
    }
 
    /* Declare misc input registers
@@ -5175,6 +5141,7 @@ st_translate_program(
 
 out:
    if (t) {
+      free(t->temps);
       free(t->insn);
       free(t->labels);
       free(t->constants);
@@ -5225,7 +5192,7 @@ get_mesa_program(struct gl_context *ctx,
    GLenum target = _mesa_shader_stage_to_program(shader->Stage);
    bool progress;
    struct gl_shader_compiler_options *options =
-         &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)];
+         &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)];
    struct pipe_screen *pscreen = ctx->st->pipe->screen;
    unsigned ptarget = shader_stage_to_ptarget(shader->Stage);
 
@@ -5247,6 +5214,7 @@ get_mesa_program(struct gl_context *ctx,
    v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget,
                                             PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
 
+   _mesa_copy_linked_program_data(shader->Stage, shader_program, prog);
    _mesa_generate_parameters_list_for_uniforms(shader_program, shader,
                                               prog->Parameters);
 
@@ -5352,10 +5320,6 @@ get_mesa_program(struct gl_context *ctx,
    case GL_GEOMETRY_SHADER:
       stgp = (struct st_geometry_program *)prog;
       stgp->glsl_to_tgsi = v;
-      stgp->Base.InputType = shader_program->Geom.InputType;
-      stgp->Base.OutputType = shader_program->Geom.OutputType;
-      stgp->Base.VerticesOut = shader_program->Geom.VerticesOut;
-      stgp->Base.Invocations = shader_program->Geom.Invocations;
       break;
    default:
       assert(!"should not be reached");
@@ -5367,34 +5331,6 @@ get_mesa_program(struct gl_context *ctx,
 
 extern "C" {
 
-struct gl_shader *
-st_new_shader(struct gl_context *ctx, GLuint name, GLuint type)
-{
-   struct gl_shader *shader;
-   assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
-          type == GL_GEOMETRY_SHADER_ARB);
-   shader = rzalloc(NULL, struct gl_shader);
-   if (shader) {
-      shader->Type = type;
-      shader->Stage = _mesa_shader_enum_to_shader_stage(type);
-      shader->Name = name;
-      _mesa_init_shader(ctx, shader);
-   }
-   return shader;
-}
-
-struct gl_shader_program *
-st_new_shader_program(struct gl_context *ctx, GLuint name)
-{
-   struct gl_shader_program *shProg;
-   shProg = rzalloc(NULL, struct gl_shader_program);
-   if (shProg) {
-      shProg->Name = name;
-      _mesa_init_shader_program(ctx, shProg);
-   }
-   return shProg;
-}
-
 /**
  * Link a shader.
  * Called via ctx->Driver.LinkShader()
@@ -5414,7 +5350,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       bool progress;
       exec_list *ir = prog->_LinkedShaders[i]->ir;
       const struct gl_shader_compiler_options *options =
-            &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)];
+            &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)];
 
       /* If there are forms of indirect addressing that the driver
        * cannot handle, perform the lowering pass.
@@ -5446,6 +5382,9 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       if (!pscreen->get_param(pscreen, PIPE_CAP_TEXTURE_GATHER_OFFSETS))
          lower_offset_arrays(ir);
       do_mat_op_to_vec(ir);
+      /* Emit saturates in the vertex shader only if SM 3.0 is supported. */
+      bool vs_sm3 = (_mesa_shader_stage_to_program(prog->_LinkedShaders[i]->Stage) ==
+                         GL_VERTEX_PROGRAM_ARB) && st_context(ctx)->has_shader_model3;
       lower_instructions(ir,
                          MOD_TO_FRACT |
                          DIV_TO_MUL_RCP |
@@ -5455,7 +5394,8 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
                          CARRY_TO_ARITH |
                          BORROW_TO_ARITH |
                          (options->EmitNoPow ? POW_TO_EXP2 : 0) |
-                         (!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0));
+                         (!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0) |
+                         (vs_sm3 ? SAT_TO_CLAMP : 0));
 
       lower_ubo_reference(prog->_LinkedShaders[i], ir);
       do_vec_index_to_cond_assign(ir);