diff options
author | Chris Forbes <chrisf@ijw.co.nz> | 2013-03-31 21:39:37 +1300 |
---|---|---|
committer | Chris Forbes <chrisf@ijw.co.nz> | 2013-10-03 07:55:59 +1300 |
commit | 4ed3930f9741721f4ace2d008678c0c88fdcc501 (patch) | |
tree | ef6b6e2718450691448bc18a7aff32b2248f539f | |
parent | 942a4ec18f7e713b962e7acc451fbd50ff9c4042 (diff) | |
download | external_mesa3d-4ed3930f9741721f4ace2d008678c0c88fdcc501.zip external_mesa3d-4ed3930f9741721f4ace2d008678c0c88fdcc501.tar.gz external_mesa3d-4ed3930f9741721f4ace2d008678c0c88fdcc501.tar.bz2 |
i965/vs: Add support for ir_tg4
Pretty much the same as the FS case. Channel select goes in the header,
V2: Less mangling.
V3: Avoid sampling at all, for degenerate swizzles.
Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 46 |
2 files changed, 45 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h index 847c75e..5b8075a 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.h +++ b/src/mesa/drivers/dri/i965/brw_vec4.h @@ -470,6 +470,7 @@ public: void emit_pack_half_2x16(dst_reg dst, src_reg src0); void emit_unpack_half_2x16(dst_reg dst, src_reg src0); + uint32_t gather_channel(ir_texture *ir, int sampler); void swizzle_result(ir_texture *ir, src_reg orig_val, int sampler); void emit_ndc_computation(); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 6b9c4c6..f6ea28a 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -2146,6 +2146,19 @@ vec4_visitor::visit(ir_texture *ir) int sampler = _mesa_get_sampler_uniform_value(ir->sampler, shader_prog, prog); + /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother + * emitting anything other than setting up the constant result. + */ + if (ir->op == ir_tg4) { + int swiz = GET_SWZ(key->tex.swizzles[sampler], 0); + if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) { + dst_reg result(this, ir->type); + this->result = src_reg(result); + emit(MOV(result, src_reg(swiz == SWIZZLE_ONE ? 1.0f : 0.0f))); + return; + } + } + /* Should be lowered by do_lower_texture_projection */ assert(!ir->projector); @@ -2195,6 +2208,7 @@ vec4_visitor::visit(ir_texture *ir) break; case ir_txb: case ir_lod: + case ir_tg4: break; } @@ -2216,18 +2230,23 @@ vec4_visitor::visit(ir_texture *ir) case ir_txs: inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXS); break; + case ir_tg4: + inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TG4); + break; case ir_txb: assert(!"TXB is not valid for vertex shaders."); break; case ir_lod: assert(!"LOD is not valid for vertex shaders."); break; + default: + assert(!"Unrecognized tex op"); } bool use_texture_offset = ir->offset != NULL && ir->op != ir_txf; /* Texel offsets go in the message header; Gen4 also requires headers. */ - inst->header_present = use_texture_offset || brw->gen < 5; + inst->header_present = use_texture_offset || brw->gen < 5 || ir->op == ir_tg4; inst->base_mrf = 2; inst->mlen = inst->header_present + 1; /* always at least one */ inst->sampler = sampler; @@ -2238,6 +2257,10 @@ vec4_visitor::visit(ir_texture *ir) if (use_texture_offset) inst->texture_offset = brw_texture_offset(ir->offset->as_constant()); + /* Stuff the channel select bits in the top of the texture offset */ + if (ir->op == ir_tg4) + inst->texture_offset |= gather_channel(ir, sampler)<<16; + /* MRF for the first parameter */ int param_base = inst->base_mrf + inst->header_present; @@ -2362,6 +2385,24 @@ vec4_visitor::visit(ir_texture *ir) swizzle_result(ir, src_reg(inst->dst), sampler); } +/** + * Set up the gather channel based on the swizzle, for gather4. + */ +uint32_t +vec4_visitor::gather_channel(ir_texture *ir, int sampler) +{ + int swiz = GET_SWZ(key->tex.swizzles[sampler], 0 /* red */); + switch (swiz) { + case SWIZZLE_X: return 0; + case SWIZZLE_Y: return 1; + case SWIZZLE_Z: return 2; + case SWIZZLE_W: return 3; + default: + assert(!"Not reached"); /* zero, one swizzles handled already */ + return 0; + } +} + void vec4_visitor::swizzle_result(ir_texture *ir, src_reg orig_val, int sampler) { @@ -2371,11 +2412,12 @@ vec4_visitor::swizzle_result(ir_texture *ir, src_reg orig_val, int sampler) dst_reg swizzled_result(this->result); if (ir->op == ir_txs || ir->type == glsl_type::float_type - || s == SWIZZLE_NOOP) { + || s == SWIZZLE_NOOP || ir->op == ir_tg4) { emit(MOV(swizzled_result, orig_val)); return; } + int zero_mask = 0, one_mask = 0, copy_mask = 0; int swizzle[4] = {0}; |