[Mesa-dev] [PATCH 04/14] radeonsi: Add buffer load functions.

Nicolai Hähnle nhaehnle at gmail.com
Tue May 10 16:13:10 UTC 2016


On 10.05.2016 05:52, Bas Nieuwenhuizen wrote:
> Signed-off-by: Bas Nieuwenhuizen <bas at 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.

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.
>    *
>


More information about the mesa-dev mailing list