Message ID | 20170131082351.GA27316@amethyst.visucore.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2017-01-31 9:23 GMT+01:00 Wladimir J. van der Laan <laanwj@gmail.com>: > Shaders using sin/cos instructions were not working on GC3000. > > The reason for this turns out to be that these chips implement sin/cos > in a different way (but using the same opcodes): > > - Need their input scaled by 1/pi instead of 2/pi. > > - Output an x and y component, which need to be multiplied to > get the result. > > - tex_amode needs to be set to 1. > > Add a new bit to the compiler specs and generate these instructions > as necessary. > > Signed-Off-By: Wladimir J. van der Laan <laanwj@gmail.com> Acked-by: Christian Gmeiner <christian.gmeiner@gmail.com> > --- > src/gallium/drivers/etnaviv/etnaviv_compiler.c | 37 +++++++++++++++++++++++++- > src/gallium/drivers/etnaviv/etnaviv_internal.h | 2 ++ > src/gallium/drivers/etnaviv/etnaviv_screen.c | 2 ++ > 3 files changed, 40 insertions(+), 1 deletion(-) > > diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c > index 59e1452..c4519e7 100644 > --- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c > +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c > @@ -1444,7 +1444,42 @@ 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_sin_cos_sqrt) { > + if (c->specs->has_new_sin_cos) { /* Alternative SIN/COS */ > + /* On newer chips alternative SIN/COS instructions are implemented, > + * which: > + * - Need their input scaled by 1/pi instead of 2/pi > + * - Output an x and y component, which need to be multiplied to > + * get the result > + */ > + /* TGSI lowering should deal with SCS */ > + assert(inst->Instruction.Opcode != TGSI_OPCODE_SCS); > + > + struct etna_native_reg temp = etna_compile_get_inner_temp(c); /* only using .xyz */ > + emit_inst(c, &(struct etna_inst) { > + .opcode = INST_OPCODE_MUL, > + .sat = 0, > + .dst = etna_native_to_dst(temp, INST_COMPS_Z), > + .src[0] = src[0], /* any swizzling happens here */ > + .src[1] = alloc_imm_f32(c, 1.0f / M_PI), > + }); > + emit_inst(c, &(struct etna_inst) { > + .opcode = inst->Instruction.Opcode == TGSI_OPCODE_COS > + ? INST_OPCODE_COS > + : INST_OPCODE_SIN, > + .sat = 0, > + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y), > + .src[2] = etna_native_to_src(temp, SWIZZLE(Z, Z, Z, Z)), > + .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 if (c->specs->has_sin_cos_sqrt) { > /* TGSI lowering should deal with SCS */ > assert(inst->Instruction.Opcode != TGSI_OPCODE_SCS); > > diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h > index f340116..2f09d55 100644 > --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h > +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h > @@ -70,6 +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; > /* can use any kind of wrapping mode on npot textures */ > unsigned npot_tex_any_wrap; > /* number of bits per TS tile */ > diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c > index 53a31c5..0af7078 100644 > --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c > +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c > @@ -620,6 +620,8 @@ 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 = > + VIV_FEATURE(screen, chipMinorFeatures3, HAS_FAST_TRANSCENDENTALS); > > if (instruction_count > 256) { /* unified instruction memory? */ > screen->specs.vs_offset = 0xC000; > -- > 2.7.4 > greets -- Christian Gmeiner, MSc https://www.youtube.com/user/AloryOFFICIAL https://soundcloud.com/christian-gmeiner
diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c index 59e1452..c4519e7 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c @@ -1444,7 +1444,42 @@ 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_sin_cos_sqrt) { + if (c->specs->has_new_sin_cos) { /* Alternative SIN/COS */ + /* On newer chips alternative SIN/COS instructions are implemented, + * which: + * - Need their input scaled by 1/pi instead of 2/pi + * - Output an x and y component, which need to be multiplied to + * get the result + */ + /* TGSI lowering should deal with SCS */ + assert(inst->Instruction.Opcode != TGSI_OPCODE_SCS); + + struct etna_native_reg temp = etna_compile_get_inner_temp(c); /* only using .xyz */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_Z), + .src[0] = src[0], /* any swizzling happens here */ + .src[1] = alloc_imm_f32(c, 1.0f / M_PI), + }); + emit_inst(c, &(struct etna_inst) { + .opcode = inst->Instruction.Opcode == TGSI_OPCODE_COS + ? INST_OPCODE_COS + : INST_OPCODE_SIN, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y), + .src[2] = etna_native_to_src(temp, SWIZZLE(Z, Z, Z, Z)), + .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 if (c->specs->has_sin_cos_sqrt) { /* TGSI lowering should deal with SCS */ assert(inst->Instruction.Opcode != TGSI_OPCODE_SCS); diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h index f340116..2f09d55 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h @@ -70,6 +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; /* can use any kind of wrapping mode on npot textures */ unsigned npot_tex_any_wrap; /* number of bits per TS tile */ diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index 53a31c5..0af7078 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -620,6 +620,8 @@ 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 = + VIV_FEATURE(screen, chipMinorFeatures3, HAS_FAST_TRANSCENDENTALS); if (instruction_count > 256) { /* unified instruction memory? */ screen->specs.vs_offset = 0xC000;
Shaders using sin/cos instructions were not working on GC3000. The reason for this turns out to be that these chips implement sin/cos in a different way (but using the same opcodes): - Need their input scaled by 1/pi instead of 2/pi. - Output an x and y component, which need to be multiplied to get the result. - tex_amode needs to be set to 1. Add a new bit to the compiler specs and generate these instructions as necessary. Signed-Off-By: Wladimir J. van der Laan <laanwj@gmail.com> --- src/gallium/drivers/etnaviv/etnaviv_compiler.c | 37 +++++++++++++++++++++++++- src/gallium/drivers/etnaviv/etnaviv_internal.h | 2 ++ src/gallium/drivers/etnaviv/etnaviv_screen.c | 2 ++ 3 files changed, 40 insertions(+), 1 deletion(-)