[Mesa-dev] [PATCH 40/53] r600/shader: handle TCS output writing.
Dave Airlie
airlied at gmail.com
Sun Nov 29 22:20:49 PST 2015
From: Dave Airlie <airlied at redhat.com>
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 <airlied at redhat.com>
---
src/gallium/drivers/r600/r600_shader.c | 100 ++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index ee83114..f199055 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -2450,6 +2450,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)
@@ -2881,6 +2965,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;
@@ -3295,11 +3385,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)
--
2.5.0
More information about the mesa-dev
mailing list