nvc0: add support for handling indirect draws with attrib conversion
[mesa.git] / src / gallium / drivers / nouveau / nvc0 / nvc0_query.c
index e4752e2dbc594c959f34327478d701f338ffdb29..1a3e4e794c0a9eb7051481e9378e2f90927bf419 100644 (file)
@@ -28,6 +28,7 @@
 #include "nvc0/nvc0_query.h"
 #include "nvc0/nvc0_query_sw.h"
 #include "nvc0/nvc0_query_hw.h"
+#include "nvc0/nvc0_query_hw_metric.h"
 #include "nvc0/nvc0_query_hw_sm.h"
 
 static struct pipe_query *
@@ -57,11 +58,12 @@ nvc0_begin_query(struct pipe_context *pipe, struct pipe_query *pq)
    return q->funcs->begin_query(nvc0_context(pipe), q);
 }
 
-static void
+static bool
 nvc0_end_query(struct pipe_context *pipe, struct pipe_query *pq)
 {
    struct nvc0_query *q = nvc0_query(pq);
    q->funcs->end_query(nvc0_context(pipe), q);
+   return true;
 }
 
 static boolean
@@ -72,10 +74,28 @@ nvc0_get_query_result(struct pipe_context *pipe, struct pipe_query *pq,
    return q->funcs->get_query_result(nvc0_context(pipe), q, wait, result);
 }
 
+static void
+nvc0_get_query_result_resource(struct pipe_context *pipe,
+                               struct pipe_query *pq,
+                               boolean wait,
+                               enum pipe_query_value_type result_type,
+                               int index,
+                               struct pipe_resource *resource,
+                               unsigned offset)
+{
+   struct nvc0_query *q = nvc0_query(pq);
+   if (!q->funcs->get_query_result_resource) {
+      assert(!"Unexpected lack of get_query_result_resource");
+      return;
+   }
+   q->funcs->get_query_result_resource(nvc0_context(pipe), q, wait, result_type,
+                                       index, resource, offset);
+}
+
 static void
 nvc0_render_condition(struct pipe_context *pipe,
                       struct pipe_query *pq,
-                      boolean condition, uint mode)
+                      boolean condition, enum pipe_render_cond_flag mode)
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
@@ -93,12 +113,14 @@ nvc0_render_condition(struct pipe_context *pipe,
       /* NOTE: comparison of 2 queries only works if both have completed */
       switch (q->type) {
       case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
+      case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
          cond = condition ? NVC0_3D_COND_MODE_EQUAL :
-                          NVC0_3D_COND_MODE_NOT_EQUAL;
+                            NVC0_3D_COND_MODE_NOT_EQUAL;
          wait = true;
          break;
       case PIPE_QUERY_OCCLUSION_COUNTER:
       case PIPE_QUERY_OCCLUSION_PREDICATE:
+      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
          if (likely(!condition)) {
             if (unlikely(hq->nesting))
                cond = wait ? NVC0_3D_COND_MODE_NOT_EQUAL :
@@ -122,15 +144,17 @@ nvc0_render_condition(struct pipe_context *pipe,
    nvc0->cond_mode = mode;
 
    if (!pq) {
-      PUSH_SPACE(push, 1);
+      PUSH_SPACE(push, 2);
       IMMED_NVC0(push, NVC0_3D(COND_MODE), cond);
+      if (nvc0->screen->compute)
+         IMMED_NVC0(push, NVC0_CP(COND_MODE), cond);
       return;
    }
 
    if (wait)
-      nvc0_hw_query_fifo_wait(push, q);
+      nvc0_hw_query_fifo_wait(nvc0, q);
 
-   PUSH_SPACE(push, 7);
+   PUSH_SPACE(push, 10);
    PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
    BEGIN_NVC0(push, NVC0_3D(COND_ADDRESS_HIGH), 3);
    PUSH_DATAh(push, hq->bo->offset + hq->offset);
@@ -139,6 +163,12 @@ nvc0_render_condition(struct pipe_context *pipe,
    BEGIN_NVC0(push, NVC0_2D(COND_ADDRESS_HIGH), 2);
    PUSH_DATAh(push, hq->bo->offset + hq->offset);
    PUSH_DATA (push, hq->bo->offset + hq->offset);
+   if (nvc0->screen->compute) {
+      BEGIN_NVC0(push, NVC0_CP(COND_ADDRESS_HIGH), 3);
+      PUSH_DATAh(push, hq->bo->offset + hq->offset);
+      PUSH_DATA (push, hq->bo->offset + hq->offset);
+      PUSH_DATA (push, cond);
+   }
 }
 
 int
@@ -161,6 +191,7 @@ nvc0_screen_get_driver_query_info(struct pipe_screen *pscreen,
    info->max_value.u64 = 0;
    info->type = PIPE_DRIVER_QUERY_TYPE_UINT64;
    info->group_id = -1;
+   info->flags = 0;
 
 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
    if (id < num_sw_queries)
@@ -182,13 +213,10 @@ nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
    count++;
 #endif
 
-   if (screen->base.device->drm_version >= 0x01000101) {
+   if (screen->base.drm->version >= 0x01000101) {
       if (screen->compute) {
-         if (screen->base.class_3d == NVE4_3D_CLASS) {
-            count++;
-         } else
-         if (screen->base.class_3d < NVE4_3D_CLASS) {
-            count++;
+         if (screen->base.class_3d <= GM200_3D_CLASS) {
+            count += 2;
          }
       }
    }
@@ -199,22 +227,22 @@ nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
    if (id == NVC0_HW_SM_QUERY_GROUP) {
       if (screen->compute) {
          info->name = "MP counters";
-         info->type = PIPE_DRIVER_QUERY_GROUP_TYPE_GPU;
-
-         /* Because we can't expose the number of hardware counters needed for
-          * each different query, we don't want to allow more than one active
-          * query simultaneously to avoid failure when the maximum number of
-          * counters is reached. Note that these groups of GPU counters are
-          * currently only used by AMD_performance_monitor.
-          */
-         info->max_active_queries = 1;
-
-         if (screen->base.class_3d == NVE4_3D_CLASS) {
-            info->num_queries = NVE4_HW_SM_QUERY_COUNT;
-            return 1;
-         } else
-         if (screen->base.class_3d < NVE4_3D_CLASS) {
-            info->num_queries = NVC0_HW_SM_QUERY_COUNT;
+
+         /* Expose the maximum number of hardware counters available, although
+          * some queries use more than one counter. Expect failures in that
+          * case but as performance counters are for developers, this should
+          * not have a real impact. */
+         info->max_active_queries = 8;
+         info->num_queries = nvc0_hw_sm_get_num_queries(screen);
+         return 1;
+      }
+   } else
+   if (id == NVC0_HW_METRIC_QUERY_GROUP) {
+      if (screen->compute) {
+          if (screen->base.class_3d <= GM200_3D_CLASS) {
+            info->name = "Performance metrics";
+            info->max_active_queries = 4; /* A metric uses at least 2 queries */
+            info->num_queries = nvc0_hw_metric_get_num_queries(screen);
             return 1;
          }
       }
@@ -222,7 +250,6 @@ nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
    else if (id == NVC0_SW_QUERY_DRV_STAT_GROUP) {
       info->name = "Driver statistics";
-      info->type = PIPE_DRIVER_QUERY_GROUP_TYPE_CPU;
       info->max_active_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
       info->num_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
       return 1;
@@ -233,10 +260,14 @@ nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
    info->name = "this_is_not_the_query_group_you_are_looking_for";
    info->max_active_queries = 0;
    info->num_queries = 0;
-   info->type = 0;
    return 0;
 }
 
+static void
+nvc0_set_active_query_state(struct pipe_context *pipe, boolean enable)
+{
+}
+
 void
 nvc0_init_query_functions(struct nvc0_context *nvc0)
 {
@@ -247,5 +278,8 @@ nvc0_init_query_functions(struct nvc0_context *nvc0)
    pipe->begin_query = nvc0_begin_query;
    pipe->end_query = nvc0_end_query;
    pipe->get_query_result = nvc0_get_query_result;
+   pipe->get_query_result_resource = nvc0_get_query_result_resource;
+   pipe->set_active_query_state = nvc0_set_active_query_state;
    pipe->render_condition = nvc0_render_condition;
+   nvc0->cond_condmode = NVC0_3D_COND_MODE_ALWAYS;
 }