[PATCH] etnaviv: Use the correct LOG instruction on GC3000

Lucas Stach l.stach at pengutronix.de
Tue Jul 11 13:17:47 UTC 2017


Am Dienstag, den 11.07.2017, 15:07 +0200 schrieb Wladimir J. van der
Laan:
> GC3000 has a new LOG instruction, similar to the new SIN and COS instructions.
> 
> Generate the new instruction sequence when appropriate; there are
> two occasions, as part of LIT and the generator for the LG2
> instruction itself.
> 
> Signed-off-by: Wladimir J. van der Laan <laanwj at gmail.com>

In a quick test this fixes all the misrendering I was observing in the
various glmark2 benchmarks on GC3000.

Tested-by: Lucas Stach <l.stach at pengutronix.de>

> ---
>  src/gallium/drivers/etnaviv/etnaviv_compiler.c | 63 +++++++++++++++++++++++---
>  src/gallium/drivers/etnaviv/etnaviv_internal.h |  4 +-
>  src/gallium/drivers/etnaviv/etnaviv_screen.c   |  2 +-
>  3 files changed, 59 insertions(+), 10 deletions(-)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> index 07315f7..6435b84 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> @@ -1389,12 +1389,27 @@ trans_lit(const struct instr_translater *t, struct etna_compile *c,
>     else
>        src_w = swizzle(src[0], SWIZZLE(W, W, W, W));
>  
> -   struct etna_inst ins[3] = { };
> -   ins[0].opcode = INST_OPCODE_LOG;
> -   ins[0].dst = etna_native_to_dst(inner_temp, INST_COMPS_X);
> -   ins[0].src[2] = src_y;
> +   if (c->specs->has_new_transcendentals) { /* Alternative LOG sequence */
> +      emit_inst(c, &(struct etna_inst) {
> +         .opcode = INST_OPCODE_LOG,
> +         .dst = etna_native_to_dst(inner_temp, INST_COMPS_X | INST_COMPS_Y),
> +         .src[2] = src_y,
> +         .tex = { .amode=1 }, /* Unknown bit needs to be set */
> +      });
> +      emit_inst(c, &(struct etna_inst) {
> +         .opcode = INST_OPCODE_MUL,
> +         .dst = etna_native_to_dst(inner_temp, INST_COMPS_X),
> +         .src[0] = etna_native_to_src(inner_temp, SWIZZLE(X, X, X, X)),
> +         .src[1] = etna_native_to_src(inner_temp, SWIZZLE(Y, Y, Y, Y)),
> +      });
> +   } else {
> +      struct etna_inst ins[3] = { };
> +      ins[0].opcode = INST_OPCODE_LOG;
> +      ins[0].dst = etna_native_to_dst(inner_temp, INST_COMPS_X);
> +      ins[0].src[2] = src_y;
>  
> -   emit_inst(c, &ins[0]);
> +      emit_inst(c, &ins[0]);
> +   }
>     emit_inst(c, &(struct etna_inst) {
>        .opcode = INST_OPCODE_MUL,
>        .sat = 0,
> @@ -1450,7 +1465,7 @@ static void
>  trans_trig(const struct instr_translater *t, struct etna_compile *c,
>             const struct tgsi_full_instruction *inst, struct etna_inst_src *src)
>  {
> -   if (c->specs->has_new_sin_cos) { /* Alternative SIN/COS */
> +   if (c->specs->has_new_transcendentals) { /* Alternative SIN/COS */
>        /* On newer chips alternative SIN/COS instructions are implemented,
>         * which:
>         * - Need their input scaled by 1/pi instead of 2/pi
> @@ -1613,6 +1628,40 @@ trans_trig(const struct instr_translater *t, struct etna_compile *c,
>  }
>  
>  static void
> +trans_lg2(const struct instr_translater *t, struct etna_compile *c,
> +            const struct tgsi_full_instruction *inst, struct etna_inst_src *src)
> +{
> +   if (c->specs->has_new_transcendentals) {
> +      /* On newer chips alternative LOG instruction is implemented,
> +       * which outputs an x and y component, which need to be multiplied to
> +       * get the result.
> +       */
> +      struct etna_native_reg temp = etna_compile_get_inner_temp(c); /* only using .xy */
> +      emit_inst(c, &(struct etna_inst) {
> +         .opcode = INST_OPCODE_LOG,
> +         .sat = 0,
> +         .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y),
> +         .src[2] = src[0],
> +         .tex = { .amode=1 }, /* Unknown bit needs to be set */
> +      });
> +      emit_inst(c, &(struct etna_inst) {
> +         .opcode = INST_OPCODE_MUL,
> +         .sat = inst->Instruction.Saturate,
> +         .dst = convert_dst(c, &inst->Dst[0]),
> +         .src[0] = etna_native_to_src(temp, SWIZZLE(X, X, X, X)),
> +         .src[1] = etna_native_to_src(temp, SWIZZLE(Y, Y, Y, Y)),
> +      });
> +   } else {
> +      emit_inst(c, &(struct etna_inst) {
> +         .opcode = INST_OPCODE_LOG,
> +         .sat = inst->Instruction.Saturate,
> +         .dst = convert_dst(c, &inst->Dst[0]),
> +         .src[2] = src[0],
> +      });
> +   }
> +}
> +
> +static void
>  trans_dph(const struct instr_translater *t, struct etna_compile *c,
>            const struct tgsi_full_instruction *inst, struct etna_inst_src *src)
>  {
> @@ -1753,7 +1802,7 @@ static const struct instr_translater translaters[TGSI_OPCODE_LAST] = {
>     INSTR(DST, trans_instr, .opc = INST_OPCODE_DST, .src = {0, 1, -1}),
>     INSTR(MAD, trans_instr, .opc = INST_OPCODE_MAD, .src = {0, 1, 2}),
>     INSTR(EX2, trans_instr, .opc = INST_OPCODE_EXP, .src = {2, -1, -1}),
> -   INSTR(LG2, trans_instr, .opc = INST_OPCODE_LOG, .src = {2, -1, -1}),
> +   INSTR(LG2, trans_lg2),
>     INSTR(SQRT, trans_instr, .opc = INST_OPCODE_SQRT, .src = {2, -1, -1}),
>     INSTR(FRC, trans_instr, .opc = INST_OPCODE_FRC, .src = {2, -1, -1}),
>     INSTR(CEIL, trans_instr, .opc = INST_OPCODE_CEIL, .src = {2, -1, -1}),
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h
> index 1212fdf..8a31167 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h
> @@ -70,8 +70,8 @@ struct etna_specs {
>     unsigned has_sign_floor_ceil : 1;
>     /* can use VS_RANGE, PS_RANGE registers*/
>     unsigned has_shader_range_registers : 1;
> -   /* has the new sin/cos functions */
> -   unsigned has_new_sin_cos : 1;
> +   /* has the new sin/cos/log functions */
> +   unsigned has_new_transcendentals : 1;
>     /* supports single-buffer rendering with multiple pixel pipes */
>     unsigned single_buffer : 1;
>     /* can use any kind of wrapping mode on npot textures */
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> index 60679fb..ec8de96 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> @@ -642,7 +642,7 @@ etna_get_specs(struct etna_screen *screen)
>        screen->model >= 0x1000 || screen->model == 0x880;
>     screen->specs.npot_tex_any_wrap =
>        VIV_FEATURE(screen, chipMinorFeatures1, NON_POWER_OF_TWO);
> -   screen->specs.has_new_sin_cos =
> +   screen->specs.has_new_transcendentals =
>        VIV_FEATURE(screen, chipMinorFeatures3, HAS_FAST_TRANSCENDENTALS);
>  
>     if (VIV_FEATURE(screen, chipMinorFeatures3, INSTRUCTION_CACHE)) {




More information about the etnaviv mailing list