summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-17 12:38:09 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-17 21:26:35 +0000
commitdd8fd6c90612ada39eb32b98adc5acc97e7902aa (patch)
treea4a4eea51cc65d6185301c7a472ec9e97a0bb265
parent8ef5d8c1955e2e2ee19c64730f600639ac42de55 (diff)
sna: Search through the inactive VMA cache for potential upload bo
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c74
-rw-r--r--src/sna/kgem.h1
2 files changed, 71 insertions, 4 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 950b8ecc..17eca52f 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -392,6 +392,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen)
list_init(&kgem->requests);
list_init(&kgem->flushing);
list_init(&kgem->vma_cache);
+ list_init(&kgem->vma_inactive);
for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++)
list_init(&kgem->inactive[i]);
for (i = 0; i < ARRAY_SIZE(kgem->active); i++)
@@ -716,6 +717,8 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
DBG(("%s: handle=%d -> inactive\n", __FUNCTION__, bo->handle));
assert(!kgem_busy(kgem, bo->handle));
list_move(&bo->list, inactive(kgem, bo->size));
+ if (bo->map)
+ list_move(&bo->vma, &kgem->vma_inactive);
kgem->need_expire = true;
}
@@ -749,6 +752,7 @@ bool kgem_retire(struct kgem *kgem)
bo->purged = true;
bo->needs_flush = false;
bo->gpu = false;
+ assert(bo->rq == NULL);
list_move(&bo->list, inactive(kgem, bo->size));
list_del(&bo->request);
} else
@@ -813,6 +817,7 @@ bool kgem_retire(struct kgem *kgem)
if (gem_madvise(kgem->fd, rq->bo->handle, I915_MADV_DONTNEED)) {
rq->bo->purged = true;
assert(rq->bo->gpu == 0);
+ assert(rq->bo->rq == NULL);
list_move(&rq->bo->list, inactive(kgem, rq->bo->size));
retired = true;
} else {
@@ -1375,6 +1380,10 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
list_del(&bo->list);
if (bo->rq == NULL)
list_del(&bo->request);
+ if (bo->map) {
+ assert(!list_is_empty(&bo->vma));
+ list_move_tail(&bo->vma, &kgem->vma_cache);
+ }
bo->tiling = I915_TILING_NONE;
bo->pitch = 0;
@@ -1624,8 +1633,56 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
flags & CREATE_SCANOUT,
width, height, bpp, tiling, &pitch);
assert(size && size <= kgem->max_object_size);
- if (flags & CREATE_INACTIVE)
+
+ if (flags & CREATE_INACTIVE) {
+ /* We presume that we will need to upload to this bo,
+ * and so would prefer to have an active VMA.
+ */
+ list_for_each_entry(bo, &kgem->vma_inactive, vma) {
+ assert(bo->refcnt == 0);
+ assert(bo->map);
+ assert(bo->rq == NULL);
+ assert(list_is_empty(&bo->request));
+
+ if (size > bo->size || 2*size < bo->size) {
+ DBG(("inactive vma too small/large: %d < %d\n",
+ bo->size, size));
+ continue;
+ }
+
+ if (bo->tiling != tiling ||
+ (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
+ DBG(("inactive vma with wrong tiling: %d < %d\n",
+ bo->tiling, tiling));
+ continue;
+ }
+
+ bo->pitch = pitch;
+ list_del(&bo->list);
+
+ if (bo->purged) {
+ if (!gem_madvise(kgem->fd, bo->handle,
+ I915_MADV_WILLNEED)) {
+ kgem_bo_free(kgem, bo);
+ break;
+ }
+
+ bo->purged = false;
+ }
+
+ bo->delta = 0;
+ bo->unique_id = kgem_get_unique_id(kgem);
+ list_move_tail(&bo->vma, &kgem->vma_cache);
+ assert(bo->pitch);
+ DBG((" from inactive vma: pitch=%d, tiling=%d: handle=%d, id=%d\n",
+ bo->pitch, bo->tiling, bo->handle, bo->unique_id));
+ assert(bo->reusable);
+ assert(bo->gpu == 0 && !kgem_busy(kgem, bo->handle));
+ return kgem_bo_reference(bo);
+ }
+
goto skip_active_search;
+ }
untiled_pitch = kgem_untiled_pitch(kgem,
width, bpp,
@@ -1725,6 +1782,9 @@ skip_active_search:
bo->purged = false;
}
+ if (bo->map)
+ list_move_tail(&bo->vma, &kgem->vma_cache);
+
bo->delta = 0;
bo->unique_id = kgem_get_unique_id(kgem);
assert(bo->pitch);
@@ -1946,9 +2006,15 @@ static void kgem_trim_vma_cache(struct kgem *kgem)
while (kgem->vma_count > MAX_VMA_CACHE) {
struct kgem_bo *old;
- old = list_first_entry(&kgem->vma_cache,
- struct kgem_bo,
- vma);
+ if (list_is_empty(&kgem->vma_inactive)) {
+ old = list_first_entry(&kgem->vma_cache,
+ struct kgem_bo,
+ vma);
+ } else {
+ old = list_last_entry(&kgem->vma_inactive,
+ struct kgem_bo,
+ vma);
+ }
DBG(("%s: discarding %s vma cache for %d\n",
__FUNCTION__, IS_CPU_MAP(old->map) ? "CPU" : "GTT",
old->handle));
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index b69f1ee6..b6455686 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -105,6 +105,7 @@ struct kgem {
struct list partial;
struct list requests;
struct list vma_cache;
+ struct list vma_inactive;
struct kgem_request *next_request;
uint16_t nbatch;