xf86-video-intel: 2 commits - test/present-speed.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Sep 23 11:25:16 UTC 2016


 test/present-speed.c |  332 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 310 insertions(+), 22 deletions(-)

New commits:
commit 8f33f80100096f7790c7b819ce37a3ed8ce8b5fa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 22 12:53:37 2016 +0100

    test/present: Busy spin on the idle fence
    
    Avoid the unix socket + libxcb to maximise the throughput.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-speed.c b/test/present-speed.c
index 9ab7482..eccde93 100644
--- a/test/present-speed.c
+++ b/test/present-speed.c
@@ -166,8 +166,8 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 	xcb_xfixes_region_t update = 0;
 	int completed = 0;
 	int queued = 0;
-	uint32_t eid;
-	void *Q;
+	uint32_t eid = 0;
+	void *Q = NULL;
 	int i, n;
 
 	list_init(&mru);
@@ -215,23 +215,35 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 		present_flags |= XCB_PRESENT_OPTION_COPY;
 	}
 
-	eid = xcb_generate_id(c);
-	xcb_present_select_input(c, eid, win,
-				 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
-				 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
-	Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
+	if (!(options & DRI3)) {
+		eid = xcb_generate_id(c);
+		xcb_present_select_input(c, eid, win,
+					 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
+					 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
+		Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
+	}
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
 	do {
 		for (n = 0; n < 1000; n++) {
 			struct buffer *tmp, *b = NULL;
+retry:
 			list_for_each_entry(tmp, &mru, link) {
+				if (tmp->fence.xid)
+					tmp->busy = !xshmfence_query(tmp->fence.addr);
 				if (!tmp->busy) {
 					b = tmp;
 					break;
 				}
 			}
-			while (b == NULL) {
+			if (options & DRI3) {
+				if (b == NULL)
+					goto retry;
+
+				xshmfence_reset(b->fence.addr);
+				queued--;
+				completed++;
+			} else while (b == NULL) {
 				xcb_present_generic_event_t *ev;
 
 				ev = (xcb_present_generic_event_t *)
@@ -261,10 +273,6 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 			}
 
 			b->busy = (options & NOCOPY) == 0;
-			if (b->fence.xid) {
-				xshmfence_await(b->fence.addr);
-				xshmfence_reset(b->fence.addr);
-			}
 			xcb_present_pixmap(c, win, b->pixmap, b->id,
 					   0, /* valid */
 					   update, /* update */
@@ -285,7 +293,33 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 		clock_gettime(CLOCK_MONOTONIC, &end);
 	} while (end.tv_sec < start.tv_sec + 10);
 
-	while (queued) {
+	if (options & DRI3) {
+		struct buffer *b;
+		XID pixmap;
+
+		pixmap = xcb_generate_id(c);
+		xcb_create_pixmap(c, depth, pixmap, win, width, height);
+		xcb_present_pixmap(c, win, pixmap, 0xdeadbeef,
+				   0, /* valid */
+				   None, /* update */
+				   0, /* x_off */
+				   0, /* y_off */
+				   None,
+				   None, /* wait fence */
+				   None,
+				   0,
+				   0, /* target msc */
+				   0, /* divisor */
+				   0, /* remainder */
+				   0, NULL);
+		xcb_flush(c);
+
+		list_for_each_entry(b, &mru, link)
+			xshmfence_await(b->fence.addr);
+
+		xcb_free_pixmap(c, pixmap);
+		completed += queued;
+	} else while (queued) {
 		xcb_present_generic_event_t *ev;
 
 		ev = (xcb_present_generic_event_t *)
@@ -318,9 +352,11 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 		xcb_free_pixmap(c, buffer[n].pixmap);
 	}
 
-	xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
-	XSync(dpy, True);
-	xcb_unregister_for_special_event(c, Q);
+	if (Q) {
+		xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
+		XSync(dpy, True);
+		xcb_unregister_for_special_event(c, Q);
+	}
 
 	test_name[0] = '\0';
 	if (options) {
@@ -359,7 +395,7 @@ static void perpixel(Display *dpy,
 	int completed = 0;
 	int i, n;
 
-	pp = malloc(sz*sizeof(*pp));
+	pp = calloc(sz, sizeof(*pp));
 	if (!pp)
 		return;
 
@@ -404,11 +440,13 @@ static void perpixel(Display *dpy,
 			list_add(&pp[i].buffer[n].link, &pp[i].mru);
 		}
 
-		pp[i].eid = xcb_generate_id(c);
-		xcb_present_select_input(c, pp[i].eid, pp[i].win,
-					 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
-					 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
-		pp[i].Q = xcb_register_for_special_xge(c, &xcb_present_id, pp[i].eid, &stamp);
+		if (!(options & DRI3)) {
+			pp[i].eid = xcb_generate_id(c);
+			xcb_present_select_input(c, pp[i].eid, pp[i].win,
+						 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
+						 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
+			pp[i].Q = xcb_register_for_special_xge(c, &xcb_present_id, pp[i].eid, &stamp);
+		}
 		pp[i].queued = 0;
 	}
 
@@ -427,13 +465,23 @@ static void perpixel(Display *dpy,
 	do {
 		for (i = 0; i < sz; i++) {
 			struct buffer *tmp, *b = NULL;
+retry:
 			list_for_each_entry(tmp, &pp[i].mru, link) {
+				if (tmp->fence.xid)
+					tmp->busy = !xshmfence_query(tmp->fence.addr);
 				if (!tmp->busy) {
 					b = tmp;
 					break;
 				}
 			}
-			while (b == NULL) {
+			if (options & DRI3) {
+				if (b == NULL)
+					goto retry;
+
+				xshmfence_reset(b->fence.addr);
+				pp[i].queued--;
+				completed++;
+			} else while (b == NULL) {
 				xcb_present_generic_event_t *ev;
 
 				ev = (xcb_present_generic_event_t *)
@@ -463,10 +511,6 @@ static void perpixel(Display *dpy,
 			}
 
 			b->busy = (options & NOCOPY) == 0;
-			if (b->fence.xid) {
-				xshmfence_await(b->fence.addr);
-				xshmfence_reset(b->fence.addr);
-			}
 			xcb_present_pixmap(c, pp[i].win, b->pixmap, b->id,
 					   0, /* valid */
 					   update, /* update */
@@ -488,7 +532,34 @@ static void perpixel(Display *dpy,
 	} while (end.tv_sec < start.tv_sec + 10);
 
 	for (i = 0; i < sz; i++) {
-		while (pp[i].queued) {
+		if (options & DRI3) {
+			int depth = DefaultDepth(dpy, DefaultScreen(dpy));
+			struct buffer *b;
+			XID pixmap;
+
+			pixmap = xcb_generate_id(c);
+			xcb_create_pixmap(c, depth, pixmap, pp[i].win, 1, 1);
+			xcb_present_pixmap(c, pp[i].win, pixmap, 0xdeadbeef,
+					   0, /* valid */
+					   None, /* update */
+					   0, /* x_off */
+					   0, /* y_off */
+					   None,
+					   None, /* wait fence */
+					   None,
+					   0,
+					   0, /* target msc */
+					   0, /* divisor */
+					   0, /* remainder */
+					   0, NULL);
+			xcb_flush(c);
+
+			list_for_each_entry(b, &pp[i].mru, link)
+				xshmfence_await(b->fence.addr);
+
+			xcb_free_pixmap(c, pixmap);
+			completed += pp[i].queued;
+		} else while (pp[i].queued) {
 			xcb_present_generic_event_t *ev;
 
 			ev = (xcb_present_generic_event_t *)
@@ -524,9 +595,11 @@ static void perpixel(Display *dpy,
 			xcb_free_pixmap(c, pp[i].buffer[n].pixmap);
 		}
 
-		xcb_discard_reply(c, xcb_present_select_input_checked(c, pp[i].eid, pp[i].win, 0).sequence);
-		XSync(dpy, True);
-		xcb_unregister_for_special_event(c, pp[i].Q);
+		if (pp[i].Q) {
+			xcb_discard_reply(c, xcb_present_select_input_checked(c, pp[i].eid, pp[i].win, 0).sequence);
+			XSync(dpy, True);
+			xcb_unregister_for_special_event(c, pp[i].Q);
+		}
 
 		XDestroyWindow(dpy, pp[i].win);
 	}
commit 0ffae5601bdb00528395f0891a680e69df89a00a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 22 11:23:36 2016 +0100

    test/present: Look at scaling to many tiny windows
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-speed.c b/test/present-speed.c
index bcaa623..9ab7482 100644
--- a/test/present-speed.c
+++ b/test/present-speed.c
@@ -145,6 +145,7 @@ struct buffer {
 	struct dri3_fence fence;
 	int fd;
 	int busy;
+	int id;
 };
 
 #define DRI3 1
@@ -177,10 +178,12 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 	_x_error_occurred = 0;
 
 	for (n = 0; n < N_BACK; n++) {
-		buffer[n].pixmap =
-			XCreatePixmap(dpy, win, width, height, depth);
+		buffer[n].pixmap = xcb_generate_id(c);
+		xcb_create_pixmap(c, depth, buffer[n].pixmap, win,
+				  width, height);
 		buffer[n].fence.xid = 0;
 		buffer[n].fd = -1;
+		buffer[n].id = n;
 		if (options & DRI3) {
 			xcb_dri3_buffer_from_pixmap_reply_t *reply;
 			int *fds;
@@ -189,8 +192,8 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 				return;
 
 			reply = xcb_dri3_buffer_from_pixmap_reply (c,
-					xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
-					NULL);
+								   xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
+								   NULL);
 			if (reply == NULL)
 				return;
 
@@ -214,8 +217,8 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 
 	eid = xcb_generate_id(c);
 	xcb_present_select_input(c, eid, win,
-                                 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
-                                 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
+				 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
+				 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
 	Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
@@ -262,7 +265,7 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 				xshmfence_await(b->fence.addr);
 				xshmfence_reset(b->fence.addr);
 			}
-			xcb_present_pixmap(c, win, b->pixmap, b - buffer,
+			xcb_present_pixmap(c, win, b->pixmap, b->id,
 					   0, /* valid */
 					   update, /* update */
 					   0, /* x_off */
@@ -312,7 +315,7 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 			dri3_fence_free(dpy, &buffer[n].fence);
 		if (buffer[n].fd != -1)
 			close(buffer[n].fd);
-		XFreePixmap(dpy, buffer[n].pixmap);
+		xcb_free_pixmap(c, buffer[n].pixmap);
 	}
 
 	xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
@@ -333,6 +336,216 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 	       completed / (elapsed(&start, &end) / 1000000));
 }
 
+struct perpixel {
+	Window win;
+	struct buffer buffer[N_BACK];
+	struct list mru;
+	uint32_t eid;
+	void *Q;
+	int queued;
+};
+
+static void perpixel(Display *dpy,
+		     int max_width, int max_height, unsigned options)
+{
+	//const int sz = max_width * max_height;
+	const int sz = 1048;
+	struct perpixel *pp;
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	struct timespec start, end;
+	char test_name[128];
+	unsigned present_flags = 0;
+	xcb_xfixes_region_t update = 0;
+	int completed = 0;
+	int i, n;
+
+	pp = malloc(sz*sizeof(*pp));
+	if (!pp)
+		return;
+
+	for (i = 0; i < sz; i++) {
+		XSetWindowAttributes attr = { .override_redirect = 1 };
+		int depth = DefaultDepth(dpy, DefaultScreen(dpy));
+		pp[i].win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+					  i % max_width, i / max_width, 1, 1, 0, depth,
+					  InputOutput,
+					  DefaultVisual(dpy, DefaultScreen(dpy)),
+					  CWOverrideRedirect, &attr);
+		XMapWindow(dpy, pp[i].win);
+		list_init(&pp[i].mru);
+		for (n = 0; n < N_BACK; n++) {
+			pp[i].buffer[n].pixmap = xcb_generate_id(c);
+			xcb_create_pixmap(c, depth, pp[i].buffer[n].pixmap,
+					  pp[i].win, 1, 1);
+			pp[i].buffer[n].fence.xid = 0;
+			pp[i].buffer[n].fd = -1;
+			pp[i].buffer[n].id = n;
+			if (options & DRI3) {
+				xcb_dri3_buffer_from_pixmap_reply_t *reply;
+				int *fds;
+
+				if (dri3_create_fence(dpy, pp[i].win, &pp[i].buffer[n].fence))
+					return;
+
+				reply = xcb_dri3_buffer_from_pixmap_reply(c,
+									  xcb_dri3_buffer_from_pixmap(c, pp[i].buffer[n].pixmap),
+									  NULL);
+				if (reply == NULL)
+					return;
+
+				fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, reply);
+				pp[i].buffer[n].fd = fds[0];
+				free(reply);
+
+				/* start idle */
+				xshmfence_trigger(pp[i].buffer[n].fence.addr);
+			}
+			pp[i].buffer[n].busy = 0;
+			list_add(&pp[i].buffer[n].link, &pp[i].mru);
+		}
+
+		pp[i].eid = xcb_generate_id(c);
+		xcb_present_select_input(c, pp[i].eid, pp[i].win,
+					 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
+					 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
+		pp[i].Q = xcb_register_for_special_xge(c, &xcb_present_id, pp[i].eid, &stamp);
+		pp[i].queued = 0;
+	}
+
+	XSync(dpy, True);
+	_x_error_occurred = 0;
+
+	if (options & ASYNC)
+		present_flags |= XCB_PRESENT_OPTION_ASYNC;
+	if (options & NOCOPY) {
+		update = xcb_generate_id(c);
+		xcb_xfixes_create_region(c, update, 0, NULL);
+		present_flags |= XCB_PRESENT_OPTION_COPY;
+	}
+
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	do {
+		for (i = 0; i < sz; i++) {
+			struct buffer *tmp, *b = NULL;
+			list_for_each_entry(tmp, &pp[i].mru, link) {
+				if (!tmp->busy) {
+					b = tmp;
+					break;
+				}
+			}
+			while (b == NULL) {
+				xcb_present_generic_event_t *ev;
+
+				ev = (xcb_present_generic_event_t *)
+					xcb_wait_for_special_event(c, pp[i].Q);
+				if (ev == NULL)
+					abort();
+
+				do {
+					switch (ev->evtype) {
+					case XCB_PRESENT_COMPLETE_NOTIFY:
+						completed++;
+						pp[i].queued--;
+						break;
+
+					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
+						{
+							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
+							assert(ie->serial < N_BACK);
+							pp[i].buffer[ie->serial].busy = 0;
+							if (b == NULL)
+								b = &pp[i].buffer[ie->serial];
+							break;
+						}
+					}
+					free(ev);
+				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
+			}
+
+			b->busy = (options & NOCOPY) == 0;
+			if (b->fence.xid) {
+				xshmfence_await(b->fence.addr);
+				xshmfence_reset(b->fence.addr);
+			}
+			xcb_present_pixmap(c, pp[i].win, b->pixmap, b->id,
+					   0, /* valid */
+					   update, /* update */
+					   0, /* x_off */
+					   0, /* y_off */
+					   None,
+					   None, /* wait fence */
+					   b->fence.xid,
+					   present_flags,
+					   0, /* target msc */
+					   0, /* divisor */
+					   0, /* remainder */
+					   0, NULL);
+			list_move(&b->link, &pp[i].mru);
+			pp[i].queued++;
+		}
+		xcb_flush(c);
+		clock_gettime(CLOCK_MONOTONIC, &end);
+	} while (end.tv_sec < start.tv_sec + 10);
+
+	for (i = 0; i < sz; i++) {
+		while (pp[i].queued) {
+			xcb_present_generic_event_t *ev;
+
+			ev = (xcb_present_generic_event_t *)
+				xcb_wait_for_special_event(c, pp[i].Q);
+			if (ev == NULL)
+				abort();
+
+			do {
+				switch (ev->evtype) {
+				case XCB_PRESENT_COMPLETE_NOTIFY:
+					completed++;
+					pp[i].queued--;
+					break;
+
+				case XCB_PRESENT_EVENT_IDLE_NOTIFY:
+					break;
+				}
+				free(ev);
+			} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
+		}
+	}
+	clock_gettime(CLOCK_MONOTONIC, &end);
+
+	if (update)
+		xcb_xfixes_destroy_region(c, update);
+
+	for (i = 0; i < sz; i++) {
+		for (n = 0; n < N_BACK; n++) {
+			if (pp[i].buffer[n].fence.xid)
+				dri3_fence_free(dpy, &pp[i].buffer[n].fence);
+			if (pp[i].buffer[n].fd != -1)
+				close(pp[i].buffer[n].fd);
+			xcb_free_pixmap(c, pp[i].buffer[n].pixmap);
+		}
+
+		xcb_discard_reply(c, xcb_present_select_input_checked(c, pp[i].eid, pp[i].win, 0).sequence);
+		XSync(dpy, True);
+		xcb_unregister_for_special_event(c, pp[i].Q);
+
+		XDestroyWindow(dpy, pp[i].win);
+	}
+	free(pp);
+
+	test_name[0] = '\0';
+	if (options) {
+		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
+			 options & NOCOPY ? " no-copy" : "",
+			 options & DRI3 ? " dri3" : "",
+			 options & ASYNC ? " async" : "");
+	}
+	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
+	       __func__, test_name,
+	       completed, elapsed(&start, &end) / 1000000,
+	       elapsed(&start, &end) / completed,
+	       completed / (elapsed(&start, &end) / 1000000));
+}
+
 static int isqrt(int x)
 {
 	int i;
@@ -649,6 +862,8 @@ static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
 			XDestroyWindow(dpy, win);
 			XSync(dpy, True);
 
+			perpixel(dpy, mode->width, mode->height, options);
+
 			siblings(dpy, mode->width, mode->height,
 				 sysconf(_SC_NPROCESSORS_ONLN),
 				 options);


More information about the xorg-commit mailing list