diff options
author | Kenneth Graunke <[email protected]> | 2011-10-26 14:00:52 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2011-12-19 16:33:10 -0800 |
commit | d93aa54d2dea79d8216e10b6bbbb00b0c8443dc2 (patch) | |
tree | 506d786abb04f927b7c6a41625de17d9749dc9fd /src/mesa/drivers | |
parent | ca182cd0fa338ad39d531cb1be6a5a1bbf455771 (diff) |
i965/vs: Implement vec4_visitor::visit(ir_texture *).
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 <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | 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 853c3eeca13..b49cf9c1fc3 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 |