[Mesa-dev] [PATCH 2/2] radeonsi: support indirect indexing in INTERP_* opcodes

Marek Olšák maraeo at gmail.com
Mon Jun 19 19:59:00 UTC 2017


Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Fri, Jun 16, 2017 at 10:37 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> The hardware doesn't support it, so we just interpolate all array elements
> and then use indirect indexing on the resulting vector.
>
> Clearly, this is not very efficient. There is an argument to be had for
> adding if/else, or perhaps even pulling the data out of LDS directly.
> Both don't really seem worth the effort, considering that it seems nobody
> actually uses this feature.
> ---
>  src/gallium/drivers/radeonsi/si_shader.c | 78 ++++++++++++++++++++++++--------
>  1 file changed, 58 insertions(+), 20 deletions(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
> index e525a18..370022f 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.c
> +++ b/src/gallium/drivers/radeonsi/si_shader.c
> @@ -3517,49 +3517,70 @@ static void interp_fetch_args(
>         }
>  }
>
>  static void build_interp_intrinsic(const struct lp_build_tgsi_action *action,
>                                 struct lp_build_tgsi_context *bld_base,
>                                 struct lp_build_emit_data *emit_data)
>  {
>         struct si_shader_context *ctx = si_shader_context(bld_base);
>         struct si_shader *shader = ctx->shader;
>         struct gallivm_state *gallivm = &ctx->gallivm;
> +       const struct tgsi_shader_info *info = &shader->selector->info;
>         LLVMValueRef interp_param;
>         const struct tgsi_full_instruction *inst = emit_data->inst;
> -       int input_index = inst->Src[0].Register.Index;
> +       const struct tgsi_full_src_register *input = &inst->Src[0];
> +       int input_base, input_array_size;
>         int chan;
>         int i;
> -       LLVMValueRef attr_number;
>         LLVMValueRef params = LLVMGetParam(ctx->main_fn, SI_PARAM_PRIM_MASK);
> +       LLVMValueRef array_idx;
>         int interp_param_idx;
> -       unsigned interp = shader->selector->info.input_interpolate[input_index];
> +       unsigned interp;
>         unsigned location;
>
> -       assert(inst->Src[0].Register.File == TGSI_FILE_INPUT);
> +       assert(input->Register.File == TGSI_FILE_INPUT);
> +
> +       if (input->Register.Indirect) {
> +               unsigned array_id = input->Indirect.ArrayID;
> +
> +               if (array_id) {
> +                       input_base = info->input_array_first[array_id];
> +                       input_array_size = info->input_array_last[array_id] - input_base + 1;
> +               } else {
> +                       input_base = inst->Src[0].Register.Index;
> +                       input_array_size = info->num_inputs - input_base;
> +               }
> +
> +               array_idx = get_indirect_index(ctx, &input->Indirect,
> +                                              input->Register.Index - input_base);
> +       } else {
> +               input_base = inst->Src[0].Register.Index;
> +               input_array_size = 1;
> +               array_idx = ctx->i32_0;
> +       }
> +
> +       interp = shader->selector->info.input_interpolate[input_base];
>
>         if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
>             inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE)
>                 location = TGSI_INTERPOLATE_LOC_CENTER;
>         else
>                 location = TGSI_INTERPOLATE_LOC_CENTROID;
>
>         interp_param_idx = lookup_interp_param_index(interp, location);
>         if (interp_param_idx == -1)
>                 return;
>         else if (interp_param_idx)
>                 interp_param = LLVMGetParam(ctx->main_fn, interp_param_idx);
>         else
>                 interp_param = NULL;
>
> -       attr_number = LLVMConstInt(ctx->i32, input_index, 0);
> -
>         if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
>             inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) {
>                 LLVMValueRef ij_out[2];
>                 LLVMValueRef ddxy_out = si_llvm_emit_ddxy_interp(bld_base, interp_param);
>
>                 /*
>                  * take the I then J parameters, and the DDX/Y for it, and
>                  * calculate the IJ inputs for the interpolator.
>                  * temp1 = ddx * offset/sample.x + I;
>                  * interp_param.I = ddy * offset/sample.y + temp1;
> @@ -3584,42 +3605,59 @@ static void build_interp_intrinsic(const struct lp_build_tgsi_action *action,
>
>                         temp1 = LLVMBuildFAdd(gallivm->builder, temp1, interp_el, "");
>
>                         temp2 = LLVMBuildFMul(gallivm->builder, ddy_el, emit_data->args[1], "");
>
>                         ij_out[i] = LLVMBuildFAdd(gallivm->builder, temp2, temp1, "");
>                 }
>                 interp_param = lp_build_gather_values(gallivm, ij_out, 2);
>         }
>
> +       if (interp_param) {
> +               interp_param = LLVMBuildBitCast(gallivm->builder,
> +                       interp_param, LLVMVectorType(ctx->f32, 2), "");
> +       }
> +
>         for (chan = 0; chan < 4; chan++) {
>                 LLVMValueRef llvm_chan;
> +               LLVMValueRef gather = LLVMGetUndef(LLVMVectorType(ctx->f32, input_array_size));
>                 unsigned schan;
>
>                 schan = tgsi_util_get_full_src_register_swizzle(&inst->Src[0], chan);
>                 llvm_chan = LLVMConstInt(ctx->i32, schan, 0);
>
> -               if (interp_param) {
> -                       interp_param = LLVMBuildBitCast(gallivm->builder,
> -                               interp_param, LLVMVectorType(ctx->f32, 2), "");
> -                       LLVMValueRef i = LLVMBuildExtractElement(
> -                               gallivm->builder, interp_param, ctx->i32_0, "");
> -                       LLVMValueRef j = LLVMBuildExtractElement(
> -                               gallivm->builder, interp_param, ctx->i32_1, "");
> -                       emit_data->output[chan] = ac_build_fs_interp(&ctx->ac,
> -                               llvm_chan, attr_number, params,
> -                               i, j);
> -               } else {
> -                       emit_data->output[chan] = ac_build_fs_interp_mov(&ctx->ac,
> -                               LLVMConstInt(ctx->i32, 2, 0), /* P0 */
> -                               llvm_chan, attr_number, params);
> +               for (unsigned i = 0; i < input_array_size; ++i) {
> +                       LLVMValueRef attr_number = LLVMConstInt(ctx->i32, input_base + i, false);
> +                       LLVMValueRef v;
> +
> +                       if (interp_param) {
> +                               interp_param = LLVMBuildBitCast(gallivm->builder,
> +                                       interp_param, LLVMVectorType(ctx->f32, 2), "");
> +                               LLVMValueRef i = LLVMBuildExtractElement(
> +                                       gallivm->builder, interp_param, ctx->i32_0, "");
> +                               LLVMValueRef j = LLVMBuildExtractElement(
> +                                       gallivm->builder, interp_param, ctx->i32_1, "");
> +                               v = ac_build_fs_interp(&ctx->ac,
> +                                       llvm_chan, attr_number, params,
> +                                       i, j);
> +                       } else {
> +                               v = ac_build_fs_interp_mov(&ctx->ac,
> +                                       LLVMConstInt(ctx->i32, 2, 0), /* P0 */
> +                                       llvm_chan, attr_number, params);
> +                       }
> +
> +                       gather = LLVMBuildInsertElement(gallivm->builder,
> +                               gather, v, LLVMConstInt(ctx->i32, i, false), "");
>                 }
> +
> +               emit_data->output[chan] = LLVMBuildExtractElement(
> +                       gallivm->builder, gather, array_idx, "");
>         }
>  }
>
>  static LLVMValueRef si_emit_ballot(struct si_shader_context *ctx,
>                                    LLVMValueRef value)
>  {
>         struct gallivm_state *gallivm = &ctx->gallivm;
>         LLVMValueRef args[3] = {
>                 value,
>                 ctx->i32_0,
> --
> 2.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list