From dfe5367f0ff2487bebbfd99aeeaab26a2fcc52b0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 10 Apr 2013 20:45:01 +0200 Subject: [PATCH] r600g: implement pipeline statistics query --- 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 a080bba..9b43cef 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -572,6 +572,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; @@ -611,7 +612,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_USER_VERTEX_BUFFERS: - 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 55e90ec..4a692e7 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+ */ -- 2.7.4