[Mesa-dev] [PATCH v2 25/73] ac, radeonsi: add ac_shader_abi::emit_outputs for hardware VS shaders

Nicolai Hähnle nhaehnle at gmail.com
Wed Jul 5 10:48:09 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

---
 src/amd/common/ac_shader_abi.h                    |  4 +++
 src/gallium/drivers/radeonsi/si_shader.c          | 37 ++++++++++++++++-------
 src/gallium/drivers/radeonsi/si_shader_internal.h |  7 +++++
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/src/amd/common/ac_shader_abi.h b/src/amd/common/ac_shader_abi.h
index a872948..81fbc22 100644
--- a/src/amd/common/ac_shader_abi.h
+++ b/src/amd/common/ac_shader_abi.h
@@ -35,13 +35,17 @@ struct ac_shader_abi {
 	LLVMValueRef draw_id;
 	LLVMValueRef vertex_id;
 	LLVMValueRef instance_id;
 
 	/* For VS and PS: pre-loaded shader inputs.
 	 *
 	 * Currently only used for NIR shaders; indexed by variables'
 	 * driver_location.
 	 */
 	LLVMValueRef *inputs;
+
+	void (*emit_outputs)(struct ac_shader_abi *abi,
+			     unsigned max_outputs,
+			     LLVMValueRef *addrs);
 };
 
 #endif /* AC_SHADER_ABI_H */
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 0619c0f..2d1a580 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2991,29 +2991,32 @@ static LLVMValueRef si_get_gs_wave_id(struct si_shader_context *ctx)
 }
 
 static void si_llvm_emit_gs_epilogue(struct lp_build_tgsi_context *bld_base)
 {
 	struct si_shader_context *ctx = si_shader_context(bld_base);
 
 	ac_build_sendmsg(&ctx->ac, AC_SENDMSG_GS_OP_NOP | AC_SENDMSG_GS_DONE,
 			 si_get_gs_wave_id(ctx));
 }
 
-static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context *bld_base)
+static void si_llvm_emit_vs_epilogue(struct ac_shader_abi *abi,
+				     unsigned max_outputs,
+				     LLVMValueRef *addrs)
 {
-	struct si_shader_context *ctx = si_shader_context(bld_base);
+	struct si_shader_context *ctx = si_shader_context_from_abi(abi);
 	struct gallivm_state *gallivm = &ctx->gallivm;
 	struct tgsi_shader_info *info = &ctx->shader->selector->info;
 	struct si_shader_output_values *outputs = NULL;
 	int i,j;
 
 	assert(!ctx->shader->is_gs_copy_shader);
+	assert(info->num_outputs <= max_outputs);
 
 	outputs = MALLOC((info->num_outputs + 1) * sizeof(outputs[0]));
 
 	/* Vertex color clamping.
 	 *
 	 * This uses a state constant loaded in a user data SGPR and
 	 * an IF statement is added that clamps all colors if the constant
 	 * is true.
 	 */
 	if (ctx->type == PIPE_SHADER_VERTEX) {
@@ -3030,66 +3033,74 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context *bld_base)
 			if (!cond) {
 				/* The state is in the first bit of the user SGPR. */
 				cond = LLVMGetParam(ctx->main_fn,
 						    ctx->param_vs_state_bits);
 				cond = LLVMBuildTrunc(gallivm->builder, cond,
 						      ctx->i1, "");
 				lp_build_if(&if_ctx, gallivm, cond);
 			}
 
 			for (j = 0; j < 4; j++) {
-				addr = ctx->outputs[i][j];
+				addr = addrs[4 * i + j];
 				val = LLVMBuildLoad(gallivm->builder, addr, "");
 				val = ac_build_clamp(&ctx->ac, val);
 				LLVMBuildStore(gallivm->builder, val, addr);
 			}
 		}
 
 		if (cond)
 			lp_build_endif(&if_ctx);
 	}
 
 	for (i = 0; i < info->num_outputs; i++) {
 		outputs[i].semantic_name = info->output_semantic_name[i];
 		outputs[i].semantic_index = info->output_semantic_index[i];
 
 		for (j = 0; j < 4; j++) {
 			outputs[i].values[j] =
 				LLVMBuildLoad(gallivm->builder,
-					      ctx->outputs[i][j],
+					      addrs[4 * i + j],
 					      "");
 			outputs[i].vertex_stream[j] =
 				(info->output_streams[i] >> (2 * j)) & 3;
 		}
 	}
 
 	if (ctx->shader->selector->so.num_outputs)
 		si_llvm_emit_streamout(ctx, outputs, i, 0);
 
 	/* Export PrimitiveID. */
 	if (ctx->shader->key.mono.u.vs_export_prim_id) {
 		outputs[i].semantic_name = TGSI_SEMANTIC_PRIMID;
 		outputs[i].semantic_index = 0;
-		outputs[i].values[0] = bitcast(bld_base, TGSI_TYPE_FLOAT,
-					       get_primitive_id(ctx, 0));
+		outputs[i].values[0] = LLVMBuildBitCast(gallivm->builder,
+				get_primitive_id(ctx, 0), ctx->f32, "");
 		for (j = 1; j < 4; j++)
 			outputs[i].values[j] = LLVMConstReal(ctx->f32, 0);
 
 		memset(outputs[i].vertex_stream, 0,
 		       sizeof(outputs[i].vertex_stream));
 		i++;
 	}
 
-	si_llvm_export_vs(bld_base, outputs, i);
+	si_llvm_export_vs(&ctx->bld_base, outputs, i);
 	FREE(outputs);
 }
 
+static void si_tgsi_emit_epilogue(struct lp_build_tgsi_context *bld_base)
+{
+	struct si_shader_context *ctx = si_shader_context(bld_base);
+
+	ctx->abi.emit_outputs(&ctx->abi, RADEON_LLVM_MAX_OUTPUTS,
+			      &ctx->outputs[0][0]);
+}
+
 struct si_ps_exports {
 	unsigned num;
 	struct ac_export_args args[10];
 };
 
 unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
 				    bool writes_samplemask)
 {
 	if (writes_z) {
 		/* Z needs 32 bits. */
@@ -5526,35 +5537,39 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx,
 	struct lp_build_tgsi_context *bld_base = &ctx->bld_base;
 
 	// TODO clean all this up!
 	switch (ctx->type) {
 	case PIPE_SHADER_VERTEX:
 		ctx->load_input = declare_input_vs;
 		if (shader->key.as_ls)
 			bld_base->emit_epilogue = si_llvm_emit_ls_epilogue;
 		else if (shader->key.as_es)
 			bld_base->emit_epilogue = si_llvm_emit_es_epilogue;
-		else
-			bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
+		else {
+			ctx->abi.emit_outputs = si_llvm_emit_vs_epilogue;
+			bld_base->emit_epilogue = si_tgsi_emit_epilogue;
+		}
 		break;
 	case PIPE_SHADER_TESS_CTRL:
 		bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_tcs;
 		bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = fetch_output_tcs;
 		bld_base->emit_store = store_output_tcs;
 		bld_base->emit_epilogue = si_llvm_emit_tcs_epilogue;
 		break;
 	case PIPE_SHADER_TESS_EVAL:
 		bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_tes;
 		if (shader->key.as_es)
 			bld_base->emit_epilogue = si_llvm_emit_es_epilogue;
-		else
-			bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
+		else {
+			ctx->abi.emit_outputs = si_llvm_emit_vs_epilogue;
+			bld_base->emit_epilogue = si_tgsi_emit_epilogue;
+		}
 		break;
 	case PIPE_SHADER_GEOMETRY:
 		bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_gs;
 		bld_base->emit_epilogue = si_llvm_emit_gs_epilogue;
 		break;
 	case PIPE_SHADER_FRAGMENT:
 		ctx->load_input = declare_input_fs;
 		bld_base->emit_epilogue = si_llvm_return_fs_outputs;
 		break;
 	case PIPE_SHADER_COMPUTE:
diff --git a/src/gallium/drivers/radeonsi/si_shader_internal.h b/src/gallium/drivers/radeonsi/si_shader_internal.h
index 2054a73..c8dcd5c 100644
--- a/src/gallium/drivers/radeonsi/si_shader_internal.h
+++ b/src/gallium/drivers/radeonsi/si_shader_internal.h
@@ -235,20 +235,27 @@ struct si_shader_context {
 
 	LLVMValueRef shared_memory;
 };
 
 static inline struct si_shader_context *
 si_shader_context(struct lp_build_tgsi_context *bld_base)
 {
 	return (struct si_shader_context*)bld_base;
 }
 
+static inline struct si_shader_context *
+si_shader_context_from_abi(struct ac_shader_abi *abi)
+{
+	struct si_shader_context *ctx = NULL;
+	return container_of(abi, ctx, abi);
+}
+
 void si_llvm_add_attribute(LLVMValueRef F, const char *name, int value);
 
 LLVMTargetRef si_llvm_get_amdgpu_target(const char *triple);
 
 unsigned si_llvm_compile(LLVMModuleRef M, struct ac_shader_binary *binary,
 			 LLVMTargetMachineRef tm,
 			 struct pipe_debug_callback *debug);
 
 LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base,
 			  enum tgsi_opcode_type type);
-- 
2.9.3



More information about the mesa-dev mailing list