[Mesa-dev] [PATCH 1/2] radeonsi: add support for indirect samplers

Marek Olšák maraeo at gmail.com
Thu Jul 23 07:26:00 PDT 2015


On Wed, Jul 22, 2015 at 3:27 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This adds the frontend support, however the llvm
> backend produces the wrong pattern, however
> we can conditionalise enabling ARB_gpu_shader5
> on whatever version of llvm we fix this in.

The driver can assume that this is fixed in LLVM 3.7. We should only
ensure that the LLVM fix will be pushed before LLVM 3.7 is released
(end of August).


>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  docs/GL3.txt                             |  2 +-
>  src/gallium/drivers/radeonsi/si_shader.c | 88 ++++++++++++++++++++++++++++----
>  2 files changed, 79 insertions(+), 11 deletions(-)
>
> diff --git a/docs/GL3.txt b/docs/GL3.txt
> index d74ae63..ca3646c 100644
> --- a/docs/GL3.txt
> +++ b/docs/GL3.txt
> @@ -98,7 +98,7 @@ GL 4.0, GLSL 4.00:
>    GL_ARB_draw_indirect                                 DONE (i965, nvc0, r600, radeonsi, llvmpipe, softpipe)
>    GL_ARB_gpu_shader5                                   DONE (i965, nvc0)
>    - 'precise' qualifier                                DONE
> -  - Dynamically uniform sampler array indices          DONE (r600, softpipe)
> +  - Dynamically uniform sampler array indices          DONE (r600, radeonsi, softpipe)
>    - Dynamically uniform UBO array indices              DONE (r600)
>    - Implicit signed -> unsigned conversions            DONE
>    - Fused multiply-add                                 DONE ()
> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
> index 2705dcc..55357fa 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.c
> +++ b/src/gallium/drivers/radeonsi/si_shader.c
> @@ -1625,6 +1625,24 @@ static bool tgsi_is_shadow_sampler(unsigned target)
>
>  static const struct lp_build_tgsi_action tex_action;
>
> +/**
> + * Return the value of tgsi_ind_register for indexing.
> + * This is the indirect index with the constant offset added to it.
> + */
> +static LLVMValueRef get_indirect_index(struct si_shader_context *si_shader_ctx,
> +                                      const struct tgsi_ind_register *ind,
> +                                      int rel_index)
> +{
> +       struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm;
> +       LLVMValueRef result;
> +
> +       result = si_shader_ctx->radeon_bld.soa.addr[ind->Index][ind->Swizzle];
> +       result = LLVMBuildLoad(gallivm->builder, result, "");
> +       result = LLVMBuildAdd(gallivm->builder, result,
> +                             lp_build_const_int32(gallivm, rel_index), "");
> +       return result;
> +}

The master branch already has this function.

> +
>  static void tex_fetch_args(
>         struct lp_build_tgsi_context * bld_base,
>         struct lp_build_emit_data * emit_data)
> @@ -1640,10 +1658,36 @@ static void tex_fetch_args(
>         unsigned num_coords = tgsi_util_get_texture_coord_dim(target, &ref_pos);
>         unsigned count = 0;
>         unsigned chan;
> -       unsigned sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
> -       unsigned sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
> +       unsigned sampler_src;
> +       unsigned sampler_index;
>         bool has_offset = HAVE_LLVM >= 0x0305 ? inst->Texture.NumOffsets > 0 : false;
> +       bool has_sampler_indirect = false;
> +       LLVMValueRef res_ptr, samp_ptr;
> +
> +       sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
> +       sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
> +
> +       if (emit_data->inst->Src[sampler_src].Register.Indirect) {
> +               const struct tgsi_full_src_register *reg = &emit_data->inst->Src[sampler_src];
> +               unsigned first = reg->Register.Index;
> +               LLVMValueRef ind_index;
>
> +               ind_index = get_indirect_index(si_shader_ctx, &reg->Indirect,
> +                                          reg->Register.Index - first);

It looks like the last parameter is always 0. (first ==
reg->Register.Index) Therefore, reg->Register.Index is unused. Is that
the correct behavior?

> +
> +               res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE);
> +               res_ptr = build_indexed_load_const(si_shader_ctx, res_ptr,
> +                                            ind_index);
> +
> +               samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER);
> +               samp_ptr = build_indexed_load_const(si_shader_ctx, samp_ptr,
> +                                             ind_index);
> +               has_sampler_indirect = true;
> +
> +       } else {
> +               res_ptr = si_shader_ctx->resources[sampler_index];
> +               samp_ptr = si_shader_ctx->samplers[sampler_index];
> +       }
>         if (target == TGSI_TEXTURE_BUFFER) {
>                 LLVMTypeRef i128 = LLVMIntTypeInContext(gallivm->context, 128);
>                 LLVMTypeRef v2i128 = LLVMVectorType(i128, 2);
> @@ -1651,7 +1695,7 @@ static void tex_fetch_args(
>                 LLVMTypeRef v16i8 = LLVMVectorType(i8, 16);
>
>                 /* Bitcast and truncate v8i32 to v16i8. */
> -               LLVMValueRef res = si_shader_ctx->resources[sampler_index];
> +               LLVMValueRef res = res_ptr;
>                 res = LLVMBuildBitCast(gallivm->builder, res, v2i128, "");
>                 res = LLVMBuildExtractElement(gallivm->builder, res, bld_base->uint_bld.one, "");
>                 res = LLVMBuildBitCast(gallivm->builder, res, v16i8, "");
> @@ -1877,7 +1921,7 @@ static void tex_fetch_args(
>         }
>
>         /* Resource */
> -       emit_data->args[1] = si_shader_ctx->resources[sampler_index];
> +       emit_data->args[1] = res_ptr;
>
>         if (opcode == TGSI_OPCODE_TXF) {
>                 /* add tex offsets */
> @@ -1923,7 +1967,7 @@ static void tex_fetch_args(
>                         4);
>         } else if (opcode == TGSI_OPCODE_TG4 ||
>                    opcode == TGSI_OPCODE_LODQ ||
> -                  has_offset) {
> +                  has_offset || has_sampler_indirect) {

Why is this here? This codepath doesn't support all sampler types and
tex instructions yet.

>                 unsigned is_array = target == TGSI_TEXTURE_1D_ARRAY ||
>                                     target == TGSI_TEXTURE_SHADOW1D_ARRAY ||
>                                     target == TGSI_TEXTURE_2D_ARRAY ||
> @@ -1960,7 +2004,7 @@ static void tex_fetch_args(
>                         dmask = 1 << gather_comp;
>                 }
>
> -               emit_data->args[2] = si_shader_ctx->samplers[sampler_index];
> +               emit_data->args[2] = samp_ptr;
>                 emit_data->args[3] = lp_build_const_int32(gallivm, dmask);
>                 emit_data->args[4] = lp_build_const_int32(gallivm, is_rect); /* unorm */
>                 emit_data->args[5] = lp_build_const_int32(gallivm, 0); /* r128 */
> @@ -1976,7 +2020,7 @@ static void tex_fetch_args(
>                         LLVMFloatTypeInContext(gallivm->context),
>                         4);
>         } else {
> -               emit_data->args[2] = si_shader_ctx->samplers[sampler_index];
> +               emit_data->args[2] = samp_ptr;
>                 emit_data->args[3] = lp_build_const_int32(gallivm, target);
>                 emit_data->arg_count = 4;
>
> @@ -2009,7 +2053,16 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
>         char intr_name[127];
>         bool has_offset = HAVE_LLVM >= 0x0305 ?
>                                 emit_data->inst->Texture.NumOffsets > 0 : false;
> +       bool has_sampler_indirect = false;
> +       unsigned sampler_src;
> +
> +       if (emit_data->inst->Instruction.NumSrcRegs) {
> +               sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
>
> +               if (emit_data->inst->Src[sampler_src].Register.Indirect) {
> +                       has_sampler_indirect = true;
> +               }
> +       }
>         if (target == TGSI_TEXTURE_BUFFER) {
>                 emit_data->output[emit_data->chan] = build_intrinsic(
>                         base->gallivm->builder,
> @@ -2021,7 +2074,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
>
>         if (opcode == TGSI_OPCODE_TG4 ||
>             opcode == TGSI_OPCODE_LODQ ||
> -           (opcode != TGSI_OPCODE_TXF && has_offset)) {
> +           (opcode != TGSI_OPCODE_TXF && has_offset) || has_sampler_indirect) {

Same as above. This codepath doesn't support all sampler types and tex
instructions yet.


>                 bool is_shadow = tgsi_is_shadow_sampler(target);
>                 const char *name = "llvm.SI.image.sample";
>                 const char *infix = "";
> @@ -2122,13 +2175,28 @@ static void txq_fetch_args(
>         const struct tgsi_full_instruction *inst = emit_data->inst;
>         struct gallivm_state *gallivm = bld_base->base.gallivm;
>         unsigned target = inst->Texture.Texture;
> +       LLVMValueRef res_ptr;
> +
> +       if (inst->Src[1].Register.Indirect) {
> +               const struct tgsi_full_src_register *reg = &inst->Src[1];
> +               unsigned first = reg->Register.Index;
> +               LLVMValueRef ind_index;
> +
> +               ind_index = get_indirect_index(si_shader_ctx, &reg->Indirect,
> +                                          reg->Register.Index - first);

Same issue as above: the last parameter is always 0 and
reg->Register.Index is unused.

Marek


More information about the mesa-dev mailing list