[Mesa-dev] [PATCH 01/16] radeonsi: Refactor shader input / output handling code

Michel Dänzer michel at daenzer.net
Fri Jan 24 01:33:13 PST 2014


From: Michel Dänzer <michel.daenzer at amd.com>

In preparation for adding geometry shader support.

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/gallium/drivers/radeonsi/si_shader.c | 486 +++++++++++++++++--------------
 1 file changed, 268 insertions(+), 218 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 5c6f128..b9c46a2 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -147,11 +147,14 @@ static LLVMValueRef get_instance_index_for_fetch(
 }
 
 static void declare_input_vs(
-	struct si_shader_context * si_shader_ctx,
+	struct radeon_llvm_context *radeon_bld,
 	unsigned input_index,
 	const struct tgsi_full_declaration *decl)
 {
-	struct lp_build_context * base = &si_shader_ctx->radeon_bld.soa.bld_base.base;
+	struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
+	struct gallivm_state *gallivm = base->gallivm;
+	struct si_shader_context *si_shader_ctx =
+		si_shader_context(&radeon_bld->soa.bld_base);
 	unsigned divisor = si_shader_ctx->shader->key.vs.instance_divisors[input_index];
 
 	unsigned chan;
@@ -168,12 +171,12 @@ static void declare_input_vs(
 	/* Load the T list */
 	t_list_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_VERTEX_BUFFER);
 
-	t_offset = lp_build_const_int32(base->gallivm, input_index);
+	t_offset = lp_build_const_int32(gallivm, input_index);
 
 	t_list = build_indexed_load(si_shader_ctx, t_list_ptr, t_offset);
 
 	/* Build the attribute offset */
-	attribute_offset = lp_build_const_int32(base->gallivm, 0);
+	attribute_offset = lp_build_const_int32(gallivm, 0);
 
 	if (divisor) {
 		/* Build index from instance ID, start instance and divisor */
@@ -190,34 +193,34 @@ static void declare_input_vs(
 	args[0] = t_list;
 	args[1] = attribute_offset;
 	args[2] = buffer_index;
-	input = build_intrinsic(base->gallivm->builder,
+	input = build_intrinsic(gallivm->builder,
 		"llvm.SI.vs.load.input", vec4_type, args, 3,
 		LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
 
 	/* Break up the vec4 into individual components */
 	for (chan = 0; chan < 4; chan++) {
-		LLVMValueRef llvm_chan = lp_build_const_int32(base->gallivm, chan);
+		LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan);
 		/* XXX: Use a helper function for this.  There is one in
  		 * tgsi_llvm.c. */
 		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, chan)] =
-				LLVMBuildExtractElement(base->gallivm->builder,
+				LLVMBuildExtractElement(gallivm->builder,
 				input, llvm_chan, "");
 	}
 }
 
 static void declare_input_fs(
-	struct si_shader_context * si_shader_ctx,
+	struct radeon_llvm_context *radeon_bld,
 	unsigned input_index,
 	const struct tgsi_full_declaration *decl)
 {
+	struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
+	struct si_shader_context *si_shader_ctx =
+		si_shader_context(&radeon_bld->soa.bld_base);
 	struct si_shader *shader = &si_shader_ctx->shader->shader;
-	struct lp_build_context * base =
-				&si_shader_ctx->radeon_bld.soa.bld_base.base;
-	struct lp_build_context *uint =
-				&si_shader_ctx->radeon_bld.soa.bld_base.uint_bld;
-	struct gallivm_state * gallivm = base->gallivm;
+	struct lp_build_context *uint =	&radeon_bld->soa.bld_base.uint_bld;
+	struct gallivm_state *gallivm = base->gallivm;
 	LLVMTypeRef input_type = LLVMFloatTypeInContext(gallivm->context);
-	LLVMValueRef main_fn = si_shader_ctx->radeon_bld.main_fn;
+	LLVMValueRef main_fn = radeon_bld->main_fn;
 
 	LLVMValueRef interp_param;
 	const char * intr_name;
@@ -229,7 +232,7 @@ static void declare_input_fs(
 	 * [32:16] ParamOffset
 	 *
 	 */
-	LLVMValueRef params = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_PRIM_MASK);
+	LLVMValueRef params = LLVMGetParam(main_fn, SI_PARAM_PRIM_MASK);
 	LLVMValueRef attr_number;
 
 	unsigned chan;
@@ -238,15 +241,15 @@ static void declare_input_fs(
 		for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
 			unsigned soa_index =
 				radeon_llvm_reg_index_soa(input_index, chan);
-			si_shader_ctx->radeon_bld.inputs[soa_index] =
+			radeon_bld->inputs[soa_index] =
 				LLVMGetParam(main_fn, SI_PARAM_POS_X_FLOAT + chan);
 
 			if (chan == 3)
 				/* RCP for fragcoord.w */
-				si_shader_ctx->radeon_bld.inputs[soa_index] =
+				radeon_bld->inputs[soa_index] =
 					LLVMBuildFDiv(gallivm->builder,
 						      lp_build_const_float(gallivm, 1.0f),
-						      si_shader_ctx->radeon_bld.inputs[soa_index],
+						      radeon_bld->inputs[soa_index],
 						      "");
 		}
 		return;
@@ -262,16 +265,16 @@ static void declare_input_fs(
 						 lp_build_const_float(gallivm, 0.0f),
 						 "");
 
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
 			LLVMBuildSelect(gallivm->builder,
 					is_face_positive,
 					lp_build_const_float(gallivm, 1.0f),
 					lp_build_const_float(gallivm, 0.0f),
 					"");
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
 			lp_build_const_float(gallivm, 0.0f);
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
 			lp_build_const_float(gallivm, 1.0f);
 
 		return;
@@ -339,16 +342,16 @@ static void declare_input_fs(
 
 			args[0] = llvm_chan;
 			args[1] = attr_number;
-			front = build_intrinsic(base->gallivm->builder, intr_name,
+			front = build_intrinsic(gallivm->builder, intr_name,
 						input_type, args, args[3] ? 4 : 3,
 						LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
 
 			args[1] = back_attr_number;
-			back = build_intrinsic(base->gallivm->builder, intr_name,
+			back = build_intrinsic(gallivm->builder, intr_name,
 					       input_type, args, args[3] ? 4 : 3,
 					       LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
 
-			si_shader_ctx->radeon_bld.inputs[soa_index] =
+			radeon_bld->inputs[soa_index] =
 				LLVMBuildSelect(gallivm->builder,
 						is_face_positive,
 						front,
@@ -364,14 +367,14 @@ static void declare_input_fs(
 		args[1] = attr_number;
 		args[2] = params;
 		args[3] = interp_param;
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
-			build_intrinsic(base->gallivm->builder, intr_name,
-						input_type, args, args[3] ? 4 : 3,
-						LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
+			build_intrinsic(gallivm->builder, intr_name,
+					input_type, args, args[3] ? 4 : 3,
+					LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
 			lp_build_const_float(gallivm, 0.0f);
-		si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
+		radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
 			lp_build_const_float(gallivm, 1.0f);
 	} else {
 		for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
@@ -382,30 +385,14 @@ static void declare_input_fs(
 			args[1] = attr_number;
 			args[2] = params;
 			args[3] = interp_param;
-			si_shader_ctx->radeon_bld.inputs[soa_index] =
-				build_intrinsic(base->gallivm->builder, intr_name,
+			radeon_bld->inputs[soa_index] =
+				build_intrinsic(gallivm->builder, intr_name,
 						input_type, args, args[3] ? 4 : 3,
 						LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
 		}
 	}
 }
 
-static void declare_input(
-	struct radeon_llvm_context * radeon_bld,
-	unsigned input_index,
-	const struct tgsi_full_declaration *decl)
-{
-	struct si_shader_context * si_shader_ctx =
-				si_shader_context(&radeon_bld->soa.bld_base);
-	if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) {
-		declare_input_vs(si_shader_ctx, input_index, decl);
-	} else if (si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT) {
-		declare_input_fs(si_shader_ctx, input_index, decl);
-	} else {
-		fprintf(stderr, "Warning: Unsupported shader type,\n");
-	}
-}
-
 static void declare_system_value(
 	struct radeon_llvm_context * radeon_bld,
 	unsigned index,
@@ -875,7 +862,34 @@ static void si_llvm_emit_streamout(struct si_shader_context *shader)
 }
 
 
-static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base)
+static int si_store_shader_io_attribs(struct si_shader *shader,
+				      struct tgsi_full_declaration *d)
+{
+	int i = -1;
+
+	switch (d->Declaration.File) {
+	case TGSI_FILE_INPUT:
+		i = shader->ninput++;
+		assert(i < Elements(shader->input));
+		shader->input[i].name = d->Semantic.Name;
+		shader->input[i].sid = d->Semantic.Index;
+		shader->input[i].interpolate = d->Interp.Interpolate;
+		shader->input[i].centroid = d->Interp.Centroid;
+		return -1;
+
+	case TGSI_FILE_OUTPUT:
+		i = shader->noutput++;
+		assert(i < Elements(shader->output));
+		shader->output[i].name = d->Semantic.Name;
+		shader->output[i].sid = d->Semantic.Index;
+		shader->output[i].interpolate = d->Interp.Interpolate;
+		break;
+	}
+
+	return i;
+}
+
+static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base)
 {
 	struct si_shader_context * si_shader_ctx = si_shader_context(bld_base);
 	struct si_shader * shader = &si_shader_ctx->shader->shader;
@@ -884,12 +898,11 @@ static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base)
 				&si_shader_ctx->radeon_bld.soa.bld_base.uint_bld;
 	struct tgsi_parse_context *parse = &si_shader_ctx->parse;
 	LLVMValueRef args[9];
-	LLVMValueRef last_args[9] = { 0 };
 	LLVMValueRef pos_args[4][9] = { { 0 } };
 	unsigned semantic_name;
 	unsigned param_count = 0;
-	int depth_index = -1, stencil_index = -1, psize_index = -1, edgeflag_index = -1;
-	int layer_index = -1;
+	unsigned pos_idx;
+	int psize_index = -1, edgeflag_index = -1, layer_index = -1;
 	int i;
 
 	if (si_shader_ctx->shader->selector->so.num_outputs) {
@@ -904,35 +917,12 @@ static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base)
 
 		tgsi_parse_token(parse);
 
-		if (parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_PROPERTY &&
-		    parse->FullToken.FullProperty.Property.PropertyName ==
-		    TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS)
-			shader->fs_write_all = TRUE;
-
 		if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION)
 			continue;
 
-		switch (d->Declaration.File) {
-		case TGSI_FILE_INPUT:
-			i = shader->ninput++;
-			assert(i < Elements(shader->input));
-			shader->input[i].name = d->Semantic.Name;
-			shader->input[i].sid = d->Semantic.Index;
-			shader->input[i].interpolate = d->Interp.Interpolate;
-			shader->input[i].centroid = d->Interp.Centroid;
-			continue;
-
-		case TGSI_FILE_OUTPUT:
-			i = shader->noutput++;
-			assert(i < Elements(shader->output));
-			shader->output[i].name = d->Semantic.Name;
-			shader->output[i].sid = d->Semantic.Index;
-			shader->output[i].interpolate = d->Interp.Interpolate;
-			break;
-
-		default:
+		i = si_store_shader_io_attribs(shader, d);
+		if (i < 0)
 			continue;
-		}
 
 		semantic_name = d->Semantic.Name;
 handle_semantic:
@@ -955,31 +945,13 @@ handle_semantic:
 				layer_index = index;
 				continue;
 			case TGSI_SEMANTIC_POSITION:
-				if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) {
-					target = V_008DFC_SQ_EXP_POS;
-					break;
-				} else {
-					depth_index = index;
-					continue;
-				}
-			case TGSI_SEMANTIC_STENCIL:
-				stencil_index = index;
-				continue;
+				target = V_008DFC_SQ_EXP_POS;
+				break;
 			case TGSI_SEMANTIC_COLOR:
-				if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) {
 			case TGSI_SEMANTIC_BCOLOR:
-					target = V_008DFC_SQ_EXP_PARAM + param_count;
-					shader->output[i].param_offset = param_count;
-					param_count++;
-				} else {
-					target = V_008DFC_SQ_EXP_MRT + shader->output[i].sid;
-					if (si_shader_ctx->shader->key.ps.alpha_to_one) {
-						si_alpha_to_one(bld_base, index);
-					}
-					if (shader->output[i].sid == 0 &&
-					    si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
-						si_alpha_test(bld_base, index);
-				}
+				target = V_008DFC_SQ_EXP_PARAM + param_count;
+				shader->output[i].param_offset = param_count;
+				param_count++;
 				break;
 			case TGSI_SEMANTIC_CLIPDIST:
 				if (!(si_shader_ctx->shader->key.vs.ucps_enabled &
@@ -1001,19 +973,170 @@ handle_semantic:
 			default:
 				target = 0;
 				fprintf(stderr,
-					"Warning: SI unhandled output type:%d\n",
+					"Warning: SI unhandled vs output type:%d\n",
 					semantic_name);
 			}
 
 			si_llvm_init_export_args(bld_base, d, index, target, args);
 
-			if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX &&
-			    target >= V_008DFC_SQ_EXP_POS &&
+			if (target >= V_008DFC_SQ_EXP_POS &&
 			    target <= (V_008DFC_SQ_EXP_POS + 3)) {
 				memcpy(pos_args[target - V_008DFC_SQ_EXP_POS],
 				       args, sizeof(args));
-			} else if (si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT &&
-				   semantic_name == TGSI_SEMANTIC_COLOR) {
+			} else {
+				lp_build_intrinsic(base->gallivm->builder,
+						   "llvm.SI.export",
+						   LLVMVoidTypeInContext(base->gallivm->context),
+						   args, 9);
+			}
+		}
+
+		if (semantic_name == TGSI_SEMANTIC_CLIPDIST) {
+			semantic_name = TGSI_SEMANTIC_GENERIC;
+			goto handle_semantic;
+		}
+	}
+
+	/* We need to add the position output manually if it's missing. */
+	if (!pos_args[0][0]) {
+		pos_args[0][0] = lp_build_const_int32(base->gallivm, 0xf); /* writemask */
+		pos_args[0][1] = uint->zero; /* EXEC mask */
+		pos_args[0][2] = uint->zero; /* last export? */
+		pos_args[0][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS);
+		pos_args[0][4] = uint->zero; /* COMPR flag */
+		pos_args[0][5] = base->zero; /* X */
+		pos_args[0][6] = base->zero; /* Y */
+		pos_args[0][7] = base->zero; /* Z */
+		pos_args[0][8] = base->one;  /* W */
+	}
+
+	/* Write the misc vector (point size, edgeflag, layer, viewport). */
+	if (shader->vs_out_misc_write) {
+		pos_args[1][0] = lp_build_const_int32(base->gallivm, /* writemask */
+						      shader->vs_out_point_size |
+						      (shader->vs_out_edgeflag << 1) |
+						      (shader->vs_out_layer << 2));
+		pos_args[1][1] = uint->zero; /* EXEC mask */
+		pos_args[1][2] = uint->zero; /* last export? */
+		pos_args[1][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + 1);
+		pos_args[1][4] = uint->zero; /* COMPR flag */
+		pos_args[1][5] = base->zero; /* X */
+		pos_args[1][6] = base->zero; /* Y */
+		pos_args[1][7] = base->zero; /* Z */
+		pos_args[1][8] = base->zero; /* W */
+
+		if (shader->vs_out_point_size) {
+			pos_args[1][5] = LLVMBuildLoad(base->gallivm->builder,
+				si_shader_ctx->radeon_bld.soa.outputs[psize_index][0], "");
+		}
+
+		if (shader->vs_out_edgeflag) {
+			LLVMValueRef output = LLVMBuildLoad(base->gallivm->builder,
+				si_shader_ctx->radeon_bld.soa.outputs[edgeflag_index][0], "");
+
+			/* The output is a float, but the hw expects an integer
+			 * with the first bit containing the edge flag. */
+			output = LLVMBuildFPToUI(base->gallivm->builder, output,
+						 bld_base->uint_bld.elem_type, "");
+
+			output = lp_build_min(&bld_base->int_bld, output, bld_base->int_bld.one);
+
+			/* The LLVM intrinsic expects a float. */
+			pos_args[1][6] = LLVMBuildBitCast(base->gallivm->builder, output,
+							  base->elem_type, "");
+		}
+
+		if (shader->vs_out_layer) {
+			pos_args[1][7] = LLVMBuildLoad(base->gallivm->builder,
+				si_shader_ctx->radeon_bld.soa.outputs[layer_index][0], "");
+		}
+	}
+
+	for (i = 0; i < 4; i++)
+		if (pos_args[i][0])
+			shader->nr_pos_exports++;
+
+	pos_idx = 0;
+	for (i = 0; i < 4; i++) {
+		if (!pos_args[i][0])
+			continue;
+
+		/* Specify the target we are exporting */
+		pos_args[i][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + pos_idx++);
+
+		if (pos_idx == shader->nr_pos_exports)
+			/* Specify that this is the last export */
+			pos_args[i][2] = uint->one;
+
+		lp_build_intrinsic(base->gallivm->builder,
+				   "llvm.SI.export",
+				   LLVMVoidTypeInContext(base->gallivm->context),
+				   pos_args[i], 9);
+	}
+}
+
+static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base)
+{
+	struct si_shader_context * si_shader_ctx = si_shader_context(bld_base);
+	struct si_shader * shader = &si_shader_ctx->shader->shader;
+	struct lp_build_context * base = &bld_base->base;
+	struct lp_build_context * uint =
+				&si_shader_ctx->radeon_bld.soa.bld_base.uint_bld;
+	struct tgsi_parse_context *parse = &si_shader_ctx->parse;
+	LLVMValueRef args[9];
+	LLVMValueRef last_args[9] = { 0 };
+	unsigned semantic_name;
+	int depth_index = -1, stencil_index = -1;
+	int i;
+
+	while (!tgsi_parse_end_of_tokens(parse)) {
+		struct tgsi_full_declaration *d =
+					&parse->FullToken.FullDeclaration;
+		unsigned target;
+		unsigned index;
+
+		tgsi_parse_token(parse);
+
+		if (parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_PROPERTY &&
+		    parse->FullToken.FullProperty.Property.PropertyName ==
+		    TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS)
+			shader->fs_write_all = TRUE;
+
+		if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION)
+			continue;
+
+		i = si_store_shader_io_attribs(shader, d);
+		if (i < 0)
+			continue;
+
+		semantic_name = d->Semantic.Name;
+		for (index = d->Range.First; index <= d->Range.Last; index++) {
+			/* Select the correct target */
+			switch(semantic_name) {
+			case TGSI_SEMANTIC_POSITION:
+				depth_index = index;
+				continue;
+			case TGSI_SEMANTIC_STENCIL:
+				stencil_index = index;
+				continue;
+			case TGSI_SEMANTIC_COLOR:
+				target = V_008DFC_SQ_EXP_MRT + d->Semantic.Index;
+				if (si_shader_ctx->shader->key.ps.alpha_to_one)
+					si_alpha_to_one(bld_base, index);
+				if (d->Semantic.Index == 0 &&
+				    si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
+					si_alpha_test(bld_base, index);
+				break;
+			default:
+				target = 0;
+				fprintf(stderr,
+					"Warning: SI unhandled fs output type:%d\n",
+					semantic_name);
+			}
+
+			si_llvm_init_export_args(bld_base, d, index, target, args);
+
+			if (semantic_name == TGSI_SEMANTIC_COLOR) {
 				/* If there is an export instruction waiting to be emitted, do so now. */
 				if (last_args[0]) {
 					lp_build_intrinsic(base->gallivm->builder,
@@ -1044,11 +1167,6 @@ handle_semantic:
 						   args, 9);
 			}
 		}
-
-		if (semantic_name == TGSI_SEMANTIC_CLIPDIST) {
-			semantic_name = TGSI_SEMANTIC_GENERIC;
-			goto handle_semantic;
-		}
 	}
 
 	if (depth_index >= 0 || stencil_index >= 0) {
@@ -1100,117 +1218,37 @@ handle_semantic:
 			memcpy(last_args, args, sizeof(args));
 	}
 
-	if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) {
-		unsigned pos_idx = 0;
-
-		/* We need to add the position output manually if it's missing. */
-		if (!pos_args[0][0]) {
-			pos_args[0][0] = lp_build_const_int32(base->gallivm, 0xf); /* writemask */
-			pos_args[0][1] = uint->zero; /* EXEC mask */
-			pos_args[0][2] = uint->zero; /* last export? */
-			pos_args[0][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS);
-			pos_args[0][4] = uint->zero; /* COMPR flag */
-			pos_args[0][5] = base->zero; /* X */
-			pos_args[0][6] = base->zero; /* Y */
-			pos_args[0][7] = base->zero; /* Z */
-			pos_args[0][8] = base->one;  /* W */
-		}
-
-		/* Write the misc vector (point size, edgeflag, layer, viewport). */
-		if (shader->vs_out_misc_write) {
-			pos_args[1][0] = lp_build_const_int32(base->gallivm, /* writemask */
-							      shader->vs_out_point_size |
-							      (shader->vs_out_edgeflag << 1) |
-							      (shader->vs_out_layer << 2));
-			pos_args[1][1] = uint->zero; /* EXEC mask */
-			pos_args[1][2] = uint->zero; /* last export? */
-			pos_args[1][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + 1);
-			pos_args[1][4] = uint->zero; /* COMPR flag */
-			pos_args[1][5] = base->zero; /* X */
-			pos_args[1][6] = base->zero; /* Y */
-			pos_args[1][7] = base->zero; /* Z */
-			pos_args[1][8] = base->zero; /* W */
-
-			if (shader->vs_out_point_size) {
-				pos_args[1][5] = LLVMBuildLoad(base->gallivm->builder,
-					si_shader_ctx->radeon_bld.soa.outputs[psize_index][0], "");
-			}
-
-			if (shader->vs_out_edgeflag) {
-				LLVMValueRef output = LLVMBuildLoad(base->gallivm->builder,
-					si_shader_ctx->radeon_bld.soa.outputs[edgeflag_index][0], "");
-
-				/* The output is a float, but the hw expects an integer
-				 * with the first bit containing the edge flag. */
-				output = LLVMBuildFPToUI(base->gallivm->builder, output,
-							 bld_base->uint_bld.elem_type, "");
-
-				output = lp_build_min(&bld_base->int_bld, output, bld_base->int_bld.one);
-
-				/* The LLVM intrinsic expects a float. */
-				pos_args[1][6] = LLVMBuildBitCast(base->gallivm->builder, output,
-								  base->elem_type, "");
-			}
-
-			if (shader->vs_out_layer) {
-				pos_args[1][7] = LLVMBuildLoad(base->gallivm->builder,
-					si_shader_ctx->radeon_bld.soa.outputs[layer_index][0], "");
-			}
-		}
-
-		for (i = 0; i < 4; i++)
-			if (pos_args[i][0])
-				shader->nr_pos_exports++;
-
-		for (i = 0; i < 4; i++) {
-			if (!pos_args[i][0])
-				continue;
-
-			/* Specify the target we are exporting */
-			pos_args[i][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + pos_idx++);
-
-			if (pos_idx == shader->nr_pos_exports)
-				/* Specify that this is the last export */
-				pos_args[i][2] = uint->one;
-
-			lp_build_intrinsic(base->gallivm->builder,
-					   "llvm.SI.export",
-					   LLVMVoidTypeInContext(base->gallivm->context),
-					   pos_args[i], 9);
-		}
-	} else {
-		if (!last_args[0]) {
-			/* Specify which components to enable */
-			last_args[0] = lp_build_const_int32(base->gallivm, 0x0);
+	if (!last_args[0]) {
+		/* Specify which components to enable */
+		last_args[0] = lp_build_const_int32(base->gallivm, 0x0);
 
-			/* Specify the target we are exporting */
-			last_args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRT);
+		/* Specify the target we are exporting */
+		last_args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRT);
 
-			/* Set COMPR flag to zero to export data as 32-bit */
-			last_args[4] = uint->zero;
+		/* Set COMPR flag to zero to export data as 32-bit */
+		last_args[4] = uint->zero;
 
-			/* dummy bits */
-			last_args[5]= uint->zero;
-			last_args[6]= uint->zero;
-			last_args[7]= uint->zero;
-			last_args[8]= uint->zero;
+		/* dummy bits */
+		last_args[5]= uint->zero;
+		last_args[6]= uint->zero;
+		last_args[7]= uint->zero;
+		last_args[8]= uint->zero;
 
-			si_shader_ctx->shader->spi_shader_col_format |=
-				V_028714_SPI_SHADER_32_ABGR;
-			si_shader_ctx->shader->cb_shader_mask |= S_02823C_OUTPUT0_ENABLE(0xf);
-		}
+		si_shader_ctx->shader->spi_shader_col_format |=
+			V_028714_SPI_SHADER_32_ABGR;
+		si_shader_ctx->shader->cb_shader_mask |= S_02823C_OUTPUT0_ENABLE(0xf);
+	}
 
-		/* Specify whether the EXEC mask represents the valid mask */
-		last_args[1] = uint->one;
+	/* Specify whether the EXEC mask represents the valid mask */
+	last_args[1] = uint->one;
 
-		/* Specify that this is the last export */
-		last_args[2] = lp_build_const_int32(base->gallivm, 1);
+	/* Specify that this is the last export */
+	last_args[2] = lp_build_const_int32(base->gallivm, 1);
 
-		lp_build_intrinsic(base->gallivm->builder,
-				   "llvm.SI.export",
-				   LLVMVoidTypeInContext(base->gallivm->context),
-				   last_args, 9);
-	}
+	lp_build_intrinsic(base->gallivm->builder,
+			   "llvm.SI.export",
+			   LLVMVoidTypeInContext(base->gallivm->context),
+			   last_args, 9);
 }
 
 static const struct lp_build_tgsi_action txf_action;
@@ -1990,7 +2028,6 @@ int si_pipe_shader_create(
 	shader->shader.uses_instanceid = shader_info.uses_instanceid;
 	bld_base->info = &shader_info;
 	bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = fetch_constant;
-	bld_base->emit_epilogue = si_llvm_emit_epilogue;
 
 	bld_base->op_actions[TGSI_OPCODE_TEX] = tex_action;
 	bld_base->op_actions[TGSI_OPCODE_TXB] = txb_action;
@@ -2007,13 +2044,26 @@ int si_pipe_shader_create(
 	bld_base->op_actions[TGSI_OPCODE_DDY].emit = si_llvm_emit_ddxy;
 #endif
 
-	si_shader_ctx.radeon_bld.load_input = declare_input;
 	si_shader_ctx.radeon_bld.load_system_value = declare_system_value;
 	si_shader_ctx.tokens = sel->tokens;
 	tgsi_parse_init(&si_shader_ctx.parse, si_shader_ctx.tokens);
 	si_shader_ctx.shader = shader;
 	si_shader_ctx.type = si_shader_ctx.parse.FullHeader.Processor.Processor;
 
+	switch (si_shader_ctx.type) {
+	case TGSI_PROCESSOR_VERTEX:
+		si_shader_ctx.radeon_bld.load_input = declare_input_vs;
+		bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
+		break;
+	case TGSI_PROCESSOR_FRAGMENT:
+		si_shader_ctx.radeon_bld.load_input = declare_input_fs;
+		bld_base->emit_epilogue = si_llvm_emit_fs_epilogue;
+		break;
+	default:
+		assert(!"Unsupported shader type");
+		return -1;
+	}
+
 	create_meta_data(&si_shader_ctx);
 	create_function(&si_shader_ctx);
 	preload_constants(&si_shader_ctx);
-- 
1.8.5.3



More information about the mesa-dev mailing list