vc4: Make sure we allocate idle BOs from the cache.
authorEric Anholt <eric@anholt.net>
Sat, 30 May 2015 01:06:32 +0000 (18:06 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 30 May 2015 01:15:00 +0000 (18:15 -0700)
We were returning the most recently freed BO, without checking if it
was idle yet.  This meant that we generally stalled immediately on the
previous frame when generating a new one.  Instead, allocate new BOs
when the *oldest* BO is still busy, so that the cache scales with how
much is needed to keep some frames outstanding, as originally
intended.

Note that if you don't have some throttling happening, this means that
you can accidentally run the system out of memory.  The kernel is now
applying some throttling on all execs, to hopefully avoid this.

src/gallium/drivers/vc4/vc4_bufmgr.c

index 8f9d9c3ff77d0cf2cccfb88ea4a04748cc3b40ef..8d9767077913cb908223ea3e6ff630694f5ae6e9 100644 (file)
@@ -49,8 +49,18 @@ vc4_bo_from_cache(struct vc4_screen *screen, uint32_t size, const char *name)
         struct vc4_bo *bo = NULL;
         pipe_mutex_lock(cache->lock);
         if (!is_empty_list(&cache->size_list[page_index])) {
-                struct simple_node *node = last_elem(&cache->size_list[page_index]);
+                struct simple_node *node = first_elem(&cache->size_list[page_index]);
                 bo = container_of(node, struct vc4_bo, size_list);
+
+                /* Check that the BO has gone idle.  If not, then we want to
+                 * allocate something new instead, since we assume that the
+                 * user will proceed to CPU map it and fill it with stuff.
+                 */
+                if (!vc4_bo_wait(bo, 0)) {
+                        pipe_mutex_unlock(cache->lock);
+                        return NULL;
+                }
+
                 pipe_reference_init(&bo->reference, 1);
                 remove_from_list(&bo->time_list);
                 remove_from_list(&bo->size_list);