Similar to ac_build_buffer_load_format(). v2: - fix out of bounds access
Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> --- src/amd/common/ac_llvm_build.c | 100 ++++++++++++++++++++++++++++++++ src/amd/common/ac_llvm_build.h | 11 ++++ src/amd/common/ac_nir_to_llvm.c | 29 +++------ 3 files changed, 119 insertions(+), 21 deletions(-) diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 2f535259f78..5d52d93d25a 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -1082,6 +1082,106 @@ LLVMValueRef ac_build_load_to_sgpr_uint_wraparound(struct ac_llvm_context *ctx, return ac_build_load_custom(ctx, base_ptr, index, true, true, false); } +static void +ac_build_buffer_store_common(struct ac_llvm_context *ctx, + LLVMValueRef rsrc, + LLVMValueRef data, + LLVMValueRef vindex, + LLVMValueRef voffset, + unsigned num_channels, + bool glc, + bool slc, + bool writeonly_memory, + bool use_format) +{ + LLVMValueRef args[] = { + data, + LLVMBuildBitCast(ctx->builder, rsrc, ctx->v4i32, ""), + vindex ? vindex : ctx->i32_0, + voffset, + LLVMConstInt(ctx->i1, glc, 0), + LLVMConstInt(ctx->i1, slc, 0) + }; + unsigned func = CLAMP(num_channels, 1, 3) - 1; + + const char *type_names[] = {"f32", "v2f32", "v4f32"}; + char name[256]; + + if (use_format) { + snprintf(name, sizeof(name), "llvm.amdgcn.buffer.store.format.%s", + type_names[func]); + } else { + snprintf(name, sizeof(name), "llvm.amdgcn.buffer.store.%s", + type_names[func]); + } + + ac_build_intrinsic(ctx, name, ctx->voidt, args, ARRAY_SIZE(args), + ac_get_store_intr_attribs(writeonly_memory)); +} + +static void +ac_build_llvm8_buffer_store_common(struct ac_llvm_context *ctx, + LLVMValueRef rsrc, + LLVMValueRef data, + LLVMValueRef vindex, + LLVMValueRef voffset, + LLVMValueRef soffset, + unsigned num_channels, + bool glc, + bool slc, + bool writeonly_memory, + bool use_format, + bool structurized) +{ + LLVMValueRef args[6]; + int idx = 0; + args[idx++] = data; + args[idx++] = LLVMBuildBitCast(ctx->builder, rsrc, ctx->v4i32, ""); + if (structurized) + args[idx++] = vindex ? vindex : ctx->i32_0; + args[idx++] = voffset ? voffset : ctx->i32_0; + args[idx++] = soffset ? soffset : ctx->i32_0; + args[idx++] = LLVMConstInt(ctx->i32, (glc ? 1 : 0) + (slc ? 2 : 0), 0); + unsigned func = CLAMP(num_channels, 1, 3) - 1; + + const char *type_names[] = {"f32", "v2f32", "v4f32"}; + const char *indexing_kind = structurized ? "struct" : "raw"; + char name[256]; + + if (use_format) { + snprintf(name, sizeof(name), "llvm.amdgcn.%s.buffer.store.format.%s", + indexing_kind, type_names[func]); + } else { + snprintf(name, sizeof(name), "llvm.amdgcn.%s.buffer.store.%s", + indexing_kind, type_names[func]); + } + + ac_build_intrinsic(ctx, name, ctx->voidt, args, idx, + ac_get_store_intr_attribs(writeonly_memory)); +} + +void +ac_build_buffer_store_format(struct ac_llvm_context *ctx, + LLVMValueRef rsrc, + LLVMValueRef data, + LLVMValueRef vindex, + LLVMValueRef voffset, + unsigned num_channels, + bool glc, + bool writeonly_memory) +{ + if (HAVE_LLVM >= 0x800) { + ac_build_llvm8_buffer_store_common(ctx, rsrc, data, vindex, + voffset, NULL, num_channels, + glc, false, writeonly_memory, + true, true); + } else { + ac_build_buffer_store_common(ctx, rsrc, data, vindex, voffset, + num_channels, glc, false, + writeonly_memory, true); + } +} + /* TBUFFER_STORE_FORMAT_{X,XY,XYZ,XYZW} <- the suffix is selected by num_channels=1..4. * The type of vdata must be one of i32 (num_channels=1), v2i32 (num_channels=2), * or v4i32 (num_channels=3,4). diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h index 0fb3eb52f05..069ba7aa3c9 100644 --- a/src/amd/common/ac_llvm_build.h +++ b/src/amd/common/ac_llvm_build.h @@ -266,6 +266,17 @@ ac_build_buffer_store_dword(struct ac_llvm_context *ctx, bool slc, bool writeonly_memory, bool swizzle_enable_hint); + +void +ac_build_buffer_store_format(struct ac_llvm_context *ctx, + LLVMValueRef rsrc, + LLVMValueRef data, + LLVMValueRef vindex, + LLVMValueRef voffset, + unsigned num_channels, + bool glc, + bool writeonly_memory); + LLVMValueRef ac_build_buffer_load(struct ac_llvm_context *ctx, LLVMValueRef rsrc, diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index ff29345ffe5..c10a0cce16f 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -2512,7 +2512,6 @@ static LLVMValueRef visit_image_load(struct ac_nir_context *ctx, static void visit_image_store(struct ac_nir_context *ctx, nir_intrinsic_instr *instr) { - LLVMValueRef params[8]; const nir_deref_instr *image_deref = get_image_deref(instr); const struct glsl_type *type = image_deref->type; const nir_variable *var = nir_deref_instr_get_variable(image_deref); @@ -2524,34 +2523,22 @@ static void visit_image_store(struct ac_nir_context *ctx, writeonly_memory); if (dim == GLSL_SAMPLER_DIM_BUF) { - char name[48]; - const char *types[] = { "f32", "v2f32", "v4f32" }; LLVMValueRef rsrc = get_image_buffer_descriptor(ctx, instr, true); LLVMValueRef src = ac_to_float(&ctx->ac, get_src(ctx, instr->src[3])); unsigned src_channels = ac_get_llvm_num_components(src); + LLVMValueRef vindex; if (src_channels == 3) src = ac_build_expand_to_vec4(&ctx->ac, src, 3); - params[0] = src; /* data */ - params[1] = rsrc; - params[2] = LLVMBuildExtractElement(ctx->ac.builder, get_src(ctx, instr->src[1]), - ctx->ac.i32_0, ""); /* vindex */ - params[3] = ctx->ac.i32_0; /* voffset */ - snprintf(name, sizeof(name), "%s.%s", - HAVE_LLVM >= 0x800 ? "llvm.amdgcn.struct.buffer.store.format" - : "llvm.amdgcn.buffer.store.format", - types[CLAMP(src_channels, 1, 3) - 1]); + vindex = LLVMBuildExtractElement(ctx->ac.builder, + get_src(ctx, instr->src[1]), + ctx->ac.i32_0, ""); - if (HAVE_LLVM >= 0x800) { - params[4] = ctx->ac.i32_0; /* soffset */ - params[5] = (args.cache_policy & ac_glc) ? ctx->ac.i32_1 : ctx->ac.i32_0; - } else { - params[4] = LLVMConstInt(ctx->ac.i1, !!(args.cache_policy & ac_glc), 0); - params[5] = ctx->ac.i1false; /* slc */ - } - ac_build_intrinsic(&ctx->ac, name, ctx->ac.voidt, params, 6, - ac_get_store_intr_attribs(writeonly_memory)); + ac_build_buffer_store_format(&ctx->ac, rsrc, src, vindex, + ctx->ac.i32_0, src_channels, + args.cache_policy & ac_glc, + writeonly_memory); } else { args.opcode = ac_image_store; args.data[0] = ac_to_float(&ctx->ac, get_src(ctx, instr->src[3])); -- 2.21.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev