diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/glsl/ir.h | 6 | ||||
| -rw-r--r-- | src/mesa/shader/ir_to_mesa.cpp | 138 | 
2 files changed, 142 insertions, 2 deletions
| diff --git a/src/glsl/ir.h b/src/glsl/ir.h index de1124975d..65026ef1f5 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -73,6 +73,7 @@ public:     virtual class ir_function *          as_function()         { return NULL; }     virtual class ir_dereference *       as_dereference()      { return NULL; }     virtual class ir_dereference_array *	as_dereference_array() { return NULL; } +   virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }     virtual class ir_rvalue *            as_rvalue()           { return NULL; }     virtual class ir_loop *              as_loop()             { return NULL; }     virtual class ir_assignment *        as_assignment()       { return NULL; } @@ -987,6 +988,11 @@ public:     virtual ir_instruction *clone(struct hash_table *) const; +   virtual ir_dereference_variable *as_dereference_variable() +   { +      return this; +   } +     /**      * Get the variable that is ultimately referenced by an r-value      */ diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index ab8aca0a81..f04518175d 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -80,6 +80,8 @@ public:     /** Pointer to the ir source this tree came from for debugging */     ir_instruction *ir;     GLboolean cond_update; +   int sampler; /**< sampler index */ +   int tex_target; /**< One of TEXTURE_*_INDEX */  };  class temp_entry : public exec_node { @@ -173,6 +175,12 @@ public:  				   ir_to_mesa_src_reg src0,  				   ir_to_mesa_src_reg src1); +   int *sampler_map; +   int sampler_map_size; + +   void map_sampler(int location, int sampler); +   int get_sampler_number(int location); +     void *mem_ctx;  }; @@ -293,6 +301,25 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,  			      src0, ir_to_mesa_undef, ir_to_mesa_undef);  } +void +ir_to_mesa_visitor::map_sampler(int location, int sampler) +{ +   if (this->sampler_map_size <= location) { +      this->sampler_map = talloc_realloc(this->mem_ctx, this->sampler_map, +					 int, location + 1); +      this->sampler_map_size = location + 1; +   } + +   this->sampler_map[location] = sampler; +} + +int +ir_to_mesa_visitor::get_sampler_number(int location) +{ +   assert(location < this->sampler_map_size); +   return this->sampler_map[location]; +} +  inline ir_to_mesa_dst_reg  ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)  { @@ -901,6 +928,21 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)  	    break;  	 /* FINISHME: Fix up uniform name for arrays and things */ +	 if (ir->var->type->base_type == GLSL_TYPE_SAMPLER) { +	    /* FINISHME: we whack the location of the var here, which +	     * is probably not expected.  But we need to communicate +	     * mesa's sampler number to the tex instruction. +	     */ +	    int sampler = _mesa_add_sampler(this->prog->Parameters, +					    ir->var->name, +					    ir->var->type->gl_type); +	    map_sampler(ir->var->location, sampler); + +	    entry = new(mem_ctx) temp_entry(ir->var, PROGRAM_SAMPLER, sampler); +	    this->variable_storage.push_tail(entry); +	    break; +	 } +  	 assert(ir->var->type->gl_type != 0 &&  		ir->var->type->gl_type != GL_INVALID_ENUM);  	 loc = _mesa_add_uniform(this->prog->Parameters, @@ -908,6 +950,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)  				 type_size(ir->var->type) * 4,  				 ir->var->type->gl_type,  				 NULL); +  	 /* Always mark the uniform used at this point.  If it isn't  	  * used, dead code elimination should have nuked the decl already.  	  */ @@ -1176,9 +1219,77 @@ ir_to_mesa_visitor::visit(ir_call *ir)  void  ir_to_mesa_visitor::visit(ir_texture *ir)  { -   assert(0); +   ir_to_mesa_src_reg result_src, coord; +   ir_to_mesa_dst_reg result_dst, lod_info; +   ir_to_mesa_instruction *inst = NULL;     ir->coordinate->accept(this); +   coord = this->result; + +   /* Storage for our result.  Ideally for an assignment we'd be using +    * the actual storage for the result here, instead. +    */ +   result_src = get_temp(glsl_type::vec4_type); +   result_dst = ir_to_mesa_dst_reg_from_src(result_src); + +   switch (ir->op) { +   case ir_tex: +      inst = ir_to_mesa_emit_op1(ir, OPCODE_TEX, result_dst, coord); +      break; +   case ir_txb: +      /* Mesa IR stores bias in the last channel of the coords. */ +      lod_info = ir_to_mesa_dst_reg_from_src(coord); +      lod_info.writemask = WRITEMASK_W; +      ir->lod_info.bias->accept(this); +      ir_to_mesa_emit_op1(ir, OPCODE_MOV, lod_info, this->result); + +      inst = ir_to_mesa_emit_op1(ir, OPCODE_TXB, result_dst, coord); +      break; +   case ir_txl: +      /* Mesa IR stores lod in the last channel of the coords. */ +      lod_info = ir_to_mesa_dst_reg_from_src(coord); +      lod_info.writemask = WRITEMASK_W; +      ir->lod_info.lod->accept(this); +      ir_to_mesa_emit_op1(ir, OPCODE_MOV, lod_info, this->result); + +      inst = ir_to_mesa_emit_op1(ir, OPCODE_TXL, result_dst, coord); +      break; +   case ir_txd: +   case ir_txf: +      assert(!"GLSL 1.30 features unsupported"); +      break; +   } + +   ir_dereference_variable *sampler = ir->sampler->as_dereference_variable(); +   assert(sampler); /* FINISHME: sampler arrays */ +   /* generate the mapping, remove when we generate storage at +    * declaration time +    */ +   sampler->accept(this); + +   inst->sampler = get_sampler_number(sampler->var->location); + +   switch (sampler->type->sampler_dimensionality) { +   case GLSL_SAMPLER_DIM_1D: +      inst->tex_target = TEXTURE_1D_INDEX; +      break; +   case GLSL_SAMPLER_DIM_2D: +      inst->tex_target = TEXTURE_2D_INDEX; +      break; +   case GLSL_SAMPLER_DIM_3D: +      inst->tex_target = TEXTURE_3D_INDEX; +      break; +   case GLSL_SAMPLER_DIM_CUBE: +      inst->tex_target = TEXTURE_CUBE_INDEX; +      break; +   default: +      assert(!"FINISHME: other texture targets"); +   } + +   assert(!ir->projector); /* FINISHME */ +   assert(!ir->shadow_comparitor); /* FINISHME */ + +   this->result = result_src;  }  void @@ -1245,6 +1356,8 @@ ir_to_mesa_visitor::ir_to_mesa_visitor()  {     result.file = PROGRAM_UNDEFINED;     next_temp = 1; +   sampler_map = NULL; +   sampler_map_size = 0;  }  static struct prog_src_register @@ -1359,9 +1472,11 @@ print_program(struct prog_instruction *mesa_instructions,  static void  count_resources(struct gl_program *prog)  { +   unsigned int i; +     prog->InputsRead = 0;     prog->OutputsWritten = 0; -   unsigned int i; +   prog->SamplersUsed = 0;     for (i = 0; i < prog->NumInstructions; i++) {        struct prog_instruction *inst = &prog->Instructions[i]; @@ -1390,7 +1505,24 @@ count_resources(struct gl_program *prog)  	    break;  	 }        } + +      /* Instead of just using the uniform's value to map to a +       * sampler, Mesa first allocates a separate number for the +       * sampler (_mesa_add_sampler), then we reindex it down to a +       * small integer (sampler_map[], SamplersUsed), then that gets +       * mapped to the uniform's value, and we get an actual sampler. +       */ +      if (_mesa_is_tex_instruction(inst->Opcode)) { +	 prog->SamplerTargets[inst->TexSrcUnit] = +	    (gl_texture_index)inst->TexSrcTarget; +	 prog->SamplersUsed |= 1 << inst->TexSrcUnit; +	 if (inst->TexShadow) { +	    prog->ShadowSamplers |= 1 << inst->TexSrcUnit; +	 } +      }     } + +   _mesa_update_shader_textures_used(prog);  }  /* Each stage has some uniforms in its Parameters list.  The Uniforms @@ -1474,6 +1606,8 @@ get_mesa_program(GLcontext *ctx, void *mem_ctx, struct glsl_shader *shader)        mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);        mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);        mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]); +      mesa_inst->TexSrcUnit = inst->sampler; +      mesa_inst->TexSrcTarget = inst->tex_target;        mesa_instruction_annotation[i] = inst->ir;        mesa_inst++; | 
