Reviewed-by: Marek Olšák <[email protected]> Marek
On Fri, Jun 16, 2017 at 10:37 PM, Nicolai Hähnle <[email protected]> wrote: > From: Nicolai Hähnle <[email protected]> > > 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 > [email protected] > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
