It would be nice if we could have a single 'reg_offset' field expressed in bytes that would serve the purpose of both, but the semantics of 'reg_offset' are quite complex currently (it's measured in units of one, eight or sixteen dwords depending on the register file and the dispatch width) and changing it to bytes would be a very intrusive change at this stage. Add a separate 'subreg_offset' field for now. --- src/mesa/drivers/dri/i965/brw_fs.cpp | 26 ++++++++++++++-------- src/mesa/drivers/dri/i965/brw_fs.h | 9 ++++++++ .../drivers/dri/i965/brw_fs_copy_propagation.cpp | 7 ++++-- src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 1 + src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 20 ++++++++--------- 5 files changed, 41 insertions(+), 22 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 761e7e6..0caae2d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -437,6 +437,7 @@ fs_reg::equals(const fs_reg &r) const return (file == r.file && reg == r.reg && reg_offset == r.reg_offset && + subreg_offset == r.subreg_offset && type == r.type && negate == r.negate && abs == r.abs && @@ -1368,7 +1369,9 @@ fs_visitor::assign_curb_setup() constant_nr % 8); inst->src[i].file = HW_REG; - inst->src[i].fixed_hw_reg = retype(brw_reg, inst->src[i].type); + inst->src[i].fixed_hw_reg = byte_offset( + retype(brw_reg, inst->src[i].type), + inst->src[i].subreg_offset); } } } @@ -2328,7 +2331,8 @@ fs_visitor::register_coalesce() inst->saturate || inst->dst.file != GRF || (inst->src[0].file != GRF && inst->src[0].file != UNIFORM)|| - inst->dst.type != inst->src[0].type) + inst->dst.type != inst->src[0].type || + inst->dst.subreg_offset != 0) continue; bool has_source_modifiers = (inst->src[0].abs || @@ -2418,6 +2422,7 @@ fs_visitor::register_coalesce() } new_src.negate ^= scan_inst->src[i].negate; new_src.sechalf = scan_inst->src[i].sechalf; + new_src.subreg_offset += scan_inst->src[i].subreg_offset; scan_inst->src[i] = new_src; } } @@ -2452,7 +2457,8 @@ fs_visitor::compute_to_mrf() inst->is_partial_write() || inst->dst.file != MRF || inst->src[0].file != GRF || inst->dst.type != inst->src[0].type || - inst->src[0].abs || inst->src[0].negate || inst->src[0].smear != -1) + inst->src[0].abs || inst->src[0].negate || + inst->src[0].smear != -1 || inst->src[0].subreg_offset) continue; /* Work out which hardware MRF registers are written by this @@ -2971,8 +2977,8 @@ fs_visitor::dump_instruction(backend_instruction *be_inst) switch (inst->dst.file) { case GRF: printf("vgrf%d", inst->dst.reg); - if (inst->dst.reg_offset) - printf("+%d", inst->dst.reg_offset); + if (inst->dst.reg_offset || inst->dst.subreg_offset) + printf("+%d.%d", inst->dst.reg_offset, inst->dst.subreg_offset); break; case MRF: printf("m%d", inst->dst.reg); @@ -3002,16 +3008,18 @@ fs_visitor::dump_instruction(backend_instruction *be_inst) switch (inst->src[i].file) { case GRF: printf("vgrf%d", inst->src[i].reg); - if (inst->src[i].reg_offset) - printf("+%d", inst->src[i].reg_offset); + if (inst->src[i].reg_offset || inst->src[i].subreg_offset) + printf("+%d.%d", inst->src[i].reg_offset, + inst->src[i].subreg_offset); break; case MRF: printf("***m%d***", inst->src[i].reg); break; case UNIFORM: printf("u%d", inst->src[i].reg); - if (inst->src[i].reg_offset) - printf(".%d", inst->src[i].reg_offset); + if (inst->src[i].reg_offset || inst->src[i].subreg_offset) + printf("+%d.%d", inst->src[i].reg_offset, + inst->src[i].subreg_offset); break; case BAD_FILE: printf("(null)"); diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index dfd3b07..93a393d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -83,10 +83,19 @@ public: bool abs; bool sechalf; int smear; /* -1, or a channel of the reg to smear to all channels. */ + int subreg_offset; /**< Offset in bytes from the start of the register. */ fs_reg *reladdr; }; +static inline fs_reg +byte_offset(fs_reg reg, unsigned delta) +{ + assert(delta == 0 || (reg.file != HW_REG && reg.file != IMM)); + reg.subreg_offset += delta; + return reg; +} + static const fs_reg reg_undef; static const fs_reg reg_null_f(retype(brw_null_reg(), BRW_REGISTER_TYPE_F)); static const fs_reg reg_null_d(retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); diff --git a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp index 26bac94..f3f44c6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp @@ -284,7 +284,8 @@ fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry) if (inst->src[arg].file != entry->dst.file || inst->src[arg].reg != entry->dst.reg || - inst->src[arg].reg_offset != entry->dst.reg_offset) { + inst->src[arg].reg_offset != entry->dst.reg_offset || + inst->src[arg].subreg_offset != entry->dst.subreg_offset) { return false; } @@ -308,6 +309,7 @@ fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry) inst->src[arg].reg_offset = entry->src.reg_offset; if (entry->src.smear != -1) inst->src[arg].smear = entry->src.smear; + inst->src[arg].subreg_offset = entry->src.subreg_offset; if (!inst->src[arg].abs) { inst->src[arg].abs = entry->src.abs; @@ -329,7 +331,8 @@ fs_visitor::try_constant_propagate(fs_inst *inst, acp_entry *entry) for (int i = 2; i >= 0; i--) { if (inst->src[i].file != entry->dst.file || inst->src[i].reg != entry->dst.reg || - inst->src[i].reg_offset != entry->dst.reg_offset) + inst->src[i].reg_offset != entry->dst.reg_offset || + inst->src[i].subreg_offset != entry->dst.subreg_offset) continue; /* Don't bother with cases that should have been taken care of by the diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp index b5882a8..a0b6135 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp @@ -996,6 +996,7 @@ brw_reg_from_fs_reg(fs_reg *reg) brw_reg = retype(brw_reg, reg->type); if (reg->sechalf) brw_reg = sechalf(brw_reg); + brw_reg = byte_offset(brw_reg, reg->subreg_offset); break; case IMM: switch (reg->type) { diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp index 8567afd..2d35909 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -685,11 +685,12 @@ fs_visitor::spill_reg(int spill_reg) int regs_read = inst->regs_read(this, i); int subset_spill_offset = (spill_offset + reg_size * inst->src[i].reg_offset); + fs_reg unspill_dst(GRF, virtual_grf_alloc(regs_read)); - inst->src[i].reg = virtual_grf_alloc(regs_read); + inst->src[i].reg = unspill_dst.reg; inst->src[i].reg_offset = 0; - emit_unspill(inst, inst->src[i], subset_spill_offset, regs_read); + emit_unspill(inst, unspill_dst, subset_spill_offset, regs_read); } } @@ -697,24 +698,21 @@ fs_visitor::spill_reg(int spill_reg) inst->dst.reg == spill_reg) { int subset_spill_offset = (spill_offset + reg_size * inst->dst.reg_offset); - inst->dst.reg = virtual_grf_alloc(inst->regs_written); + fs_reg spill_src(GRF, virtual_grf_alloc(inst->regs_written)); + + inst->dst.reg = spill_src.reg; inst->dst.reg_offset = 0; /* If our write is going to affect just part of the * inst->regs_written(), then we need to unspill the destination * since we write back out all of the regs_written(). */ - if (inst->predicate || inst->force_uncompressed || inst->force_sechalf) { - emit_unspill(inst, inst->dst, subset_spill_offset, + if (inst->predicate || inst->force_uncompressed || + inst->force_sechalf || inst->dst.subreg_offset) { + emit_unspill(inst, spill_src, subset_spill_offset, inst->regs_written); } - fs_reg spill_src = inst->dst; - spill_src.reg_offset = 0; - spill_src.abs = false; - spill_src.negate = false; - spill_src.smear = -1; - for (int chan = 0; chan < inst->regs_written; chan++) { fs_inst *spill_inst = new(mem_ctx) fs_inst(SHADER_OPCODE_GEN4_SCRATCH_WRITE, -- 1.8.3.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev