xf86-video-intel: 3 commits - configure.ac src/sna/kgem.c src/sna/kgem.h src/sna/sna_blt.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Jul 9 12:47:07 PDT 2013


 configure.ac      |   12 ++++-
 src/sna/kgem.c    |  122 ++++++++++++++++++++++++++++++++++++++++++++++++------
 src/sna/kgem.h    |    1 
 src/sna/sna_blt.c |   28 +++++++-----
 4 files changed, 140 insertions(+), 23 deletions(-)

New commits:
commit ccf0fdd56dc6efd30e425209d753ed4f90562d76
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 9 20:41:51 2013 +0100

    sna: Only flush after the BLT operation if we have more than 2 distinct bo
    
    In order to preserve the optimisation of discarding incomplete batches,
    we don't always want to immediately submit the batch after inserting the
    first command. As we currently only cancel a batch if it only touches
    the bo being discarded, we can skip the immediate flush if it only
    accesses one bo and maybe be able to use the undo optimisation later.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 796aa63..ec3278b 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -85,7 +85,7 @@ static const uint8_t fill_ROP[] = {
 static void nop_done(struct sna *sna, const struct sna_composite_op *op)
 {
 	assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
-	if (sna->kgem.nreloc && __kgem_ring_empty(&sna->kgem))
+	if (sna->kgem.nexec > 1 && __kgem_ring_empty(&sna->kgem))
 		_kgem_submit(&sna->kgem);
 	(void)op;
 }
@@ -95,7 +95,7 @@ static void gen6_blt_copy_done(struct sna *sna, const struct sna_composite_op *o
 	struct kgem *kgem = &sna->kgem;
 
 	assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem));
-	if (kgem->nreloc && __kgem_ring_empty(kgem)) {
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
 		_kgem_submit(kgem);
 		return;
 	}
@@ -2301,7 +2301,7 @@ static void convert_done(struct sna *sna, const struct sna_composite_op *op)
 	struct kgem *kgem = &sna->kgem;
 
 	assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem));
-	if (kgem->nreloc && __kgem_ring_empty(kgem))
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem))
 		_kgem_submit(kgem);
 
 	kgem_bo_destroy(kgem, op->src.bo);
@@ -2800,7 +2800,7 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
 		}
 	} while (nbox);
 
-	if (kgem->nreloc && __kgem_ring_empty(kgem))
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem))
 		_kgem_submit(kgem);
 
 	return true;
@@ -2989,7 +2989,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
 		} while (1);
 	}
 
-	if (kgem->nreloc && __kgem_ring_empty(kgem)) {
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
 		_kgem_submit(kgem);
 	} else if (kgem->gen >= 060 && kgem_check_batch(kgem, 3)) {
 		uint32_t *b = kgem->batch + kgem->nbatch;
commit d935912d9c13ec8cf4f641c55846714d4e9ba929
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 9 20:38:32 2013 +0100

    sna: Free the source reference after performing a BLT composite
    
    Fixes regression from
    commit 8751c0f5ad202850bdd56dbb4eedb211c023cf23
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Fri Jul 5 17:55:10 2013 +0100
    
        sna: Flush blt copies if no operations pending
    
    Reported-by: Andreas Reis <andreas.reis at gmail.com>
    Reported-by: Mike Lothian <mike at fireburn.co.uk>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66742
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 54cf4f8..796aa63 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -2301,12 +2301,18 @@ static void convert_done(struct sna *sna, const struct sna_composite_op *op)
 	struct kgem *kgem = &sna->kgem;
 
 	assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem));
-	if (kgem->nreloc && __kgem_ring_empty(kgem)) {
+	if (kgem->nreloc && __kgem_ring_empty(kgem))
 		_kgem_submit(kgem);
-		return;
-	}
 
-	if (kgem->gen >= 060 && op->src.bo == op->dst.bo && kgem_check_batch(kgem, 3)) {
+	kgem_bo_destroy(kgem, op->src.bo);
+	sna_render_composite_redirect_done(sna, op);
+}
+
+static void gen6_convert_done(struct sna *sna, const struct sna_composite_op *op)
+{
+	struct kgem *kgem = &sna->kgem;
+
+	if (kgem_check_batch(kgem, 3)) {
 		uint32_t *b = kgem->batch + kgem->nbatch;
 		b[0] = XY_SETUP_CLIP;
 		b[1] = b[2] = 0;
@@ -2314,8 +2320,7 @@ static void convert_done(struct sna *sna, const struct sna_composite_op *op)
 		assert(kgem->nbatch < kgem->surface);
 	}
 
-	kgem_bo_destroy(kgem, op->src.bo);
-	sna_render_composite_redirect_done(sna, op);
+	convert_done(sna, op);
 }
 
 bool
@@ -2446,6 +2451,9 @@ sna_blt_composite__convert(struct sna *sna,
 	}
 
 	tmp->done = convert_done;
+	if (sna->kgem.gen >= 060 && tmp->src.bo == tmp->dst.bo)
+		tmp->done = gen6_convert_done;
+
 	return true;
 }
 
commit b202008f8f6470f256d3b9000a9f78b6ca8d932b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jul 5 13:50:34 2013 +0100

    sna: Experiment with a new ioctl to create buffers from stolen memory
    
    If there is stolen memory reserved by the BIOS, we want to utilize it in
    preference to regular system memory. However, given the caveat that it
    is not suitable for CPU access, rules out most use cases - but it is a
    good match for framebuffers.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 79018d5..46a5a6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -328,6 +328,16 @@ if test "x$accel" = xnone -a "x$UMS_ONLY" != "xyes"; then
 	AC_MSG_ERROR([No default acceleration option])
 fi
 
+AC_ARG_ENABLE(create2,
+	      AS_HELP_STRING([--enable-create2],
+			     [Enable use of create2 ioctl (experimental) [default=no]]),
+	      [CREATE2="$enableval"],
+	      [CREATE2=no])
+AM_CONDITIONAL(USE_CREATE2, test x$CREATE2 = xyes)
+if test "x$CREATE2" = xyes; then
+	AC_DEFINE(USE_CREATE2,1,[Assume "create2" support])
+fi
+
 AC_ARG_ENABLE(userptr,
 	      AS_HELP_STRING([--enable-userptr],
 			     [Enable use of userptr (experimental) [default=no]]),
@@ -335,7 +345,7 @@ AC_ARG_ENABLE(userptr,
 	      [USERPTR=no])
 AM_CONDITIONAL(USE_USERPTR, test x$USERPTR = xyes)
 if test "x$USERPTR" = xyes; then
-	AC_DEFINE(USE_USERPTR,1,[Assume USERPTR support])
+	AC_DEFINE(USE_USERPTR,1,[Assume "userptr" support])
 fi
 
 AC_ARG_ENABLE(async-swap,
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index cb6276d..7091ca4 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -61,6 +61,7 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
 #define DBG_NO_CACHE 0
 #define DBG_NO_CACHE_LEVEL 0
 #define DBG_NO_CPU 0
+#define DBG_NO_CREATE2 0
 #define DBG_NO_USERPTR 0
 #define DBG_NO_UNSYNCHRONIZED_USERPTR 0
 #define DBG_NO_LLC 0
@@ -126,7 +127,21 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
 #define LOCAL_I915_EXEC_NO_RELOC		(1<<11)
 #define LOCAL_I915_EXEC_HANDLE_LUT		(1<<12)
 
-#define LOCAL_I915_GEM_USERPTR       0x32
+#define LOCAL_I915_GEM_CREATE2       0x32
+#define LOCAL_IOCTL_I915_GEM_CREATE2 DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_CREATE2, struct local_i915_gem_create2)
+struct local_i915_gem_create2 {
+	uint64_t size;
+	uint32_t domain;
+#define LOCAL_I915_CREATE_DOMAIN_SYSTEM 0
+#define LOCAL_I915_CREATE_DOMAIN_STOLEN 1
+	uint32_t caching;
+	uint32_t tiling_mode;
+	uint32_t stride;
+	uint32_t flags;
+	uint32_t handle;
+};
+
+#define LOCAL_I915_GEM_USERPTR       0x33
 #define LOCAL_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_USERPTR, struct local_i915_gem_userptr)
 struct local_i915_gem_userptr {
 	uint64_t user_ptr;
@@ -890,6 +905,31 @@ static bool test_has_userptr(struct kgem *kgem)
 #endif
 }
 
+static bool test_has_create2(struct kgem *kgem)
+{
+#if defined(USE_CREATE2)
+	struct local_i915_gem_create2 args;
+
+	if (DBG_NO_CREATE2)
+		return false;
+
+	VG_CLEAR(args);
+	args.size = PAGE_SIZE;
+	args.domain = LOCAL_I915_CREATE_DOMAIN_SYSTEM;
+	args.caching = UNCACHED;
+	args.tiling_mode = I915_TILING_NONE;
+	args.stride = 0;
+	args.flags = 0;
+	args.handle = 0;
+	if (drmIoctl(kgem->fd, LOCAL_IOCTL_I915_GEM_CREATE2, &args) == 0)
+		gem_close(kgem->fd, args.handle);
+
+	return args.handle != 0;
+#else
+	return false;
+#endif
+}
+
 static bool test_has_secure_batches(struct kgem *kgem)
 {
 	if (DBG_NO_SECURE_BATCHES)
@@ -1071,6 +1111,10 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
 	DBG(("%s: has userptr? %d\n", __FUNCTION__,
 	     kgem->has_userptr));
 
+	kgem->has_create2 = test_has_create2(kgem);
+	DBG(("%s: has create2? %d\n", __FUNCTION__,
+	     kgem->has_create2));
+
 	kgem->has_no_reloc = test_has_no_reloc(kgem);
 	DBG(("%s: has no-reloc? %d\n", __FUNCTION__,
 	     kgem->has_no_reloc));
@@ -1846,7 +1890,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 
 	assert(list_is_empty(&bo->list));
 	assert(bo->refcnt == 0);
-	assert(!bo->purged);
+	assert(!bo->purged || !bo->reusable);
 	assert(bo->proxy == NULL);
 	assert_tiling(kgem, bo);
 
@@ -2196,7 +2240,6 @@ static void kgem_commit(struct kgem *kgem)
 		     bo->gpu_dirty, bo->needs_flush, bo->snoop,
 		     (unsigned)bo->exec->offset));
 
-		assert(!bo->purged);
 		assert(bo->exec);
 		assert(bo->proxy == NULL || bo->exec == &_kgem_dummy_exec);
 		assert(RQ(bo->rq) == rq || (RQ(bo->proxy->rq) == rq));
@@ -2912,8 +2955,11 @@ void kgem_clean_scanout_cache(struct kgem *kgem)
 			break;
 
 		list_del(&bo->list);
-		kgem_bo_clear_scanout(kgem, bo);
-		__kgem_bo_destroy(kgem, bo);
+		if (!bo->purged) {
+			kgem_bo_clear_scanout(kgem, bo);
+			__kgem_bo_destroy(kgem, bo);
+		} else
+			kgem_bo_free(kgem, bo);
 	}
 }
 
@@ -3683,6 +3729,45 @@ inline int kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo)
 	return size;
 }
 
+static struct kgem_bo *
+__kgem_bo_create_from_stolen(struct kgem *kgem, int size, int tiling, int pitch)
+
+{
+	struct local_i915_gem_create2 args;
+	struct kgem_bo *bo;
+
+	if (!kgem->has_create2)
+		return NULL;
+
+	VG_CLEAR(args);
+	args.size = size * PAGE_SIZE;
+	args.domain = LOCAL_I915_CREATE_DOMAIN_STOLEN;
+	args.caching = UNCACHED;
+	args.tiling_mode = tiling;
+	args.stride = pitch;
+	args.flags = 0;
+
+	if (drmIoctl(kgem->fd, LOCAL_IOCTL_I915_GEM_CREATE2, &args))
+		return NULL;
+
+	bo = __kgem_bo_alloc(args.handle, size);
+	if (bo == NULL) {
+		gem_close(kgem->fd, args.handle);
+		return NULL;
+	}
+
+	bo->unique_id = kgem_get_unique_id(kgem);
+	bo->tiling = tiling;
+	bo->pitch = pitch;
+	bo->purged = true; /* for asserts against CPU access */
+	bo->reusable = false; /* so that unclaimed scanouts are freed */
+
+	assert_tiling(kgem, bo);
+	debug_alloc__bo(kgem, bo);
+
+	return bo;
+}
+
 struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 			       int width,
 			       int height,
@@ -3720,7 +3805,6 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 		list_for_each_entry_reverse(bo, &kgem->scanout, list) {
 			assert(bo->scanout);
 			assert(bo->delta);
-			assert(!bo->purged);
 			assert(!bo->flush);
 			assert_tiling(kgem, bo);
 
@@ -3750,6 +3834,10 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 			bo->refcnt = 1;
 			return bo;
 		}
+
+		bo = __kgem_bo_create_from_stolen(kgem, size, tiling, pitch);
+		if (bo)
+			return bo;
 	}
 
 	if (bucket >= NUM_CACHE_BUCKETS) {
@@ -4420,8 +4508,11 @@ bool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo)
 {
 	uint32_t size;
 
+	assert(bo->refcnt);
 	while (bo->proxy)
 		bo = bo->proxy;
+	assert(bo->refcnt);
+
 	if (bo->exec) {
 		if (kgem->gen < 040 &&
 		    bo->tiling != I915_TILING_NONE &&
@@ -4488,8 +4579,10 @@ bool kgem_check_many_bo_fenced(struct kgem *kgem, ...)
 
 	va_start(ap, kgem);
 	while ((bo = va_arg(ap, struct kgem_bo *))) {
+		assert(bo->refcnt);
 		while (bo->proxy)
 			bo = bo->proxy;
+		assert(bo->refcnt);
 		if (bo->exec) {
 			if (kgem->gen >= 040 || bo->tiling == I915_TILING_NONE)
 				continue;
@@ -4565,8 +4658,6 @@ uint32_t kgem_add_reloc(struct kgem *kgem,
 	kgem->reloc[index].offset = pos * sizeof(kgem->batch[0]);
 	if (bo) {
 		assert(bo->refcnt);
-		assert(!bo->purged);
-
 		while (bo->proxy) {
 			DBG(("%s: adding proxy [delta=%d] for handle=%d\n",
 			     __FUNCTION__, bo->delta, bo->handle));
@@ -4586,8 +4677,8 @@ uint32_t kgem_add_reloc(struct kgem *kgem,
 
 			bo = bo->proxy;
 			assert(bo->refcnt);
-			assert(!bo->purged);
 		}
+		assert(bo->refcnt);
 
 		if (bo->exec == NULL)
 			kgem_add_bo(kgem, bo);
@@ -4689,7 +4780,6 @@ void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo)
 	DBG(("%s: handle=%d, offset=%d, tiling=%d, map=%p, domain=%d\n", __FUNCTION__,
 	     bo->handle, bo->presumed_offset, bo->tiling, bo->map, bo->domain));
 
-	assert(!bo->purged);
 	assert(bo->proxy == NULL);
 	assert(list_is_empty(&bo->list));
 	assert(!IS_USER_MAP(bo->map));
@@ -4733,7 +4823,6 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
 	DBG(("%s: handle=%d, offset=%d, tiling=%d, map=%p, domain=%d\n", __FUNCTION__,
 	     bo->handle, bo->presumed_offset, bo->tiling, bo->map, bo->domain));
 
-	assert(!bo->purged);
 	assert(bo->proxy == NULL);
 	assert(list_is_empty(&bo->list));
 	assert(!IS_USER_MAP(bo->map));
@@ -4802,7 +4891,6 @@ void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
 	DBG(("%s: handle=%d, offset=%d, tiling=%d, map=%p, domain=%d\n", __FUNCTION__,
 	     bo->handle, bo->presumed_offset, bo->tiling, bo->map, bo->domain));
 
-	assert(!bo->purged);
 	assert(bo->exec == NULL);
 	assert(list_is_empty(&bo->list));
 	assert(!IS_USER_MAP(bo->map));
@@ -5041,8 +5129,12 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 	kgem_bo_submit(kgem, bo);
 
 	/* SHM pixmaps use proxies for subpage offsets */
+	assert(!bo->purged);
+	assert(bo->refcnt);
 	while (bo->proxy)
 		bo = bo->proxy;
+	assert(bo->refcnt);
+	assert(!bo->purged);
 
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
@@ -5072,8 +5164,12 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 		kgem_bo_submit(kgem, bo);
 
 	/* SHM pixmaps use proxies for subpage offsets */
+	assert(!bo->purged);
+	assert(bo->refcnt);
 	while (bo->proxy)
 		bo = bo->proxy;
+	assert(bo->refcnt);
+	assert(!bo->purged);
 
 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
@@ -5099,7 +5195,9 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
 {
 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+	assert(bo->refcnt);
 	assert(bo->proxy == NULL);
+
 	kgem_bo_submit(kgem, bo);
 
 	if (bo->domain != DOMAIN_GTT || FORCE_MMAP_SYNC & (1 << DOMAIN_GTT)) {
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 044dbba..8e8e883 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -169,6 +169,7 @@ struct kgem {
 	uint32_t scanout_busy:1;
 	uint32_t busy:1;
 
+	uint32_t has_create2 :1;
 	uint32_t has_userptr :1;
 	uint32_t has_blt :1;
 	uint32_t has_relaxed_fencing :1;


More information about the xorg-commit mailing list