[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