[Mesa-dev] [PATCH] r600g: get and use backends mask for occlusion queries

Vadim Girlin vadimgirlin at gmail.com
Sun Jul 10 13:31:59 PDT 2011


This patch uses ZPASS_DONE counters to get the mask on context creation,
then uses it for query buffer initialization. 

Signed-off-by: Vadim Girlin <vadimgirlin at gmail.com>
---

Probably it's not the best way, but i hope it should be more reliable than
the current implementation. I've tested it with the juniper card which uses
backends 0 & 2 only (don't know if it is normal, maybe the card is broken,
or it's hw configuration bug, but it works fine). This patch fixes lockups with
conditional rendering. Current implementation doesn't set highest bits for
backends 1 & 3 and then conditional rendering causes gpu lockups.

 src/gallium/drivers/r600/r600.h                    |    2 +
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |    2 +
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   68 +++++++++++++++++++-
 3 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 2af4d31..b9689df 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -254,6 +254,7 @@ struct r600_context {
 	u32			*pm4;
 	struct list_head	query_list;
 	unsigned		num_query_running;
+	unsigned		zpass_backends_mask;
 	struct list_head	fenced_bo;
 	unsigned                max_db; /* for OQ */
 	unsigned                num_dest_buffers;
@@ -275,6 +276,7 @@ struct r600_draw {
 	struct r600_bo		*indices;
 };
 
+void r600_get_zpass_backends_mask(struct r600_context *ctx);
 int r600_context_init(struct r600_context *ctx, struct radeon *radeon);
 void r600_context_fini(struct r600_context *ctx);
 void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state);
diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index 4d9dd50..87445ab 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -1018,6 +1018,8 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
 
 	LIST_INITHEAD(&ctx->fenced_bo);
 
+	r600_get_zpass_backends_mask(ctx);
+
 	return 0;
 out_err:
 	r600_context_fini(ctx);
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index a2f13ff..2fafe35 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -40,6 +40,64 @@
 
 #define GROUP_FORCE_NEW_BLOCK	0
 
+/* Get backends mask for ZPASS_DONE event */
+void r600_get_zpass_backends_mask(struct r600_context *ctx)
+{
+	struct r600_bo * buffer;
+	u32 * results;
+	unsigned i, mask = 0;
+
+	/* create buffer for event data */
+	buffer = r600_bo(ctx->radeon, ctx->max_db*16, 1, 0,
+				PIPE_USAGE_STAGING);
+	if (!buffer)
+		goto err;
+
+	/* initialize buffer with zeroes */
+	results = r600_bo_map(ctx->radeon, buffer, PB_USAGE_CPU_WRITE, NULL);
+	if (results) {
+		memset(results, 0, ctx->max_db * 4 * 4);
+		r600_bo_unmap(ctx->radeon, buffer);
+
+		/* emit EVENT_WRITE for ZPASS_DONE */
+		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2, 0);
+		ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
+		ctx->pm4[ctx->pm4_cdwords++] = r600_bo_offset(buffer);
+		ctx->pm4[ctx->pm4_cdwords++] = 0;
+
+		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0);
+		ctx->pm4[ctx->pm4_cdwords++] = 0;
+		r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], buffer);
+
+		/* execute */
+		r600_context_flush(ctx);
+
+		/* analyze results */
+		results = r600_bo_map(ctx->radeon, buffer, PB_USAGE_CPU_READ, NULL);
+		if (results) {
+			for(i = 0; i < ctx->max_db; i++) {
+				/* if highest bit is set then backend is used */
+				if (results[i*4 + 1] & 0x80000000) {
+					mask |= (1<<i);
+				}
+			}
+			r600_bo_unmap(ctx->radeon, buffer);
+		}
+	}
+
+	r600_bo_reference(ctx->radeon, &buffer, NULL);
+
+	if (mask != 0) {
+		ctx->zpass_backends_mask = mask;
+		return;
+	}
+
+err:
+	/* fallback to old method - set num_backends lower bits to 1 */
+	ctx->zpass_backends_mask = (~((u32)0))>>(32-r600_get_num_backends(ctx->radeon));
+	return;
+}
+
 static inline void r600_context_ps_partial_flush(struct r600_context *ctx)
 {
 	if (!(ctx->flags & R600_CONTEXT_DRAW_PENDING))
@@ -899,6 +957,8 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
 
 	ctx->max_db = 4;
 
+	r600_get_zpass_backends_mask(ctx);
+
 	return 0;
 out_err:
 	r600_context_fini(ctx);
@@ -1759,9 +1819,11 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
 		if (results) {
 			memset(results + query->num_results, 0, ctx->max_db * 4 * 4);
 
-			for (i = num_backends; i < ctx->max_db; i++) {
-				results[(i * 4)+1] = 0x80000000;
-				results[(i * 4)+3] = 0x80000000;
+			for (i = 0; i < ctx->max_db; i++) {
+				if (!(ctx->zpass_backends_mask & (1<<i))) {
+					results[(i * 4)+1] = 0x80000000;
+					results[(i * 4)+3] = 0x80000000;
+				}
 			}
 			r600_bo_unmap(ctx->radeon, query->buffer);
 		}
-- 
1.7.6



More information about the mesa-dev mailing list