freedreno: Avoid duplicate BO relocs in FD_RINGBUFFER_OBJECTs.
authorEric Anholt <eric@anholt.net>
Fri, 8 May 2020 21:53:47 +0000 (14:53 -0700)
committerMarge Bot <eric+marge@anholt.net>
Thu, 14 May 2020 14:12:15 +0000 (14:12 +0000)
For the piglit drawoverhead case, 5/18 of the objects' relocs were
duplicated.  We can dedupe them at object create time (since objects are
long-lived) and avoid repeated relocation work at emit time.

nohw drawoverhead program statechange throughput 2.34082% +/- 0.645832%
(n=10).

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5020>

src/freedreno/drm/msm_ringbuffer_sp.c

index 6bab90b190a058799946f1a427378b9c0dc42e99..869c41ddda66c8ceaaf82ad5379b543938abb10c 100644 (file)
@@ -385,9 +385,23 @@ msm_ringbuffer_sp_emit_reloc(struct fd_ringbuffer *ring,
        struct fd_pipe *pipe;
 
        if (ring->flags & _FD_RINGBUFFER_OBJECT) {
-               unsigned idx = APPEND(&msm_ring->u, reloc_bos);
-
-               msm_ring->u.reloc_bos[idx] = fd_bo_ref(reloc->bo);
+               /* Avoid emitting duplicate BO references into the list.  Ringbuffer
+                * objects are long-lived, so this saves ongoing work at draw time in
+                * exchange for a bit at context setup/first draw.  And the number of
+                * relocs per ringbuffer object is fairly small, so the O(n^2) doesn't
+                * hurt much.
+                */
+               bool found = false;
+               for (int i = 0; i < msm_ring->u.nr_reloc_bos; i++) {
+                       if (msm_ring->u.reloc_bos[i] == reloc->bo) {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found) {
+                       unsigned idx = APPEND(&msm_ring->u, reloc_bos);
+                       msm_ring->u.reloc_bos[idx] = fd_bo_ref(reloc->bo);
+               }
 
                pipe = msm_ring->u.pipe;
        } else {