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 <kenneth@whitecape.org>
This commit is contained in:
Kenneth Graunke 2011-10-26 14:00:52 -07:00
parent ca182cd0fa
commit d93aa54d2d

View file

@ -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