[Mesa-dev] [PATCH 2/2] ac/radeonsi: add support for tex instr without a derefence

Timothy Arceri tarceri at itsqueeze.com
Wed Nov 1 01:43:46 UTC 2017


These are produced by nir_lower_bitmap(), adding the missing derefence
would cause other issues that need to be hacked around such as
skipping sampler lowering and uniform location assignment, so this
change seems the correct way to go.

Fixes 194 piglit crashes on radeonsi using NIR.
---
 src/amd/common/ac_nir_to_llvm.c              | 80 ++++++++++++++++------------
 src/gallium/drivers/radeonsi/si_shader_nir.c |  5 ++
 2 files changed, 51 insertions(+), 34 deletions(-)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index a736d34d12..2ec30517e0 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -173,20 +173,21 @@ struct nir_to_llvm_context {
 static inline struct nir_to_llvm_context *
 nir_to_llvm_context_from_abi(struct ac_shader_abi *abi)
 {
 	struct nir_to_llvm_context *ctx = NULL;
 	return container_of(abi, ctx, abi);
 }
 
 static LLVMValueRef get_sampler_desc(struct ac_nir_context *ctx,
 				     const nir_deref_var *deref,
 				     enum ac_descriptor_type desc_type,
+				     const nir_tex_instr *instr,
 				     bool image, bool write);
 
 static unsigned radeon_llvm_reg_index_soa(unsigned index, unsigned chan)
 {
 	return (index * 4) + chan;
 }
 
 static unsigned shader_io_get_unique_index(gl_varying_slot slot)
 {
 	/* handle patch indices separate */
@@ -3385,21 +3386,21 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
 					LLVMBuildAdd(ctx->ac.builder, fmask_load_address[chan],
 						LLVMBuildFPToUI(ctx->ac.builder, ctx->abi->frag_pos[chan],
 								ctx->ac.i32, ""), "");
 			fmask_load_address[2] = ac_to_integer(&ctx->ac, ctx->abi->inputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)]);
 		}
 		sample_index = adjust_sample_index_using_fmask(&ctx->ac,
 							       fmask_load_address[0],
 							       fmask_load_address[1],
 							       fmask_load_address[2],
 							       sample_index,
-							       get_sampler_desc(ctx, instr->variables[0], AC_DESC_FMASK, true, false));
+							       get_sampler_desc(ctx, instr->variables[0], AC_DESC_FMASK, NULL, true, false));
 	}
 	if (count == 1 && !gfx9_1d) {
 		if (instr->src[0].ssa->num_components)
 			res = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[0], "");
 		else
 			res = src0;
 	} else {
 		int chan;
 		if (is_ms)
 			count--;
@@ -3444,42 +3445,42 @@ static LLVMValueRef visit_image_load(struct ac_nir_context *ctx,
 	LLVMValueRef res;
 	char intrinsic_name[64];
 	const nir_variable *var = instr->variables[0]->var;
 	const struct glsl_type *type = var->type;
 
 	if(instr->variables[0]->deref.child)
 		type = instr->variables[0]->deref.child->type;
 
 	type = glsl_without_array(type);
 	if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) {
-		params[0] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER, true, false);
+		params[0] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER, NULL, true, false);
 		params[1] = LLVMBuildExtractElement(ctx->ac.builder, get_src(ctx, instr->src[0]),
 						    ctx->ac.i32_0, ""); /* vindex */
 		params[2] = ctx->ac.i32_0; /* voffset */
 		params[3] = ctx->ac.i1false;  /* glc */
 		params[4] = ctx->ac.i1false;  /* slc */
 		res = ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.buffer.load.format.v4f32", ctx->ac.v4f32,
 					 params, 5, 0);
 
 		res = trim_vector(&ctx->ac, res, instr->dest.ssa.num_components);
 		res = ac_to_integer(&ctx->ac, res);
 	} else {
 		bool is_da = glsl_sampler_type_is_array(type) ||
 			     glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ||
 			     glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_SUBPASS ||
 			     glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_SUBPASS_MS;
 		LLVMValueRef da = is_da ? ctx->ac.i1true : ctx->ac.i1false;
 		LLVMValueRef glc = ctx->ac.i1false;
 		LLVMValueRef slc = ctx->ac.i1false;
 
 		params[0] = get_image_coords(ctx, instr);
-		params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, true, false);
+		params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, NULL, true, false);
 		params[2] = LLVMConstInt(ctx->ac.i32, 15, false); /* dmask */
 		if (HAVE_LLVM <= 0x0309) {
 			params[3] = ctx->ac.i1false;  /* r128 */
 			params[4] = da;
 			params[5] = glc;
 			params[6] = slc;
 		} else {
 			LLVMValueRef lwe = ctx->ac.i1false;
 			params[3] = glc;
 			params[4] = slc;
@@ -3506,37 +3507,37 @@ static void visit_image_store(struct ac_nir_context *ctx,
 	char intrinsic_name[64];
 	const nir_variable *var = instr->variables[0]->var;
 	const struct glsl_type *type = glsl_without_array(var->type);
 	LLVMValueRef glc = ctx->ac.i1false;
 	bool force_glc = ctx->ac.chip_class == SI;
 	if (force_glc)
 		glc = ctx->ac.i1true;
 
 	if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) {
 		params[0] = ac_to_float(&ctx->ac, get_src(ctx, instr->src[2])); /* data */
-		params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER, true, true);
+		params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER, NULL, true, true);
 		params[2] = LLVMBuildExtractElement(ctx->ac.builder, get_src(ctx, instr->src[0]),
 						    ctx->ac.i32_0, ""); /* vindex */
 		params[3] = ctx->ac.i32_0; /* voffset */
 		params[4] = glc;  /* glc */
 		params[5] = ctx->ac.i1false;  /* slc */
 		ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.buffer.store.format.v4f32", ctx->ac.voidt,
 				   params, 6, 0);
 	} else {
 		bool is_da = glsl_sampler_type_is_array(type) ||
 			     glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE;
 		LLVMValueRef da = is_da ? ctx->ac.i1true : ctx->ac.i1false;
 		LLVMValueRef slc = ctx->ac.i1false;
 
 		params[0] = ac_to_float(&ctx->ac, get_src(ctx, instr->src[2]));
 		params[1] = get_image_coords(ctx, instr); /* coords */
-		params[2] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, true, true);
+		params[2] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, NULL, true, true);
 		params[3] = LLVMConstInt(ctx->ac.i32, 15, false); /* dmask */
 		if (HAVE_LLVM <= 0x0309) {
 			params[4] = ctx->ac.i1false;  /* r128 */
 			params[5] = da;
 			params[6] = glc;
 			params[7] = slc;
 		} else {
 			LLVMValueRef lwe = ctx->ac.i1false;
 			params[4] = glc;
 			params[5] = slc;
@@ -3598,37 +3599,37 @@ static LLVMValueRef visit_image_atomic(struct ac_nir_context *ctx,
 	default:
 		abort();
 	}
 
 	if (instr->intrinsic == nir_intrinsic_image_atomic_comp_swap)
 		params[param_count++] = get_src(ctx, instr->src[3]);
 	params[param_count++] = get_src(ctx, instr->src[2]);
 
 	if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) {
 		params[param_count++] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER,
-							 true, true);
+							 NULL, true, true);
 		params[param_count++] = LLVMBuildExtractElement(ctx->ac.builder, get_src(ctx, instr->src[0]),
 								ctx->ac.i32_0, ""); /* vindex */
 		params[param_count++] = ctx->ac.i32_0; /* voffset */
 		params[param_count++] = ctx->ac.i1false;  /* slc */
 
 		length = snprintf(intrinsic_name, sizeof(intrinsic_name),
 				  "llvm.amdgcn.buffer.atomic.%s", atomic_name);
 	} else {
 		char coords_type[8];
 
 		bool da = glsl_sampler_type_is_array(type) ||
 		          glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE;
 
 		LLVMValueRef coords = params[param_count++] = get_image_coords(ctx, instr);
 		params[param_count++] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE,
-							 true, true);
+							 NULL, true, true);
 		params[param_count++] = ctx->ac.i1false; /* r128 */
 		params[param_count++] = da ? ctx->ac.i1true : ctx->ac.i1false;      /* da */
 		params[param_count++] = ctx->ac.i1false;  /* slc */
 
 		build_int_type_name(LLVMTypeOf(coords),
 				    coords_type, sizeof(coords_type));
 
 		length = snprintf(intrinsic_name, sizeof(intrinsic_name),
 				  "llvm.amdgcn.image.atomic.%s.%s", atomic_name, coords_type);
 	}
@@ -3644,27 +3645,27 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx,
 	const nir_variable *var = instr->variables[0]->var;
 	const struct glsl_type *type = instr->variables[0]->var->type;
 	bool da = glsl_sampler_type_is_array(var->type) ||
 	          glsl_get_sampler_dim(var->type) == GLSL_SAMPLER_DIM_CUBE;
 	if(instr->variables[0]->deref.child)
 		type = instr->variables[0]->deref.child->type;
 
 	if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF)
 		return get_buffer_size(ctx,
 			get_sampler_desc(ctx, instr->variables[0],
-					 AC_DESC_BUFFER, true, false), true);
+					 AC_DESC_BUFFER, NULL, true, false), true);
 
 	struct ac_image_args args = { 0 };
 
 	args.da = da;
 	args.dmask = 0xf;
-	args.resource = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, true, false);
+	args.resource = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE, NULL, true, false);
 	args.opcode = ac_image_get_resinfo;
 	args.addr = ctx->ac.i32_0;
 
 	res = ac_build_image_opcode(&ctx->ac, &args);
 
 	LLVMValueRef two = LLVMConstInt(ctx->ac.i32, 2, false);
 
 	if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE &&
 	    glsl_sampler_type_is_array(type)) {
 		LLVMValueRef six = LLVMConstInt(ctx->ac.i32, 6, false);
@@ -4318,55 +4319,66 @@ static LLVMValueRef radv_get_sampler_desc(struct ac_shader_abi *abi,
 
 	list = ac_build_gep0(&ctx->ac, list, LLVMConstInt(ctx->i32, offset, 0));
 	list = LLVMBuildPointerCast(builder, list, const_array(type, 0), "");
 
 	return ac_build_load_to_sgpr(&ctx->ac, list, index);
 }
 
 static LLVMValueRef get_sampler_desc(struct ac_nir_context *ctx,
 				     const nir_deref_var *deref,
 				     enum ac_descriptor_type desc_type,
+				     const nir_tex_instr *tex_instr,
 				     bool image, bool write)
 {
 	LLVMValueRef index = NULL;
 	unsigned constant_index = 0;
-	const nir_deref *tail = &deref->deref;
+	unsigned descriptor_set;
+	unsigned base_index;
 
-	while (tail->child) {
-		const nir_deref_array *child = nir_deref_as_array(tail->child);
-		unsigned array_size = glsl_get_aoa_size(tail->child->type);
+	if (!deref) {
+		assert(tex_instr && !image);
+		descriptor_set = 0;
+		base_index = tex_instr->sampler_index;
+	} else {
+		const nir_deref *tail = &deref->deref;
+		while (tail->child) {
+			const nir_deref_array *child = nir_deref_as_array(tail->child);
+			unsigned array_size = glsl_get_aoa_size(tail->child->type);
 
-		if (!array_size)
-			array_size = 1;
+			if (!array_size)
+				array_size = 1;
 
-		assert(child->deref_array_type != nir_deref_array_type_wildcard);
+			assert(child->deref_array_type != nir_deref_array_type_wildcard);
 
-		if (child->deref_array_type == nir_deref_array_type_indirect) {
-			LLVMValueRef indirect = get_src(ctx, child->indirect);
+			if (child->deref_array_type == nir_deref_array_type_indirect) {
+				LLVMValueRef indirect = get_src(ctx, child->indirect);
 
-			indirect = LLVMBuildMul(ctx->ac.builder, indirect,
-				LLVMConstInt(ctx->ac.i32, array_size, false), "");
+				indirect = LLVMBuildMul(ctx->ac.builder, indirect,
+					LLVMConstInt(ctx->ac.i32, array_size, false), "");
 
-			if (!index)
-				index = indirect;
-			else
-				index = LLVMBuildAdd(ctx->ac.builder, index, indirect, "");
-		}
+				if (!index)
+					index = indirect;
+				else
+					index = LLVMBuildAdd(ctx->ac.builder, index, indirect, "");
+			}
 
-		constant_index += child->base_offset * array_size;
+			constant_index += child->base_offset * array_size;
 
-		tail = &child->deref;
+			tail = &child->deref;
+		}
+		descriptor_set = deref->var->data.descriptor_set;
+		base_index = deref->var->data.binding;
 	}
 
 	return ctx->abi->load_sampler_desc(ctx->abi,
-					  deref->var->data.descriptor_set,
-					  deref->var->data.binding,
+					  descriptor_set,
+					  base_index,
 					  constant_index, index,
 					  desc_type, image, write);
 }
 
 static void set_tex_fetch_args(struct ac_llvm_context *ctx,
 			       struct ac_image_args *args,
 			       const nir_tex_instr *instr,
 			       nir_texop op,
 			       LLVMValueRef res_ptr, LLVMValueRef samp_ptr,
 			       LLVMValueRef *param, unsigned count,
@@ -4427,34 +4439,34 @@ static LLVMValueRef sici_fix_sampler_aniso(struct ac_nir_context *ctx,
 	return LLVMBuildInsertElement(builder, samp, samp0,
 	                              LLVMConstInt(ctx->ac.i32, 0, 0), "");
 }
 
 static void tex_fetch_ptrs(struct ac_nir_context *ctx,
 			   nir_tex_instr *instr,
 			   LLVMValueRef *res_ptr, LLVMValueRef *samp_ptr,
 			   LLVMValueRef *fmask_ptr)
 {
 	if (instr->sampler_dim  == GLSL_SAMPLER_DIM_BUF)
-		*res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_BUFFER, false, false);
+		*res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_BUFFER, instr, false, false);
 	else
-		*res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_IMAGE, false, false);
+		*res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_IMAGE, instr, false, false);
 	if (samp_ptr) {
 		if (instr->sampler)
-			*samp_ptr = get_sampler_desc(ctx, instr->sampler, AC_DESC_SAMPLER, false, false);
+			*samp_ptr = get_sampler_desc(ctx, instr->sampler, AC_DESC_SAMPLER, instr, false, false);
 		else
-			*samp_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_SAMPLER, false, false);
+			*samp_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_SAMPLER, instr, false, false);
 		if (instr->sampler_dim < GLSL_SAMPLER_DIM_RECT)
 			*samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
 	}
 	if (fmask_ptr && !instr->sampler && (instr->op == nir_texop_txf_ms ||
 					     instr->op == nir_texop_samples_identical))
-		*fmask_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_FMASK, false, false);
+		*fmask_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_FMASK, instr, false, false);
 }
 
 static LLVMValueRef apply_round_slice(struct ac_llvm_context *ctx,
 				      LLVMValueRef coord)
 {
 	coord = ac_to_float(ctx, coord);
 	coord = ac_build_intrinsic(ctx, "llvm.rint.f32", ctx->f32, &coord, 1, 0);
 	coord = ac_to_integer(ctx, coord);
 	return coord;
 }
diff --git a/src/gallium/drivers/radeonsi/si_shader_nir.c b/src/gallium/drivers/radeonsi/si_shader_nir.c
index 7a88227381..32f6d86647 100644
--- a/src/gallium/drivers/radeonsi/si_shader_nir.c
+++ b/src/gallium/drivers/radeonsi/si_shader_nir.c
@@ -52,20 +52,25 @@ static void scan_instruction(struct tgsi_shader_info *info,
 		case nir_op_fddx_coarse:
 		case nir_op_fddy_coarse:
 			info->uses_derivatives = true;
 			break;
 		default:
 			break;
 		}
 	} else if (instr->type == nir_instr_type_tex) {
 		nir_tex_instr *tex = nir_instr_as_tex(instr);
 
+		if (!tex->texture) {
+			info->samplers_declared |=
+				u_bit_consecutive(tex->sampler_index, 1);
+		}
+
 		switch (tex->op) {
 		case nir_texop_tex:
 		case nir_texop_txb:
 		case nir_texop_lod:
 			info->uses_derivatives = true;
 			break;
 		default:
 			break;
 		}
 	} else if (instr->type == nir_instr_type_intrinsic) {
-- 
2.14.3



More information about the mesa-dev mailing list