summaryrefslogtreecommitdiff
path: root/src/sna/kgem.c
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/sna/kgem.c
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/sna/kgem.c')
-rw-r--r--src/sna/kgem.c73
1 files changed, 63 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;