On 10.05.2016 11:36, Bas Nieuwenhuizen wrote:
On Tue, May 10, 2016 at 6:28 PM, Nicolai Hähnle <nhaeh...@gmail.com> wrote:
On 10.05.2016 11:25, Bas Nieuwenhuizen wrote:

On Tue, May 10, 2016 at 6:13 PM, Nicolai Hähnle <nhaeh...@gmail.com>
wrote:

On 10.05.2016 05:52, Bas Nieuwenhuizen wrote:


Signed-off-by: Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl>
---
    src/gallium/drivers/radeonsi/si_shader.c | 81
++++++++++++++++++++++++++++++++
    1 file changed, 81 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c
b/src/gallium/drivers/radeonsi/si_shader.c
index 5897149..d3df4d6 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -733,6 +733,87 @@ static void build_tbuffer_store_dwords(struct
si_shader_context *ctx,
                              V_008F0C_BUF_NUM_FORMAT_UINT, 1, 0, 1, 1,
0);
    }

+static LLVMValueRef build_buffer_load(struct si_shader_context *ctx,
+                               LLVMValueRef rsrc,
+                               int num_channels,
+                               LLVMValueRef vindex,
+                               LLVMValueRef voffset,
+                               LLVMValueRef soffset,
+                               unsigned inst_offset,
+                               unsigned glc,
+                               unsigned slc)
+{
+       struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+       LLVMValueRef args[] = {
+               LLVMBuildBitCast(gallivm->builder, rsrc, ctx->v16i8,
""),
+               voffset ? voffset : vindex,
+               soffset,
+               LLVMConstInt(ctx->i32, inst_offset, 0),
+               LLVMConstInt(ctx->i32, voffset ? 1 : 0, 0), // offen
+               LLVMConstInt(ctx->i32, vindex ? 1 : 0, 0), //idxen
+               LLVMConstInt(ctx->i32, glc, 0),
+               LLVMConstInt(ctx->i32, slc, 0),
+               LLVMConstInt(ctx->i32, 0, 0), // TFE
+       };
+
+       unsigned func = CLAMP(num_channels, 1, 3) - 1;
+       LLVMTypeRef types[] = {ctx->i32, LLVMVectorType(ctx->i32, 2),
ctx->v4i32};
+       const char *type_names[] = {"i32", "v2i32", "v4i32"};
+       const char *arg_type = "i32";
+
+       if (voffset && vindex) {
+               LLVMValueRef vaddr[] = {vindex, voffset};
+
+               arg_type = "v2i32";
+               args[1] = lp_build_gather_values(gallivm, vaddr, 2);
+       }
+
+       char name[256];
+       snprintf(name, sizeof(name), "llvm.SI.buffer.load.dword.%s.%s",
+                type_names[func], arg_type);



We're generally trying to get away from the llvm.SI.* intrinsics and use
the
llvm.amdgcn.* intrinsic instead - in this case llvm.amdgcn.buffer.load.


The llvm.amdgcn.buffer.load doesn't allow specifiying VGPR + SGPR +
immediate offset separately though as far as I can see. Furthermore I
was trying to avoid a LLVM 3.9 dependency, although I can solve that
with if based on LLVM version.


Fair enough on the LLVM version dependency.

I also think you're right about llvm.amdgcn.buffer.load, but that's
something that should be fixed on the LLVM side eventually without
introducing a new intrinsic.

I am not sure if LLVM can eventually be able to. I don't know if the
vgpr + sgpr + immediate offset is wrapped around in 32-bit. Otherwise
a v_add and the offsets have different behavior and LLVM should not
sink the add into the load instruction.

That's a good point. I don't know the answer unfortunately...

Nicolai


- Bas


I think we should go for the if (HAVE_LLVM) approach even if it produces
slightly worse code for now (it really should be only one additional v_add
at most).

Nicolai


- Bas


Nicolai


+
+       return lp_build_intrinsic(gallivm->builder, name, types[func],
args,
+                                 ARRAY_SIZE(args),
LLVMReadOnlyAttribute
|
+
LLVMNoUnwindAttribute);
+}
+
+static LLVMValueRef buffer_load(struct lp_build_tgsi_context *bld_base,
+                                enum tgsi_opcode_type type, unsigned
swizzle,
+                                LLVMValueRef buffer, LLVMValueRef
offset,
+                                LLVMValueRef base)
+{
+       struct si_shader_context *ctx = si_shader_context(bld_base);
+       struct gallivm_state *gallivm = bld_base->base.gallivm;
+       LLVMValueRef value, value2;
+       LLVMTypeRef llvm_type = tgsi2llvmtype(bld_base, type);
+       LLVMTypeRef vec_type = LLVMVectorType(llvm_type, 4);
+
+       if (swizzle == ~0) {
+
+               value = build_buffer_load(ctx, buffer, 4, NULL, base,
offset,
+                                         0, 1, 0);
+
+               return LLVMBuildBitCast(gallivm->builder, value,
vec_type,
"");
+       }
+
+       if (type != TGSI_TYPE_DOUBLE) {
+               value = build_buffer_load(ctx, buffer, 4, NULL, base,
offset,
+                                         0, 1, 0);
+
+               value = LLVMBuildBitCast(gallivm->builder, value,
vec_type, "");
+               return LLVMBuildExtractElement(gallivm->builder, value,
+                                   lp_build_const_int32(gallivm,
swizzle), "");
+       }
+
+       value = build_buffer_load(ctx, buffer, 1, NULL, base, offset,
+                                 swizzle * 4, 1, 0);
+
+       value2 = build_buffer_load(ctx, buffer, 1, NULL, base, offset,
+                                  swizzle * 4 + 4, 1, 0);
+
+       return radeon_llvm_emit_fetch_double(bld_base, value, value2);
+}
+
    /**
     * Load from LDS.
     *



_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to