ilo: rework query support
[mesa.git] / src / gallium / drivers / ilo / ilo_query.c
index 812e056996ef033154f65a71b101f21bf73ec1b0..e0cd4ee755438444bae84aadfcbcbb36022284d6 100644 (file)
 #include "ilo_query.h"
 
 static const struct {
-   const char *name;
-
-   void (*begin)(struct ilo_context *ilo, struct ilo_query *q);
-   void (*end)(struct ilo_context *ilo, struct ilo_query *q);
-   void (*process)(struct ilo_context *ilo, struct ilo_query *q);
-} query_info[PIPE_QUERY_TYPES] = {
-#define INFO(prefix, desc) {        \
-   .name = desc,                    \
-   .begin = prefix ## _begin_query, \
-   .end = prefix ## _end_query,     \
-   .process = prefix ## _process_query, \
+   bool (*init)(struct pipe_context *pipe, struct ilo_query *q);
+   void (*begin)(struct pipe_context *pipe, struct ilo_query *q);
+   void (*end)(struct pipe_context *pipe, struct ilo_query *q);
+   void (*process)(struct pipe_context *pipe, struct ilo_query *q);
+} ilo_query_table[PIPE_QUERY_TYPES] = {
+#define INFO(prefix) {                    \
+   .init = prefix ## _init_query,         \
+   .begin = prefix ## _begin_query,       \
+   .end = prefix ## _end_query,           \
+   .process = prefix ## _process_query,   \
 }
-#define INFOX(prefix, desc) { desc, NULL, NULL, NULL, }
-
-   [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(ilo_3d, "occlusion counter"),
-   [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(ilo_3d, "occlusion pred."),
-   [PIPE_QUERY_TIMESTAMP]              = INFO(ilo_3d, "timestamp"),
-   [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(ilo_3d, "timestamp disjoint"),
-   [PIPE_QUERY_TIME_ELAPSED]           = INFO(ilo_3d, "time elapsed"),
-   [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(ilo_3d, "primitives generated"),
-   [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(ilo_3d, "primitives emitted"),
-   [PIPE_QUERY_SO_STATISTICS]          = INFOX(ilo_3d, "so statistics"),
-   [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(ilo_3d, "so overflow pred."),
-   [PIPE_QUERY_GPU_FINISHED]           = INFOX(ilo_3d, "gpu finished"),
-   [PIPE_QUERY_PIPELINE_STATISTICS]    = INFO(ilo_3d, "pipeline statistics"),
+#define INFOX(prefix) { NULL, NULL, NULL, NULL, }
+
+   [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(ilo_3d),
+   [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(ilo_3d),
+   [PIPE_QUERY_TIMESTAMP]              = INFO(ilo_3d),
+   [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(ilo_3d),
+   [PIPE_QUERY_TIME_ELAPSED]           = INFO(ilo_3d),
+   [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(ilo_3d),
+   [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(ilo_3d),
+   [PIPE_QUERY_SO_STATISTICS]          = INFOX(ilo_3d),
+   [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(ilo_3d),
+   [PIPE_QUERY_GPU_FINISHED]           = INFOX(ilo_3d),
+   [PIPE_QUERY_PIPELINE_STATISTICS]    = INFO(ilo_3d),
 
 #undef INFO
 #undef INFOX
@@ -91,8 +90,15 @@ ilo_create_query(struct pipe_context *pipe, unsigned query_type, unsigned index)
       return NULL;
 
    q->type = query_type;
+   q->index = index;
+
    list_inithead(&q->list);
 
+   if (!ilo_query_table[q->type].init(pipe, q)) {
+      FREE(q);
+      return NULL;
+   }
+
    return (struct pipe_query *) q;
 }
 
@@ -110,62 +116,71 @@ ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
 static void
 ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
 {
-   struct ilo_context *ilo = ilo_context(pipe);
    struct ilo_query *q = ilo_query(query);
 
+   if (q->active)
+      return;
+
+   util_query_clear_result(&q->result, q->type);
+   q->used = 0;
    q->active = true;
 
-   query_info[q->type].begin(ilo, q);
+   ilo_query_table[q->type].begin(pipe, q);
 }
 
 static void
 ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
 {
-   struct ilo_context *ilo = ilo_context(pipe);
    struct ilo_query *q = ilo_query(query);
 
-   query_info[q->type].end(ilo, q);
+   if (!q->active) {
+      /* require ilo_begin_query() first */
+      if (q->in_pairs)
+         return;
+
+      ilo_begin_query(pipe, query);
+   }
 
-   /*
-    * some queries such as timestamp query does not require a call to
-    * begin_query() so q->active is always false
-    */
    q->active = false;
+
+   ilo_query_table[q->type].end(pipe, q);
 }
 
 /**
- * The type (union pipe_query_result) indicates only the size of the buffer.
- * Callers expect the result to be "serialized".
+ * Serialize the result.  The size of \p buf is
+ * sizeof(union pipe_query_result).
  */
 static void
-serialize_query_data(unsigned type, const union pipe_query_result *data,
-                     void *buf)
+query_serialize(const struct ilo_query *q, void *buf)
 {
-   switch (type) {
+   switch (q->type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
    case PIPE_QUERY_TIMESTAMP:
    case PIPE_QUERY_TIME_ELAPSED:
    case PIPE_QUERY_PRIMITIVES_GENERATED:
    case PIPE_QUERY_PRIMITIVES_EMITTED:
       {
-         uint64_t *r = buf;
-         r[0] = data->u64;
+         uint64_t *dst = buf;
+         dst[0] = q->result.u64;
       }
       break;
    case PIPE_QUERY_PIPELINE_STATISTICS:
       {
-         uint64_t *r = buf;
-         r[0] = data->pipeline_statistics.ia_vertices;
-         r[1] = data->pipeline_statistics.ia_primitives;
-         r[2] = data->pipeline_statistics.vs_invocations;
-         r[3] = data->pipeline_statistics.gs_invocations;
-         r[4] = data->pipeline_statistics.gs_primitives;
-         r[5] = data->pipeline_statistics.c_invocations;
-         r[6] = data->pipeline_statistics.c_primitives;
-         r[7] = data->pipeline_statistics.ps_invocations;
-         r[8] = data->pipeline_statistics.hs_invocations;
-         r[9] = data->pipeline_statistics.ds_invocations;
-         r[10] = data->pipeline_statistics.cs_invocations;
+         const struct pipe_query_data_pipeline_statistics *stats =
+            &q->result.pipeline_statistics;
+         uint64_t *dst = buf;
+
+         dst[0] = stats->ia_vertices;
+         dst[1] = stats->ia_primitives;
+         dst[2] = stats->vs_invocations;
+         dst[3] = stats->gs_invocations;
+         dst[4] = stats->gs_primitives;
+         dst[5] = stats->c_invocations;
+         dst[6] = stats->c_primitives;
+         dst[7] = stats->ps_invocations;
+         dst[8] = stats->hs_invocations;
+         dst[9] = stats->ds_invocations;
+         dst[10] = stats->cs_invocations;
       }
       break;
    default:
@@ -178,70 +193,29 @@ static boolean
 ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
                      boolean wait, union pipe_query_result *result)
 {
-   struct ilo_context *ilo = ilo_context(pipe);
    struct ilo_query *q = ilo_query(query);
 
    if (q->active)
       return false;
 
    if (q->bo) {
-      if (ilo_builder_has_reloc(&ilo->cp->builder, q->bo))
-         ilo_cp_submit(ilo->cp, "syncing for queries");
+      struct ilo_cp *cp = ilo_context(pipe)->cp;
+
+      if (ilo_builder_has_reloc(&cp->builder, q->bo))
+         ilo_cp_submit(cp, "syncing for queries");
 
       if (!wait && intel_bo_is_busy(q->bo))
          return false;
-
-      query_info[q->type].process(ilo, q);
    }
 
+   ilo_query_table[q->type].process(pipe, q);
+
    if (result)
-      serialize_query_data(q->type, &q->data, (void *) result);
+      query_serialize(q, (void *) result);
 
    return true;
 }
 
-/**
- * Allocate a query bo for reading hardware statistics.
- *
- * \param reg_count specifies how many registers need to be read.
- * \param repeat_count specifies how many times the registers are read.  If
- *        zero or negative, a 4KB bo is allocated.
- */
-bool
-ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count,
-                   struct intel_winsys *winsys)
-{
-   const char *name;
-   int reg_total;
-
-   name = query_info[q->type].name;
-
-   reg_total = reg_count * repeat_count;
-   if (reg_total <= 0)
-      reg_total = 4096 / sizeof(uint64_t);
-
-   /* (re-)allocate the bo */
-   if (q->reg_total < reg_total) {
-      /* registers are 64-bit */
-      const int size = reg_total * sizeof(uint64_t);
-
-      if (q->bo)
-         intel_bo_unreference(q->bo);
-
-      q->bo = intel_winsys_alloc_buffer(winsys,
-            name, size, false);
-      q->reg_total = (q->bo) ? reg_total : 0;
-   }
-
-   /* avoid partial reads */
-   if (reg_count)
-      q->reg_total -= q->reg_total % reg_count;
-
-   q->reg_read = 0;
-
-   return (q->bo != NULL);
-}
-
 /**
  * Initialize query-related functions.
  */