summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2011-10-26 14:00:52 -0700
committerKenneth Graunke <[email protected]>2011-12-19 16:33:10 -0800
commitd93aa54d2dea79d8216e10b6bbbb00b0c8443dc2 (patch)
tree506d786abb04f927b7c6a41625de17d9749dc9fd
parentca182cd0fa338ad39d531cb1be6a5a1bbf455771 (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]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp127
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