broadcom/compiler: allow pipelining of flat and noperspective varyings

These end up having a NOP between the ldvary and the next instruction
in the sequence (a MOV for flat and an FADD for noperspetive):

nop                  ; nop               ; ldvary.r0
nop                  ; nop
fadd  rf6, r0, r5    ; nop               ; ldvary.r1
nop                  ; nop
fadd  rf5, r1, r5    ; nop               ; ldvary.r2
nop                  ; nop
fadd  rf4, r2, r5    ; nop               ; ldvary.r3

To pipeline these, we can reuse the same infrastructure we have in
place for smooth varyings but we need to avoid breaking the sequence
due to the NOP instruction. We do that by testing if dropping the
sequence when we failed to pick up the next instruction also fails
to choose an instruction.

This is not perfect, because we may be able to choose an instruction
outside the sequence such as an ldunif, and use that to break a
sequence that we could otherwise continue after scheduling the NOP
instruction, but it is still better than nothing.

total instructions in shared programs: 13820690 -> 13819774 (<.01%)
instructions in affected programs: 64026 -> 63110 (-1.43%)
helped: 479
HURT: 62
Instructions are helped.

total max-temps in shared programs: 2326435 -> 2326423 (<.01%)
max-temps in affected programs: 102 -> 90 (-11.76%)
helped: 7
HURT: 0
Max-temps are helped.

total sfu-stalls in shared programs: 30683 -> 30710 (0.09%)
sfu-stalls in affected programs: 13 -> 40 (207.69%)
helped: 2
HURT: 24
Sfu-stalls are HURT.

total inst-and-stalls in shared programs: 13851373 -> 13850484 (<.01%)
inst-and-stalls in affected programs: 62818 -> 61929 (-1.42%)
helped: 466
HURT: 65
Inst-and-stalls are helped.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9304>
This commit is contained in:
Iago Toral Quiroga
2021-03-01 09:18:39 +01:00
parent 1784dd22a3
commit 05f8efbc2c
2 changed files with 49 additions and 9 deletions

View File

@@ -932,10 +932,8 @@ ldvary_sequence_inst(struct v3d_compile *c, struct qreg result)
return result;
}
static struct qreg
emit_smooth_varying(struct v3d_compile *c,
struct qinst *ldvary,
struct qreg vary, struct qreg w, struct qreg r5)
static void
track_ldvary_pipelining(struct v3d_compile *c, struct qinst *ldvary)
{
if (ldvary) {
c->ldvary_sequence_length++;
@@ -945,10 +943,38 @@ emit_smooth_varying(struct v3d_compile *c,
c->ldvary_sequence_start_inst = ldvary;
}
}
}
static struct qreg
emit_smooth_varying(struct v3d_compile *c,
struct qinst *ldvary,
struct qreg vary, struct qreg w, struct qreg r5)
{
track_ldvary_pipelining(c, ldvary);
return ldvary_sequence_inst(c, vir_FADD(c,
ldvary_sequence_inst(c, vir_FMUL(c, vary, w)), r5));
}
static struct qreg
emit_noperspective_varying(struct v3d_compile *c,
struct qinst *ldvary,
struct qreg vary, struct qreg r5)
{
track_ldvary_pipelining(c, ldvary);
return ldvary_sequence_inst(c, vir_FADD(c,
ldvary_sequence_inst(c, vir_MOV(c, vary)), r5));
}
static struct qreg
emit_flat_varying(struct v3d_compile *c,
struct qinst *ldvary,
struct qreg vary, struct qreg r5)
{
track_ldvary_pipelining(c, ldvary);
vir_MOV_dest(c, c->undef, vary);
return ldvary_sequence_inst(c, vir_MOV(c, r5));
}
static void
break_smooth_varying_sequence(struct v3d_compile *c)
{
@@ -1032,16 +1058,13 @@ emit_fragment_varying(struct v3d_compile *c, nir_variable *var,
break;
case INTERP_MODE_NOPERSPECTIVE:
break_smooth_varying_sequence(c);
BITSET_SET(c->noperspective_flags, i);
result = vir_FADD(c, vir_MOV(c, vary), r5);
result = emit_noperspective_varying(c, ldvary, vary, r5);
break;
case INTERP_MODE_FLAT:
break_smooth_varying_sequence(c);
BITSET_SET(c->flat_shade_flags, i);
vir_MOV_dest(c, c->undef, vary);
result = vir_MOV(c, r5);
result = emit_flat_varying(c, ldvary, vary, r5);
break;
default:

View File

@@ -1050,10 +1050,27 @@ choose_instruction_to_schedule(const struct v3d_device_info *devinfo,
* them, however, if we failed to find anything to schedule then we
* can't possibly continue the sequence and we need to stop the
* pipelining process and try again.
*
* There is one exception to the above: noperspective or flat
* varyings can cause us to not be able to pick an instruction
* because they need a nop between the ldvary and the next instruction
* to account for the ldvary r5 write latency. We can try to detect this
* by checking if we are also unable to schedule an instruction after
* disabling pipelining.
*
* FIXME: dropping pipelining and picking up another instruction could
* break the sequence for flat/noperspective varyings we could've been
* able to continue if we returned NULL here and scheduled a NOP as a
* result, but detecting this case would require us to know in advance
* that emitting the next NOP will guarantee that we will be able to
* continue the sequence.
*/
if (scoreboard->ldvary_pipelining && !prev_inst && !chosen) {
bool prev_ldvary_pipelining = scoreboard->ldvary_pipelining;
scoreboard->ldvary_pipelining = false;
chosen = choose_instruction_to_schedule(devinfo, scoreboard, prev_inst);
if (!chosen)
scoreboard->ldvary_pipelining = prev_ldvary_pipelining;
} else if (chosen) {
if (scoreboard->ldvary_pipelining) {
assert(chosen->inst->ldvary_pipelining);