[Mesa-dev] [PATCH 03/10] i965/vs: Implement vec4_visitor::visit(ir_texture *).

Kenneth Graunke kenneth at whitecape.org
Mon Dec 19 11:09:05 PST 2011


This translates the GLSL compiler's IR into vec4_instruction IR,
generating code to load coordinates, LOD info, shadow comparitors, and
so on into the appropriate message registers.

It turns out that the SIMD4x2 parameters are identical on Gen 5-7, and
the Gen4 code is similar enough that, unlike in the FS, it's easy enough
to support all generations in a single function.

v2: Load zeros for missing coordinates (fixing vs-texelFetch-sampler1D
and 2D on G45), and fix G45 message length for shadow comparisons.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp |  127 ++++++++++++++++++++++--
 1 files changed, 120 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 853c3ee..b49cf9c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -25,6 +25,7 @@
 extern "C" {
 #include "main/macros.h"
 #include "program/prog_parameter.h"
+#include "program/sampler.h"
 }
 
 namespace brw {
@@ -1755,13 +1756,125 @@ vec4_visitor::visit(ir_call *ir)
 void
 vec4_visitor::visit(ir_texture *ir)
 {
-   /* FINISHME: Implement vertex texturing.
-    *
-    * With 0 vertex samplers available, the linker will reject
-    * programs that do vertex texturing, but after our visitor has
-    * run.
-    */
-   this->result = src_reg(this, glsl_type::vec4_type);
+   int sampler = _mesa_get_sampler_uniform_value(ir->sampler, prog, &vp->Base);
+   sampler = vp->Base.SamplerUnits[sampler];
+
+   /* Should be lowered by do_lower_texture_projection */
+   assert(!ir->projector);
+
+   vec4_instruction *inst;
+   switch (ir->op) {
+   case ir_tex:
+   case ir_txl:
+      inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXL);
+      break;
+   case ir_txd:
+      inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXD);
+      break;
+   case ir_txf:
+      inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXF);
+      break;
+   case ir_txs:
+      inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXS);
+      break;
+   case ir_txb:
+      assert(!"TXB is not valid for vertex shaders.");
+   }
+
+   inst->header_present = intel->gen < 5;
+   inst->base_mrf = 2;
+   inst->mlen = inst->header_present + 1; /* always at least one */
+   inst->sampler = sampler;
+   inst->dst = dst_reg(this, glsl_type::get_instance(ir->type->base_type,4,1));
+   inst->shadow_compare = ir->shadow_comparitor != NULL;
+
+   /* MRF for the first parameter */
+   int param_base = inst->base_mrf + inst->header_present;
+
+   if (ir->op == ir_txs) {
+      ir->lod_info.lod->accept(this);
+      int writemask = intel->gen == 4 ? WRITEMASK_W : WRITEMASK_X;
+      emit(MOV(dst_reg(MRF, param_base, ir->lod_info.lod->type, writemask),
+	   this->result));
+   } else {
+      int i, coord_mask = 0, zero_mask = 0;
+      /* Load the coordinate */
+      /* FINISHME: gl_clamp_mask and saturate */
+      for (i = 0; i < ir->coordinate->type->vector_elements; i++)
+	 coord_mask |= (1 << i);
+      for (; i < 4; i++)
+	 zero_mask |= (1 << i);
+
+      ir->coordinate->accept(this);
+      emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, coord_mask),
+	       this->result));
+      emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, zero_mask),
+	       src_reg(0)));
+      /* Load the shadow comparitor */
+      if (ir->shadow_comparitor) {
+	 ir->shadow_comparitor->accept(this);
+	 emit(MOV(dst_reg(MRF, param_base + 1, ir->shadow_comparitor->type,
+			  WRITEMASK_X),
+		  this->result));
+	 inst->mlen++;
+      }
+
+      /* Load the LOD info */
+      if (ir->op == ir_txl) {
+	 int mrf, writemask;
+	 if (intel->gen >= 5) {
+	    mrf = param_base + 1;
+	    if (ir->shadow_comparitor) {
+	       writemask = WRITEMASK_Y;
+	       /* mlen already incremented */
+	    } else {
+	       writemask = WRITEMASK_X;
+	       inst->mlen++;
+	    }
+	 } else /* intel->gen == 4 */ {
+	    mrf = param_base;
+	    writemask = WRITEMASK_Z;
+	 }
+	 ir->lod_info.lod->accept(this);
+	 emit(MOV(dst_reg(MRF, mrf, ir->lod_info.lod->type, writemask),
+		  this->result));
+      } else if (ir->op == ir_txf) {
+	 ir->lod_info.lod->accept(this);
+	 emit(MOV(dst_reg(MRF, param_base, ir->lod_info.lod->type, WRITEMASK_W),
+		  this->result));
+      } else if (ir->op == ir_txd) {
+	 const glsl_type *type = ir->lod_info.grad.dPdx->type;
+
+	 ir->lod_info.grad.dPdx->accept(this);
+	 src_reg dPdx = this->result;
+	 ir->lod_info.grad.dPdy->accept(this);
+	 src_reg dPdy = this->result;
+
+	 if (intel->gen >= 5) {
+	    dPdx.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
+	    dPdy.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
+	    emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), dPdx));
+	    emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), dPdy));
+	    inst->mlen++;
+
+	    if (ir->type->vector_elements == 3) {
+	       dPdx.swizzle = BRW_SWIZZLE_ZZZZ;
+	       dPdy.swizzle = BRW_SWIZZLE_ZZZZ;
+	       emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), dPdx));
+	       emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), dPdy));
+	       inst->mlen++;
+	    }
+	 } else /* intel->gen == 4 */ {
+	    emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), dPdx));
+	    emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), dPdy));
+	    inst->mlen += 2;
+	 }
+      }
+   }
+
+   emit(inst);
+
+   this->result = src_reg(inst->dst);
 }
 
 void
-- 
1.7.7.3



More information about the mesa-dev mailing list