Module: Mesa
Branch: master
Commit: 05f8efbc2cb35298d07ab55d4319cbe470c42108
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=05f8efbc2cb35298d07ab55d4319cbe470c42108

Author: Iago Toral Quiroga <[email protected]>
Date:   Mon Mar  1 09:18:39 2021 +0100

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 <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9304>

---

 src/broadcom/compiler/nir_to_vir.c   | 41 ++++++++++++++++++++++++++++--------
 src/broadcom/compiler/qpu_schedule.c | 17 +++++++++++++++
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/broadcom/compiler/nir_to_vir.c 
b/src/broadcom/compiler/nir_to_vir.c
index 9e7d308745b..dc83c015821 100644
--- a/src/broadcom/compiler/nir_to_vir.c
+++ b/src/broadcom/compiler/nir_to_vir.c
@@ -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:
diff --git a/src/broadcom/compiler/qpu_schedule.c 
b/src/broadcom/compiler/qpu_schedule.c
index 571a89fb7be..f4b0d5a86e5 100644
--- a/src/broadcom/compiler/qpu_schedule.c
+++ b/src/broadcom/compiler/qpu_schedule.c
@@ -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);

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to