From 6069e78238ca57e3433d528680fe04766a1e5307 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Sep 2012 16:22:49 +0100 Subject: sna: Keep a very small, short-lived cache of large buffers As we now regularly retire and so discard the temporary large buffers, we find them in short supply and ourselves wasting lots of time creating and destroying the transient buffers. Signed-off-by: Chris Wilson --- src/sna/kgem.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/sna/kgem.h | 1 + 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index d675ebb8..f68b0546 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -858,6 +858,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen) list_init(&kgem->active_buffers); list_init(&kgem->flushing); list_init(&kgem->large); + list_init(&kgem->large_inactive); list_init(&kgem->snoop); for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) list_init(&kgem->inactive[i]); @@ -1287,8 +1288,10 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem, assert(!bo->needs_flush); assert(list_is_empty(&bo->vma)); + kgem->need_expire = true; + if (bucket(bo) >= NUM_CACHE_BUCKETS) { - kgem_bo_free(kgem, bo); + list_move(&bo->list, &kgem->large_inactive); return; } @@ -1306,8 +1309,6 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem, kgem->vma[type].count++; } } - - kgem->need_expire = true; } inline static void kgem_bo_remove_from_inactive(struct kgem *kgem, @@ -2411,6 +2412,13 @@ bool kgem_expire_cache(struct kgem *kgem) free(rq); } + while (!list_is_empty(&kgem->large_inactive)) { + kgem_bo_free(kgem, + list_first_entry(&kgem->large_inactive, + struct kgem_bo, list)); + + } + expire = 0; list_for_each_entry(bo, &kgem->snoop, list) { if (bo->delta) { @@ -3095,9 +3103,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, __FUNCTION__, size, bucket)); if (flags & CREATE_INACTIVE) - goto create; + goto large_inactive; - tiled_height = kgem_aligned_height(kgem, height, I915_TILING_Y); + tiled_height = kgem_aligned_height(kgem, height, tiling); untiled_pitch = kgem_untiled_pitch(kgem, width, bpp, flags); list_for_each_entry(bo, &kgem->large, list) { @@ -3105,18 +3113,28 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, assert(bo->refcnt == 0); assert(bo->reusable); - if (bo->tiling) { + if (kgem->gen < 40) { if (bo->pitch < pitch) { DBG(("tiled and pitch too small: tiling=%d, (want %d), pitch=%d, need %d\n", bo->tiling, tiling, bo->pitch, pitch)); continue; } - } else - bo->pitch = untiled_pitch; - if (bo->pitch * tiled_height > bytes(bo)) - continue; + if (bo->pitch * tiled_height > bytes(bo)) + continue; + } else { + if (num_pages(bo) < size) + continue; + + if (bo->pitch != pitch || bo->tiling != tiling) { + if (gem_set_tiling(kgem->fd, bo->handle, + tiling, pitch) != tiling) + continue; + + bo->pitch = pitch; + } + } kgem_bo_remove_from_active(kgem, bo); @@ -3129,6 +3147,39 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, return bo; } +large_inactive: + list_for_each_entry(bo, &kgem->large_inactive, list) { + assert(bo->refcnt == 0); + assert(bo->reusable); + + if (size > num_pages(bo)) + continue; + + if (bo->tiling != tiling || + (tiling != I915_TILING_NONE && bo->pitch != pitch)) { + if (tiling != gem_set_tiling(kgem->fd, + bo->handle, + tiling, pitch)) + continue; + } + + if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) { + kgem_bo_free(kgem, bo); + break; + } + + list_del(&bo->list); + + bo->unique_id = kgem_get_unique_id(kgem); + bo->pitch = pitch; + bo->delta = 0; + DBG((" 1:from large inactive: pitch=%d, tiling=%d, handle=%d, id=%d\n", + bo->pitch, bo->tiling, bo->handle, bo->unique_id)); + assert(bo->pitch*kgem_aligned_height(kgem, height, bo->tiling) <= kgem_bo_size(bo)); + bo->refcnt = 1; + return bo; + } + goto create; } @@ -3407,6 +3458,8 @@ search_inactive: } create: + if (bucket >= NUM_CACHE_BUCKETS) + size = ALIGN(size, 1024); handle = gem_create(kgem->fd, size); if (handle == 0) return NULL; diff --git a/src/sna/kgem.h b/src/sna/kgem.h index fb8be3d0..073635f9 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -123,6 +123,7 @@ struct kgem { struct list flushing; struct list large; + struct list large_inactive; struct list active[NUM_CACHE_BUCKETS][3]; struct list inactive[NUM_CACHE_BUCKETS]; struct list snoop; -- cgit v1.2.3