i965/fs: Use the gen7 scratch read opcode when possible.
This avoids a lot of message setup we had to do otherwise. Improves GLB2.7 performance with register spilling force enabled by 1.6442% +/- 0.553218% (n=4). v2: Use BRW_PREDICATE_NONE, improve a comment (by Paul). Reviewed-by: Paul Berry <stereotype441@gmail.com>
This commit is contained in:
parent
6032261682
commit
8dfc9f038e
|
@ -780,6 +780,7 @@ enum opcode {
|
|||
|
||||
SHADER_OPCODE_GEN4_SCRATCH_READ,
|
||||
SHADER_OPCODE_GEN4_SCRATCH_WRITE,
|
||||
SHADER_OPCODE_GEN7_SCRATCH_READ,
|
||||
|
||||
FS_OPCODE_DDX,
|
||||
FS_OPCODE_DDY,
|
||||
|
@ -1141,6 +1142,12 @@ enum brw_message_target {
|
|||
#define GEN7_DATAPORT_DC_BYTE_SCATTERED_WRITE 12
|
||||
#define GEN7_DATAPORT_DC_UNTYPED_SURFACE_WRITE 13
|
||||
|
||||
#define GEN7_DATAPORT_SCRATCH_READ ((1 << 18) | \
|
||||
(0 << 17))
|
||||
#define GEN7_DATAPORT_SCRATCH_WRITE ((1 << 18) | \
|
||||
(1 << 17))
|
||||
#define GEN7_DATAPORT_SCRATCH_NUM_REGS_SHIFT 12
|
||||
|
||||
/* HSW */
|
||||
#define HSW_DATAPORT_DC_PORT0_OWORD_BLOCK_READ 0
|
||||
#define HSW_DATAPORT_DC_PORT0_UNALIGNED_OWORD_BLOCK_READ 1
|
||||
|
|
|
@ -379,6 +379,11 @@ void brw_oword_block_write_scratch(struct brw_compile *p,
|
|||
int num_regs,
|
||||
GLuint offset);
|
||||
|
||||
void gen7_block_read_scratch(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
int num_regs,
|
||||
GLuint offset);
|
||||
|
||||
void brw_shader_time_add(struct brw_compile *p,
|
||||
struct brw_reg payload,
|
||||
uint32_t surf_index);
|
||||
|
|
|
@ -2055,6 +2055,48 @@ brw_oword_block_read_scratch(struct brw_compile *p,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
gen7_block_read_scratch(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
int num_regs,
|
||||
GLuint offset)
|
||||
{
|
||||
dest = retype(dest, BRW_REGISTER_TYPE_UW);
|
||||
|
||||
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
|
||||
|
||||
assert(insn->header.predicate_control == BRW_PREDICATE_NONE);
|
||||
insn->header.compression_control = BRW_COMPRESSION_NONE;
|
||||
|
||||
brw_set_dest(p, insn, dest);
|
||||
|
||||
/* The HW requires that the header is present; this is to get the g0.5
|
||||
* scratch offset.
|
||||
*/
|
||||
bool header_present = true;
|
||||
brw_set_src0(p, insn, brw_vec8_grf(0, 0));
|
||||
|
||||
brw_set_message_descriptor(p, insn,
|
||||
GEN7_SFID_DATAPORT_DATA_CACHE,
|
||||
1, /* mlen: just g0 */
|
||||
num_regs,
|
||||
header_present,
|
||||
false);
|
||||
|
||||
insn->bits3.ud |= GEN7_DATAPORT_SCRATCH_READ;
|
||||
|
||||
assert(num_regs == 1 || num_regs == 2 || num_regs == 4);
|
||||
insn->bits3.ud |= (num_regs - 1) << GEN7_DATAPORT_SCRATCH_NUM_REGS_SHIFT;
|
||||
|
||||
/* According to the docs, offset is "A 12-bit HWord offset into the memory
|
||||
* Immediate Memory buffer as specified by binding table 0xFF." An HWORD
|
||||
* is 32 bytes, which happens to be the size of a register.
|
||||
*/
|
||||
offset /= REG_SIZE;
|
||||
assert(offset < (1 << 12));
|
||||
insn->bits3.ud |= offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a float[4] vector from the data port Data Cache (const buffer).
|
||||
* Location (in buffer) should be a multiple of 16.
|
||||
|
|
|
@ -525,6 +525,7 @@ private:
|
|||
bool negate_value);
|
||||
void generate_scratch_write(fs_inst *inst, struct brw_reg src);
|
||||
void generate_scratch_read(fs_inst *inst, struct brw_reg dst);
|
||||
void generate_scratch_read_gen7(fs_inst *inst, struct brw_reg dst);
|
||||
void generate_uniform_pull_constant_load(fs_inst *inst, struct brw_reg dst,
|
||||
struct brw_reg index,
|
||||
struct brw_reg offset);
|
||||
|
|
|
@ -769,6 +769,12 @@ fs_generator::generate_scratch_read(fs_inst *inst, struct brw_reg dst)
|
|||
dispatch_width / 8, inst->offset);
|
||||
}
|
||||
|
||||
void
|
||||
fs_generator::generate_scratch_read_gen7(fs_inst *inst, struct brw_reg dst)
|
||||
{
|
||||
gen7_block_read_scratch(p, dst, dispatch_width / 8, inst->offset);
|
||||
}
|
||||
|
||||
void
|
||||
fs_generator::generate_uniform_pull_constant_load(fs_inst *inst,
|
||||
struct brw_reg dst,
|
||||
|
@ -1587,6 +1593,10 @@ fs_generator::generate_code(exec_list *instructions)
|
|||
generate_scratch_read(inst, dst);
|
||||
break;
|
||||
|
||||
case SHADER_OPCODE_GEN7_SCRATCH_READ:
|
||||
generate_scratch_read_gen7(inst, dst);
|
||||
break;
|
||||
|
||||
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
|
||||
generate_uniform_pull_constant_load(inst, dst, src[0], src[1]);
|
||||
break;
|
||||
|
|
|
@ -542,14 +542,22 @@ fs_visitor::emit_unspill(fs_inst *inst, fs_reg dst, uint32_t spill_offset,
|
|||
int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
/* The gen7 descriptor-based offset is 12 bits of HWORD units. */
|
||||
bool gen7_read = brw->gen >= 7 && spill_offset < (1 << 12) * REG_SIZE;
|
||||
|
||||
fs_inst *unspill_inst =
|
||||
new(mem_ctx) fs_inst(SHADER_OPCODE_GEN4_SCRATCH_READ, dst);
|
||||
new(mem_ctx) fs_inst(gen7_read ?
|
||||
SHADER_OPCODE_GEN7_SCRATCH_READ :
|
||||
SHADER_OPCODE_GEN4_SCRATCH_READ,
|
||||
dst);
|
||||
unspill_inst->offset = spill_offset;
|
||||
unspill_inst->ir = inst->ir;
|
||||
unspill_inst->annotation = inst->annotation;
|
||||
|
||||
unspill_inst->base_mrf = 14;
|
||||
unspill_inst->mlen = 1; /* header contains offset */
|
||||
if (!gen7_read) {
|
||||
unspill_inst->base_mrf = 14;
|
||||
unspill_inst->mlen = 1; /* header contains offset */
|
||||
}
|
||||
inst->insert_before(unspill_inst);
|
||||
|
||||
dst.reg_offset++;
|
||||
|
@ -617,6 +625,7 @@ fs_visitor::choose_spill_reg(struct ra_graph *g)
|
|||
break;
|
||||
|
||||
case SHADER_OPCODE_GEN4_SCRATCH_READ:
|
||||
case SHADER_OPCODE_GEN7_SCRATCH_READ:
|
||||
if (inst->dst.file == GRF)
|
||||
no_spill[inst->dst.reg] = true;
|
||||
break;
|
||||
|
|
|
@ -342,6 +342,18 @@ schedule_node::set_latency_gen7(bool is_haswell)
|
|||
latency = 200;
|
||||
break;
|
||||
|
||||
case SHADER_OPCODE_GEN7_SCRATCH_READ:
|
||||
/* Testing a load from offset 0, that had been previously written:
|
||||
*
|
||||
* send(8) g114<1>UW g0<8,8,1>F data (0, 0, 0) mlen 1 rlen 1 { align1 WE_normal 1Q };
|
||||
* mov(8) null g114<8,8,1>F { align1 WE_normal 1Q };
|
||||
*
|
||||
* The cycles spent seemed to be grouped around 40-50 (as low as 38),
|
||||
* then around 140. Presumably this is cache hit vs miss.
|
||||
*/
|
||||
latency = 50;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 2 cycles:
|
||||
* mul(8) g4<1>F g2<0,1,0>F 0.5F { align1 WE_normal 1Q };
|
||||
|
|
|
@ -458,6 +458,8 @@ brw_instruction_name(enum opcode op)
|
|||
return "gen4_scratch_read";
|
||||
case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
|
||||
return "gen4_scratch_write";
|
||||
case SHADER_OPCODE_GEN7_SCRATCH_READ:
|
||||
return "gen7_scratch_read";
|
||||
|
||||
case FS_OPCODE_DDX:
|
||||
return "ddx";
|
||||
|
|
Loading…
Reference in New Issue