[Mesa-dev] [PATCH 02/10] radeonsi: communicate cube map coordinates more explicitly

Nicolai Hähnle nhaehnle at gmail.com
Tue Jan 10 15:12:14 UTC 2017


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

---
 src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c | 76 +++++++++++++----------
 1 file changed, 43 insertions(+), 33 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c
index 277ed5b..c0d7220 100644
--- a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c
+++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c
@@ -900,88 +900,98 @@ void si_shader_context_init_alu(struct lp_build_tgsi_context *bld_base)
 	bld_base->op_actions[TGSI_OPCODE_U64SHL].emit = emit_shl;
 	bld_base->op_actions[TGSI_OPCODE_U64SHR].emit = emit_ushr;
 	bld_base->op_actions[TGSI_OPCODE_I64SHR].emit = emit_ishr;
 
 	bld_base->op_actions[TGSI_OPCODE_U64MOD].emit = emit_umod;
 	bld_base->op_actions[TGSI_OPCODE_I64MOD].emit = emit_mod;
 	bld_base->op_actions[TGSI_OPCODE_U64DIV].emit = emit_udiv;
 	bld_base->op_actions[TGSI_OPCODE_I64DIV].emit = emit_idiv;
 }
 
-static LLVMValueRef build_cube_intrinsic(struct gallivm_state *gallivm,
-					 LLVMValueRef in[3])
+/* Coordinates for cube map selection. sc, tc, and ma are as in Table 8.27
+ * of the OpenGL 4.5 (Compatibility Profile) specification, except ma is
+ * already multiplied by two. id is the cube face number.
+ */
+struct cube_selection_coords {
+	LLVMValueRef stc[2];
+	LLVMValueRef ma;
+	LLVMValueRef id;
+};
+
+static void build_cube_intrinsic(struct gallivm_state *gallivm,
+				 LLVMValueRef in[3],
+				 struct cube_selection_coords *out)
 {
+	LLVMBuilderRef builder = gallivm->builder;
+
 	if (HAVE_LLVM >= 0x0309) {
 		LLVMTypeRef f32 = LLVMTypeOf(in[0]);
-		LLVMValueRef out[4];
 
-		out[0] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubetc",
+		out->stc[1] = lp_build_intrinsic(builder, "llvm.amdgcn.cubetc",
 					    f32, in, 3, LP_FUNC_ATTR_READNONE);
-		out[1] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubesc",
+		out->stc[0] = lp_build_intrinsic(builder, "llvm.amdgcn.cubesc",
 					    f32, in, 3, LP_FUNC_ATTR_READNONE);
-		out[2] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubema",
+		out->ma = lp_build_intrinsic(builder, "llvm.amdgcn.cubema",
 					    f32, in, 3, LP_FUNC_ATTR_READNONE);
-		out[3] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubeid",
+		out->id = lp_build_intrinsic(builder, "llvm.amdgcn.cubeid",
 					    f32, in, 3, LP_FUNC_ATTR_READNONE);
-
-		return lp_build_gather_values(gallivm, out, 4);
 	} else {
 		LLVMValueRef c[4] = {
 			in[0],
 			in[1],
 			in[2],
 			LLVMGetUndef(LLVMTypeOf(in[0]))
 		};
 		LLVMValueRef vec = lp_build_gather_values(gallivm, c, 4);
 
-		return lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.cube",
+		LLVMValueRef tmp =
+			lp_build_intrinsic(builder, "llvm.AMDGPU.cube",
 					  LLVMTypeOf(vec), &vec, 1,
 					  LP_FUNC_ATTR_READNONE);
+
+		out->stc[1] = LLVMBuildExtractElement(builder, tmp,
+				lp_build_const_int32(gallivm, 0), "");
+		out->stc[0] = LLVMBuildExtractElement(builder, tmp,
+				lp_build_const_int32(gallivm, 1), "");
+		out->ma = LLVMBuildExtractElement(builder, tmp,
+				lp_build_const_int32(gallivm, 2), "");
+		out->id = LLVMBuildExtractElement(builder, tmp,
+				lp_build_const_int32(gallivm, 3), "");
 	}
 }
 
 static void si_llvm_cube_to_2d_coords(struct lp_build_tgsi_context *bld_base,
 				      LLVMValueRef *in, LLVMValueRef *out)
 {
 	struct gallivm_state *gallivm = bld_base->base.gallivm;
 	LLVMBuilderRef builder = gallivm->builder;
 	LLVMTypeRef type = bld_base->base.elem_type;
-	LLVMValueRef coords[4];
+	struct cube_selection_coords coords;
+	LLVMValueRef invma;
 	LLVMValueRef mad_args[3];
-	LLVMValueRef v;
-	unsigned i;
-
-	v = build_cube_intrinsic(gallivm, in);
 
-	for (i = 0; i < 4; ++i)
-		coords[i] = LLVMBuildExtractElement(builder, v,
-						    lp_build_const_int32(gallivm, i), "");
+	build_cube_intrinsic(gallivm, in, &coords);
 
-	coords[2] = lp_build_intrinsic(builder, "llvm.fabs.f32",
-			type, &coords[2], 1, LP_FUNC_ATTR_READNONE);
-	coords[2] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_RCP, coords[2]);
+	invma = lp_build_intrinsic(builder, "llvm.fabs.f32",
+			type, &coords.ma, 1, LP_FUNC_ATTR_READNONE);
+	invma = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_RCP, invma);
 
-	mad_args[1] = coords[2];
+	mad_args[1] = invma;
 	mad_args[2] = LLVMConstReal(type, 0.5);
 
-	mad_args[0] = coords[0];
-	coords[0] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD,
-			mad_args[0], mad_args[1], mad_args[2]);
-
-	mad_args[0] = coords[1];
-	coords[1] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD,
-			mad_args[0], mad_args[1], mad_args[2]);
+	for (int i = 0; i < 2; ++i) {
+		mad_args[0] = coords.stc[i];
+		out[i] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD,
+				mad_args[0], mad_args[1], mad_args[2]);
+	}
 
-	/* apply xyz = yxw swizzle to cooords */
-	out[0] = coords[1];
-	out[1] = coords[0];
-	out[2] = coords[3];
+	out[2] = coords.id;
 }
 
 void si_prepare_cube_coords(struct lp_build_tgsi_context *bld_base,
 			    struct lp_build_emit_data *emit_data,
 			    LLVMValueRef *coords_arg,
 			    LLVMValueRef *derivs_arg)
 {
 
 	unsigned target = emit_data->inst->Texture.Texture;
 	unsigned opcode = emit_data->inst->Instruction.Opcode;
-- 
2.7.4



More information about the mesa-dev mailing list