ilo: hook up pipe context query functions
authorChia-I Wu <olv@lunarg.com>
Wed, 12 Dec 2012 21:20:40 +0000 (05:20 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 26 Apr 2013 08:16:43 +0000 (16:16 +0800)
None of the query types are supported yet.

src/gallium/drivers/ilo/ilo_query.c
src/gallium/drivers/ilo/ilo_query.h

index bb7971d09dcb6fee634df9eca0a3719cf2ce47dd..0af8ca833380dd8b68e1cb4e0c91b2fcd1bdfff7 100644 (file)
  *    Chia-I Wu <olv@lunarg.com>
  */
 
+#include "intel_winsys.h"
+
 #include "ilo_context.h"
+#include "ilo_cp.h"
 #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, \
+}
+#define INFOX(prefix, desc) { desc, NULL, NULL, NULL, }
+
+   [PIPE_QUERY_OCCLUSION_COUNTER]      = INFOX(ilo_3d, "occlusion counter"),
+   [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(ilo_3d, "occlusion pred."),
+   [PIPE_QUERY_TIMESTAMP]              = INFOX(ilo_3d, "timestamp"),
+   [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(ilo_3d, "timestamp disjoint"),
+   [PIPE_QUERY_TIME_ELAPSED]           = INFOX(ilo_3d, "time elapsed"),
+   [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFOX(ilo_3d, "primitives generated"),
+   [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFOX(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]    = INFOX(ilo_3d, "pipeline statistics"),
+
+#undef INFO
+#undef INFOX
+};
+
+static inline struct ilo_query *
+ilo_query(struct pipe_query *query)
+{
+   return (struct ilo_query *) query;
+}
+
+static struct pipe_query *
+ilo_create_query(struct pipe_context *pipe, unsigned query_type)
+{
+   struct ilo_query *q;
+
+   switch (query_type) {
+   default:
+      return NULL;
+   }
+
+   q = CALLOC_STRUCT(ilo_query);
+   if (!q)
+      return NULL;
+
+   q->type = query_type;
+   list_inithead(&q->list);
+
+   return (struct pipe_query *) q;
+}
+
+static void
+ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
+{
+   struct ilo_query *q = ilo_query(query);
+
+   if (q->bo)
+      q->bo->unreference(q->bo);
+
+   FREE(q);
+}
+
+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);
+
+   q->active = true;
+
+   query_info[q->type].begin(ilo, 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);
+
+   /*
+    * some queries such as timestamp query does not require a call to
+    * begin_query() so q->active is always false
+    */
+   q->active = false;
+}
+
+/**
+ * The type (union pipe_query_result) indicates only the size of the buffer.
+ * Callers expect the result to be "serialized".
+ */
+static void
+serialize_query_data(unsigned type, const union pipe_query_result *data,
+                     void *buf)
+{
+   switch (type) {
+   default:
+      memset(buf, 0, sizeof(union pipe_query_result));
+      break;
+   }
+}
+
+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->cp->bo->references(ilo->cp->bo, q->bo))
+         ilo_cp_flush(ilo->cp);
+
+      if (!wait && intel_bo_is_busy(q->bo))
+         return false;
+
+      query_info[q->type].process(ilo, q);
+   }
+
+   if (result)
+      serialize_query_data(q->type, &q->data, (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)
+         q->bo->unreference(q->bo);
+
+      q->bo = winsys->alloc_buffer(winsys, name, size, 0);
+      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.
  */
 void
 ilo_init_query_functions(struct ilo_context *ilo)
 {
-   ilo->base.create_query = NULL;
-   ilo->base.destroy_query = NULL;
-   ilo->base.begin_query = NULL;
-   ilo->base.end_query = NULL;
-   ilo->base.get_query_result = NULL;
+   ilo->base.create_query = ilo_create_query;
+   ilo->base.destroy_query = ilo_destroy_query;
+   ilo->base.begin_query = ilo_begin_query;
+   ilo->base.end_query = ilo_end_query;
+   ilo->base.get_query_result = ilo_get_query_result;
 }
index e30f7e1f28369cf374b0dd1e8808072714007ff9..7fedb2fbe03c796a97d654ff32a4918144910414 100644 (file)
 
 #include "ilo_common.h"
 
+struct intel_bo;
 struct ilo_context;
 
+/**
+ * Queries can be bound to various places in the driver.  While bound, it tells
+ * the driver to collect the data indicated by the type of the query.
+ */
+struct ilo_query {
+   unsigned type;
+   bool active;
+
+   struct list_head list;
+
+   /* storage for the collected data */
+   union pipe_query_result data;
+
+   /* for queries that need to read hardware statistics */
+   struct intel_bo *bo;
+   int reg_read, reg_total;
+   int reg_cmd_size; /* in dwords, as expected by ilo_cp */
+};
+
 void
 ilo_init_query_functions(struct ilo_context *ilo);
 
+bool
+ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count,
+                   struct intel_winsys *winsys);
+
 #endif /* ILO_QUERY_H */