nv50,nvc0: Mark PIPE_QUERY_TIMESTAMP_DISJOINT as ready immediately
[mesa.git] / src / gallium / drivers / nouveau / nvc0 / nvc0_query.c
index 21aa3580e7c16494ac7e051518c5eee162ff4935..ec464b51a710a68ddf818577bbce974d47ae6051 100644 (file)
@@ -108,7 +108,7 @@ nvc0_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
 }
 
 static struct pipe_query *
-nvc0_query_create(struct pipe_context *pipe, unsigned type)
+nvc0_query_create(struct pipe_context *pipe, unsigned type, unsigned index)
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
    struct nvc0_query *q;
@@ -136,6 +136,7 @@ nvc0_query_create(struct pipe_context *pipe, unsigned type)
    case PIPE_QUERY_PRIMITIVES_GENERATED:
    case PIPE_QUERY_PRIMITIVES_EMITTED:
       q->is64bit = TRUE;
+      q->index = index;
       space = 32;
       break;
    case PIPE_QUERY_TIME_ELAPSED:
@@ -396,6 +397,10 @@ nvc0_query_end(struct pipe_context *pipe, struct pipe_query *pq)
       /* indexed by TFB buffer instead of by vertex stream */
       nvc0_query_get(push, q, 0x00, 0x0d005002 | (q->index << 5));
       break;
+   case PIPE_QUERY_TIMESTAMP_DISJOINT:
+      /* This query is not issued on GPU because disjoint is forced to FALSE */
+      q->state = NVC0_QUERY_STATE_READY;
+      break;
    default:
 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
       if (q->type >= NVC0_QUERY_DRV_STAT(0) &&
@@ -541,56 +546,64 @@ nvc0_render_condition(struct pipe_context *pipe,
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    struct nvc0_query *q;
    uint32_t cond;
-   boolean negated = FALSE;
    boolean wait =
       mode != PIPE_RENDER_COND_NO_WAIT &&
       mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
 
+   if (!pq) {
+      cond = NVC0_3D_COND_MODE_ALWAYS;
+   }
+   else {
+      q = nvc0_query(pq);
+      /* NOTE: comparison of 2 queries only works if both have completed */
+      switch (q->type) {
+      case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
+         cond = condition ? NVC0_3D_COND_MODE_EQUAL :
+                          NVC0_3D_COND_MODE_NOT_EQUAL;
+         wait = TRUE;
+         break;
+      case PIPE_QUERY_OCCLUSION_COUNTER:
+      case PIPE_QUERY_OCCLUSION_PREDICATE:
+         if (likely(!condition)) {
+            if (unlikely(q->nesting))
+               cond = wait ? NVC0_3D_COND_MODE_NOT_EQUAL :
+                             NVC0_3D_COND_MODE_ALWAYS;
+            else
+               cond = NVC0_3D_COND_MODE_RES_NON_ZERO;
+         } else {
+            cond = wait ? NVC0_3D_COND_MODE_EQUAL : NVC0_3D_COND_MODE_ALWAYS;
+         }
+         break;
+      default:
+         assert(!"render condition query not a predicate");
+         cond = NVC0_3D_COND_MODE_ALWAYS;
+         break;
+      }
+   }
+
    nvc0->cond_query = pq;
    nvc0->cond_cond = condition;
+   nvc0->cond_condmode = cond;
    nvc0->cond_mode = mode;
 
    if (!pq) {
       PUSH_SPACE(push, 1);
-      IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS);
+      IMMED_NVC0(push, NVC0_3D(COND_MODE), cond);
       return;
    }
-   q = nvc0_query(pq);
-
-   /* NOTE: comparison of 2 queries only works if both have completed */
-   switch (q->type) {
-   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
-      cond = negated ? NVC0_3D_COND_MODE_EQUAL :
-                       NVC0_3D_COND_MODE_NOT_EQUAL;
-      wait = TRUE;
-      break;
-   case PIPE_QUERY_OCCLUSION_COUNTER:
-   case PIPE_QUERY_OCCLUSION_PREDICATE:
-      if (likely(!negated)) {
-         if (unlikely(q->nesting))
-            cond = wait ? NVC0_3D_COND_MODE_NOT_EQUAL :
-                          NVC0_3D_COND_MODE_ALWAYS;
-         else
-            cond = NVC0_3D_COND_MODE_RES_NON_ZERO;
-      } else {
-         cond = wait ? NVC0_3D_COND_MODE_EQUAL : NVC0_3D_COND_MODE_ALWAYS;
-      }
-      break;
-   default:
-      assert(!"render condition query not a predicate");
-      mode = NVC0_3D_COND_MODE_ALWAYS;
-      break;
-   }
 
    if (wait)
       nvc0_query_fifo_wait(push, pq);
 
-   PUSH_SPACE(push, 4);
+   PUSH_SPACE(push, 7);
    PUSH_REFN (push, q->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
    BEGIN_NVC0(push, NVC0_3D(COND_ADDRESS_HIGH), 3);
    PUSH_DATAh(push, q->bo->offset + q->offset);
    PUSH_DATA (push, q->bo->offset + q->offset);
    PUSH_DATA (push, cond);
+   BEGIN_NVC0(push, NVC0_2D(COND_ADDRESS_HIGH), 2);
+   PUSH_DATAh(push, q->bo->offset + q->offset);
+   PUSH_DATA (push, q->bo->offset + q->offset);
 }
 
 void
@@ -1063,6 +1076,7 @@ nvc0_mp_pm_query_begin(struct nvc0_context *nvc0, struct nvc0_query *q)
 {
    struct nvc0_screen *screen = nvc0->screen;
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+   const boolean is_nve4 = screen->base.class_3d >= NVE4_3D_CLASS;
    const struct nvc0_mp_pm_query_cfg *cfg;
    unsigned i, c;
    unsigned num_ab[2] = { 0, 0 };
@@ -1080,7 +1094,7 @@ nvc0_mp_pm_query_begin(struct nvc0_context *nvc0, struct nvc0_query *q)
    }
 
    assert(cfg->num_counters <= 4);
-   PUSH_SPACE(push, 4 * 8 + 6);
+   PUSH_SPACE(push, 4 * 8 * (is_nve4 ? 1 : 6) + 6);
 
    if (!screen->pm.mp_counters_enabled) {
       screen->pm.mp_counters_enabled = TRUE;
@@ -1114,7 +1128,7 @@ nvc0_mp_pm_query_begin(struct nvc0_context *nvc0, struct nvc0_query *q)
       assert(c <= (d * 4 + 3)); /* must succeed, already checked for space */
 
       /* configure and reset the counter(s) */
-      if (screen->base.class_3d >= NVE4_3D_CLASS) {
+      if (is_nve4) {
          if (d == 0)
             BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_A_SIGSEL(c & 3)), 1);
          else
@@ -1328,14 +1342,14 @@ nvc0_mp_pm_query_result(struct nvc0_context *nvc0, struct nvc0_query *q,
       for (c = 0; c < cfg->num_counters; ++c)
          for (p = 0; p < mp_count; ++p)
             v |= count[p][c];
-      value = (v * cfg->norm[0]) / cfg->norm[1];
+      value = ((uint64_t)v * cfg->norm[0]) / cfg->norm[1];
    } else
    if (cfg->op == NVC0_COUNTER_OPn_AND) {
       uint32_t v = ~0;
       for (c = 0; c < cfg->num_counters; ++c)
          for (p = 0; p < mp_count; ++p)
             v &= count[p][c];
-      value = (v * cfg->norm[0]) / cfg->norm[1];
+      value = ((uint64_t)v * cfg->norm[0]) / cfg->norm[1];
    } else
    if (cfg->op == NVC0_COUNTER_OP2_REL_SUM_MM) {
       uint64_t v[2] = { 0, 0 };
@@ -1360,7 +1374,7 @@ nvc0_mp_pm_query_result(struct nvc0_context *nvc0, struct nvc0_query *q,
          if (count[p][1])
             value += (count[p][0] * cfg->norm[0]) / count[p][1];
       if (mp_used)
-         value /= mp_used * cfg->norm[1];
+         value /= (uint64_t)mp_used * cfg->norm[1];
    } else
    if (cfg->op == NVC0_COUNTER_OP2_AVG_DIV_M0) {
       unsigned mp_used = 0;
@@ -1368,7 +1382,7 @@ nvc0_mp_pm_query_result(struct nvc0_context *nvc0, struct nvc0_query *q,
          value += count[p][0];
       if (count[0][1] && mp_used) {
          value *= cfg->norm[0];
-         value /= count[0][1] * mp_used * cfg->norm[1];
+         value /= (uint64_t)count[0][1] * mp_used * cfg->norm[1];
       } else {
          value = 0;
       }