Mesa (master): radeon: re-prepare query buffers on begin_query for predicate queries

Nicolai Hähnle nh at kemper.freedesktop.org
Fri Nov 20 21:47:06 UTC 2015


Module: Mesa
Branch: master
Commit: 5bda3d0958967b88e739302a480499d1428a0b2a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5bda3d0958967b88e739302a480499d1428a0b2a

Author: Nicolai Hähnle <nhaehnle at gmail.com>
Date:   Fri Nov 20 12:58:55 2015 +0100

radeon: re-prepare query buffers on begin_query for predicate queries

The point of prepare_buffer is to ensure that the query buffer contains valid
initial data for conditional rendering: as long as the buffer is initialized
correctly, the GPU is able to tell whether query results have been written
already (and wait or fall back to unconditional rendering if desired).

This means prepare_buffer needs to be called again when a buffer is reused.

Conversely, for queries that cannot be used for conditional rendering
(notably pipeline statistics), we can re-use buffers immediately, and they
do not need to be initialized.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Tested-by: Andy Furniss <adf.lists at gmail.com>

---

 src/gallium/drivers/radeon/r600_query.c |   32 ++++++++++++++++---------------
 src/gallium/drivers/radeon/r600_query.h |    1 +
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_query.c b/src/gallium/drivers/radeon/r600_query.c
index 526be16..b1cfb6e 100644
--- a/src/gallium/drivers/radeon/r600_query.c
+++ b/src/gallium/drivers/radeon/r600_query.c
@@ -242,7 +242,7 @@ static struct r600_resource *r600_new_query_buffer(struct r600_common_context *c
 		pipe_buffer_create(ctx->b.screen, PIPE_BIND_CUSTOM,
 				   PIPE_USAGE_STAGING, buf_size);
 
-	if (query->ops->prepare_buffer)
+	if (query->flags & R600_QUERY_HW_FLAG_PREDICATE)
 		query->ops->prepare_buffer(ctx, query, buf);
 
 	return buf;
@@ -251,15 +251,11 @@ static struct r600_resource *r600_new_query_buffer(struct r600_common_context *c
 static void r600_query_hw_prepare_buffer(struct r600_common_context *ctx,
 					 struct r600_query_hw *query,
 					 struct r600_resource *buffer)
- {
-	uint32_t *results;
-
-	if (query->b.type == PIPE_QUERY_TIME_ELAPSED ||
-	    query->b.type == PIPE_QUERY_TIMESTAMP)
-		return;
-
-	results = r600_buffer_map_sync_with_rings(ctx, buffer,
-						  PIPE_TRANSFER_WRITE);
+{
+	/* Callers ensure that the buffer is currently unused by the GPU. */
+	uint32_t *results = ctx->ws->buffer_map(buffer->cs_buf, NULL,
+						PIPE_TRANSFER_WRITE |
+						PIPE_TRANSFER_UNSYNCHRONIZED);
 
 	memset(results, 0, buffer->b.b.width0);
 
@@ -339,6 +335,7 @@ static struct pipe_query *r600_query_hw_create(struct r600_common_context *rctx,
 		query->result_size = 16 * rctx->max_db;
 		query->num_cs_dw_begin = 6;
 		query->num_cs_dw_end = 6;
+		query->flags |= R600_QUERY_HW_FLAG_PREDICATE;
 		break;
 	case PIPE_QUERY_TIME_ELAPSED:
 		query->result_size = 16;
@@ -361,6 +358,7 @@ static struct pipe_query *r600_query_hw_create(struct r600_common_context *rctx,
 		query->num_cs_dw_begin = 6;
 		query->num_cs_dw_end = 6;
 		query->stream = index;
+		query->flags |= R600_QUERY_HW_FLAG_PREDICATE;
 		break;
 	case PIPE_QUERY_PIPELINE_STATISTICS:
 		/* 11 values on EG, 8 on R600. */
@@ -667,11 +665,15 @@ static void r600_query_hw_reset_buffers(struct r600_common_context *rctx,
 		FREE(qbuf);
 	}
 
-	/* Obtain a new buffer if the current one can't be mapped without a stall. */
-	if (r600_rings_is_buffer_referenced(rctx, query->buffer.buf->cs_buf, RADEON_USAGE_READWRITE) ||
-	    !rctx->ws->buffer_wait(query->buffer.buf->buf, 0, RADEON_USAGE_READWRITE)) {
-		pipe_resource_reference((struct pipe_resource**)&query->buffer.buf, NULL);
-		query->buffer.buf = r600_new_query_buffer(rctx, query);
+	if (query->flags & R600_QUERY_HW_FLAG_PREDICATE) {
+		/* Obtain a new buffer if the current one can't be mapped without a stall. */
+		if (r600_rings_is_buffer_referenced(rctx, query->buffer.buf->cs_buf, RADEON_USAGE_READWRITE) ||
+		    !rctx->ws->buffer_wait(query->buffer.buf->buf, 0, RADEON_USAGE_READWRITE)) {
+			pipe_resource_reference((struct pipe_resource**)&query->buffer.buf, NULL);
+			query->buffer.buf = r600_new_query_buffer(rctx, query);
+		} else {
+			query->ops->prepare_buffer(rctx, query, query->buffer.buf);
+		}
 	}
 
 	query->buffer.results_end = 0;
diff --git a/src/gallium/drivers/radeon/r600_query.h b/src/gallium/drivers/radeon/r600_query.h
index 9bd3b5d..0ea5707 100644
--- a/src/gallium/drivers/radeon/r600_query.h
+++ b/src/gallium/drivers/radeon/r600_query.h
@@ -71,6 +71,7 @@ struct r600_query {
 enum {
 	R600_QUERY_HW_FLAG_NO_START = (1 << 0),
 	R600_QUERY_HW_FLAG_TIMER = (1 << 1),
+	R600_QUERY_HW_FLAG_PREDICATE = (1 << 2),
 };
 
 struct r600_query_hw_ops {




More information about the mesa-commit mailing list