From: Eric Anholt Date: Wed, 7 Nov 2012 19:18:34 +0000 (-0800) Subject: i965/fs: Add instruction emit for varying-index reads of uniforms. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d8214e4384aaf0ee412ad9aea80f9fec522c1e4a;p=mesa.git 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. --- 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;