diff options
| author | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-19 21:46:33 +0100 | 
|---|---|---|
| committer | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-19 21:46:33 +0100 | 
| commit | 0f68236a2487dbeb0396b996debcda595b0b54a1 (patch) | |
| tree | 938ae3b779349b6dba6f5a891550604f9a9ca895 /src/mesa/program | |
| parent | d047168d81cfeb39a98f3ae16416872facc6237c (diff) | |
| parent | 237880463d5168cad8df0bae6018b5fd76617777 (diff) | |
Merge remote branch 'origin/master' into nvc0-new
Diffstat (limited to 'src/mesa/program')
| -rw-r--r-- | src/mesa/program/arbprogparse.h | 6 | ||||
| -rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 491 | ||||
| -rw-r--r-- | src/mesa/program/ir_to_mesa.h | 7 | ||||
| -rw-r--r-- | src/mesa/program/nvfragparse.h | 5 | ||||
| -rw-r--r-- | src/mesa/program/nvvertparse.h | 5 | ||||
| -rw-r--r-- | src/mesa/program/prog_cache.h | 3 | ||||
| -rw-r--r-- | src/mesa/program/prog_execute.c | 12 | ||||
| -rw-r--r-- | src/mesa/program/prog_instruction.h | 2 | ||||
| -rw-r--r-- | src/mesa/program/prog_optimize.h | 3 | ||||
| -rw-r--r-- | src/mesa/program/prog_print.c | 20 | ||||
| -rw-r--r-- | src/mesa/program/prog_print.h | 3 | ||||
| -rw-r--r-- | src/mesa/program/prog_statevars.c | 30 | ||||
| -rw-r--r-- | src/mesa/program/prog_statevars.h | 5 | ||||
| -rw-r--r-- | src/mesa/program/program.c | 97 | ||||
| -rw-r--r-- | src/mesa/program/program.h | 6 | ||||
| -rw-r--r-- | src/mesa/program/symbol_table.c | 85 | ||||
| -rw-r--r-- | src/mesa/program/symbol_table.h | 4 | 
17 files changed, 707 insertions, 77 deletions
diff --git a/src/mesa/program/arbprogparse.h b/src/mesa/program/arbprogparse.h index 08e25a1c16..4c0c300720 100644 --- a/src/mesa/program/arbprogparse.h +++ b/src/mesa/program/arbprogparse.h @@ -26,7 +26,11 @@  #ifndef ARBPROGPARSE_H  #define ARBPROGPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_fragment_program; +struct gl_vertex_program;  extern void  _mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index f45bbf5582..490c4cab7a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -65,7 +65,7 @@ static int swizzle_for_size(int size);  typedef struct ir_to_mesa_src_reg {     ir_to_mesa_src_reg(int file, int index, const glsl_type *type)     { -      this->file = file; +      this->file = (gl_register_file) file;        this->index = index;        if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))  	 this->swizzle = swizzle_for_size(type->vector_elements); @@ -84,7 +84,7 @@ typedef struct ir_to_mesa_src_reg {        this->reladdr = NULL;     } -   int file; /**< PROGRAM_* from Mesa */ +   gl_register_file file; /**< PROGRAM_* from Mesa */     int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */     GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */     int negate; /**< NEGATE_XYZW mask from mesa */ @@ -123,6 +123,7 @@ public:     /** Pointer to the ir source this tree came from for debugging */     ir_instruction *ir;     GLboolean cond_update; +   bool saturate;     int sampler; /**< sampler index */     int tex_target; /**< One of TEXTURE_*_INDEX */     GLboolean tex_shadow; @@ -132,13 +133,13 @@ public:  class variable_storage : public exec_node {  public: -   variable_storage(ir_variable *var, int file, int index) +   variable_storage(ir_variable *var, gl_register_file file, int index)        : file(file), index(index), var(var)     {        /* empty */     } -   int file; +   gl_register_file file;     int index;     ir_variable *var; /* variable that maps to this, if any */  }; @@ -282,8 +283,17 @@ public:  				   ir_to_mesa_src_reg src0,  				   ir_to_mesa_src_reg src1); +   void emit_scs(ir_instruction *ir, enum prog_opcode op, +		 ir_to_mesa_dst_reg dst, +		 const ir_to_mesa_src_reg &src); +     GLboolean try_emit_mad(ir_expression *ir,  			  int mul_operand); +   GLboolean try_emit_sat(ir_expression *ir); + +   void emit_swz(ir_expression *ir); + +   bool process_move_condition(ir_rvalue *ir);     void *mem_ctx;  }; @@ -473,6 +483,10 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,        GLuint src0_swiz = GET_SWZ(src0.swizzle, i);        GLuint src1_swiz = GET_SWZ(src1.swizzle, i);        for (j = i + 1; j < 4; j++) { +	 /* If there is another enabled component in the destination that is +	  * derived from the same inputs, generate its value on this pass as +	  * well. +	  */  	 if (!(done_mask & (1 << j)) &&  	     GET_SWZ(src0.swizzle, j) == src0_swiz &&  	     GET_SWZ(src1.swizzle, j) == src1_swiz) { @@ -506,6 +520,102 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,     ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);  } +/** + * Emit an OPCODE_SCS instruction + * + * The \c SCS opcode functions a bit differently than the other Mesa (or + * ARB_fragment_program) opcodes.  Instead of splatting its result across all + * four components of the destination, it writes one value to the \c x + * component and another value to the \c y component. + * + * \param ir        IR instruction being processed + * \param op        Either \c OPCODE_SIN or \c OPCODE_COS depending on which + *                  value is desired. + * \param dst       Destination register + * \param src       Source register + */ +void +ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op, +			     ir_to_mesa_dst_reg dst, +			     const ir_to_mesa_src_reg &src) +{ +   /* Vertex programs cannot use the SCS opcode. +    */ +   if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) { +      ir_to_mesa_emit_scalar_op1(ir, op, dst, src); +      return; +   } + +   const unsigned component = (op == OPCODE_SIN) ? 0 : 1; +   const unsigned scs_mask = (1U << component); +   int done_mask = ~dst.writemask; +   ir_to_mesa_src_reg tmp; + +   assert(op == OPCODE_SIN || op == OPCODE_COS); + +   /* If there are compnents in the destination that differ from the component +    * that will be written by the SCS instrution, we'll need a temporary. +    */ +   if (scs_mask != unsigned(dst.writemask)) { +      tmp = get_temp(glsl_type::vec4_type); +   } + +   for (unsigned i = 0; i < 4; i++) { +      unsigned this_mask = (1U << i); +      ir_to_mesa_src_reg src0 = src; + +      if ((done_mask & this_mask) != 0) +	 continue; + +      /* The source swizzle specified which component of the source generates +       * sine / cosine for the current component in the destination.  The SCS +       * instruction requires that this value be swizzle to the X component. +       * Replace the current swizzle with a swizzle that puts the source in +       * the X component. +       */ +      unsigned src0_swiz = GET_SWZ(src.swizzle, i); + +      src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz, +				   src0_swiz, src0_swiz); +      for (unsigned j = i + 1; j < 4; j++) { +	 /* If there is another enabled component in the destination that is +	  * derived from the same inputs, generate its value on this pass as +	  * well. +	  */ +	 if (!(done_mask & (1 << j)) && +	     GET_SWZ(src0.swizzle, j) == src0_swiz) { +	    this_mask |= (1 << j); +	 } +      } + +      if (this_mask != scs_mask) { +	 ir_to_mesa_instruction *inst; +	 ir_to_mesa_dst_reg tmp_dst = ir_to_mesa_dst_reg_from_src(tmp); + +	 /* Emit the SCS instruction. +	  */ +	 inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, tmp_dst, src0); +	 inst->dst_reg.writemask = scs_mask; + +	 /* Move the result of the SCS instruction to the desired location in +	  * the destination. +	  */ +	 tmp.swizzle = MAKE_SWIZZLE4(component, component, +				     component, component); +	 inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, tmp); +	 inst->dst_reg.writemask = this_mask; +      } else { +	 /* Emit the SCS instruction to write directly to the destination. +	  */ +	 ir_to_mesa_instruction *inst = +	    ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, src0); +	 inst->dst_reg.writemask = scs_mask; +      } + +      done_mask |= this_mask; +   } +} +  struct ir_to_mesa_src_reg  ir_to_mesa_visitor::src_reg_for_float(float val)  { @@ -831,6 +941,32 @@ ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)     return true;  } +GLboolean +ir_to_mesa_visitor::try_emit_sat(ir_expression *ir) +{ +   /* Saturates were only introduced to vertex programs in +    * NV_vertex_program3, so don't give them to drivers in the VP. +    */ +   if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) +      return false; + +   ir_rvalue *sat_src = ir->as_rvalue_to_saturate(); +   if (!sat_src) +      return false; + +   sat_src->accept(this); +   ir_to_mesa_src_reg src = this->result; + +   this->result = get_temp(ir->type); +   ir_to_mesa_instruction *inst; +   inst = ir_to_mesa_emit_op1(ir, OPCODE_MOV, +			      ir_to_mesa_dst_reg_from_src(this->result), +			      src); +   inst->saturate = true; + +   return true; +} +  void  ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,  				    ir_to_mesa_src_reg *reg, int *num_reladdr) @@ -852,10 +988,127 @@ ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,  }  void +ir_to_mesa_visitor::emit_swz(ir_expression *ir) +{ +   /* Assume that the vector operator is in a form compatible with OPCODE_SWZ. +    * This means that each of the operands is either an immediate value of -1, +    * 0, or 1, or is a component from one source register (possibly with +    * negation). +    */ +   uint8_t components[4] = { 0 }; +   bool negate[4] = { false }; +   ir_variable *var = NULL; + +   for (unsigned i = 0; i < ir->type->vector_elements; i++) { +      ir_rvalue *op = ir->operands[i]; + +      assert(op->type->is_scalar()); + +      while (op != NULL) { +	 switch (op->ir_type) { +	 case ir_type_constant: { + +	    assert(op->type->is_scalar()); + +	    const ir_constant *const c = op->as_constant(); +	    if (c->is_one()) { +	       components[i] = SWIZZLE_ONE; +	    } else if (c->is_zero()) { +	       components[i] = SWIZZLE_ZERO; +	    } else if (c->is_negative_one()) { +	       components[i] = SWIZZLE_ONE; +	       negate[i] = true; +	    } else { +	       assert(!"SWZ constant must be 0.0 or 1.0."); +	    } + +	    op = NULL; +	    break; +	 } + +	 case ir_type_dereference_variable: { +	    ir_dereference_variable *const deref = +	       (ir_dereference_variable *) op; + +	    assert((var == NULL) || (deref->var == var)); +	    components[i] = SWIZZLE_X; +	    var = deref->var; +	    op = NULL; +	    break; +	 } + +	 case ir_type_expression: { +	    ir_expression *const expr = (ir_expression *) op; + +	    assert(expr->operation == ir_unop_neg); +	    negate[i] = true; + +	    op = expr->operands[0]; +	    break; +	 } + +	 case ir_type_swizzle: { +	    ir_swizzle *const swiz = (ir_swizzle *) op; + +	    components[i] = swiz->mask.x; +	    op = swiz->val; +	    break; +	 } + +	 default: +	    assert(!"Should not get here."); +	    return; +	 } +      } +   } + +   assert(var != NULL); + +   ir_dereference_variable *const deref = +      new(mem_ctx) ir_dereference_variable(var); + +   this->result.file = PROGRAM_UNDEFINED; +   deref->accept(this); +   if (this->result.file == PROGRAM_UNDEFINED) { +      ir_print_visitor v; +      printf("Failed to get tree for expression operand:\n"); +      deref->accept(&v); +      exit(1); +   } + +   ir_to_mesa_src_reg src; + +   src = this->result; +   src.swizzle = MAKE_SWIZZLE4(components[0], +			       components[1], +			       components[2], +			       components[3]); +   src.negate = ((unsigned(negate[0]) << 0) +		 | (unsigned(negate[1]) << 1) +		 | (unsigned(negate[2]) << 2) +		 | (unsigned(negate[3]) << 3)); + +   /* Storage for our result.  Ideally for an assignment we'd be using the +    * actual storage for the result here, instead. +    */ +   const ir_to_mesa_src_reg result_src = get_temp(ir->type); +   ir_to_mesa_dst_reg result_dst = ir_to_mesa_dst_reg_from_src(result_src); + +   /* Limit writes to the channels that will be used by result_src later. +    * This does limit this temp's use as a temporary for multi-instruction +    * sequences. +    */ +   result_dst.writemask = (1 << ir->type->vector_elements) - 1; + +   ir_to_mesa_emit_op1(ir, OPCODE_SWZ, result_dst, src); +   this->result = result_src; +} + +void  ir_to_mesa_visitor::visit(ir_expression *ir)  {     unsigned int operand; -   struct ir_to_mesa_src_reg op[2]; +   struct ir_to_mesa_src_reg op[Elements(ir->operands)];     struct ir_to_mesa_src_reg result_src;     struct ir_to_mesa_dst_reg result_dst; @@ -867,6 +1120,13 @@ ir_to_mesa_visitor::visit(ir_expression *ir)        if (try_emit_mad(ir, 0))  	 return;     } +   if (try_emit_sat(ir)) +      return; + +   if (ir->operation == ir_quadop_vector) { +      this->emit_swz(ir); +      return; +   }     for (operand = 0; operand < ir->get_num_operands(); operand++) {        this->result.file = PROGRAM_UNDEFINED; @@ -940,6 +1200,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)     case ir_unop_cos:        ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);        break; +   case ir_unop_sin_reduced: +      emit_scs(ir, OPCODE_SIN, result_dst, op[0]); +      break; +   case ir_unop_cos_reduced: +      emit_scs(ir, OPCODE_COS, result_dst, op[0]); +      break;     case ir_unop_dFdx:        ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]); @@ -1058,10 +1324,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir)  			 ir->operands[0]->type->vector_elements);        break; -   case ir_binop_cross: -      ir_to_mesa_emit_op2(ir, OPCODE_XPD, result_dst, op[0], op[1]); -      break; -     case ir_unop_sqrt:        /* sqrt(x) = x * rsq(x). */        ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); @@ -1123,6 +1385,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)     case ir_unop_round_even:        assert(!"GLSL 1.30 features unsupported");        break; + +   case ir_quadop_vector: +      /* This operation should have already been handled. +       */ +      assert(!"Should not get here."); +      break;     }     this->result = result_src; @@ -1301,7 +1569,13 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir)  	 break;        offset += type_size(struct_type->fields.structure[i].type);     } -   this->result.swizzle = swizzle_for_size(ir->type->vector_elements); + +   /* If the type is smaller than a vec4, replicate the last channel out. */ +   if (ir->type->is_scalar() || ir->type->is_vector()) +      this->result.swizzle = swizzle_for_size(ir->type->vector_elements); +   else +      this->result.swizzle = SWIZZLE_NOOP; +     this->result.index += offset;  } @@ -1330,6 +1604,93 @@ get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)     return ir_to_mesa_dst_reg_from_src(v->result);  } +/** + * Process the condition of a conditional assignment + * + * Examines the condition of a conditional assignment to generate the optimal + * first operand of a \c CMP instruction.  If the condition is a relational + * operator with 0 (e.g., \c ir_binop_less), the value being compared will be + * used as the source for the \c CMP instruction.  Otherwise the comparison + * is processed to a boolean result, and the boolean result is used as the + * operand to the CMP instruction. + */ +bool +ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir) +{ +   ir_rvalue *src_ir = ir; +   bool negate = true; +   bool switch_order = false; + +   ir_expression *const expr = ir->as_expression(); +   if ((expr != NULL) && (expr->get_num_operands() == 2)) { +      bool zero_on_left = false; + +      if (expr->operands[0]->is_zero()) { +	 src_ir = expr->operands[1]; +	 zero_on_left = true; +      } else if (expr->operands[1]->is_zero()) { +	 src_ir = expr->operands[0]; +	 zero_on_left = false; +      } + +      /*      a is -  0  +            -  0  + +       * (a <  0)  T  F  F  ( a < 0)  T  F  F +       * (0 <  a)  F  F  T  (-a < 0)  F  F  T +       * (a <= 0)  T  T  F  (-a < 0)  F  F  T  (swap order of other operands) +       * (0 <= a)  F  T  T  ( a < 0)  T  F  F  (swap order of other operands) +       * (a >  0)  F  F  T  (-a < 0)  F  F  T +       * (0 >  a)  T  F  F  ( a < 0)  T  F  F +       * (a >= 0)  F  T  T  ( a < 0)  T  F  F  (swap order of other operands) +       * (0 >= a)  T  T  F  (-a < 0)  F  F  T  (swap order of other operands) +       * +       * Note that exchanging the order of 0 and 'a' in the comparison simply +       * means that the value of 'a' should be negated. +       */ +      if (src_ir != ir) { +	 switch (expr->operation) { +	 case ir_binop_less: +	    switch_order = false; +	    negate = zero_on_left; +	    break; + +	 case ir_binop_greater: +	    switch_order = false; +	    negate = !zero_on_left; +	    break; + +	 case ir_binop_lequal: +	    switch_order = true; +	    negate = !zero_on_left; +	    break; + +	 case ir_binop_gequal: +	    switch_order = true; +	    negate = zero_on_left; +	    break; + +	 default: +	    /* This isn't the right kind of comparison afterall, so make sure +	     * the whole condition is visited. +	     */ +	    src_ir = ir; +	    break; +	 } +      } +   } + +   src_ir->accept(this); + +   /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves, and the +    * condition we produced is 0.0 or 1.0.  By flipping the sign, we can +    * choose which value OPCODE_CMP produces without an extra instruction +    * computing the condition. +    */ +   if (negate) +      this->result.negate = ~this->result.negate; + +   return switch_order; +} +  void  ir_to_mesa_visitor::visit(ir_assignment *ir)  { @@ -1389,20 +1750,18 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)     assert(r.file != PROGRAM_UNDEFINED);     if (ir->condition) { -      ir_to_mesa_src_reg condition; - -      ir->condition->accept(this); -      condition = this->result; +      const bool switch_order = this->process_move_condition(ir->condition); +      ir_to_mesa_src_reg condition = this->result; -      /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves, -       * and the condition we produced is 0.0 or 1.0.  By flipping the -       * sign, we can choose which value OPCODE_CMP produces without -       * an extra computing the condition. -       */ -      condition.negate = ~condition.negate;        for (i = 0; i < type_size(ir->lhs->type); i++) { -	 ir_to_mesa_emit_op3(ir, OPCODE_CMP, l, -			     condition, r, ir_to_mesa_src_reg_from_dst(l)); +	 if (switch_order) { +	    ir_to_mesa_emit_op3(ir, OPCODE_CMP, l, +				condition, ir_to_mesa_src_reg_from_dst(l), r); +	 } else { +	    ir_to_mesa_emit_op3(ir, OPCODE_CMP, l, +				condition, r, ir_to_mesa_src_reg_from_dst(l)); +	 } +  	 l.index++;  	 r.index++;        } @@ -1813,9 +2172,14 @@ ir_to_mesa_visitor::visit(ir_discard *ir)  {     struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; -   assert(ir->condition == NULL); /* FINISHME */ +   if (ir->condition) { +      ir->condition->accept(this); +      this->result.negate = ~this->result.negate; +      ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result); +   } else { +      ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV); +   } -   ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);     fp->UsesKill = GL_TRUE;  } @@ -1886,7 +2250,7 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)     struct prog_src_register mesa_reg;     mesa_reg.File = reg.file; -   assert(reg.index < (1 << INST_INDEX_BITS) - 1); +   assert(reg.index < (1 << INST_INDEX_BITS));     mesa_reg.Index = reg.index;     mesa_reg.Swizzle = reg.swizzle;     mesa_reg.RelAddr = reg.reladdr != NULL; @@ -2256,8 +2620,9 @@ set_uniform_initializers(struct gl_context *ctx,  /**   * Convert a shader's GLSL IR into a Mesa gl_program.   */ -struct gl_program * -get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, +static struct gl_program * +get_mesa_program(struct gl_context *ctx, +                 struct gl_shader_program *shader_program,  		 struct gl_shader *shader)  {     ir_to_mesa_visitor v; @@ -2280,6 +2645,10 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra        target = GL_FRAGMENT_PROGRAM_ARB;        target_string = "fragment";        break; +   case GL_GEOMETRY_SHADER: +      target = GL_GEOMETRY_PROGRAM_NV; +      target_string = "geometry"; +      break;     default:        assert(!"should not be reached");        return NULL; @@ -2355,6 +2724,8 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra        mesa_inst->Opcode = inst->op;        mesa_inst->CondUpdate = inst->cond_update; +      if (inst->saturate) +	 mesa_inst->SaturateMode = SATURATE_ZERO_ONE;        mesa_inst->DstReg.File = inst->dst_reg.file;        mesa_inst->DstReg.Index = inst->dst_reg.index;        mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask; @@ -2401,6 +2772,15 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra        mesa_inst++;        i++; + +      if (!shader_program->LinkStatus) +         break; +   } + +   if (!shader_program->LinkStatus) { +      free(mesa_instructions); +      _mesa_reference_program(ctx, &shader->Program, NULL); +      return NULL;     }     set_branchtargets(&v, mesa_instructions, num_instructions); @@ -2475,16 +2855,20 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)  	 /* Lowering */  	 do_mat_op_to_vec(ir); -	 do_mod_to_fract(ir); -	 do_div_to_mul_rcp(ir); -	 do_explog_to_explog2(ir); +	 lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 +				 | LOG_TO_LOG2 +				 | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));  	 progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;  	 progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress; -	 if (options->EmitNoIfs) +	 progress = lower_quadop_vector(ir, true) || progress; + +	 if (options->EmitNoIfs) { +	    progress = lower_discard(ir) || progress;  	    progress = do_if_to_cond_assign(ir) || progress; +	 }  	 if (options->EmitNoNoise)  	    progress = lower_noise(ir) || progress; @@ -2510,30 +2894,40 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)     for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {        struct gl_program *linked_prog; -      bool ok = true;        if (prog->_LinkedShaders[i] == NULL)  	 continue;        linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); -      switch (prog->_LinkedShaders[i]->Type) { -      case GL_VERTEX_SHADER: -	 _mesa_reference_vertprog(ctx, &prog->VertexProgram, -				  (struct gl_vertex_program *)linked_prog); -	 ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, -					      linked_prog); -	 break; -      case GL_FRAGMENT_SHADER: -	 _mesa_reference_fragprog(ctx, &prog->FragmentProgram, -				  (struct gl_fragment_program *)linked_prog); -	 ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, -					      linked_prog); -	 break; -      } -      if (!ok) { -	 return GL_FALSE; +      if (linked_prog) { +         bool ok = true; + +         switch (prog->_LinkedShaders[i]->Type) { +         case GL_VERTEX_SHADER: +            _mesa_reference_vertprog(ctx, &prog->VertexProgram, +                                     (struct gl_vertex_program *)linked_prog); +            ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, +                                                 linked_prog); +            break; +         case GL_FRAGMENT_SHADER: +            _mesa_reference_fragprog(ctx, &prog->FragmentProgram, +                                     (struct gl_fragment_program *)linked_prog); +            ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, +                                                 linked_prog); +            break; +         case GL_GEOMETRY_SHADER: +            _mesa_reference_geomprog(ctx, &prog->GeometryProgram, +                                     (struct gl_geometry_program *)linked_prog); +            ok = ctx->Driver.ProgramStringNotify(ctx, GL_GEOMETRY_PROGRAM_NV, +                                                 linked_prog); +            break; +         } +         if (!ok) { +            return GL_FALSE; +         }        } +        _mesa_reference_program(ctx, &linked_prog, NULL);     } @@ -2651,6 +3045,7 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)     prog->Varying = _mesa_new_parameter_list();     _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);     _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL); +   _mesa_reference_geomprog(ctx, &prog->GeometryProgram, NULL);     if (prog->LinkStatus) {        link_shaders(ctx, prog); diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h index 7197615f94..7410e14973 100644 --- a/src/mesa/program/ir_to_mesa.h +++ b/src/mesa/program/ir_to_mesa.h @@ -25,8 +25,11 @@  extern "C" {  #endif -#include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_shader; +struct gl_shader_program;  void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh);  void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h index 3e85dd2c30..088e7527d5 100644 --- a/src/mesa/program/nvfragparse.h +++ b/src/mesa/program/nvfragparse.h @@ -30,7 +30,10 @@  #ifndef NVFRAGPARSE_H  #define NVFRAGPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_fragment_program;  extern void  _mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h index e98e867320..7318e14941 100644 --- a/src/mesa/program/nvvertparse.h +++ b/src/mesa/program/nvvertparse.h @@ -29,7 +29,10 @@  #ifndef NVVERTPARSE_H  #define NVVERTPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_vertex_program;  extern void  _mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h index 4907ae3030..0167334827 100644 --- a/src/mesa/program/prog_cache.h +++ b/src/mesa/program/prog_cache.h @@ -30,8 +30,9 @@  #define PROG_CACHE_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context;  /** Opaque type */  struct gl_program_cache; diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c index 1d97a077f5..dd15e9a1cc 100644 --- a/src/mesa/program/prog_execute.c +++ b/src/mesa/program/prog_execute.c @@ -1670,6 +1670,18 @@ _mesa_execute_program(struct gl_context * ctx,              fetch_texel(ctx, machine, inst, texcoord, lodBias, color); +            if (DEBUG_PROG) { +               printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]" +                      "  bias %g\n", +                      color[0], color[1], color[2], color[3], +                      inst->TexSrcUnit, +                      texcoord[0], +                      texcoord[1], +                      texcoord[2], +                      texcoord[3], +                      lodBias); +            } +              store_vector4(inst, machine, color);           }           break; diff --git a/src/mesa/program/prog_instruction.h b/src/mesa/program/prog_instruction.h index ca90de7ce1..a383828e34 100644 --- a/src/mesa/program/prog_instruction.h +++ b/src/mesa/program/prog_instruction.h @@ -247,7 +247,7 @@ typedef enum prog_opcode {   * Number of bits for the src/dst register Index field.   * This limits the size of temp/uniform register files.   */ -#define INST_INDEX_BITS 10 +#define INST_INDEX_BITS 11  /** diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h index 00f1080449..463f5fc51c 100644 --- a/src/mesa/program/prog_optimize.h +++ b/src/mesa/program/prog_optimize.h @@ -27,9 +27,10 @@  #include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context;  struct gl_program;  struct prog_instruction; diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 79c01020eb..abebf392c0 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -42,8 +42,8 @@  /**   * Return string name for given program/register file.   */ -static const char * -file_string(gl_register_file f, gl_prog_print_mode mode) +const char * +_mesa_register_file_name(gl_register_file f)  {     switch (f) {     case PROGRAM_TEMPORARY: @@ -275,7 +275,8 @@ reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,     switch (mode) {     case PROG_PRINT_DEBUG: -      sprintf(str, "%s[%s%d]", file_string(f, mode), addr, index); +      sprintf(str, "%s[%s%d]", +              _mesa_register_file_name(f), addr, index);        if (hasIndex2) {           int offset = strlen(str);           const char *addr2 = relAddr2 ? "ADDR+" : ""; @@ -497,7 +498,7 @@ fprint_dst_reg(FILE * f,  #if 0     fprintf(f, "%s[%d]%s", -	   file_string((gl_register_file) dstReg->File, mode), +	   _mesa_register_file_name((gl_register_file) dstReg->File),  	   dstReg->Index,  	   _mesa_writemask_string(dstReg->WriteMask));  #endif @@ -522,7 +523,7 @@ fprint_src_reg(FILE *f,  	   abs);  #if 0     fprintf(f, "%s[%d]%s", -	   file_string((gl_register_file) srcReg->File, mode), +	   _mesa_register_file_name((gl_register_file) srcReg->File),  	   srcReg->Index,  	   _mesa_swizzle_string(srcReg->Swizzle,  				srcReg->Negate, GL_FALSE)); @@ -615,8 +616,7 @@ _mesa_fprint_instruction_opt(FILE *f,        if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {           fprintf(f, ", ");           fprintf(f, "%s[%d]%s", -		 file_string((gl_register_file) inst->SrcReg[0].File, -			     mode), +                 _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File),  		 inst->SrcReg[0].Index,  		 _mesa_swizzle_string(inst->SrcReg[0].Swizzle,  				      inst->SrcReg[0].Negate, GL_FALSE)); @@ -632,8 +632,7 @@ _mesa_fprint_instruction_opt(FILE *f,        fprintf(f, " ");        fprint_dst_reg(f, &inst->DstReg, mode, prog);        fprintf(f, ", %s[%d], %s", -	      file_string((gl_register_file) inst->SrcReg[0].File, -			  mode), +	      _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File),  	      inst->SrcReg[0].Index,  	      _mesa_swizzle_string(inst->SrcReg[0].Swizzle,  				   inst->SrcReg[0].Negate, GL_TRUE)); @@ -964,7 +963,6 @@ static void  _mesa_fprint_parameter_list(FILE *f,                              const struct gl_program_parameter_list *list)  { -   const gl_prog_print_mode mode = PROG_PRINT_DEBUG;     GLuint i;     if (!list) @@ -978,7 +976,7 @@ _mesa_fprint_parameter_list(FILE *f,        const GLfloat *v = list->ParameterValues[i];        fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",  	      i, param->Size, -	      file_string(list->Parameters[i].Type, mode), +	      _mesa_register_file_name(list->Parameters[i].Type),  	      param->Name, v[0], v[1], v[2], v[3]);        if (param->Flags & PROG_PARAM_BIT_CENTROID)           fprintf(f, " Centroid"); diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h index f080b3fd2e..d962087db3 100644 --- a/src/mesa/program/prog_print.h +++ b/src/mesa/program/prog_print.h @@ -47,6 +47,9 @@ typedef enum {  } gl_prog_print_mode; +extern const char * +_mesa_register_file_name(gl_register_file f); +  extern void  _mesa_print_vp_inputs(GLbitfield inputs); diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index baac29ff0d..c310acb01d 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -572,6 +572,24 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],           value[3] = 0.0F;           return; +      case STATE_FB_WPOS_Y_TRANSFORM: +         /* A driver may negate this conditional by using ZW swizzle +          * instead of XY (based on e.g. some other state). */ +         if (ctx->DrawBuffer->Name != 0) { +            /* Identity (XY) followed by flipping Y upside down (ZW). */ +            value[0] = 1.0F; +            value[1] = 0.0F; +            value[2] = -1.0F; +            value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1); +         } else { +            /* Flipping Y upside down (XY) followed by identity (ZW). */ +            value[0] = -1.0F; +            value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); +            value[2] = 1.0F; +            value[3] = 0.0F; +         } +         return; +        case STATE_ROT_MATRIX_0:           {              const int unit = (int) state[2]; @@ -695,6 +713,7 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])           return _NEW_PIXEL;        case STATE_FB_SIZE: +      case STATE_FB_WPOS_Y_TRANSFORM:           return _NEW_BUFFERS;        default: @@ -900,6 +919,9 @@ append_token(char *dst, gl_state_index k)     case STATE_FB_SIZE:        append(dst, "FbSize");        break; +   case STATE_FB_WPOS_Y_TRANSFORM: +      append(dst, "FbWposYTransform"); +      break;     case STATE_ROT_MATRIX_0:        append(dst, "rotMatrixRow0");        break; @@ -1046,7 +1068,9 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])   * Loop over all the parameters in a parameter list.  If the parameter   * is a GL state reference, look up the current value of that state   * variable and put it into the parameter's Value[4] array. - * This would be called at glBegin time when using a fragment program. + * Other parameter types never change or are explicitly set by the user + * with glUniform() or glProgramParameter(), etc. + * This would be called at glBegin time.   */  void  _mesa_load_state_parameters(struct gl_context *ctx, @@ -1057,12 +1081,10 @@ _mesa_load_state_parameters(struct gl_context *ctx,     if (!paramList)        return; -   /*assert(ctx->Driver.NeedFlush == 0);*/ -     for (i = 0; i < paramList->NumParameters; i++) {        if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {           _mesa_fetch_state(ctx, -			   (gl_state_index *) paramList->Parameters[i].StateIndexes, +			   paramList->Parameters[i].StateIndexes,                             paramList->ParameterValues[i]);        }     } diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index 6e5be53630..f2407af9c8 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -25,8 +25,10 @@  #ifndef PROG_STATEVARS_H  #define PROG_STATEVARS_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; +struct gl_program_parameter_list;  /**   * Number of STATE_* values we need to address any GL state. @@ -117,6 +119,7 @@ typedef enum gl_state_index_ {     STATE_PT_BIAS,               /**< Pixel transfer RGBA bias */     STATE_SHADOW_AMBIENT,        /**< ARB_shadow_ambient fail value; token[2] is texture unit index */     STATE_FB_SIZE,               /**< (width-1, height-1, 0, 0) */ +   STATE_FB_WPOS_Y_TRANSFORM,   /**< (1, 0, -1, height-1) if a FBO is bound, (-1, height-1, 1, 0) otherwise */     STATE_ROT_MATRIX_0,          /**< ATI_envmap_bumpmap, rot matrix row 0 */     STATE_ROT_MATRIX_1,          /**< ATI_envmap_bumpmap, rot matrix row 1 */     STATE_INTERNAL_DRIVER	/* first available state index for drivers (must be last) */ diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c index 4cacde9aed..9ffa49bb01 100644 --- a/src/mesa/program/program.c +++ b/src/mesa/program/program.c @@ -917,6 +917,103 @@ _mesa_find_free_register(const GLboolean used[],  } + +/** + * Check if the given register index is valid (doesn't exceed implementation- + * dependent limits). + * \return GL_TRUE if OK, GL_FALSE if bad index + */ +GLboolean +_mesa_valid_register_index(const struct gl_context *ctx, +                           gl_shader_type shaderType, +                           gl_register_file file, GLint index) +{ +   const struct gl_program_constants *c; + +   switch (shaderType) { +   case MESA_SHADER_VERTEX: +      c = &ctx->Const.VertexProgram; +      break; +   case MESA_SHADER_FRAGMENT: +      c = &ctx->Const.FragmentProgram; +      break; +   case MESA_SHADER_GEOMETRY: +      c = &ctx->Const.GeometryProgram; +      break; +   default: +      _mesa_problem(ctx, +                    "unexpected shader type in _mesa_valid_register_index()"); +      return GL_FALSE; +   } + +   switch (file) { +   case PROGRAM_UNDEFINED: +      return GL_TRUE;  /* XXX or maybe false? */ + +   case PROGRAM_TEMPORARY: +      return index >= 0 && index < c->MaxTemps; + +   case PROGRAM_ENV_PARAM: +      return index >= 0 && index < c->MaxEnvParams; + +   case PROGRAM_LOCAL_PARAM: +      return index >= 0 && index < c->MaxLocalParams; + +   case PROGRAM_NAMED_PARAM: +      return index >= 0 && index < c->MaxParameters; + +   case PROGRAM_UNIFORM: +   case PROGRAM_STATE_VAR: +      /* aka constant buffer */ +      return index >= 0 && index < c->MaxUniformComponents / 4; + +   case PROGRAM_CONSTANT: +      /* constant buffer w/ possible relative negative addressing */ +      return (index > (int) c->MaxUniformComponents / -4 && +              index < c->MaxUniformComponents / 4); + +   case PROGRAM_INPUT: +      if (index < 0) +         return GL_FALSE; + +      switch (shaderType) { +      case MESA_SHADER_VERTEX: +         return index < VERT_ATTRIB_GENERIC0 + c->MaxAttribs; +      case MESA_SHADER_FRAGMENT: +         return index < FRAG_ATTRIB_VAR0 + ctx->Const.MaxVarying; +      case MESA_SHADER_GEOMETRY: +         return index < GEOM_ATTRIB_VAR0 + ctx->Const.MaxVarying; +      default: +         return GL_FALSE; +      } + +   case PROGRAM_OUTPUT: +      if (index < 0) +         return GL_FALSE; + +      switch (shaderType) { +      case MESA_SHADER_VERTEX: +         return index < VERT_RESULT_VAR0 + ctx->Const.MaxVarying; +      case MESA_SHADER_FRAGMENT: +         return index < FRAG_RESULT_DATA0 + ctx->Const.MaxDrawBuffers; +      case MESA_SHADER_GEOMETRY: +         return index < GEOM_RESULT_VAR0 + ctx->Const.MaxVarying; +      default: +         return GL_FALSE; +      } + +   case PROGRAM_ADDRESS: +      return index >= 0 && index < c->MaxAddressRegs; + +   default: +      _mesa_problem(ctx, +                    "unexpected register file in _mesa_valid_register_index()"); +      return GL_FALSE; +   } +} + + +  /**   * "Post-process" a GPU program.  This is intended to be used for debugging.   * Example actions include no-op'ing instructions or changing instruction diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h index 70cc2c3aae..ce37b95bf8 100644 --- a/src/mesa/program/program.h +++ b/src/mesa/program/program.h @@ -165,6 +165,12 @@ extern GLint  _mesa_find_free_register(const GLboolean used[],                           GLuint maxRegs, GLuint firstReg); + +extern GLboolean +_mesa_valid_register_index(const struct gl_context *ctx, +                           gl_shader_type shaderType, +                           gl_register_file file, GLint index); +  extern void  _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog); diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c index 09e7cb44ef..004f1f8fa7 100644 --- a/src/mesa/program/symbol_table.c +++ b/src/mesa/program/symbol_table.c @@ -336,12 +336,12 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,      check_symbol_table(table);      if (hdr == NULL) { -        hdr = calloc(1, sizeof(*hdr)); -        hdr->name = strdup(name); +       hdr = calloc(1, sizeof(*hdr)); +       hdr->name = strdup(name); -        hash_table_insert(table->ht, hdr, hdr->name); -	hdr->next = table->hdr; -	table->hdr = hdr; +       hash_table_insert(table->ht, hdr, hdr->name); +       hdr->next = table->hdr; +       table->hdr = hdr;      }      check_symbol_table(table); @@ -376,6 +376,81 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,  } +int +_mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table, +				     int name_space, const char *name, +				     void *declaration) +{ +    struct symbol_header *hdr; +    struct symbol *sym; +    struct symbol *curr; +    struct scope_level *top_scope; + +    check_symbol_table(table); + +    hdr = find_symbol(table, name); + +    check_symbol_table(table); + +    if (hdr == NULL) { +        hdr = calloc(1, sizeof(*hdr)); +        hdr->name = strdup(name); + +        hash_table_insert(table->ht, hdr, hdr->name); +        hdr->next = table->hdr; +        table->hdr = hdr; +    } + +    check_symbol_table(table); + +    /* If the symbol already exists in this namespace at this scope, it cannot +     * be added to the table. +     */ +    for (sym = hdr->symbols +	 ; (sym != NULL) && (sym->name_space != name_space) +	 ; sym = sym->next_with_same_name) { +       /* empty */ +    } + +    if (sym && sym->depth == 0) +       return -1; + +    /* Find the top-level scope */ +    for (top_scope = table->current_scope +	 ; top_scope->next != NULL +	 ; top_scope = top_scope->next) { +       /* empty */ +    } + +    sym = calloc(1, sizeof(*sym)); +    sym->next_with_same_scope = top_scope->symbols; +    sym->hdr = hdr; +    sym->name_space = name_space; +    sym->data = declaration; + +    assert(sym->hdr == hdr); + +    /* Since next_with_same_name is ordered by scope, we need to append the +     * new symbol to the _end_ of the list. +     */ +    if (hdr->symbols == NULL) { +       hdr->symbols = sym; +    } else { +       for (curr = hdr->symbols +	    ; curr->next_with_same_name != NULL +	    ; curr = curr->next_with_same_name) { +	  /* empty */ +       } +       curr->next_with_same_name = sym; +    } +    top_scope->symbols = sym; + +    check_symbol_table(table); +    return 0; +} + + +  struct _mesa_symbol_table *  _mesa_symbol_table_ctor(void)  { diff --git a/src/mesa/program/symbol_table.h b/src/mesa/program/symbol_table.h index 1d570fc1a0..f9d91649bb 100644 --- a/src/mesa/program/symbol_table.h +++ b/src/mesa/program/symbol_table.h @@ -33,6 +33,10 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);  extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,      int name_space, const char *name, void *declaration); +extern int _mesa_symbol_table_add_global_symbol( +    struct _mesa_symbol_table *symtab, int name_space, const char *name, +    void *declaration); +  extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,      int name_space, const char *name);  | 
