[Mesa-dev] [PATCH 1/2] radeonsi: add support for indirect samplers

Dave Airlie airlied at gmail.com
Tue Jul 21 18:27:19 PDT 2015


From: Dave Airlie <airlied at redhat.com>

This adds the frontend support, however the llvm
backend produces the wrong pattern, however
we can conditionalise enabling ARB_gpu_shader5
on whatever version of llvm we fix this in.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 docs/GL3.txt                             |  2 +-
 src/gallium/drivers/radeonsi/si_shader.c | 88 ++++++++++++++++++++++++++++----
 2 files changed, 79 insertions(+), 11 deletions(-)

diff --git a/docs/GL3.txt b/docs/GL3.txt
index d74ae63..ca3646c 100644
--- a/docs/GL3.txt
+++ b/docs/GL3.txt
@@ -98,7 +98,7 @@ GL 4.0, GLSL 4.00:
   GL_ARB_draw_indirect                                 DONE (i965, nvc0, r600, radeonsi, llvmpipe, softpipe)
   GL_ARB_gpu_shader5                                   DONE (i965, nvc0)
   - 'precise' qualifier                                DONE
-  - Dynamically uniform sampler array indices          DONE (r600, softpipe)
+  - Dynamically uniform sampler array indices          DONE (r600, radeonsi, softpipe)
   - Dynamically uniform UBO array indices              DONE (r600)
   - Implicit signed -> unsigned conversions            DONE
   - Fused multiply-add                                 DONE ()
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 2705dcc..55357fa 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -1625,6 +1625,24 @@ static bool tgsi_is_shadow_sampler(unsigned target)
 
 static const struct lp_build_tgsi_action tex_action;
 
+/**
+ * Return the value of tgsi_ind_register for indexing.
+ * This is the indirect index with the constant offset added to it.
+ */
+static LLVMValueRef get_indirect_index(struct si_shader_context *si_shader_ctx,
+				       const struct tgsi_ind_register *ind,
+				       int rel_index)
+{
+	struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm;
+	LLVMValueRef result;
+
+	result = si_shader_ctx->radeon_bld.soa.addr[ind->Index][ind->Swizzle];
+	result = LLVMBuildLoad(gallivm->builder, result, "");
+	result = LLVMBuildAdd(gallivm->builder, result,
+			      lp_build_const_int32(gallivm, rel_index), "");
+	return result;
+}
+
 static void tex_fetch_args(
 	struct lp_build_tgsi_context * bld_base,
 	struct lp_build_emit_data * emit_data)
@@ -1640,10 +1658,36 @@ static void tex_fetch_args(
 	unsigned num_coords = tgsi_util_get_texture_coord_dim(target, &ref_pos);
 	unsigned count = 0;
 	unsigned chan;
-	unsigned sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
-	unsigned sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
+	unsigned sampler_src;
+	unsigned sampler_index;
 	bool has_offset = HAVE_LLVM >= 0x0305 ? inst->Texture.NumOffsets > 0 : false;
+	bool has_sampler_indirect = false;
+	LLVMValueRef res_ptr, samp_ptr;
+
+	sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
+	sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
+
+	if (emit_data->inst->Src[sampler_src].Register.Indirect) {
+		const struct tgsi_full_src_register *reg = &emit_data->inst->Src[sampler_src];
+		unsigned first = reg->Register.Index;
+		LLVMValueRef ind_index;
 
+		ind_index = get_indirect_index(si_shader_ctx, &reg->Indirect,
+					   reg->Register.Index - first);
+
+		res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE);
+		res_ptr = build_indexed_load_const(si_shader_ctx, res_ptr,
+					     ind_index);
+
+		samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER);
+		samp_ptr = build_indexed_load_const(si_shader_ctx, samp_ptr,
+					      ind_index);
+		has_sampler_indirect = true;
+
+	} else {
+		res_ptr = si_shader_ctx->resources[sampler_index];
+		samp_ptr = si_shader_ctx->samplers[sampler_index];
+	}
 	if (target == TGSI_TEXTURE_BUFFER) {
 		LLVMTypeRef i128 = LLVMIntTypeInContext(gallivm->context, 128);
 		LLVMTypeRef v2i128 = LLVMVectorType(i128, 2);
@@ -1651,7 +1695,7 @@ static void tex_fetch_args(
 		LLVMTypeRef v16i8 = LLVMVectorType(i8, 16);
 
 		/* Bitcast and truncate v8i32 to v16i8. */
-		LLVMValueRef res = si_shader_ctx->resources[sampler_index];
+		LLVMValueRef res = res_ptr;
 		res = LLVMBuildBitCast(gallivm->builder, res, v2i128, "");
 		res = LLVMBuildExtractElement(gallivm->builder, res, bld_base->uint_bld.one, "");
 		res = LLVMBuildBitCast(gallivm->builder, res, v16i8, "");
@@ -1877,7 +1921,7 @@ static void tex_fetch_args(
 	}
 
 	/* Resource */
-	emit_data->args[1] = si_shader_ctx->resources[sampler_index];
+	emit_data->args[1] = res_ptr;
 
 	if (opcode == TGSI_OPCODE_TXF) {
 		/* add tex offsets */
@@ -1923,7 +1967,7 @@ static void tex_fetch_args(
 			4);
 	} else if (opcode == TGSI_OPCODE_TG4 ||
 		   opcode == TGSI_OPCODE_LODQ ||
-		   has_offset) {
+		   has_offset || has_sampler_indirect) {
 		unsigned is_array = target == TGSI_TEXTURE_1D_ARRAY ||
 				    target == TGSI_TEXTURE_SHADOW1D_ARRAY ||
 				    target == TGSI_TEXTURE_2D_ARRAY ||
@@ -1960,7 +2004,7 @@ static void tex_fetch_args(
 			dmask = 1 << gather_comp;
 		}
 
-		emit_data->args[2] = si_shader_ctx->samplers[sampler_index];
+		emit_data->args[2] = samp_ptr;
 		emit_data->args[3] = lp_build_const_int32(gallivm, dmask);
 		emit_data->args[4] = lp_build_const_int32(gallivm, is_rect); /* unorm */
 		emit_data->args[5] = lp_build_const_int32(gallivm, 0); /* r128 */
@@ -1976,7 +2020,7 @@ static void tex_fetch_args(
 			LLVMFloatTypeInContext(gallivm->context),
 			4);
 	} else {
-		emit_data->args[2] = si_shader_ctx->samplers[sampler_index];
+		emit_data->args[2] = samp_ptr;
 		emit_data->args[3] = lp_build_const_int32(gallivm, target);
 		emit_data->arg_count = 4;
 
@@ -2009,7 +2053,16 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
 	char intr_name[127];
 	bool has_offset = HAVE_LLVM >= 0x0305 ?
 				emit_data->inst->Texture.NumOffsets > 0 : false;
+	bool has_sampler_indirect = false;
+	unsigned sampler_src;
+
+	if (emit_data->inst->Instruction.NumSrcRegs) {
+		sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
 
+		if (emit_data->inst->Src[sampler_src].Register.Indirect) {
+			has_sampler_indirect = true;
+		}
+	}
 	if (target == TGSI_TEXTURE_BUFFER) {
 		emit_data->output[emit_data->chan] = build_intrinsic(
 			base->gallivm->builder,
@@ -2021,7 +2074,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
 
 	if (opcode == TGSI_OPCODE_TG4 ||
 	    opcode == TGSI_OPCODE_LODQ ||
-	    (opcode != TGSI_OPCODE_TXF && has_offset)) {
+	    (opcode != TGSI_OPCODE_TXF && has_offset) || has_sampler_indirect) {
 		bool is_shadow = tgsi_is_shadow_sampler(target);
 		const char *name = "llvm.SI.image.sample";
 		const char *infix = "";
@@ -2122,13 +2175,28 @@ static void txq_fetch_args(
 	const struct tgsi_full_instruction *inst = emit_data->inst;
 	struct gallivm_state *gallivm = bld_base->base.gallivm;
 	unsigned target = inst->Texture.Texture;
+	LLVMValueRef res_ptr;
+
+	if (inst->Src[1].Register.Indirect) {
+		const struct tgsi_full_src_register *reg = &inst->Src[1];
+		unsigned first = reg->Register.Index;
+		LLVMValueRef ind_index;
+
+		ind_index = get_indirect_index(si_shader_ctx, &reg->Indirect,
+					   reg->Register.Index - first);
+
+		res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE);
+		res_ptr = build_indexed_load_const(si_shader_ctx, res_ptr,
+						   ind_index);
+	} else
+		res_ptr = si_shader_ctx->resources[inst->Src[1].Register.Index];
 
 	if (target == TGSI_TEXTURE_BUFFER) {
 		LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context);
 		LLVMTypeRef v8i32 = LLVMVectorType(i32, 8);
 
 		/* Read the size from the buffer descriptor directly. */
-		LLVMValueRef size = si_shader_ctx->resources[inst->Src[1].Register.Index];
+		LLVMValueRef size = res_ptr;
 		size = LLVMBuildBitCast(gallivm->builder, size, v8i32, "");
 		size = LLVMBuildExtractElement(gallivm->builder, size,
 					      lp_build_const_int32(gallivm, 6), "");
@@ -2140,7 +2208,7 @@ static void txq_fetch_args(
 	emit_data->args[0] = lp_build_emit_fetch(bld_base, inst, 0, TGSI_CHAN_X);
 
 	/* Resource */
-	emit_data->args[1] = si_shader_ctx->resources[inst->Src[1].Register.Index];
+	emit_data->args[1] = res_ptr;
 
 	/* Texture target */
 	if (target == TGSI_TEXTURE_CUBE_ARRAY ||
-- 
2.4.3



More information about the mesa-dev mailing list