Mesa (master): nouveau: implement missing timer query functionality

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Fri Jul 13 15:27:10 UTC 2012


Module: Mesa
Branch: master
Commit: 9ed65301e044711de0db51b4986085fca170d764
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9ed65301e044711de0db51b4986085fca170d764

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Thu Jul 12 13:59:52 2012 +0200

nouveau: implement missing timer query functionality

---

 src/gallium/drivers/nouveau/nouveau_screen.c |   24 ++++++++++++++++++++++++
 src/gallium/drivers/nouveau/nouveau_screen.h |    2 ++
 src/gallium/drivers/nv30/nv30_query.c        |   10 ++++++++--
 src/gallium/drivers/nv30/nv30_screen.c       |    2 +-
 src/gallium/drivers/nv50/nv50_query.c        |   11 +++++++++--
 src/gallium/drivers/nv50/nv50_screen.c       |    2 +-
 src/gallium/drivers/nvc0/nvc0_screen.c       |    2 +-
 7 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 9baa68c..d129a55 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -8,10 +8,14 @@
 #include "util/u_format_s3tc.h"
 #include "util/u_string.h"
 
+#include "os/os_time.h"
+
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
 
+#include <libdrm/nouveau_drm.h>
+
 #include "nouveau_winsys.h"
 #include "nouveau_screen.h"
 #include "nouveau_fence.h"
@@ -39,6 +43,16 @@ nouveau_screen_get_vendor(struct pipe_screen *pscreen)
 	return "nouveau";
 }
 
+static uint64_t
+nouveau_screen_get_timestamp(struct pipe_screen *pscreen)
+{
+	int64_t cpu_time = os_time_get() * 1000;
+
+        /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */
+
+	return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta;
+}
+
 static void
 nouveau_screen_fence_ref(struct pipe_screen *pscreen,
 			 struct pipe_fence_handle **ptr,
@@ -108,6 +122,7 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
 	struct pipe_screen *pscreen = &screen->base;
 	struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 };
 	struct nvc0_fifo nvc0_data = { };
+	uint64_t time;
 	int size, ret;
 	void *data;
 	union nouveau_bo_config mm_config;
@@ -139,9 +154,18 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
 	if (ret)
 		return ret;
 
+        /* getting CPU time first appears to be more accurate */
+        screen->cpu_gpu_time_delta = os_time_get();
+
+        ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time);
+        if (!ret)
+           screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000;
+
 	pscreen->get_name = nouveau_screen_get_name;
 	pscreen->get_vendor = nouveau_screen_get_vendor;
 
+	pscreen->get_timestamp = nouveau_screen_get_timestamp;
+
 	pscreen->fence_reference = nouveau_screen_fence_ref;
 	pscreen->fence_signalled = nouveau_screen_fence_signalled;
 	pscreen->fence_finish = nouveau_screen_fence_finish;
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index 5a3cfab..335b958 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -39,6 +39,8 @@ struct nouveau_screen {
 
 	struct nouveau_mman *mm_VRAM;
 	struct nouveau_mman *mm_GART;
+
+	int64_t cpu_gpu_time_delta;
 };
 
 static INLINE struct nouveau_screen *
diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c
index fb4be31..001aba1 100644
--- a/src/gallium/drivers/nv30/nv30_query.c
+++ b/src/gallium/drivers/nv30/nv30_query.c
@@ -114,6 +114,7 @@ nv30_query_create(struct pipe_context *pipe, unsigned type)
    q->type = type;
 
    switch (q->type) {
+   case PIPE_QUERY_TIMESTAMP:
    case PIPE_QUERY_TIME_ELAPSED:
       q->enable = 0x0000;
       q->report = 1;
@@ -158,6 +159,8 @@ nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
          PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start);
       }
       break;
+   case PIPE_QUERY_TIMESTAMP:
+      return;
    default:
       BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1);
       PUSH_DATA (push, q->report);
@@ -193,13 +196,13 @@ nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
 
 static boolean
 nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
-                  boolean wait, void *result)
+                  boolean wait, union pipe_query_result *result)
 {
    struct nv30_screen *screen = nv30_screen(pipe->screen);
    struct nv30_query *q = nv30_query(pq);
    volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]);
    volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]);
-   uint64_t *res64 = result;
+   uint64_t *res64 = &result->u64;
 
    if (ntfy1) {
       while (ntfy1[3] & 0xff000000) {
@@ -208,6 +211,9 @@ nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
       }
 
       switch (q->type) {
+      case PIPE_QUERY_TIMESTAMP:
+         q->result = *(uint64_t *)&ntfy1[0];
+         break;
       case PIPE_QUERY_TIME_ELAPSED:
          q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0];
          break;
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
index 88e428b..1752d10 100644
--- a/src/gallium/drivers/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -70,6 +70,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_SCALED_RESOLVE:
    case PIPE_CAP_OCCLUSION_QUERY:
    case PIPE_CAP_TIMER_QUERY:
+   case PIPE_CAP_QUERY_TIMESTAMP:
    case PIPE_CAP_TEXTURE_SHADOW_MAP:
    case PIPE_CAP_TEXTURE_SWIZZLE:
    case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
@@ -116,7 +117,6 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
    case PIPE_CAP_START_INSTANCE:
-   case PIPE_CAP_QUERY_TIMESTAMP:
       return 0;
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 8e62c5f..f9ac33d 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -215,11 +215,15 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
       nv50_query_get(push, q, 0x00, 0x05805002);
       nv50_query_get(push, q, 0x10, 0x06805002);
       break;
+   case PIPE_QUERY_TIMESTAMP:
+      q->sequence++;
+      /* fall through */
    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    case PIPE_QUERY_TIME_ELAPSED:
       nv50_query_get(push, q, 0, 0x00005002);
       break;
    case PIPE_QUERY_GPU_FINISHED:
+      q->sequence++;
       nv50_query_get(push, q, 0, 0x1000f010);
       break;
    case NVA0_QUERY_STREAM_OUTPUT_BUFFER_OFFSET:
@@ -229,7 +233,7 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
       assert(0);
       break;
    }
-   q->flushed = FALSE;
+   q->ready = q->flushed = FALSE;
 }
 
 static INLINE boolean
@@ -280,9 +284,12 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
       res64[0] = data64[0] - data64[4];
       res64[1] = data64[2] - data64[6];
       break;
+   case PIPE_QUERY_TIMESTAMP:
+      res64[0] = data64[1];
+      break;
    case PIPE_QUERY_TIMESTAMP_DISJOINT: /* u32 sequence, u32 0, u64 time */
       res64[0] = 1000000000;
-      res8[8] = (data64[0] == data64[2]) ? FALSE : TRUE;
+      res8[8] = (data64[1] == data64[3]) ? FALSE : TRUE;
       break;
    case PIPE_QUERY_TIME_ELAPSED:
       res64[0] = data64[1] - data64[3];
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index c7344a1..3d510ea 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -128,6 +128,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
    case PIPE_CAP_VERTEX_COLOR_CLAMPED:
       return 1;
+   case PIPE_CAP_QUERY_TIMESTAMP:
    case PIPE_CAP_TIMER_QUERY:
    case PIPE_CAP_OCCLUSION_QUERY:
       return 1;
@@ -172,7 +173,6 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
-   case PIPE_CAP_QUERY_TIMESTAMP:
       return 0;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 02a408e..eb74e95 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -108,6 +108,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
    case PIPE_CAP_VERTEX_COLOR_CLAMPED:
       return 1;
+   case PIPE_CAP_QUERY_TIMESTAMP:
    case PIPE_CAP_TIMER_QUERY:
    case PIPE_CAP_OCCLUSION_QUERY:
    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
@@ -150,7 +151,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
-   case PIPE_CAP_QUERY_TIMESTAMP:
       return 0;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);




More information about the mesa-commit mailing list