r600g: implement pipeline statistics query
authorMarek Olšák <maraeo@gmail.com>
Wed, 10 Apr 2013 18:45:01 +0000 (20:45 +0200)
committerMarek Olšák <maraeo@gmail.com>
Tue, 16 Apr 2013 11:56:47 +0000 (13:56 +0200)
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_query.c
src/gallium/drivers/r600/r600d.h

index a080bba5906a52020a977533644b760160c22f86..9b43cef27373e18b082fb021e5874d30874bc9d5 100644 (file)
@@ -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. */
index 55e90ec27aeedfedb71061c674c38c11317556d6..4a692e78302d80bbb8131d6f633b3f8f2526eaab 100644 (file)
@@ -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. */
index 80528cc229dca9b8fa63402f8de33bf4c70e9895..d264b7f3970b192708b3804619da6e3783e1b5ad 100644 (file)
@@ -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);
        }
index 9b31383046d38c9a2505a5aff16a09b6bbcf5f11..89b09ddfa529bc97fb71cb73cd9a64a7fd376101 100644 (file)
 #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+ */