[Mesa-dev] [PATCH 4/4] r600g: implement pipeline statistics query

Marek Olšák maraeo at gmail.com
Thu Apr 11 03:43:29 PDT 2013


---
 src/gallium/drivers/r600/r600_pipe.c  |    2 +-
 src/gallium/drivers/r600/r600_pipe.h  |    1 +
 src/gallium/drivers/r600/r600_query.c |   95 +++++++++++++++++++++++++++++++++
 src/gallium/drivers/r600/r600d.h      |    3 ++
 4 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index aeff693..d8f05b8 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -566,6 +566,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
 	case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
         case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
+	case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
 		return 1;
 	case PIPE_CAP_TGSI_TEXCOORD:
 		return 0;
@@ -603,7 +604,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_VERTEX_COLOR_CLAMPED:
 	case PIPE_CAP_USER_VERTEX_BUFFERS:
 	case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
-	case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
 		return 0;
 
 	/* Stream output. */
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 329944d..7cd8881 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -623,6 +623,7 @@ struct r600_context {
 	/* Queries. */
 	/* The list of active queries. Only one query of each type can be active. */
 	int				num_occlusion_queries;
+	int				num_pipelinestat_queries;
 	/* Keep track of non-timer queries, because they should be suspended
 	 * during context flushing.
 	 * The timer queries (TIME_ELAPSED) shouldn't be suspended. */
diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c
index 80528cc..d264b7f 100644
--- a/src/gallium/drivers/r600/r600_query.c
+++ b/src/gallium/drivers/r600/r600_query.c
@@ -85,6 +85,7 @@ static struct r600_resource *r600_new_query_buffer(struct r600_context *ctx, uns
 	case PIPE_QUERY_PRIMITIVES_GENERATED:
 	case PIPE_QUERY_SO_STATISTICS:
 	case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
+	case PIPE_QUERY_PIPELINE_STATISTICS:
 		results = r600_buffer_mmap_sync_with_rings(ctx, buf, PIPE_TRANSFER_WRITE);
 		memset(results, 0, buf_size);
 		ctx->ws->buffer_unmap(buf->cs_buf);
@@ -160,6 +161,17 @@ static void r600_emit_query_begin(struct r600_context *ctx, struct r600_query *q
 		cs->buf[cs->cdw++] = 0;
 		cs->buf[cs->cdw++] = 0;
 		break;
+	case PIPE_QUERY_PIPELINE_STATISTICS:
+		if (!ctx->num_pipelinestat_queries) {
+			cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0);
+			cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_START) | EVENT_INDEX(0);
+		}
+		ctx->num_pipelinestat_queries++;
+		cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 2, 0);
+		cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_SAMPLE_PIPELINESTAT) | EVENT_INDEX(2);
+		cs->buf[cs->cdw++] = va;
+		cs->buf[cs->cdw++] = (va >> 32UL) & 0xFF;
+		break;
 	default:
 		assert(0);
 	}
@@ -213,6 +225,19 @@ static void r600_emit_query_end(struct r600_context *ctx, struct r600_query *que
 		cs->buf[cs->cdw++] = 0;
 		cs->buf[cs->cdw++] = 0;
 		break;
+	case PIPE_QUERY_PIPELINE_STATISTICS:
+		assert(ctx->num_pipelinestat_queries > 0);
+		ctx->num_pipelinestat_queries--;
+		if (!ctx->num_pipelinestat_queries) {
+			cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0);
+			cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_STOP) | EVENT_INDEX(0);
+		}
+		va += query->buffer.results_end + query->result_size/2;
+		cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 2, 0);
+		cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_SAMPLE_PIPELINESTAT) | EVENT_INDEX(2);
+		cs->buf[cs->cdw++] = va;
+		cs->buf[cs->cdw++] = (va >> 32UL) & 0xFF;
+		break;
 	default:
 		assert(0);
 	}
@@ -311,6 +336,11 @@ static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned q
 		query->result_size = 32;
 		query->num_cs_dw = 6;
 		break;
+	case PIPE_QUERY_PIPELINE_STATISTICS:
+		/* 11 values on EG, 8 on R600. */
+		query->result_size = (rctx->chip_class >= EVERGREEN ? 11 : 8) * 16;
+		query->num_cs_dw = 8;
+		break;
 	/* Non-GPU queries. */
 	case R600_QUERY_DRAW_CALLS:
 	case R600_QUERY_REQUESTED_VRAM:
@@ -540,6 +570,71 @@ static boolean r600_get_query_buffer_result(struct r600_context *ctx,
 			results_base += query->result_size;
 		}
 		break;
+	case PIPE_QUERY_PIPELINE_STATISTICS:
+		if (ctx->chip_class >= EVERGREEN) {
+			while (results_base != qbuf->results_end) {
+				result->pipeline_statistics.ps_invocations +=
+					r600_query_read_result(map + results_base, 0, 22, false);
+				result->pipeline_statistics.c_primitives +=
+					r600_query_read_result(map + results_base, 2, 24, false);
+				result->pipeline_statistics.c_invocations +=
+					r600_query_read_result(map + results_base, 4, 26, false);
+				result->pipeline_statistics.vs_invocations +=
+					r600_query_read_result(map + results_base, 6, 28, false);
+				result->pipeline_statistics.gs_invocations +=
+					r600_query_read_result(map + results_base, 8, 30, false);
+				result->pipeline_statistics.gs_primitives +=
+					r600_query_read_result(map + results_base, 10, 32, false);
+				result->pipeline_statistics.ia_primitives +=
+					r600_query_read_result(map + results_base, 12, 34, false);
+				result->pipeline_statistics.ia_vertices +=
+					r600_query_read_result(map + results_base, 14, 36, false);
+				result->pipeline_statistics.hs_invocations +=
+					r600_query_read_result(map + results_base, 16, 38, false);
+				result->pipeline_statistics.ds_invocations +=
+					r600_query_read_result(map + results_base, 18, 40, false);
+				result->pipeline_statistics.cs_invocations +=
+					r600_query_read_result(map + results_base, 20, 42, false);
+				results_base += query->result_size;
+			}
+		} else {
+			while (results_base != qbuf->results_end) {
+				result->pipeline_statistics.ps_invocations +=
+					r600_query_read_result(map + results_base, 0, 16, false);
+				result->pipeline_statistics.c_primitives +=
+					r600_query_read_result(map + results_base, 2, 18, false);
+				result->pipeline_statistics.c_invocations +=
+					r600_query_read_result(map + results_base, 4, 20, false);
+				result->pipeline_statistics.vs_invocations +=
+					r600_query_read_result(map + results_base, 6, 22, false);
+				result->pipeline_statistics.gs_invocations +=
+					r600_query_read_result(map + results_base, 8, 24, false);
+				result->pipeline_statistics.gs_primitives +=
+					r600_query_read_result(map + results_base, 10, 26, false);
+				result->pipeline_statistics.ia_primitives +=
+					r600_query_read_result(map + results_base, 12, 28, false);
+				result->pipeline_statistics.ia_vertices +=
+					r600_query_read_result(map + results_base, 14, 30, false);
+				results_base += query->result_size;
+			}
+		}
+#if 0 /* for testing */
+		printf("Pipeline stats: IA verts=%llu, IA prims=%llu, VS=%llu, HS=%llu, "
+		       "DS=%llu, GS=%llu, GS prims=%llu, Clipper=%llu, "
+		       "Clipper prims=%llu, PS=%llu, CS=%llu\n",
+		       result->pipeline_statistics.ia_vertices,
+		       result->pipeline_statistics.ia_primitives,
+		       result->pipeline_statistics.vs_invocations,
+		       result->pipeline_statistics.hs_invocations,
+		       result->pipeline_statistics.ds_invocations,
+		       result->pipeline_statistics.gs_invocations,
+		       result->pipeline_statistics.gs_primitives,
+		       result->pipeline_statistics.c_invocations,
+		       result->pipeline_statistics.c_primitives,
+		       result->pipeline_statistics.ps_invocations,
+		       result->pipeline_statistics.cs_invocations);
+#endif
+		break;
 	default:
 		assert(0);
 	}
diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h
index 9b31383..89b09dd 100644
--- a/src/gallium/drivers/r600/r600d.h
+++ b/src/gallium/drivers/r600/r600d.h
@@ -117,6 +117,9 @@
 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT 0x14
 #define EVENT_TYPE_ZPASS_DONE                  0x15
 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT   0x16
+#define EVENT_TYPE_PIPELINESTAT_START		25
+#define EVENT_TYPE_PIPELINESTAT_STOP		26
+#define EVENT_TYPE_SAMPLE_PIPELINESTAT		30
 #define EVENT_TYPE_SO_VGTSTREAMOUT_FLUSH	0x1f
 #define EVENT_TYPE_SAMPLE_STREAMOUTSTATS	0x20
 #define EVENT_TYPE_FLUSH_AND_INV_DB_META       0x2c /* supported on r700+ */
-- 
1.7.10.4



More information about the mesa-dev mailing list