diff options
author | Dave Airlie <[email protected]> | 2015-11-30 15:46:58 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2015-12-07 09:59:01 +1000 |
commit | cfc2818e2302aba4d4f4ac13edff7f2b10b6302a (patch) | |
tree | 0b38f7ccec8be40efda963295cefe979cb63855a /src/gallium | |
parent | 892cc65fa3edf64e509d627439eacd75f00b532b (diff) |
r600/shader: handle TCS output writing.
TCS outputs whenever they are written in the shader,
need to be written to LDS not temporaries, this handles
this case. It also fixes up the case where the output
is a relative addressed output, so we don't try to apply
the relative address at the wrong time.
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 100 |
1 files changed, 98 insertions, 2 deletions
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 48dd7c25525..4210c3af685 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -2480,6 +2480,90 @@ static int emit_lds_vs_writes(struct r600_shader_ctx *ctx) return 0; } +static int r600_store_tcs_output(struct r600_shader_ctx *ctx) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + const struct tgsi_full_dst_register *dst = &inst->Dst[0]; + int i, r, lasti; + int temp_reg = r600_get_temp(ctx); + struct r600_bytecode_alu alu; + unsigned write_mask = dst->Register.WriteMask; + + if (inst->Dst[0].Register.File != TGSI_FILE_OUTPUT) + return 0; + + r = get_lds_offset0(ctx, 1, temp_reg, dst->Register.Dimension ? false : true); + if (r) + return r; + + /* the base address is now in temp.x */ + r = r600_get_byte_address(ctx, temp_reg, + &inst->Dst[0], NULL, ctx->tess_output_info, 1); + if (r) + return r; + + /* LDS write */ + lasti = tgsi_last_instruction(write_mask); + for (i = 1; i <= lasti; i++) { + + if (!(write_mask & (1 << i))) + continue; + r = single_alu_op2(ctx, ALU_OP2_ADD_INT, + temp_reg, i, + temp_reg, 0, + V_SQ_ALU_SRC_LITERAL, 4 * i); + if (r) + return r; + } + + for (i = 0; i <= lasti; i++) { + if (!(write_mask & (1 << i))) + continue; + + if ((i == 0 && ((write_mask & 3) == 3)) || + (i == 2 && ((write_mask & 0xc) == 0xc))) { + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = LDS_OP3_LDS_WRITE_REL; + alu.src[0].sel = temp_reg; + alu.src[0].chan = i; + + alu.src[1].sel = dst->Register.Index; + alu.src[1].sel += ctx->file_offset[dst->Register.File]; + alu.src[1].chan = i; + + alu.src[2].sel = dst->Register.Index; + alu.src[2].sel += ctx->file_offset[dst->Register.File]; + alu.src[2].chan = i + 1; + alu.lds_idx = 1; + alu.dst.chan = 0; + alu.last = 1; + alu.is_lds_idx_op = true; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + i += 1; + continue; + } + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = LDS_OP2_LDS_WRITE; + alu.src[0].sel = temp_reg; + alu.src[0].chan = i; + + alu.src[1].sel = dst->Register.Index; + alu.src[1].sel += ctx->file_offset[dst->Register.File]; + alu.src[1].chan = i; + + alu.src[2].sel = V_SQ_ALU_SRC_0; + alu.dst.chan = 0; + alu.last = 1; + alu.is_lds_idx_op = true; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + } + return 0; +} + static int r600_shader_from_tgsi(struct r600_context *rctx, struct r600_pipe_shader *pipeshader, union r600_shader_key key) @@ -2916,6 +3000,12 @@ static int r600_shader_from_tgsi(struct r600_context *rctx, r = ctx.inst_info->process(&ctx); if (r) goto out_err; + + if (ctx.type == TGSI_PROCESSOR_TESS_CTRL) { + r = r600_store_tcs_output(&ctx); + if (r) + goto out_err; + } break; default: break; @@ -3330,11 +3420,17 @@ static void tgsi_dst(struct r600_shader_ctx *ctx, r600_dst->sel += ctx->file_offset[tgsi_dst->Register.File]; r600_dst->chan = swizzle; r600_dst->write = 1; - if (tgsi_dst->Register.Indirect) - r600_dst->rel = V_SQ_REL_RELATIVE; if (inst->Instruction.Saturate) { r600_dst->clamp = 1; } + if (ctx->type == TGSI_PROCESSOR_TESS_CTRL) { + if (tgsi_dst->Register.File == TGSI_FILE_OUTPUT) { + return; + } + } + if (tgsi_dst->Register.Indirect) + r600_dst->rel = V_SQ_REL_RELATIVE; + } static int tgsi_op2_64_params(struct r600_shader_ctx *ctx, bool singledest, bool swap) |