[Nouveau] [PATCH 1/2] libdrm/nouveau: new optimized libdrm pushbuffer ABI

Luca Barbieri luca at luca-barbieri.com
Fri Jan 29 00:53:24 PST 2010


This patch changes the pushbuffer ABI to:

1. No longer use/expose nouveau_pushbuffer. Everything is directly
   in nouveau_channel. This saves the extra "pushbuf" pointer dereference.

2. Use cur/end pointers instead of tracking the remaining size.
   Pushing data now only needs to alter cur and not both cur and remaining.

The goal is to make the *_RING macros faster and make the interface simpler
and cleaner in the process.

The *_RING APIs are unchanged, but those are inlined and the ABI is changed.
The libdrm version is thus bumped.

Also, anything accessing pushbuf->remaining instead of using AVAIL_RING
will need to be fixed.
---
 include/drm/nouveau_drm.h |    2 +-
 nouveau/nouveau_bo.c      |    2 +-
 nouveau/nouveau_channel.h |    5 ++-
 nouveau/nouveau_device.c  |    2 +-
 nouveau/nouveau_private.h |    3 --
 nouveau/nouveau_pushbuf.c |   47 ++++++++++++++++++++------------------------
 nouveau/nouveau_pushbuf.h |   22 ++++++--------------
 7 files changed, 34 insertions(+), 49 deletions(-)

diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index 1e67c44..f764174 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -25,7 +25,7 @@
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
 
 struct drm_nouveau_channel_alloc {
 	uint32_t     fb_ctxdma_handle;
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
index 10cc8a6..ac1b37f 100644
--- a/nouveau/nouveau_bo.c
+++ b/nouveau/nouveau_bo.c
@@ -565,7 +565,7 @@ nouveau_bo_pending(struct nouveau_bo *bo)
 struct drm_nouveau_gem_pushbuf_bo *
 nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
 {
-	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
 	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 	struct drm_nouveau_gem_pushbuf_bo *pbbo;
 	struct nouveau_bo *ref = NULL;
diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
index 294f749..ddcf8e4 100644
--- a/nouveau/nouveau_channel.h
+++ b/nouveau/nouveau_channel.h
@@ -29,11 +29,12 @@ struct nouveau_subchannel {
 };
 
 struct nouveau_channel {
+	uint32_t *cur;
+	uint32_t *end;
+
 	struct nouveau_device *device;
 	int id;
 
-	struct nouveau_pushbuf *pushbuf;
-
 	struct nouveau_grobj *nullobj;
 	struct nouveau_grobj *vram;
 	struct nouveau_grobj *gart;
diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
index 0982d3b..14bf8bb 100644
--- a/nouveau/nouveau_device.c
+++ b/nouveau/nouveau_device.c
@@ -26,7 +26,7 @@
 
 #include "nouveau_private.h"
 
-#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 15
+#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 16
 #error nouveau_drm.h does not match expected patchlevel, update libdrm.
 #endif
 
diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
index 39758d1..0e526a1 100644
--- a/nouveau/nouveau_private.h
+++ b/nouveau/nouveau_private.h
@@ -39,8 +39,6 @@
 #define CALPB_BUFFERS 4
 #define CALPB_BUFSZ   16384
 struct nouveau_pushbuf_priv {
-	struct nouveau_pushbuf base;
-
 	int no_aper_update;
 	int use_cal;
 	uint32_t cal_suffix0;
@@ -50,7 +48,6 @@ struct nouveau_pushbuf_priv {
 	int current_offset;
 
 	unsigned *pushbuf;
-	unsigned  size;
 
 	unsigned marker;
 	unsigned marker_relocs;
diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
index 7da3a47..b6af216 100644
--- a/nouveau/nouveau_pushbuf.c
+++ b/nouveau/nouveau_pushbuf.c
@@ -37,12 +37,13 @@ nouveau_pushbuf_space_call(struct nouveau_channel *chan, unsigned min)
 	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
 	struct nouveau_bo *bo;
 	int ret;
+	unsigned size;
 
 	if (min < PB_MIN_USER_DWORDS)
 		min = PB_MIN_USER_DWORDS;
 
-	nvpb->current_offset = nvpb->base.cur - nvpb->pushbuf;
-	if (nvpb->current_offset + min + 2 <= nvpb->size)
+	nvpb->current_offset = chan->cur - nvpb->pushbuf;
+	if (chan->cur + min + 2 <= chan->end)
 		return 0;
 
 	nvpb->current++;
@@ -54,13 +55,12 @@ nouveau_pushbuf_space_call(struct nouveau_channel *chan, unsigned min)
 	if (ret)
 		return ret;
 
-	nvpb->size = (bo->size - 8) / 4;
+	size = (bo->size - 8) / 4;
 	nvpb->pushbuf = bo->map;
 	nvpb->current_offset = 0;
 
-	nvpb->base.channel = chan;
-	nvpb->base.remaining = nvpb->size;
-	nvpb->base.cur = nvpb->pushbuf;
+	chan->cur = nvpb->pushbuf;
+	chan->end = nvpb->pushbuf + size;
 
 	nouveau_bo_unmap(bo);
 	return 0;
@@ -71,6 +71,7 @@ nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
 {
 	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
 	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+	unsigned size;
 
 	if (nvpb->use_cal)
 		return nouveau_pushbuf_space_call(chan, min);
@@ -80,12 +81,11 @@ nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
 		nvpb->pushbuf = NULL;
 	}
 
-	nvpb->size = min < PB_MIN_USER_DWORDS ? PB_MIN_USER_DWORDS : min;
-	nvpb->pushbuf = malloc(sizeof(uint32_t) * nvpb->size);
+	size = min < PB_MIN_USER_DWORDS ? PB_MIN_USER_DWORDS : min;
+	nvpb->pushbuf = malloc(sizeof(uint32_t) * size);
 
-	nvpb->base.channel = chan;
-	nvpb->base.remaining = nvpb->size;
-	nvpb->base.cur = nvpb->pushbuf;
+	chan->cur = nvpb->pushbuf;
+	chan->end = nvpb->pushbuf + size;
 
 	return 0;
 }
@@ -165,8 +165,6 @@ nouveau_pushbuf_init(struct nouveau_channel *chan)
 			       sizeof(struct drm_nouveau_gem_pushbuf_bo));
 	nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
 			      sizeof(struct drm_nouveau_gem_pushbuf_reloc));
-
-	chan->pushbuf = &nvpb->base;
 	return 0;
 }
 
@@ -189,16 +187,14 @@ nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
 	unsigned i;
 	int ret;
 
-	if (nvpb->base.remaining == nvpb->size)
+	if (chan->cur == nvpb->pushbuf)
 		return 0;
 
 	if (nvpb->use_cal) {
 		struct drm_nouveau_gem_pushbuf_call req;
 
-		*(nvpb->base.cur++) = nvpb->cal_suffix0;
-		*(nvpb->base.cur++) = nvpb->cal_suffix1;
-		if (nvpb->base.remaining > 2) /* space() will fixup if not */
-			nvpb->base.remaining -= 2;
+		*(chan->cur++) = nvpb->cal_suffix0;
+		*(chan->cur++) = nvpb->cal_suffix1;
 
 restart_cal:
 		req.channel = chan->id;
@@ -208,7 +204,7 @@ restart_cal:
 		req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
 		req.nr_relocs = nvpb->nr_relocs;
 		req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
-		req.nr_dwords = (nvpb->base.cur - nvpb->pushbuf) -
+		req.nr_dwords = (chan->cur - nvpb->pushbuf) -
 				nvpb->current_offset;
 		req.suffix0 = nvpb->cal_suffix0;
 		req.suffix1 = nvpb->cal_suffix1;
@@ -229,7 +225,7 @@ restart_cal:
 
 restart_push:
 		req.channel = chan->id;
-		req.nr_dwords = nvpb->size - nvpb->base.remaining;
+		req.nr_dwords = chan->cur - nvpb->pushbuf;
 		req.dwords = (uint64_t)(unsigned long)nvpb->pushbuf;
 		req.nr_buffers = nvpb->nr_buffers;
 		req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
@@ -281,7 +277,7 @@ int
 nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
 			    unsigned wait_dwords, unsigned wait_relocs)
 {
-	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
 
 	if (AVAIL_RING(chan) < wait_dwords)
 		return nouveau_pushbuf_flush(chan, wait_dwords);
@@ -289,7 +285,7 @@ nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
 	if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
 		return nouveau_pushbuf_flush(chan, wait_dwords);
 
-	nvpb->marker = nvpb->base.cur - nvpb->pushbuf;
+	nvpb->marker = chan->cur - nvpb->pushbuf;
 	nvpb->marker_relocs = nvpb->nr_relocs;
 	return 0;
 }
@@ -297,7 +293,7 @@ nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
 void
 nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
 {
-	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
 	unsigned i;
 
 	if (!nvpb->marker)
@@ -321,8 +317,7 @@ nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
 	nvpb->nr_relocs = nvpb->marker_relocs;
 
 	/* reset pushbuf back to last marker */
-	nvpb->base.cur = nvpb->pushbuf + nvpb->marker;
-	nvpb->base.remaining = nvpb->size - nvpb->marker;
+	chan->cur = nvpb->pushbuf + nvpb->marker;
 	nvpb->marker = 0;
 }
 
@@ -355,7 +350,7 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
 			   struct nouveau_bo *bo, uint32_t data, uint32_t data2,
 			   uint32_t flags, uint32_t vor, uint32_t tor)
 {
-	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
 	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 	struct drm_nouveau_gem_pushbuf_reloc *r;
 	struct drm_nouveau_gem_pushbuf_bo *pbbo;
diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
index 46982af..803e129 100644
--- a/nouveau/nouveau_pushbuf.h
+++ b/nouveau/nouveau_pushbuf.h
@@ -29,13 +29,6 @@
 #include "nouveau_bo.h"
 #include "nouveau_grobj.h"
 
-struct nouveau_pushbuf {
-	struct nouveau_channel *channel;
-
-	unsigned remaining;
-	uint32_t *cur;
-};
-
 int
 nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
 
@@ -67,14 +60,14 @@ MARK_UNDO(struct nouveau_channel *chan)
 static __inline__ void
 OUT_RING(struct nouveau_channel *chan, unsigned data)
 {
-	*(chan->pushbuf->cur++) = (data);
+	*(chan->cur++) = (data);
 }
 
 static __inline__ void
 OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
 {
-	memcpy(chan->pushbuf->cur, data, size * 4);
-	chan->pushbuf->cur += size;
+	memcpy(chan->cur, data, size * 4);
+	chan->cur += size;
 }
 
 static __inline__ void
@@ -88,13 +81,13 @@ OUT_RINGf(struct nouveau_channel *chan, float f)
 static __inline__ unsigned
 AVAIL_RING(struct nouveau_channel *chan)
 {
-	return chan->pushbuf->remaining;
+	return chan->end - chan->cur;
 }
 
 static __inline__ void
 WAIT_RING(struct nouveau_channel *chan, unsigned size)
 {
-	if (chan->pushbuf->remaining < size)
+	if (chan->cur + size > chan->end)
 		nouveau_pushbuf_flush(chan, size);
 }
 
@@ -108,7 +101,6 @@ BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
 
 	WAIT_RING(chan, size + 1);
 	OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
-	chan->pushbuf->remaining -= (size + 1);
 }
 
 /* non-incrementing BEGIN_RING */
@@ -147,7 +139,7 @@ static __inline__ int
 OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
 	  unsigned data, unsigned flags, unsigned vor, unsigned tor)
 {
-	return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
+	return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
 					  data, 0, flags, vor, tor);
 }
 
@@ -156,7 +148,7 @@ OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
 	   unsigned data, unsigned data2, unsigned flags,
 	   unsigned vor, unsigned tor)
 {
-	return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
+	return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
 					  data, data2, flags, vor, tor);
 }
 
-- 
1.6.6.1.476.g01ddb



More information about the Nouveau mailing list