diff options
author | Chris Forbes <[email protected]> | 2014-08-10 12:02:22 +1200 |
---|---|---|
committer | Chris Forbes <[email protected]> | 2014-08-15 19:13:32 +1200 |
commit | fbfcd671a1c74eebc00c56f609a8792fedb0a45d (patch) | |
tree | 549d9bbf0a8680a59bb395de39b3f0f8c4803274 | |
parent | 4ba5171f307873c7f5d6ac07f86bfbc26a82e00e (diff) |
i965/fs: Add support for non-const sampler indices in generator
Signed-off-by: Chris Forbes <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp index c7c8c5f4f6c..1cf5a886fa2 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp @@ -598,7 +598,57 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src brw_mark_surface_used(&prog_data->base, sampler + base_binding_table_index); } else { - /* XXX: Non-const sampler index */ + /* Non-const sampler index */ + /* Note: this clobbers `dst` as a temporary before emitting the send */ + + struct brw_reg addr = vec1(retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD)); + struct brw_reg temp = vec1(retype(dst, BRW_REGISTER_TYPE_UD)); + + struct brw_reg sampler_reg = vec1(retype(sampler_index, BRW_REGISTER_TYPE_UD)); + + brw_push_insn_state(p); + brw_set_default_mask_control(p, BRW_MASK_DISABLE); + brw_set_default_access_mode(p, BRW_ALIGN_1); + + /* Some care required: `sampler` and `temp` may alias: + * addr = sampler & 0xff + * temp = (sampler << 8) & 0xf00 + * addr = addr | temp + */ + brw_ADD(p, addr, sampler_reg, brw_imm_ud(base_binding_table_index)); + brw_SHL(p, temp, sampler_reg, brw_imm_ud(8u)); + brw_AND(p, temp, temp, brw_imm_ud(0x0f00)); + brw_AND(p, addr, addr, brw_imm_ud(0x0ff)); + brw_OR(p, addr, addr, temp); + + /* a0.0 |= <descriptor> */ + brw_inst *insn_or = brw_next_insn(p, BRW_OPCODE_OR); + brw_set_sampler_message(p, insn_or, + 0 /* surface */, + 0 /* sampler */, + msg_type, + rlen, + inst->mlen /* mlen */, + inst->header_present /* header */, + simd_mode, + return_format); + brw_inst_set_exec_size(p->brw, insn_or, BRW_EXECUTE_1); + brw_inst_set_src1_reg_type(p->brw, insn_or, BRW_REGISTER_TYPE_UD); + brw_set_src0(p, insn_or, addr); + brw_set_dest(p, insn_or, addr); + + + /* dst = send(offset, a0.0) */ + brw_inst *insn_send = brw_next_insn(p, BRW_OPCODE_SEND); + brw_set_dest(p, insn_send, dst); + brw_set_src0(p, insn_send, src); + brw_set_indirect_send_descriptor(p, insn_send, BRW_SFID_SAMPLER, addr); + + brw_pop_insn_state(p); + + /* visitor knows more than we do about the surface limit required, + * so has already done marking. + */ } } |