summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>2016-05-02 14:55:52 +0200
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>2016-05-26 22:07:04 +0200
commita4e2146a9d24592ed7e3bf778e3c21c6cfb89330 (patch)
tree22c833205f564016e5b75c762ab868e52ca9feec /src/gallium/drivers
parent6217716e8f6091f7bbacbb9fa2f52997d3ac5d03 (diff)
downloadexternal_mesa3d-a4e2146a9d24592ed7e3bf778e3c21c6cfb89330.zip
external_mesa3d-a4e2146a9d24592ed7e3bf778e3c21c6cfb89330.tar.gz
external_mesa3d-a4e2146a9d24592ed7e3bf778e3c21c6cfb89330.tar.bz2
radeonsi: Use buffer loads and stores for passing data from TCS to TES.
We always try to use 4-component loads, as LLVM does not combine loads and they bypass the L1 cache. We can't use a similar strategy for stores and this is especially notable with the tess factors, as they are often set with separate MOV's per component in the TGSI. We keep storing to LDS and the LDS space, so we can load the outputs later, either due to the shader, of for wrting the tess factors. Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index b04d0f7..6694f00 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -1082,18 +1082,18 @@ static LLVMValueRef fetch_input_tes(
enum tgsi_opcode_type type, unsigned swizzle)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMValueRef dw_addr, stride;
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMValueRef rw_buffers, buffer, base, addr;
- if (reg->Register.Dimension) {
- stride = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8);
- dw_addr = get_tcs_out_current_patch_offset(ctx);
- dw_addr = get_dw_address(ctx, NULL, reg, stride, dw_addr);
- } else {
- dw_addr = get_tcs_out_current_patch_data_offset(ctx);
- dw_addr = get_dw_address(ctx, NULL, reg, NULL, dw_addr);
- }
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ SI_PARAM_RW_BUFFERS);
+ buffer = build_indexed_load_const(ctx, rw_buffers,
+ lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- return lds_load(bld_base, type, swizzle, dw_addr);
+ base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ addr = get_tcs_tes_buffer_address_from_reg(ctx, NULL, reg);
+
+ return buffer_load(bld_base, type, swizzle, buffer, base, addr);
}
static void store_output_tcs(struct lp_build_tgsi_context *bld_base,
@@ -1102,9 +1102,12 @@ static void store_output_tcs(struct lp_build_tgsi_context *bld_base,
LLVMValueRef dst[4])
{
struct si_shader_context *ctx = si_shader_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
const struct tgsi_full_dst_register *reg = &inst->Dst[0];
unsigned chan_index;
LLVMValueRef dw_addr, stride;
+ LLVMValueRef rw_buffers, buffer, base, buf_addr;
+ LLVMValueRef values[4];
/* Only handle per-patch and per-vertex outputs here.
* Vectors will be lowered to scalars and this function will be called again.
@@ -1124,6 +1127,15 @@ static void store_output_tcs(struct lp_build_tgsi_context *bld_base,
dw_addr = get_dw_address(ctx, reg, NULL, NULL, dw_addr);
}
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ SI_PARAM_RW_BUFFERS);
+ buffer = build_indexed_load_const(ctx, rw_buffers,
+ lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
+
+ base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ buf_addr = get_tcs_tes_buffer_address_from_reg(ctx, reg, NULL);
+
+
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
LLVMValueRef value = dst[chan_index];
@@ -1131,6 +1143,22 @@ static void store_output_tcs(struct lp_build_tgsi_context *bld_base,
value = radeon_llvm_saturate(bld_base, value);
lds_store(bld_base, chan_index, dw_addr, value);
+
+ value = LLVMBuildBitCast(gallivm->builder, value, ctx->i32, "");
+ values[chan_index] = value;
+
+ if (inst->Dst[0].Register.WriteMask != 0xF) {
+ build_tbuffer_store_dwords(ctx, buffer, value, 1,
+ buf_addr, base,
+ 4 * chan_index);
+ }
+ }
+
+ if (inst->Dst[0].Register.WriteMask == 0xF) {
+ LLVMValueRef value = lp_build_gather_values(bld_base->base.gallivm,
+ values, 4);
+ build_tbuffer_store_dwords(ctx, buffer, value, 4, buf_addr,
+ base, 0);
}
}
@@ -1641,15 +1669,21 @@ static void declare_system_value(
case TGSI_SEMANTIC_TESSINNER:
case TGSI_SEMANTIC_TESSOUTER:
{
- LLVMValueRef dw_addr;
+ LLVMValueRef rw_buffers, buffer, base, addr;
int param = si_shader_io_get_unique_index(decl->Semantic.Name, 0);
- dw_addr = get_tcs_out_current_patch_data_offset(ctx);
- dw_addr = LLVMBuildAdd(gallivm->builder, dw_addr,
- lp_build_const_int32(gallivm, param * 4), "");
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ SI_PARAM_RW_BUFFERS);
+ buffer = build_indexed_load_const(ctx, rw_buffers,
+ lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
+
+ base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ addr = get_tcs_tes_buffer_address(ctx, NULL,
+ lp_build_const_int32(gallivm, param));
+
+ value = buffer_load(&radeon_bld->soa.bld_base, TGSI_TYPE_FLOAT,
+ ~0, buffer, base, addr);
- value = lds_load(&radeon_bld->soa.bld_base, TGSI_TYPE_FLOAT,
- ~0, dw_addr);
break;
}