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:
@@ -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:
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user