[Mesa-dev] [PATCH 25/61] radeonsi/gfx9: add TCS epilog support for merged LS-HS

Marek Olšák maraeo at gmail.com
Mon Apr 24 08:45:22 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/radeonsi/si_shader.c | 110 +++++++++++++++++++++----------
 1 file changed, 76 insertions(+), 34 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index f0e3f0c..907bc9c 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2604,71 +2604,89 @@ static void si_write_tess_factors(struct lp_build_tgsi_context *bld_base,
 				    lp_build_gather_values(gallivm, inner, inner_comps);
 			ac_build_buffer_store_dword(&ctx->ac, buf, inner_vec,
 						    inner_comps, tf_inner_offset,
 						    base, 0, 1, 0, true, false);
 		}
 	}
 
 	lp_build_endif(&if_ctx);
 }
 
+static LLVMValueRef
+si_insert_input_ptr_as_2xi32(struct si_shader_context *ctx, LLVMValueRef ret,
+			     unsigned param, unsigned return_index)
+{
+	LLVMBuilderRef builder = ctx->gallivm.builder;
+	LLVMValueRef ptr, lo, hi;
+
+	ptr = LLVMGetParam(ctx->main_fn, param);
+	ptr = LLVMBuildPtrToInt(builder, ptr, ctx->i64, "");
+	ptr = LLVMBuildBitCast(builder, ptr, ctx->v2i32, "");
+	lo = LLVMBuildExtractElement(builder, ptr, ctx->i32_0, "");
+	hi = LLVMBuildExtractElement(builder, ptr, ctx->i32_1, "");
+	ret = LLVMBuildInsertValue(builder, ret, lo, return_index, "");
+	return LLVMBuildInsertValue(builder, ret, hi, return_index + 1, "");
+}
+
 /* This only writes the tessellation factor levels. */
 static void si_llvm_emit_tcs_epilogue(struct lp_build_tgsi_context *bld_base)
 {
 	struct si_shader_context *ctx = si_shader_context(bld_base);
 	LLVMValueRef rel_patch_id, invocation_id, tf_lds_offset;
 	LLVMValueRef offchip_soffset, offchip_layout;
 
 	si_copy_tcs_inputs(bld_base);
 
 	rel_patch_id = get_rel_patch_id(ctx);
 	invocation_id = unpack_param(ctx, ctx->param_tcs_rel_ids, 8, 5);
 	tf_lds_offset = get_tcs_out_current_patch_data_offset(ctx);
 
 	/* Return epilog parameters from this function. */
 	LLVMBuilderRef builder = ctx->gallivm.builder;
 	LLVMValueRef ret = ctx->return_value;
-	LLVMValueRef rw_buffers, rw0, rw1, tf_soffset;
+	LLVMValueRef tf_soffset;
 	unsigned vgpr;
 
-	/* RW_BUFFERS pointer */
-	rw_buffers = LLVMGetParam(ctx->main_fn,
-				  ctx->param_rw_buffers);
-	rw_buffers = LLVMBuildPtrToInt(builder, rw_buffers, ctx->i64, "");
-	rw_buffers = LLVMBuildBitCast(builder, rw_buffers, ctx->v2i32, "");
-	rw0 = LLVMBuildExtractElement(builder, rw_buffers,
-				      ctx->i32_0, "");
-	rw1 = LLVMBuildExtractElement(builder, rw_buffers,
-				      ctx->i32_1, "");
-	ret = LLVMBuildInsertValue(builder, ret, rw0, 0, "");
-	ret = LLVMBuildInsertValue(builder, ret, rw1, 1, "");
-
-	/* Tess offchip and factor buffer soffset are after user SGPRs. */
 	offchip_layout = LLVMGetParam(ctx->main_fn,
 				      ctx->param_tcs_offchip_layout);
 	offchip_soffset = LLVMGetParam(ctx->main_fn,
 				       ctx->param_tcs_offchip_offset);
 	tf_soffset = LLVMGetParam(ctx->main_fn,
 				  ctx->param_tcs_factor_offset);
-	ret = LLVMBuildInsertValue(builder, ret, offchip_layout,
-				   GFX6_SGPR_TCS_OFFCHIP_LAYOUT, "");
-	ret = LLVMBuildInsertValue(builder, ret, offchip_soffset,
-				   GFX6_TCS_NUM_USER_SGPR, "");
-	ret = LLVMBuildInsertValue(builder, ret, tf_soffset,
-				   GFX6_TCS_NUM_USER_SGPR + 1, "");
+
+	if (ctx->screen->b.chip_class >= GFX9) {
+		ret = si_insert_input_ptr_as_2xi32(ctx, ret,
+						   ctx->param_rw_buffers, 8);
+		ret = LLVMBuildInsertValue(builder, ret, offchip_layout,
+					   8 + GFX9_SGPR_TCS_OFFCHIP_LAYOUT, "");
+		/* Tess offchip and tess factor offsets are at the beginning. */
+		ret = LLVMBuildInsertValue(builder, ret, offchip_soffset, 2, "");
+		ret = LLVMBuildInsertValue(builder, ret, tf_soffset, 4, "");
+		vgpr = 8 + GFX9_SGPR_TCS_OFFCHIP_LAYOUT + 1;
+	} else {
+		ret = si_insert_input_ptr_as_2xi32(ctx, ret,
+						   ctx->param_rw_buffers, 0);
+		ret = LLVMBuildInsertValue(builder, ret, offchip_layout,
+					   GFX6_SGPR_TCS_OFFCHIP_LAYOUT, "");
+		/* Tess offchip and tess factor offsets are after user SGPRs. */
+		ret = LLVMBuildInsertValue(builder, ret, offchip_soffset,
+					   GFX6_TCS_NUM_USER_SGPR, "");
+		ret = LLVMBuildInsertValue(builder, ret, tf_soffset,
+					   GFX6_TCS_NUM_USER_SGPR + 1, "");
+		vgpr = GFX6_TCS_NUM_USER_SGPR + 2;
+	}
 
 	/* VGPRs */
 	rel_patch_id = bitcast(bld_base, TGSI_TYPE_FLOAT, rel_patch_id);
 	invocation_id = bitcast(bld_base, TGSI_TYPE_FLOAT, invocation_id);
 	tf_lds_offset = bitcast(bld_base, TGSI_TYPE_FLOAT, tf_lds_offset);
 
-	vgpr = GFX6_TCS_NUM_USER_SGPR + 2;
 	ret = LLVMBuildInsertValue(builder, ret, rel_patch_id, vgpr++, "");
 	ret = LLVMBuildInsertValue(builder, ret, invocation_id, vgpr++, "");
 	ret = LLVMBuildInsertValue(builder, ret, tf_lds_offset, vgpr++, "");
 	ctx->return_value = ret;
 }
 
 static void si_llvm_emit_ls_epilogue(struct lp_build_tgsi_context *bld_base)
 {
 	struct si_shader_context *ctx = si_shader_context(bld_base);
 	struct si_shader *shader = ctx->shader;
@@ -5811,24 +5829,25 @@ static void create_function(struct si_shader_context *ctx)
 					       &num_prolog_vgprs);
 
 			/* LS return values are inputs to the TCS main shader part. */
 			for (i = 0; i < 8 + GFX9_TCS_NUM_USER_SGPR; i++)
 				returns[num_returns++] = ctx->i32; /* SGPRs */
 			for (i = 0; i < 2; i++)
 				returns[num_returns++] = ctx->f32; /* VGPRs */
 		} else {
 			/* TCS return values are inputs to the TCS epilog.
 			 *
-			 * param_tcs_offchip_offset and param_tcs_factor_offset
+			 * param_tcs_offchip_offset, param_tcs_factor_offset,
+			 * param_tcs_offchip_layout, and param_rw_buffers
 			 * should be passed to the epilog.
 			 */
-			for (i = 0; i <= ctx->param_tcs_factor_offset; i++)
+			for (i = 0; i <= 8 + GFX9_SGPR_TCS_OFFCHIP_LAYOUT; i++)
 				returns[num_returns++] = ctx->i32; /* SGPRs */
 			for (i = 0; i < 3; i++)
 				returns[num_returns++] = ctx->f32; /* VGPRs */
 		}
 		break;
 
 	case SI_SHADER_MERGED_VERTEX_OR_TESSEVAL_GEOMETRY:
 		assert(!"unimplemented merged ES-GS shader");
 		break;
 
@@ -8218,37 +8237,60 @@ static bool si_shader_select_tes_parts(struct si_screen *sscreen,
 
 /**
  * Compile the TCS epilog function. This writes tesselation factors to memory
  * based on the output primitive type of the tesselator (determined by TES).
  */
 static void si_build_tcs_epilog_function(struct si_shader_context *ctx,
 					 union si_shader_part_key *key)
 {
 	struct gallivm_state *gallivm = &ctx->gallivm;
 	struct lp_build_tgsi_context *bld_base = &ctx->bld_base;
-	LLVMTypeRef params[16];
+	LLVMTypeRef params[32];
 	LLVMValueRef func;
 	int last_sgpr, num_params = 0;
 
 	/* Declare inputs. Only RW_BUFFERS and TESS_FACTOR_OFFSET are used. */
+	if (ctx->screen->b.chip_class >= GFX9) {
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[ctx->param_tcs_offchip_offset = num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32; /* wave info */
+		params[ctx->param_tcs_factor_offset = num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+	}
 	params[ctx->param_rw_buffers = num_params++] =
 		const_array(ctx->v16i8, SI_NUM_RW_BUFFERS);
-	params[ctx->param_const_buffers = num_params++] = ctx->i64;
-	params[ctx->param_samplers = num_params++] = ctx->i64;
-	params[ctx->param_images = num_params++] = ctx->i64;
-	params[ctx->param_shader_buffers = num_params++] = ctx->i64;
-	params[ctx->param_tcs_offchip_layout = num_params++] = ctx->i32;
-	params[ctx->param_tcs_out_lds_offsets = num_params++] = ctx->i32;
-	params[ctx->param_tcs_out_lds_layout = num_params++] = ctx->i32;
-	params[ctx->param_vs_state_bits = num_params++] = ctx->i32;
-	params[ctx->param_tcs_offchip_offset = num_params++] = ctx->i32;
-	params[ctx->param_tcs_factor_offset = num_params++] = ctx->i32;
+	if (ctx->screen->b.chip_class >= GFX9) {
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[ctx->param_tcs_offchip_layout = num_params++] = ctx->i32;
+	} else {
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[num_params++] = ctx->i64;
+		params[ctx->param_tcs_offchip_layout = num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[num_params++] = ctx->i32;
+		params[ctx->param_tcs_offchip_offset = num_params++] = ctx->i32;
+		params[ctx->param_tcs_factor_offset = num_params++] = ctx->i32;
+	}
 	last_sgpr = num_params - 1;
 
 	params[num_params++] = ctx->i32; /* patch index within the wave (REL_PATCH_ID) */
 	params[num_params++] = ctx->i32; /* invocation ID within the patch */
 	params[num_params++] = ctx->i32; /* LDS offset where tess factors should be loaded from */
 
 	/* Create the function. */
 	si_create_function(ctx, "tcs_epilog", NULL, 0, params, num_params, last_sgpr);
 	declare_tess_lds(ctx);
 	func = ctx->main_fn;
-- 
2.7.4



More information about the mesa-dev mailing list