summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2012-11-07 11:18:34 -0800
committerEric Anholt <[email protected]>2012-12-04 16:27:53 -0800
commitd8214e4384aaf0ee412ad9aea80f9fec522c1e4a (patch)
treec297544b6188cef26163815bd9409820d82ff0b7
parent29340d02dc38a9cc352d44412871dc9d4e3f878a (diff)
i965/fs: Add instruction emit for varying-index reads of uniforms.
The gen7 send-from-GRF path is sufficiently different from the perspective of IR generation and optimization that I just made it a separate opcode. v2: fix whitespace, rebase on Ken's recent refactor.
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h3
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h6
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_emit.cpp94
4 files changed, 105 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index 6e4fb134b30..3423178b371 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -675,6 +675,8 @@ enum opcode {
FS_OPCODE_SPILL,
FS_OPCODE_UNSPILL,
FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD,
+ FS_OPCODE_VARYING_PULL_CONSTANT_LOAD,
+ FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7,
FS_OPCODE_MOV_DISPATCH_TO_FLAGS,
VS_OPCODE_URB_WRITE,
@@ -909,6 +911,7 @@ enum brw_message_target {
/* GEN7 */
#define GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 10
+#define GEN7_DATAPORT_DC_DWORD_SCATTERED_READ 3
#define BRW_MATH_FUNCTION_INV 1
#define BRW_MATH_FUNCTION_LOG 2
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 21473e94c63..669f408087a 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -518,6 +518,8 @@ fs_visitor::implied_mrf_writes(fs_inst *inst)
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
case FS_OPCODE_UNSPILL:
return 1;
+ case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD:
+ return inst->header_present;
case FS_OPCODE_SPILL:
return 2;
default:
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index c14e779a0ed..dae78155269 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -484,6 +484,12 @@ private:
void generate_uniform_pull_constant_load(fs_inst *inst, struct brw_reg dst,
struct brw_reg index,
struct brw_reg offset);
+ void generate_varying_pull_constant_load(fs_inst *inst, struct brw_reg dst,
+ struct brw_reg index);
+ void generate_varying_pull_constant_load_gen7(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg index,
+ struct brw_reg offset);
void generate_mov_dispatch_to_flags();
struct brw_context *brw;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
index 87a5e53c3a6..37eed1b9f74 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
@@ -648,6 +648,92 @@ fs_generator::generate_uniform_pull_constant_load(fs_inst *inst,
}
}
+void
+fs_generator::generate_varying_pull_constant_load(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg index)
+{
+ assert(intel->gen < 7); /* Should use the gen7 variant. */
+ assert(inst->header_present);
+
+ assert(index.file == BRW_IMMEDIATE_VALUE &&
+ index.type == BRW_REGISTER_TYPE_UD);
+ uint32_t surf_index = index.dw1.ud;
+
+ uint32_t msg_type, msg_control, rlen;
+ if (intel->gen >= 6)
+ msg_type = GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
+ else if (intel->gen == 5 || intel->is_g4x)
+ msg_type = G45_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
+ else
+ msg_type = BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
+
+ if (dispatch_width == 16) {
+ msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS;
+ rlen = 2;
+ } else {
+ msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS;
+ rlen = 1;
+ }
+
+ struct brw_reg header = brw_vec8_grf(0, 0);
+ gen6_resolve_implied_move(p, &header, inst->base_mrf);
+
+ struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_set_dest(p, send, dst);
+ brw_set_src0(p, send, header);
+ if (intel->gen < 6)
+ send->header.destreg__conditionalmod = inst->base_mrf;
+ brw_set_dp_read_message(p, send,
+ surf_index,
+ msg_control,
+ msg_type,
+ BRW_DATAPORT_READ_TARGET_DATA_CACHE,
+ inst->mlen,
+ inst->header_present,
+ rlen);
+}
+
+void
+fs_generator::generate_varying_pull_constant_load_gen7(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg index,
+ struct brw_reg offset)
+{
+ assert(intel->gen >= 7);
+ /* Varying-offset pull constant loads are treated as a normal expression on
+ * gen7, so the fact that it's a send message is hidden at the IR level.
+ */
+ assert(!inst->header_present);
+ assert(!inst->mlen);
+
+ assert(index.file == BRW_IMMEDIATE_VALUE &&
+ index.type == BRW_REGISTER_TYPE_UD);
+ uint32_t surf_index = index.dw1.ud;
+
+ uint32_t msg_control, rlen, mlen;
+ if (dispatch_width == 16) {
+ msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS;
+ mlen = rlen = 2;
+ } else {
+ msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS;
+ mlen = rlen = 1;
+ }
+
+ struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
+ brw_set_dest(p, send, dst);
+ brw_set_src0(p, send, offset);
+ if (intel->gen < 6)
+ send->header.destreg__conditionalmod = inst->base_mrf;
+ brw_set_dp_read_message(p, send,
+ surf_index,
+ msg_control,
+ GEN7_DATAPORT_DC_DWORD_SCATTERED_READ,
+ BRW_DATAPORT_READ_TARGET_DATA_CACHE,
+ mlen,
+ inst->header_present,
+ rlen);
+}
/**
* Cause the current pixel/sample mask (from R1.7 bits 15:0) to be transferred
@@ -1021,6 +1107,14 @@ fs_generator::generate_code(exec_list *instructions)
generate_uniform_pull_constant_load(inst, dst, src[0], src[1]);
break;
+ case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD:
+ generate_varying_pull_constant_load(inst, dst, src[0]);
+ break;
+
+ case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7:
+ generate_varying_pull_constant_load_gen7(inst, dst, src[0], src[1]);
+ break;
+
case FS_OPCODE_FB_WRITE:
generate_fb_write(inst);
break;