[Mesa-dev] [PATCH 1/2] amd/common: Rework buffer resource loading for uniform blocks.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Tue Sep 18 21:34:40 UTC 2018


Pointer to descriptor becomes hard if the set does not contain a
descriptor. Furthermore we have no extra channel to pass whether
the given pointer points to a descriptor or not.
---
 src/amd/common/ac_nir_to_llvm.c               | 98 +++++++++++++------
 src/amd/common/ac_shader_abi.h                | 34 +++----
 src/amd/vulkan/radv_nir_to_llvm.c             | 31 ++----
 src/gallium/drivers/radeonsi/si_shader.c      |  4 +-
 .../drivers/radeonsi/si_shader_tgsi_mem.c     |  4 +-
 5 files changed, 97 insertions(+), 74 deletions(-)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index b01309cc2a9..ddb47d42687 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -1363,15 +1363,46 @@ static LLVMValueRef build_tex_intrinsic(struct ac_nir_context *ctx,
 	return ac_build_image_opcode(&ctx->ac, args);
 }
 
-static LLVMValueRef visit_vulkan_resource_reindex(struct ac_nir_context *ctx,
-                                                  nir_intrinsic_instr *instr)
+
+static bool is_vulkan_buffer(nir_ssa_def *value)
 {
-	LLVMValueRef ptr = get_src(ctx, instr->src[0]);
-	LLVMValueRef index = get_src(ctx, instr->src[1]);
+	if (value->parent_instr->type != nir_instr_type_intrinsic)
+		return false;
 
-	LLVMValueRef result = LLVMBuildGEP(ctx->ac.builder, ptr, &index, 1, "");
-	LLVMSetMetadata(result, ctx->ac.uniform_md_kind, ctx->ac.empty_md);
-	return result;
+	nir_intrinsic_instr *instr = (nir_intrinsic_instr*)value->parent_instr;
+	return instr->intrinsic == nir_intrinsic_vulkan_resource_index ||
+	       instr->intrinsic == nir_intrinsic_vulkan_resource_reindex;
+}
+
+static void get_buffer_resource(struct ac_nir_context *ctx,
+				nir_src value,
+				int *set,
+				int *binding,
+				LLVMValueRef *index)
+{
+	if (is_vulkan_buffer(value.ssa)) {
+		LLVMValueRef idx = ctx->ac.i32_0;
+		for(;;) {
+			assert(value.ssa->parent_instr->type == nir_instr_type_intrinsic);
+
+			nir_intrinsic_instr *instr = (nir_intrinsic_instr*)value.ssa->parent_instr;
+
+			if (instr->intrinsic == nir_intrinsic_vulkan_resource_index) {
+				*set = nir_intrinsic_desc_set(instr);
+				*binding = nir_intrinsic_binding(instr);
+				*index = LLVMBuildAdd(ctx->ac.builder, idx, get_src(ctx, instr->src[0]), "");
+				break;
+			}
+
+			idx = LLVMBuildAdd(ctx->ac.builder, idx, get_src(ctx, instr->src[1]), "");
+			value = instr->src[0];
+		}
+	} else {
+		/* For GL we get a plain index. */
+		*set = 0;
+		*binding = 0;
+		*index = get_src(ctx, value);
+	}
 }
 
 static LLVMValueRef visit_load_push_constant(struct ac_nir_context *ctx,
@@ -1412,9 +1443,13 @@ static LLVMValueRef visit_load_push_constant(struct ac_nir_context *ctx,
 static LLVMValueRef visit_get_buffer_size(struct ac_nir_context *ctx,
                                           const nir_intrinsic_instr *instr)
 {
-	LLVMValueRef index = get_src(ctx, instr->src[0]);
+	LLVMValueRef rsrc_index, rsrc;
+	int set, binding;
+
+	get_buffer_resource(ctx, instr->src[0], &set, &binding, &rsrc_index);
+	rsrc = ctx->abi->load_ssbo(ctx->abi, set, binding, rsrc_index, false);
 
-	return get_buffer_size(ctx, ctx->abi->load_ssbo(ctx->abi, index, false), false);
+	return get_buffer_size(ctx, rsrc, false);
 }
 
 static uint32_t widen_mask(uint32_t mask, unsigned multiplier)
@@ -1457,8 +1492,12 @@ static void visit_store_ssbo(struct ac_nir_context *ctx,
 	int elem_size_bytes = ac_get_elem_bits(&ctx->ac, LLVMTypeOf(src_data)) / 8;
 	unsigned writemask = nir_intrinsic_write_mask(instr);
 
-	LLVMValueRef rsrc = ctx->abi->load_ssbo(ctx->abi,
-				        get_src(ctx, instr->src[1]), true);
+	LLVMValueRef rsrc_index, rsrc;
+	int set, binding;
+
+	get_buffer_resource(ctx, instr->src[1], &set, &binding, &rsrc_index);
+	rsrc = ctx->abi->load_ssbo(ctx->abi, set, binding, rsrc_index, true);
+
 	LLVMValueRef base_data = ac_to_float(&ctx->ac, src_data);
 	base_data = ac_trim_vector(&ctx->ac, base_data, instr->num_components);
 	LLVMValueRef base_offset = get_src(ctx, instr->src[2]);
@@ -1555,14 +1594,16 @@ static LLVMValueRef visit_atomic_ssbo(struct ac_nir_context *ctx,
 	const char *name;
 	LLVMValueRef params[6];
 	int arg_count = 0;
+	LLVMValueRef rsrc_index;
+	int set, binding;
+
+	get_buffer_resource(ctx, instr->src[0], &set, &binding, &rsrc_index);
 
 	if (instr->intrinsic == nir_intrinsic_ssbo_atomic_comp_swap) {
 		params[arg_count++] = ac_llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[3]), 0);
 	}
 	params[arg_count++] = ac_llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[2]), 0);
-	params[arg_count++] = ctx->abi->load_ssbo(ctx->abi,
-						 get_src(ctx, instr->src[0]),
-						 true);
+	params[arg_count++] = ctx->abi->load_ssbo(ctx->abi, set, binding, rsrc_index, true);
 	params[arg_count++] = ctx->ac.i32_0; /* vindex */
 	params[arg_count++] = get_src(ctx, instr->src[1]);      /* voffset */
 	params[arg_count++] = LLVMConstInt(ctx->ac.i1, 0, false);  /* slc */
@@ -1613,6 +1654,11 @@ static LLVMValueRef visit_load_buffer(struct ac_nir_context *ctx,
 	int elem_size_bytes = instr->dest.ssa.bit_size / 8;
 	int num_components = instr->num_components;
 	int num_bytes = num_components * elem_size_bytes;
+	LLVMValueRef rsrc_index, rsrc;
+	int set, binding;
+
+	get_buffer_resource(ctx, instr->src[0], &set, &binding, &rsrc_index);
+	rsrc = ctx->abi->load_ssbo(ctx->abi, set, binding, rsrc_index, false);
 
 	for (int i = 0; i < num_bytes; i += load_bytes) {
 		load_bytes = MIN2(num_bytes - i, 16);
@@ -1620,8 +1666,6 @@ static LLVMValueRef visit_load_buffer(struct ac_nir_context *ctx,
 		LLVMTypeRef data_type;
 		LLVMValueRef offset = get_src(ctx, instr->src[1]);
 		LLVMValueRef immoffset = LLVMConstInt(ctx->ac.i32, i, false);
-		LLVMValueRef rsrc = ctx->abi->load_ssbo(ctx->abi,
-							get_src(ctx, instr->src[0]), false);
 		LLVMValueRef vindex = ctx->ac.i32_0;
 
 		int idx = i ? 1 : 0;
@@ -1690,13 +1734,13 @@ static LLVMValueRef visit_load_buffer(struct ac_nir_context *ctx,
 static LLVMValueRef visit_load_ubo_buffer(struct ac_nir_context *ctx,
                                           const nir_intrinsic_instr *instr)
 {
-	LLVMValueRef ret;
-	LLVMValueRef rsrc = get_src(ctx, instr->src[0]);
+	LLVMValueRef ret, rsrc_index, rsrc;
+	int set, binding;
 	LLVMValueRef offset = get_src(ctx, instr->src[1]);
 	int num_components = instr->num_components;
 
-	if (ctx->abi->load_ubo)
-		rsrc = ctx->abi->load_ubo(ctx->abi, rsrc);
+	get_buffer_resource(ctx, instr->src[0], &set, &binding, &rsrc_index);
+	rsrc = ctx->abi->load_ubo(ctx->abi, set, binding, rsrc_index);
 
 	if (instr->dest.ssa.bit_size == 64)
 		num_components *= 2;
@@ -2994,18 +3038,10 @@ static void visit_intrinsic(struct ac_nir_context *ctx,
 	case nir_intrinsic_load_push_constant:
 		result = visit_load_push_constant(ctx, instr);
 		break;
-	case nir_intrinsic_vulkan_resource_index: {
-		LLVMValueRef index = get_src(ctx, instr->src[0]);
-		unsigned desc_set = nir_intrinsic_desc_set(instr);
-		unsigned binding = nir_intrinsic_binding(instr);
-
-		result = ctx->abi->load_resource(ctx->abi, index, desc_set,
-						 binding);
-		break;
-	}
+	case nir_intrinsic_vulkan_resource_index:
 	case nir_intrinsic_vulkan_resource_reindex:
-		result = visit_vulkan_resource_reindex(ctx, instr);
-		break;
+		/* Handled at the load/store instruction. */
+		return;
 	case nir_intrinsic_store_ssbo:
 		visit_store_ssbo(ctx, instr);
 		break;
diff --git a/src/amd/common/ac_shader_abi.h b/src/amd/common/ac_shader_abi.h
index 6b9a91c92a9..4df92a100f0 100644
--- a/src/amd/common/ac_shader_abi.h
+++ b/src/amd/common/ac_shader_abi.h
@@ -127,18 +127,30 @@ struct ac_shader_abi {
 	LLVMValueRef (*load_tess_level)(struct ac_shader_abi *abi,
 					unsigned varying_id);
 
-
-	LLVMValueRef (*load_ubo)(struct ac_shader_abi *abi, LLVMValueRef index);
+	/**
+	 * Load the descriptor for the given buffer.
+	 *
+	 * \param set the descriptor set to load the ssbo from. (ignored for GL).
+	 * \param binding the binding in the descriptor set to load the ssbo from
+	 *                (ignored for GL).
+	 * \param index the dynamic index. In GL/Gallium this is the full buffer
+	 *              index.
+	 */
+	LLVMValueRef (*load_ubo)(struct ac_shader_abi *abi, int set, int binding,
+	                         LLVMValueRef index);
 
 	/**
 	 * Load the descriptor for the given buffer.
 	 *
-	 * \param buffer the buffer as presented in NIR: this is the descriptor
-	 *               in Vulkan, and the buffer index in OpenGL/Gallium
+	 * \param set the descriptor set to load the ssbo from. (ignored for GL).
+	 * \param binding the binding in the descriptor set to load the ssbo from
+	 *                (ignored for GL).
+	 * \param index the dynamic index. In GL/Gallium this is the full buffer
+	 *              index.
 	 * \param write whether buffer contents will be written
 	 */
 	LLVMValueRef (*load_ssbo)(struct ac_shader_abi *abi,
-				  LLVMValueRef buffer, bool write);
+				  int set, int binding, LLVMValueRef index, bool write);
 
 	/**
 	 * Load a descriptor associated to a sampler.
@@ -160,18 +172,6 @@ struct ac_shader_abi {
 					  bool image, bool write,
 					  bool bindless);
 
-	/**
-	 * Load a Vulkan-specific resource.
-	 *
-	 * \param index resource index
-	 * \param desc_set descriptor set
-	 * \param binding descriptor set binding
-	 */
-	LLVMValueRef (*load_resource)(struct ac_shader_abi *abi,
-				      LLVMValueRef index,
-				      unsigned desc_set,
-				      unsigned binding);
-
 	LLVMValueRef (*lookup_interp_param)(struct ac_shader_abi *abi,
 					    enum glsl_interp_mode interp,
 					    unsigned location);
diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c
index 32d347ebd0f..8b7113efd28 100644
--- a/src/amd/vulkan/radv_nir_to_llvm.c
+++ b/src/amd/vulkan/radv_nir_to_llvm.c
@@ -1203,10 +1203,9 @@ static void create_function(struct radv_shader_context *ctx,
 
 
 static LLVMValueRef
-radv_load_resource(struct ac_shader_abi *abi, LLVMValueRef index,
+radv_load_resource(struct radv_shader_context *ctx, LLVMValueRef index,
 		   unsigned desc_set, unsigned binding)
 {
-	struct radv_shader_context *ctx = radv_shader_context_from_abi(abi);
 	LLVMValueRef desc_ptr = ctx->descriptor_sets[desc_set];
 	struct radv_pipeline_layout *pipeline_layout = ctx->options->layout;
 	struct radv_descriptor_set_layout *layout = pipeline_layout->set[desc_set].layout;
@@ -1230,7 +1229,10 @@ radv_load_resource(struct ac_shader_abi *abi, LLVMValueRef index,
 	desc_ptr = ac_cast_ptr(&ctx->ac, desc_ptr, ctx->ac.v4i32);
 	LLVMSetMetadata(desc_ptr, ctx->ac.uniform_md_kind, ctx->ac.empty_md);
 
-	return desc_ptr;
+	LLVMValueRef desc = LLVMBuildLoad(ctx->ac.builder, desc_ptr, "");
+	LLVMSetMetadata(desc, ctx->ac.invariant_load_md_kind, ctx->ac.empty_md);
+
+	return desc;
 }
 
 
@@ -1801,30 +1803,16 @@ static LLVMValueRef radv_load_base_vertex(struct ac_shader_abi *abi)
 }
 
 static LLVMValueRef radv_load_ssbo(struct ac_shader_abi *abi,
-				   LLVMValueRef buffer_ptr, bool write)
+				   int set, int binding, LLVMValueRef index, bool write)
 {
 	struct radv_shader_context *ctx = radv_shader_context_from_abi(abi);
-	LLVMValueRef result;
-
-	LLVMSetMetadata(buffer_ptr, ctx->ac.uniform_md_kind, ctx->ac.empty_md);
-
-	result = LLVMBuildLoad(ctx->ac.builder, buffer_ptr, "");
-	LLVMSetMetadata(result, ctx->ac.invariant_load_md_kind, ctx->ac.empty_md);
-
-	return result;
+	return radv_load_resource(ctx, index, set, binding);
 }
 
-static LLVMValueRef radv_load_ubo(struct ac_shader_abi *abi, LLVMValueRef buffer_ptr)
+static LLVMValueRef radv_load_ubo(struct ac_shader_abi *abi, int set, int binding, LLVMValueRef index)
 {
 	struct radv_shader_context *ctx = radv_shader_context_from_abi(abi);
-	LLVMValueRef result;
-
-	LLVMSetMetadata(buffer_ptr, ctx->ac.uniform_md_kind, ctx->ac.empty_md);
-
-	result = LLVMBuildLoad(ctx->ac.builder, buffer_ptr, "");
-	LLVMSetMetadata(result, ctx->ac.invariant_load_md_kind, ctx->ac.empty_md);
-
-	return result;
+	return radv_load_resource(ctx, index, set, binding);
 }
 
 static LLVMValueRef radv_get_sampler_desc(struct ac_shader_abi *abi,
@@ -3270,7 +3258,6 @@ LLVMModuleRef ac_translate_nir_to_llvm(struct ac_llvm_compiler *ac_llvm,
 	ctx.abi.load_ubo = radv_load_ubo;
 	ctx.abi.load_ssbo = radv_load_ssbo;
 	ctx.abi.load_sampler_desc = radv_get_sampler_desc;
-	ctx.abi.load_resource = radv_load_resource;
 	ctx.abi.clamp_shadow_reference = false;
 	ctx.abi.gfx9_stride_size_workaround = ctx.ac.chip_class == GFX9;
 
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 36f58e2ce52..9a8243aea6e 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2362,7 +2362,7 @@ static LLVMValueRef load_const_buffer_desc(struct si_shader_context *ctx, int i)
 				     LLVMConstInt(ctx->i32, si_get_constbuf_slot(i), 0));
 }
 
-static LLVMValueRef load_ubo(struct ac_shader_abi *abi, LLVMValueRef index)
+static LLVMValueRef load_ubo(struct ac_shader_abi *abi, int set, int binding, LLVMValueRef index)
 {
 	struct si_shader_context *ctx = si_shader_context_from_abi(abi);
 	struct si_shader_selector *sel = ctx->shader->selector;
@@ -2382,7 +2382,7 @@ static LLVMValueRef load_ubo(struct ac_shader_abi *abi, LLVMValueRef index)
 }
 
 static LLVMValueRef
-load_ssbo(struct ac_shader_abi *abi, LLVMValueRef index, bool write)
+load_ssbo(struct ac_shader_abi *abi, int set, int binding, LLVMValueRef index, bool write)
 {
 	struct si_shader_context *ctx = si_shader_context_from_abi(abi);
 	LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->main_fn,
diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
index cabc448a082..b352c23a4a1 100644
--- a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
+++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
@@ -82,9 +82,9 @@ shader_buffer_fetch_rsrc(struct si_shader_context *ctx,
 	}
 
 	if (ubo)
-		return ctx->abi.load_ubo(&ctx->abi, index);
+		return ctx->abi.load_ubo(&ctx->abi, 0, 0, index);
 	else
-		return ctx->abi.load_ssbo(&ctx->abi, index, false);
+		return ctx->abi.load_ssbo(&ctx->abi, 0, 0, index, false);
 }
 
 static enum ac_image_dim
-- 
2.19.0



More information about the mesa-dev mailing list