diff options
author | Dave Airlie <[email protected]> | 2015-11-30 15:34:14 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2015-12-07 09:59:01 +1000 |
commit | 0696ebc899d3aa125ae85b757c5fba137617ecaa (patch) | |
tree | f09423c7041a9c6c7c0b4f57b69e5fa9b3ac66fb /src/gallium/drivers/r600/r600_shader.c | |
parent | 09d25a9b37eeb34b3475fe486b82e12e904bcb28 (diff) |
r600/shader: add utility functions to do single slot arithmatic
These utilities are to be used to do things like integer adds and
multiplies to be used in calculating the LDS offsets etc.
It handles CAYMAN MULLO differences as well.
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/r600_shader.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 284eeead3e4..8d117c1cb5f 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -666,6 +666,101 @@ static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int back return 0; } +/* execute a single slot ALU calculation */ +static int single_alu_op2(struct r600_shader_ctx *ctx, int op, + int dst_sel, int dst_chan, + int src0_sel, unsigned src0_chan_val, + int src1_sel, unsigned src1_chan_val) +{ + struct r600_bytecode_alu alu; + int r, i; + + if (ctx->bc->chip_class == CAYMAN && op == ALU_OP2_MULLO_INT) { + for (i = 0; i < 4; i++) { + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = op; + alu.src[0].sel = src0_sel; + if (src0_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[0].value = src0_chan_val; + else + alu.src[0].chan = src0_chan_val; + alu.src[1].sel = src1_sel; + if (src1_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[1].value = src1_chan_val; + else + alu.src[1].chan = src1_chan_val; + alu.dst.sel = dst_sel; + alu.dst.chan = i; + alu.dst.write = i == dst_chan; + alu.last = (i == 3); + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + } + return 0; + } + + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = op; + alu.src[0].sel = src0_sel; + if (src0_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[0].value = src0_chan_val; + else + alu.src[0].chan = src0_chan_val; + alu.src[1].sel = src1_sel; + if (src1_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[1].value = src1_chan_val; + else + alu.src[1].chan = src1_chan_val; + alu.dst.sel = dst_sel; + alu.dst.chan = dst_chan; + alu.dst.write = 1; + alu.last = 1; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + return 0; +} + +/* execute a single slot ALU calculation */ +static int single_alu_op3(struct r600_shader_ctx *ctx, int op, + int dst_sel, int dst_chan, + int src0_sel, unsigned src0_chan_val, + int src1_sel, unsigned src1_chan_val, + int src2_sel, unsigned src2_chan_val) +{ + struct r600_bytecode_alu alu; + int r; + + /* validate this for other ops */ + assert(op == ALU_OP3_MULADD_UINT24); + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = op; + alu.src[0].sel = src0_sel; + if (src0_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[0].value = src0_chan_val; + else + alu.src[0].chan = src0_chan_val; + alu.src[1].sel = src1_sel; + if (src1_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[1].value = src1_chan_val; + else + alu.src[1].chan = src1_chan_val; + alu.src[2].sel = src2_sel; + if (src2_sel == V_SQ_ALU_SRC_LITERAL) + alu.src[2].value = src2_chan_val; + else + alu.src[2].chan = src2_chan_val; + alu.dst.sel = dst_sel; + alu.dst.chan = dst_chan; + alu.is_op3 = 1; + alu.last = 1; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + return 0; +} + static inline int get_address_file_reg(struct r600_shader_ctx *ctx, int index) { return index > 0 ? ctx->bc->index_reg[index - 1] : ctx->bc->ar_reg; |