xf86-video-intel: 4 commits - src/sna/kgem.c src/sna/kgem.h

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 12 08:35:06 PDT 2012


 src/sna/kgem.c |  101 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 src/sna/kgem.h |    1 
 2 files changed, 89 insertions(+), 13 deletions(-)

New commits:
commit 6069e78238ca57e3433d528680fe04766a1e5307
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 12 16:22:49 2012 +0100

    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 at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d675ebb..f68b054 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 fb8be3d..073635f 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;
commit 1e2a03ad19664e846ece4110e53d26babb5a2159
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 12 16:15:22 2012 +0100

    sna: Propagate busyness when creating the proxy
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 0fabb01..d675ebb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -4178,6 +4178,13 @@ struct kgem_bo *kgem_create_proxy(struct kgem *kgem,
 
 	bo->proxy = kgem_bo_reference(target);
 	bo->delta = offset;
+
+	if (target->exec) {
+		list_move_tail(&bo->request, &kgem->next_request->buffers);
+		bo->exec = &_kgem_dummy_exec;
+	}
+	bo->rq = target->rq;
+
 	return bo;
 }
 
commit e28f5a2537821dc170a7ef78bf33ecbd3c032da0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 12 15:21:27 2012 +0100

    sna: Add some DBG as to why kgem_check_bo() flushes
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d6a6d28..0fabb01 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3595,14 +3595,23 @@ bool kgem_check_bo(struct kgem *kgem, ...)
 	if (!num_pages)
 		return true;
 
-	if (kgem->aperture > kgem->aperture_low)
+	if (kgem->aperture > kgem->aperture_low && kgem_is_idle(kgem)) {
+		DBG(("%s: current aperture usage (%d) is greater than low water mark (%d)\n",
+		     __FUNCTION__, kgem->aperture, kgem->aperture_low));
 		return false;
+	}
 
-	if (num_pages + kgem->aperture > kgem->aperture_high)
+	if (num_pages + kgem->aperture > kgem->aperture_high) {
+		DBG(("%s: final aperture usage (%d) is greater than high water mark (%d)\n",
+		     __FUNCTION__, num_pages + kgem->aperture, kgem->aperture_high));
 		return false;
+	}
 
-	if (kgem->nexec + num_exec >= KGEM_EXEC_SIZE(kgem))
+	if (kgem->nexec + num_exec >= KGEM_EXEC_SIZE(kgem)) {
+		DBG(("%s: out of exec slots (%d + %d / %d)\n", __FUNCTION__,
+		     kgem->nexec, num_exec, KGEM_EXEC_SIZE(kgem)));
 		return false;
+	}
 
 	return true;
 }
commit 1af1dae1feefd6567017170bab241570fb528e5c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 12 15:20:49 2012 +0100

    sna: Ensure tiling upload buffers are trimmed to fit in the cache
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 727cb51..d6a6d28 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -947,6 +947,12 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen)
 	kgem->large_object_size = MAX_CACHE_SIZE;
 	if (kgem->large_object_size > kgem->max_gpu_size)
 		kgem->large_object_size = kgem->max_gpu_size;
+
+	if (kgem->max_upload_tile_size > kgem->large_object_size)
+		kgem->max_upload_tile_size = kgem->large_object_size;
+	if (kgem->max_copy_tile_size > kgem->large_object_size)
+		kgem->max_copy_tile_size = kgem->large_object_size;
+
 	if (kgem->has_llc | kgem->has_cacheing | kgem->has_userptr) {
 		if (kgem->large_object_size > kgem->max_cpu_size)
 			kgem->large_object_size = kgem->max_cpu_size;


More information about the xorg-commit mailing list