[Mesa-dev] [PATCH v2 28/73] ac/nir: split scanning outputs from setting up output allocas

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


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

The scanning phase sets the driver_location, because it is part of the
ABI: radeonsi does the assignment differently.
---
 src/amd/common/ac_nir_to_llvm.c | 51 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index d82e682..5f7a938 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -4975,26 +4975,27 @@ ac_build_alloca(struct ac_llvm_context *ac,
 static LLVMValueRef si_build_alloca_undef(struct ac_llvm_context *ac,
 					  LLVMTypeRef type,
 					  const char *name)
 {
 	LLVMValueRef ptr = ac_build_alloca(ac, type, name);
 	LLVMBuildStore(ac->builder, LLVMGetUndef(type), ptr);
 	return ptr;
 }
 
 static void
-handle_shader_output_decl(struct nir_to_llvm_context *ctx,
-			  struct nir_variable *variable)
+scan_shader_output_decl(struct nir_to_llvm_context *ctx,
+			struct nir_variable *variable)
 {
 	int idx = variable->data.location + variable->data.index;
 	unsigned attrib_count = glsl_count_attribute_slots(variable->type, false);
 	uint64_t mask_attribs;
+
 	variable->data.driver_location = idx * 4;
 
 	/* tess ctrl has it's own load/store paths for outputs */
 	if (ctx->stage == MESA_SHADER_TESS_CTRL)
 		return;
 
 	mask_attribs = ((1ull << attrib_count) - 1) << idx;
 	if (ctx->stage == MESA_SHADER_VERTEX ||
 	    ctx->stage == MESA_SHADER_TESS_EVAL ||
 	    ctx->stage == MESA_SHADER_GEOMETRY) {
@@ -5010,27 +5011,56 @@ handle_shader_output_decl(struct nir_to_llvm_context *ctx,
 			}
 
 			if (length > 4)
 				attrib_count = 2;
 			else
 				attrib_count = 1;
 			mask_attribs = 1ull << idx;
 		}
 	}
 
+	ctx->output_mask |= mask_attribs;
+}
+
+static void
+handle_shader_output_decl(struct ac_nir_context *ctx,
+			  struct nir_shader *nir,
+			  struct nir_variable *variable)
+{
+	unsigned output_loc = variable->data.driver_location / 4;
+	unsigned attrib_count = glsl_count_attribute_slots(variable->type, false);
+
+	/* tess ctrl has it's own load/store paths for outputs */
+	if (ctx->stage == MESA_SHADER_TESS_CTRL)
+		return;
+
+	if (ctx->stage == MESA_SHADER_VERTEX ||
+	    ctx->stage == MESA_SHADER_TESS_EVAL ||
+	    ctx->stage == MESA_SHADER_GEOMETRY) {
+		int idx = variable->data.location + variable->data.index;
+		if (idx == VARYING_SLOT_CLIP_DIST0) {
+			int length = nir->info.clip_distance_array_size +
+				     nir->info.cull_distance_array_size;
+
+			if (length > 4)
+				attrib_count = 2;
+			else
+				attrib_count = 1;
+		}
+	}
+
 	for (unsigned i = 0; i < attrib_count; ++i) {
 		for (unsigned chan = 0; chan < 4; chan++) {
-			ctx->nir->outputs[radeon_llvm_reg_index_soa(idx + i, chan)] =
-		                       si_build_alloca_undef(&ctx->ac, ctx->f32, "");
+			ctx->outputs[radeon_llvm_reg_index_soa(output_loc + i, chan)] =
+		                       si_build_alloca_undef(&ctx->ac, ctx->ac.f32, "");
 		}
 	}
-	ctx->output_mask |= mask_attribs;
 }
 
 static void
 setup_locals(struct ac_nir_context *ctx,
 	     struct nir_function *func)
 {
 	int i, j;
 	ctx->num_locals = 0;
 	nir_foreach_variable(variable, &func->impl->locals) {
 		unsigned attrib_count = glsl_count_attribute_slots(variable->type, false);
@@ -5974,21 +6004,21 @@ void ac_nir_translate(struct ac_llvm_context *ac, struct ac_shader_abi *abi,
 	ctx.ac = *ac;
 	ctx.abi = abi;
 
 	ctx.nctx = nctx;
 	if (nctx)
 		nctx->nir = &ctx;
 
 	ctx.stage = nir->stage;
 
 	nir_foreach_variable(variable, &nir->outputs)
-		handle_shader_output_decl(nctx, variable);
+		handle_shader_output_decl(&ctx, nir, variable);
 
 	ctx.defs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
 	                                   _mesa_key_pointer_equal);
 	ctx.phis = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
 	                                   _mesa_key_pointer_equal);
 
 	func = (struct nir_function *)exec_list_get_head(&nir->functions);
 
 	setup_locals(&ctx, func);
 
@@ -6087,20 +6117,23 @@ LLVMModuleRef ac_translate_nir_to_llvm(LLVMTargetMachineRef tm,
 
 	nir_foreach_variable(variable, &nir->inputs)
 		handle_shader_input_decl(&ctx, variable);
 
 	if (nir->stage == MESA_SHADER_FRAGMENT)
 		handle_fs_inputs_pre(&ctx, nir);
 
 	ctx.abi.inputs = &ctx.inputs[0];
 	ctx.abi.emit_outputs = handle_shader_outputs_post;
 
+	nir_foreach_variable(variable, &nir->outputs)
+		scan_shader_output_decl(&ctx, variable);
+
 	ac_nir_translate(&ctx.ac, &ctx.abi, nir, &ctx);
 
 	LLVMBuildRetVoid(ctx.builder);
 
 	ac_llvm_finalize_module(&ctx);
 
 	ac_nir_eliminate_const_vs_outputs(&ctx);
 
 	if (nir->stage == MESA_SHADER_GEOMETRY) {
 		unsigned addclip = ctx.num_output_clips + ctx.num_output_culls > 4;
@@ -6374,22 +6407,24 @@ void ac_create_gs_copy_shader(LLVMTargetMachineRef tm,
 	ctx.num_output_clips = geom_shader->info.clip_distance_array_size;
 	ctx.num_output_culls = geom_shader->info.cull_distance_array_size;
 
 	struct ac_nir_context nir_ctx = {};
 	nir_ctx.ac = ctx.ac;
 	nir_ctx.abi = &ctx.abi;
 
 	nir_ctx.nctx = &ctx;
 	ctx.nir = &nir_ctx;
 
-	nir_foreach_variable(variable, &geom_shader->outputs)
-		handle_shader_output_decl(&ctx, variable);
+	nir_foreach_variable(variable, &geom_shader->outputs) {
+		scan_shader_output_decl(&ctx, variable);
+		handle_shader_output_decl(&nir_ctx, geom_shader, variable);
+	}
 
 	ac_gs_copy_shader_emit(&ctx);
 
 	ctx.nir = NULL;
 
 	LLVMBuildRetVoid(ctx.builder);
 
 	ac_llvm_finalize_module(&ctx);
 
 	ac_compile_llvm_module(tm, ctx.module, binary, config, shader_info,
-- 
2.9.3



More information about the mesa-dev mailing list