summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-09-12 16:22:49 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-09-12 16:24:25 +0100
commit6069e78238ca57e3433d528680fe04766a1e5307 (patch)
treecb5f62a54eed680785124241fa4c60a030e4c64a /src
parent1e2a03ad19664e846ece4110e53d26babb5a2159 (diff)
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 <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/sna/kgem.c73
-rw-r--r--src/sna/kgem.h1
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;