etnaviv: Generate new sin/cos instructions on GC3000
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. CC: <mesa-stable@lists.freedesktop.org> Signed-off-by: Wladimir J. van der Laan <laanwj@gmail.com> Acked-by: Christian Gmeiner <christian.gmeiner@gmail.com>
This commit is contained in:
parent
33e0c5d003
commit
fe3bb8cdb5
|
@ -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);
|
||||
|
||||
|
|
|
@ -59,6 +59,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 */
|
||||
|
|
|
@ -622,6 +622,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;
|
||||
|
|
Loading…
Reference in New Issue