Mesa (8.0): r600g: Use a fake reloc to sleep for fences

Michel Dänzer daenzer at kemper.freedesktop.org
Thu Feb 16 16:52:30 UTC 2012


Module: Mesa
Branch: 8.0
Commit: 106ea10d1b246aba1a0f4e171fd7d21268f3960f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=106ea10d1b246aba1a0f4e171fd7d21268f3960f

Author: Simon Farnsworth <simon.farnsworth at onelan.co.uk>
Date:   Tue Feb 14 12:06:20 2012 +0000

r600g: Use a fake reloc to sleep for fences

r300g is able to sleep until a fence completes rather than busywait because
it creates a special buffer object and relocation that stays busy until the
CS containing the fence is finished.

Copy the idea into r600g, and use it to sleep if the user asked for an
infinite wait, falling back to busywaiting if the user provided a timeout.

Signed-off-by: Simon Farnsworth <simon.farnsworth at onelan.co.uk>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
(cherry picked from commit 8cd03b933cf868ff867e2db4a0937005a02fd0e4)

Conflicts:

	src/gallium/drivers/r600/r600_pipe.c

---

 src/gallium/drivers/r600/r600_pipe.c |   25 +++++++++++++++++++++++--
 src/gallium/drivers/r600/r600_pipe.h |    1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 43d6fea..008a0b9 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -47,6 +47,7 @@
 #include "r600_resource.h"
 #include "r600_shader.h"
 #include "r600_pipe.h"
+#include "r600_hw_context_priv.h"
 
 /*
  * pipe_context
@@ -116,6 +117,14 @@ static struct r600_fence *r600_create_fence(struct r600_pipe_context *ctx)
 
 	rscreen->fences.data[fence->index] = 0;
 	r600_context_emit_fence(&ctx->ctx, rscreen->fences.bo, fence->index, 1);
+
+	/* Create a dummy BO so that fence_finish without a timeout can sleep waiting for completion */
+	fence->sleep_bo = (struct r600_resource*)
+			pipe_buffer_create(&ctx->ctx.screen->screen, PIPE_BIND_CUSTOM,
+					   PIPE_USAGE_STAGING, 1);
+	/* Add the fence as a dummy relocation. */
+	r600_context_bo_reloc(&ctx->ctx, fence->sleep_bo, RADEON_USAGE_READWRITE);
+
 out:
 	pipe_mutex_unlock(rscreen->fences.mutex);
 	return fence;
@@ -568,6 +577,7 @@ static void r600_fence_reference(struct pipe_screen *pscreen,
 	if (pipe_reference(&(*oldf)->reference, &newf->reference)) {
 		struct r600_screen *rscreen = (struct r600_screen *)pscreen;
 		pipe_mutex_lock(rscreen->fences.mutex);
+		pipe_resource_reference((struct pipe_resource**)&(*oldf)->sleep_bo, NULL);
 		LIST_ADDTAIL(&(*oldf)->head, &rscreen->fences.pool);
 		pipe_mutex_unlock(rscreen->fences.mutex);
 	}
@@ -601,6 +611,17 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen,
 	}
 
 	while (rscreen->fences.data[rfence->index] == 0) {
+		/* Special-case infinite timeout - wait for the dummy BO to become idle */
+		if (timeout == PIPE_TIMEOUT_INFINITE) {
+			rscreen->ws->buffer_wait(rfence->sleep_bo->buf, RADEON_USAGE_READWRITE);
+			break;
+		}
+
+		/* The dummy BO will be busy until the CS including the fence has completed, or
+		 * the GPU is reset. Don't bother continuing to spin when the BO is idle. */
+		if (!rscreen->ws->buffer_is_busy(rfence->sleep_bo->buf, RADEON_USAGE_READWRITE))
+			break;
+
 		if (++spins % 256)
 			continue;
 #ifdef PIPE_OS_UNIX
@@ -610,11 +631,11 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen,
 #endif
 		if (timeout != PIPE_TIMEOUT_INFINITE &&
 		    os_time_get() - start_time >= timeout) {
-			return FALSE;
+			break;
 		}
 	}
 
-	return TRUE;
+	return rscreen->fences.data[rfence->index] != 0;
 }
 
 static int r600_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config)
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 015d5e0..5e62210 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -172,6 +172,7 @@ struct r600_textures_info {
 struct r600_fence {
 	struct pipe_reference		reference;
 	unsigned			index; /* in the shared bo */
+	struct r600_resource            *sleep_bo;
 	struct list_head		head;
 };
 




More information about the mesa-commit mailing list