void gen8_vec4_generator::generate_scratch_write(vec4_instruction *ir, struct brw_reg dst, struct brw_reg src, struct brw_reg index) { struct brw_reg header = brw_vec8_grf(GEN7_MRF_HACK_START + ir->base_mrf, 0); MOV_RAW(header, brw_vec8_grf(0, 0)); generate_oword_dual_block_offsets(brw_message_reg(ir->base_mrf + 1), index); MOV(retype(brw_message_reg(ir->base_mrf + 2), BRW_REGISTER_TYPE_D), retype(src, BRW_REGISTER_TYPE_D)); /* Each of the 8 channel enables is considered for whether each * dword is written. */ gen8_instruction *send = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, send, dst); gen8_set_src0(brw, send, header); gen8_set_pred_control(send, ir->predicate); gen8_set_dp_message(brw, send, GEN7_SFID_DATAPORT_DATA_CACHE, 255, /* binding table index: stateless access */ GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE, BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, 3, /* mlen */ 0, /* rlen */ true, /* header present */ false); /* EOT */ }
void vec4_generator::generate_scratch_read(vec4_instruction *inst, struct brw_reg dst, struct brw_reg index) { struct brw_reg header = brw_vec8_grf(0, 0); gen6_resolve_implied_move(p, &header, inst->base_mrf); generate_oword_dual_block_offsets(brw_message_reg(inst->base_mrf + 1), index); uint32_t msg_type; if (brw->gen >= 6) msg_type = GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; else if (brw->gen == 5 || brw->is_g4x) msg_type = G45_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; else msg_type = BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; /* Each of the 8 channel enables is considered for whether each * dword is written. */ struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); brw_set_dest(p, send, dst); brw_set_src0(p, send, header); if (brw->gen < 6) send->header.destreg__conditionalmod = inst->base_mrf; brw_set_dp_read_message(p, send, 255, /* binding table index: stateless access */ BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, msg_type, BRW_DATAPORT_READ_TARGET_RENDER_CACHE, 2, /* mlen */ true, /* header_present */ 1 /* rlen */); }
void vec4_generator::generate_scratch_write(vec4_instruction *inst, struct brw_reg dst, struct brw_reg src, struct brw_reg index) { struct brw_reg header = brw_vec8_grf(0, 0); bool write_commit; /* If the instruction is predicated, we'll predicate the send, not * the header setup. */ brw_set_predicate_control(p, false); gen6_resolve_implied_move(p, &header, inst->base_mrf); generate_oword_dual_block_offsets(brw_message_reg(inst->base_mrf + 1), index); brw_MOV(p, retype(brw_message_reg(inst->base_mrf + 2), BRW_REGISTER_TYPE_D), retype(src, BRW_REGISTER_TYPE_D)); uint32_t msg_type; if (brw->gen >= 7) msg_type = GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; else if (brw->gen == 6) msg_type = GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; else msg_type = BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; brw_set_predicate_control(p, inst->predicate); /* Pre-gen6, we have to specify write commits to ensure ordering * between reads and writes within a thread. Afterwards, that's * guaranteed and write commits only matter for inter-thread * synchronization. */ if (brw->gen >= 6) { write_commit = false; } else { /* The visitor set up our destination register to be g0. This * means that when the next read comes along, we will end up * reading from g0 and causing a block on the write commit. For * write-after-read, we are relying on the value of the previous * read being used (and thus blocking on completion) before our * write is executed. This means we have to be careful in * instruction scheduling to not violate this assumption. */ write_commit = true; } /* Each of the 8 channel enables is considered for whether each * dword is written. */ struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); brw_set_dest(p, send, dst); brw_set_src0(p, send, header); if (brw->gen < 6) send->header.destreg__conditionalmod = inst->base_mrf; brw_set_dp_write_message(p, send, 255, /* binding table index: stateless access */ BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, msg_type, 3, /* mlen */ true, /* header present */ false, /* not a render target write */ write_commit, /* rlen */ false, /* eot */ write_commit); }