[Mesa-dev] [PATCH] r600g: tgsi-to-llvm generates interpolation intrinsics

Vincent Lejeune vljn at ovi.com
Wed Sep 19 05:55:48 PDT 2012


---
 src/gallium/drivers/r600/r600_llvm.c     | 118 ++++++++++++++++++-
 src/gallium/drivers/r600/r600_shader.c   | 192 +++++++++++++++----------------
 src/gallium/drivers/r600/r600_shader.h   |  38 ++++++
 src/gallium/drivers/radeon/radeon_llvm.h |   9 +-
 4 files changed, 255 insertions(+), 102 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_llvm.c b/src/gallium/drivers/r600/r600_llvm.c
index e77758b..d78fb63 100644
--- a/src/gallium/drivers/r600/r600_llvm.c
+++ b/src/gallium/drivers/r600/r600_llvm.c
@@ -16,7 +16,7 @@
 
 #include <stdio.h>
 
-#if defined R600_USE_LLVM || defined HAVE_OPENCL
+#if 1//defined R600_USE_LLVM || defined HAVE_OPENCL
 
 static LLVMValueRef llvm_fetch_const(
 	struct lp_build_tgsi_context * bld_base,
@@ -66,7 +66,7 @@ static LLVMValueRef llvm_fetch_system_value(
 	return bitcast(bld_base, type, cval);
 }
 
-static void llvm_load_input(
+static void llvm_load_input_pre_evergreen(
 	struct radeon_llvm_context * ctx,
 	unsigned input_index,
 	const struct tgsi_full_declaration *decl)
@@ -89,6 +89,115 @@ static void llvm_load_input(
 	}
 }
 
+static void llvm_load_input_evergreen(
+	struct radeon_llvm_context * ctx,
+	unsigned input_index,
+	const struct tgsi_full_declaration *decl)
+{
+	unsigned chan;
+	const char * intr_name;
+
+	for (chan = 0; chan < 4; chan++) {
+		unsigned soa_index = radeon_llvm_reg_index_soa(input_index,
+	                                               chan);
+
+		int reg_index = 0;
+	
+		if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
+			if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
+				intr_name = "llvm.AMDGPU.load.input.position";
+				reg_index = ctx->reserved_reg_count * 4 + chan;
+			} else if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
+				LLVMValueRef reg = lp_build_const_int32(
+				ctx->soa.bld_base.base.gallivm,
+				ctx->tgsi_inputs[input_index].gpr * 4);
+				LLVMValueRef face = build_intrinsic(
+				   ctx->soa.bld_base.base.gallivm->builder,
+				   "llvm.AMDGPU.load.input.face",
+				   LLVMInt1TypeInContext(ctx->soa.bld_base.base.gallivm->context),
+				   &reg, 1,
+				   LLVMReadNoneAttribute);
+				LLVMValueRef one = lp_build_const_float(
+				   ctx->soa.bld_base.base.gallivm,
+				   1.0f);
+				LLVMValueRef minus_one = lp_build_const_float(
+				   ctx->soa.bld_base.base.gallivm,
+				   -1.0f);
+				ctx->inputs[soa_index] = LLVMBuildSelect(
+				   ctx->soa.bld_base.base.gallivm->builder,
+				   face,
+				   one, minus_one, "");
+				continue;
+			} else {
+				reg_index = ctx->first_lds ++;
+				switch (decl->Interp.Interpolate) {
+				case TGSI_INTERPOLATE_COLOR:
+					intr_name = "llvm.AMDGPU.load.input.perspective";
+					break;
+				case TGSI_INTERPOLATE_CONSTANT:
+					intr_name = "llvm.AMDGPU.load.input.constant";
+					break;
+				case TGSI_INTERPOLATE_LINEAR:
+					intr_name = "llvm.AMDGPU.load.input.linear";
+					break;
+				case TGSI_INTERPOLATE_PERSPECTIVE:
+					intr_name = "llvm.AMDGPU.load.input.perspective";
+					break;
+				default:
+					fprintf(stderr, "Warning: Unhandled interpolation mode.\n");
+					return;
+				}
+			}
+		} else {
+			reg_index = ctx->reserved_reg_count * 4 + soa_index;
+			intr_name = "llvm.R600.load.input";
+		}
+	
+	
+		/* The * 4 is assuming that we are in soa mode. */
+		LLVMValueRef reg = lp_build_const_int32(
+		   ctx->soa.bld_base.base.gallivm,
+		   reg_index);
+	
+		ctx->inputs[soa_index] = build_intrinsic(
+		   ctx->soa.bld_base.base.gallivm->builder,
+		   intr_name,
+		   ctx->soa.bld_base.base.elem_type, &reg, 1,
+		   LLVMReadNoneAttribute);
+	}
+   
+	if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR && ctx->two_side) {
+		for (chan = 0; chan < 4; chan++) {
+			unsigned soa_index = radeon_llvm_reg_index_soa(input_index,
+			   chan);
+			LLVMValueRef backcolor_reg = lp_build_const_int32(
+			   ctx->soa.bld_base.base.gallivm,
+			   ctx->last_lds * 4 + chan);
+			LLVMValueRef backcolor = build_intrinsic(
+			   ctx->soa.bld_base.base.gallivm->builder,
+			   intr_name,
+			   ctx->soa.bld_base.base.elem_type, &backcolor_reg, 1,
+			   LLVMReadNoneAttribute);
+			LLVMValueRef face_reg = lp_build_const_int32(
+			   ctx->soa.bld_base.base.gallivm,
+			   ctx->face_input * 4);
+			LLVMValueRef face = build_intrinsic(
+			   ctx->soa.bld_base.base.gallivm->builder,
+			   "llvm.AMDGPU.load.input.face",
+			   LLVMInt1TypeInContext(ctx->soa.bld_base.base.gallivm->context),
+			   &face_reg, 1,
+			   LLVMReadNoneAttribute);
+			ctx->inputs[soa_index] = LLVMBuildSelect(
+			   ctx->soa.bld_base.base.gallivm->builder,
+			   face,
+			   ctx->inputs[soa_index],
+			   backcolor,
+			   "");
+		}
+		ctx->last_lds++;
+	}
+}
+
 static void llvm_emit_prologue(struct lp_build_tgsi_context * bld_base)
 {
 	struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
@@ -225,7 +334,10 @@ LLVMModuleRef r600_tgsi_llvm(
 	bld_base->emit_prologue = llvm_emit_prologue;
 	bld_base->emit_epilogue = llvm_emit_epilogue;
 	ctx->userdata = ctx;
-	ctx->load_input = llvm_load_input;
+	if (ctx->chip_class == EVERGREEN || ctx->chip_class == CAYMAN)
+		ctx->load_input = llvm_load_input_evergreen;
+	else
+		ctx->load_input = llvm_load_input_pre_evergreen;	
 	ctx->load_system_value = llvm_load_system_value;
 
 	bld_base->op_actions[TGSI_OPCODE_DP2] = dot_action;
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 3e79764..a860604 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -28,8 +28,6 @@
 
 #include "pipe/p_shader_tokens.h"
 #include "tgsi/tgsi_info.h"
-#include "tgsi/tgsi_parse.h"
-#include "tgsi/tgsi_scan.h"
 #include "tgsi/tgsi_dump.h"
 #include "util/u_memory.h"
 #include <stdio.h>
@@ -164,42 +162,6 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader
  */
 struct r600_shader_tgsi_instruction;
 
-struct r600_shader_src {
-	unsigned				sel;
-	unsigned				swizzle[4];
-	unsigned				neg;
-	unsigned				abs;
-	unsigned				rel;
-	uint32_t				value[4];
-};
-
-struct r600_shader_ctx {
-	struct tgsi_shader_info			info;
-	struct tgsi_parse_context		parse;
-	const struct tgsi_token			*tokens;
-	unsigned				type;
-	unsigned				file_offset[TGSI_FILE_COUNT];
-	unsigned				temp_reg;
-	struct r600_shader_tgsi_instruction	*inst_info;
-	struct r600_bytecode			*bc;
-	struct r600_shader			*shader;
-	struct r600_shader_src			src[4];
-	uint32_t				*literals;
-	uint32_t				nliterals;
-	uint32_t				max_driver_temp_used;
-	/* needed for evergreen interpolation */
-	boolean                                 input_centroid;
-	boolean                                 input_linear;
-	boolean                                 input_perspective;
-	int					num_interp_gpr;
-	int					face_gpr;
-	int					colors_used;
-	boolean                 clip_vertex_write;
-	unsigned                cv_output;
-	int					fragcoord_input;
-	int					native_integers;
-};
-
 struct r600_shader_tgsi_instruction {
 	unsigned	tgsi_opcode;
 	unsigned	is_op3;
@@ -317,6 +279,21 @@ static unsigned r600_alu_from_byte_stream(struct r600_shader_ctx *ctx,
 	alu.bank_swizzle_force = bytes[bytes_read++];
 	alu.omod = bytes[bytes_read++];
 	alu.index_mode = bytes[bytes_read++];
+	
+	if (alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_XY)
+	{
+	  alu.src[1].sel += 448;
+	  alu.bank_swizzle_force = SQ_ALU_VEC_210;
+	}
+	
+	if( alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_ZW) {
+  	   alu.src[1].sel += 448;
+	   alu.bank_swizzle_force = SQ_ALU_VEC_210;
+	}
+	
+	if (alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_LOAD_P0) {
+	   alu.src[0].sel += 448;
+	}
 
 
 	if (alu.inst == CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE) ||
@@ -741,16 +718,18 @@ static int r600_spi_sid(struct r600_shader_io * io)
 };
 
 /* turn input into interpolate on EG */
-static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index)
+static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index, unsigned use_llvm)
 {
 	int r = 0;
 
 	if (ctx->shader->input[index].spi_sid) {
 		ctx->shader->input[index].lds_pos = ctx->shader->nlds++;
-		if (ctx->shader->input[index].interpolate > 0) {
-			r = evergreen_interp_alu(ctx, index);
-		} else {
-			r = evergreen_interp_flat(ctx, index);
+		if (!use_llvm) {
+			if (ctx->shader->input[index].interpolate > 0) {
+				r = evergreen_interp_alu(ctx, index);
+			} else {
+				r = evergreen_interp_flat(ctx, index);
+			}
 		}
 	}
 	return r;
@@ -785,7 +764,7 @@ static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int back
 	return 0;
 }
 
-static int tgsi_declaration(struct r600_shader_ctx *ctx)
+static int tgsi_declaration(struct r600_shader_ctx *ctx, unsigned use_llvm)
 {
 	struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration;
 	unsigned i;
@@ -813,7 +792,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
 				break;
 			}
 			if (ctx->bc->chip_class >= EVERGREEN) {
-				if ((r = evergreen_interp_input(ctx, i)))
+				if ((r = evergreen_interp_input(ctx, i, use_llvm)))
 					return r;
 			}
 		}
@@ -1119,7 +1098,7 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx)
 	return 0;
 }
 
-static int process_twoside_color_inputs(struct r600_shader_ctx *ctx)
+static int process_twoside_color_inputs(struct r600_shader_ctx *ctx, unsigned use_llvm)
 {
 	int i, r, count = ctx->shader->ninput;
 
@@ -1146,15 +1125,17 @@ static int process_twoside_color_inputs(struct r600_shader_ctx *ctx)
 			ctx->shader->input[ni].spi_sid = r600_spi_sid(&ctx->shader->input[ni]);
 			ctx->shader->input[ni].gpr = gpr++;
 
-			if (ctx->bc->chip_class >= EVERGREEN) {
-				r = evergreen_interp_input(ctx, ni);
+			if (!use_llvm) {
+				if (ctx->bc->chip_class >= EVERGREEN) {
+					r = evergreen_interp_input(ctx, ni, use_llvm);
+					if (r)
+						return r;
+				}
+
+				r = select_twoside_color(ctx, i, ni);
 				if (r)
 					return r;
 			}
-
-			r = select_twoside_color(ctx, i, ni);
-			if (r)
-				return r;
 		}
 	}
 	return 0;
@@ -1239,7 +1220,6 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh
 		ctx.file_offset[TGSI_FILE_INPUT] = evergreen_gpr_count(&ctx);
 	}
 
-	/* LLVM backend setup */
 #ifdef R600_USE_LLVM
 	if (use_llvm && ctx.info.indirect_files) {
 		fprintf(stderr, "Warning: R600 LLVM backend does not support "
@@ -1247,34 +1227,13 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh
 				"backend.\n");
 		use_llvm = 0;
 	}
-	if (use_llvm) {
-		struct radeon_llvm_context radeon_llvm_ctx;
-		LLVMModuleRef mod;
-		unsigned dump = 0;
-		memset(&radeon_llvm_ctx, 0, sizeof(radeon_llvm_ctx));
-		radeon_llvm_ctx.reserved_reg_count = ctx.file_offset[TGSI_FILE_INPUT];
-		mod = r600_tgsi_llvm(&radeon_llvm_ctx, tokens);
-		if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE)) {
-			dump = 1;
-		}
-		if (r600_llvm_compile(mod, &inst_bytes, &inst_byte_count,
-							rctx->family, dump)) {
-			FREE(inst_bytes);
-			radeon_llvm_dispose(&radeon_llvm_ctx);
-			use_llvm = 0;
-			fprintf(stderr, "R600 LLVM backend failed to compile "
-				"shader.  Falling back to TGSI\n");
-		} else {
-			ctx.file_offset[TGSI_FILE_OUTPUT] =
-					ctx.file_offset[TGSI_FILE_INPUT];
-		}
-		radeon_llvm_dispose(&radeon_llvm_ctx);
-	}
 #endif
-	/* End of LLVM backend setup */
 
-	if (!use_llvm) {
+	if (use_llvm) {
 		ctx.file_offset[TGSI_FILE_OUTPUT] =
+			ctx.file_offset[TGSI_FILE_INPUT];
+	} else {
+	   ctx.file_offset[TGSI_FILE_OUTPUT] =
 			ctx.file_offset[TGSI_FILE_INPUT] +
 			ctx.info.file_max[TGSI_FILE_INPUT] + 1;
 	}
@@ -1310,7 +1269,7 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh
 			ctx.nliterals++;
 			break;
 		case TGSI_TOKEN_TYPE_DECLARATION:
-			r = tgsi_declaration(&ctx);
+			r = tgsi_declaration(&ctx, use_llvm);
 			if (r)
 				goto out_err;
 			break;
@@ -1336,12 +1295,62 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh
 		}
 	}
 
+/* LLVM backend setup */
+#ifdef R600_USE_LLVM
+	if (use_llvm) {
+		struct radeon_llvm_context radeon_llvm_ctx;
+		LLVMModuleRef mod;
+		unsigned dump = 0;
+		memset(&radeon_llvm_ctx, 0, sizeof(radeon_llvm_ctx));
+		radeon_llvm_ctx.reserved_reg_count = ctx.file_offset[TGSI_FILE_INPUT];
+		radeon_llvm_ctx.type = ctx.type;
+		radeon_llvm_ctx.two_side = shader->two_side;
+		radeon_llvm_ctx.face_input = (ctx.face_gpr>=0)?ctx.face_gpr:(ctx.file_offset[TGSI_FILE_INPUT] +
+		                                                              ctx.info.file_max[TGSI_FILE_INPUT] + 1);
+		radeon_llvm_ctx.tgsi_inputs = ctx.shader->input;
+		radeon_llvm_ctx.last_lds = ctx.shader->nlds;
+		radeon_llvm_ctx.chip_class = ctx.bc->chip_class;
+		mod = r600_tgsi_llvm(&radeon_llvm_ctx, tokens);
+		if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE)) {
+			dump = 1;
+		}
+		if (r600_llvm_compile(mod, &inst_bytes, &inst_byte_count,
+							rctx->family, dump)) {
+			FREE(inst_bytes);
+			radeon_llvm_dispose(&radeon_llvm_ctx);
+			use_llvm = 0;
+			fprintf(stderr, "R600 LLVM backend failed to compile "
+				"shader.  Falling back to TGSI\n");
+		} else {
+			ctx.file_offset[TGSI_FILE_OUTPUT] =
+					ctx.file_offset[TGSI_FILE_INPUT];
+		}
+		radeon_llvm_dispose(&radeon_llvm_ctx);
+	}
+#endif
+/* End of LLVM backend setup */
+
 	if (shader->fs_write_all && rctx->chip_class >= EVERGREEN)
 		shader->nr_ps_max_color_exports = 8;
 
-	if (ctx.fragcoord_input >= 0) {
-		if (ctx.bc->chip_class == CAYMAN) {
-			for (j = 0 ; j < 4; j++) {
+	if (!use_llvm) {
+		if (ctx.fragcoord_input >= 0) {
+			if (ctx.bc->chip_class == CAYMAN) {
+				for (j = 0 ; j < 4; j++) {
+					struct r600_bytecode_alu alu;
+					memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+					alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE);
+					alu.src[0].sel = shader->input[ctx.fragcoord_input].gpr;
+					alu.src[0].chan = 3;
+
+					alu.dst.sel = shader->input[ctx.fragcoord_input].gpr;
+					alu.dst.chan = j;
+					alu.dst.write = (j == 3);
+					alu.last = 1;
+					if ((r = r600_bytecode_add_alu(ctx.bc, &alu)))
+						return r;
+				}
+			} else {
 				struct r600_bytecode_alu alu;
 				memset(&alu, 0, sizeof(struct r600_bytecode_alu));
 				alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE);
@@ -1349,30 +1358,17 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh
 				alu.src[0].chan = 3;
 
 				alu.dst.sel = shader->input[ctx.fragcoord_input].gpr;
-				alu.dst.chan = j;
-				alu.dst.write = (j == 3);
+				alu.dst.chan = 3;
+				alu.dst.write = 1;
 				alu.last = 1;
 				if ((r = r600_bytecode_add_alu(ctx.bc, &alu)))
 					return r;
 			}
-		} else {
-			struct r600_bytecode_alu alu;
-			memset(&alu, 0, sizeof(struct r600_bytecode_alu));
-			alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE);
-			alu.src[0].sel = shader->input[ctx.fragcoord_input].gpr;
-			alu.src[0].chan = 3;
-
-			alu.dst.sel = shader->input[ctx.fragcoord_input].gpr;
-			alu.dst.chan = 3;
-			alu.dst.write = 1;
-			alu.last = 1;
-			if ((r = r600_bytecode_add_alu(ctx.bc, &alu)))
-				return r;
 		}
 	}
 
 	if (shader->two_side && ctx.colors_used) {
-		if ((r = process_twoside_color_inputs(&ctx)))
+		if ((r = process_twoside_color_inputs(&ctx, use_llvm)))
 			return r;
 	}
 
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index eb0bbf6..8f70241 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -24,6 +24,44 @@
 #define R600_SHADER_H
 
 #include "r600_asm.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+
+struct r600_shader_src {
+	unsigned				sel;
+	unsigned				swizzle[4];
+	unsigned				neg;
+	unsigned				abs;
+	unsigned				rel;
+	uint32_t				value[4];
+};
+
+struct r600_shader_ctx {
+	struct tgsi_shader_info			info;
+	struct tgsi_parse_context		parse;
+	const struct tgsi_token			*tokens;
+	unsigned				type;
+	unsigned				file_offset[TGSI_FILE_COUNT];
+	unsigned				temp_reg;
+	struct r600_shader_tgsi_instruction	*inst_info;
+	struct r600_bytecode			*bc;
+	struct r600_shader			*shader;
+	struct r600_shader_src			src[4];
+	uint32_t				*literals;
+	uint32_t				nliterals;
+	uint32_t				max_driver_temp_used;
+	/* needed for evergreen interpolation */
+	boolean                                 input_centroid;
+	boolean                                 input_linear;
+	boolean                                 input_perspective;
+	int					num_interp_gpr;
+	int					face_gpr;
+	int					colors_used;
+	boolean                 clip_vertex_write;
+	unsigned                cv_output;
+	int					fragcoord_input;
+	int					native_integers;
+};
 
 struct r600_shader_io {
 	unsigned		name;
diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h
index 7a32bb0..c1d8aaa 100644
--- a/src/gallium/drivers/radeon/radeon_llvm.h
+++ b/src/gallium/drivers/radeon/radeon_llvm.h
@@ -51,8 +51,15 @@ struct radeon_llvm_loop {
 };
 
 struct radeon_llvm_context {
-
+	unsigned chip_class;
 	struct lp_build_tgsi_soa_context soa;
+	unsigned type;
+	unsigned fragcoord_input;
+	unsigned face_input;
+	unsigned two_side;
+	unsigned last_lds;
+	unsigned first_lds;
+	struct r600_shader_io * tgsi_inputs;
 
 	/*=== Front end configuration ===*/
 
-- 
1.7.11.4



More information about the mesa-dev mailing list