[Mesa-dev] [PATCH] r600g: implement timestamp query and get_timestamp hook

Marek Olšák maraeo at gmail.com
Sun Aug 12 08:54:36 PDT 2012


---
 src/gallium/drivers/r600/r600_pipe.c              |   13 ++++++++++++-
 src/gallium/drivers/r600/r600_query.c             |   17 ++++++++++++++++-
 src/gallium/winsys/radeon/drm/radeon_drm_winsys.c |   21 +++++++++++++++++++++
 src/gallium/winsys/radeon/drm/radeon_winsys.h     |    7 +++++++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 76a019d..edeca2a 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -416,7 +416,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
 	case PIPE_CAP_VERTEX_COLOR_CLAMPED:
 	case PIPE_CAP_USER_VERTEX_BUFFERS:
-	case PIPE_CAP_QUERY_TIMESTAMP:
 		return 0;
 
 	/* Stream output. */
@@ -450,6 +449,9 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	/* Timer queries, present when the clock frequency is non zero. */
 	case PIPE_CAP_TIMER_QUERY:
 		return rscreen->info.r600_clock_crystal_freq != 0;
+	case PIPE_CAP_QUERY_TIMESTAMP:
+		return rscreen->info.drm_minor >= 20 &&
+		       rscreen->info.r600_clock_crystal_freq != 0;
 
 	case PIPE_CAP_MIN_TEXEL_OFFSET:
 		return -8;
@@ -873,6 +875,14 @@ static unsigned radeon_family_from_device(unsigned device)
 	}
 }
 
+static uint64_t r600_get_timestamp(struct pipe_screen *screen)
+{
+	struct r600_screen *rscreen = (struct r600_screen*)screen;
+
+	return 1000000 * rscreen->ws->query_timestamp(rscreen->ws) /
+			rscreen->info.r600_clock_crystal_freq;
+}
+
 struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
 {
 	struct r600_screen *rscreen = CALLOC_STRUCT(r600_screen);
@@ -929,6 +939,7 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
 	rscreen->screen.get_paramf = r600_get_paramf;
 	rscreen->screen.get_video_param = r600_get_video_param;
 	rscreen->screen.get_compute_param = r600_get_compute_param;
+	rscreen->screen.get_timestamp = r600_get_timestamp;
 
 	if (rscreen->chip_class >= EVERGREEN) {
 		rscreen->screen.is_format_supported = evergreen_is_format_supported;
diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c
index 90b7a66..440b8c9 100644
--- a/src/gallium/drivers/r600/r600_query.c
+++ b/src/gallium/drivers/r600/r600_query.c
@@ -69,6 +69,7 @@ static struct r600_resource *r600_new_query_buffer(struct r600_context *ctx, uns
 		ctx->ws->buffer_unmap(buf->cs_buf);
 		break;
 	case PIPE_QUERY_TIME_ELAPSED:
+	case PIPE_QUERY_TIMESTAMP:
 		break;
 	case PIPE_QUERY_PRIMITIVES_EMITTED:
 	case PIPE_QUERY_PRIMITIVES_GENERATED:
@@ -174,6 +175,8 @@ static void r600_emit_query_end(struct r600_context *ctx, struct r600_query *que
 		break;
 	case PIPE_QUERY_TIME_ELAPSED:
 		va += query->buffer.results_end + query->result_size/2;
+		/* fall through */
+	case PIPE_QUERY_TIMESTAMP:
 		cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0);
 		cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
 		cs->buf[cs->cdw++] = va;
@@ -267,6 +270,10 @@ static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned q
 		query->result_size = 16;
 		query->num_cs_dw = 8;
 		break;
+	case PIPE_QUERY_TIMESTAMP:
+		query->result_size = 8;
+		query->num_cs_dw = 8;
+		break;
 	case PIPE_QUERY_PRIMITIVES_EMITTED:
 	case PIPE_QUERY_PRIMITIVES_GENERATED:
 	case PIPE_QUERY_SO_STATISTICS:
@@ -435,6 +442,13 @@ static boolean r600_get_query_buffer_result(struct r600_context *ctx,
 			results_base += query->result_size;
 		}
 		break;
+	case PIPE_QUERY_TIMESTAMP:
+	{
+		uint32_t *current_result = (uint32_t*)map;
+		result->u64 = (uint64_t)current_result[0] |
+			      (uint64_t)current_result[1] << 32;
+		break;
+	}
 	case PIPE_QUERY_PRIMITIVES_EMITTED:
 		/* SAMPLE_STREAMOUTSTATS stores this structure:
 		 * {
@@ -498,7 +512,8 @@ static boolean r600_get_query_result(struct pipe_context *ctx,
 	}
 
 	/* Convert the time to expected units. */
-	if (rquery->type == PIPE_QUERY_TIME_ELAPSED) {
+	if (rquery->type == PIPE_QUERY_TIME_ELAPSED ||
+	    rquery->type == PIPE_QUERY_TIMESTAMP) {
 		result->u64 = (1000000 * result->u64) / rctx->screen->info.r600_clock_crystal_freq;
 	}
 	return TRUE;
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
index c9c6932..c03dd04 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
@@ -85,6 +85,10 @@
 #define RADEON_INFO_MAX_PIPES 0x10
 #endif
 
+#ifndef RADEON_INFO_TIMESTAMP
+#define RADEON_INFO_TIMESTAMP 0x11
+#endif
+
 
 /* Enable/disable feature access for one command stream.
  * If enable == TRUE, return TRUE on success.
@@ -375,6 +379,22 @@ static int radeon_drm_winsys_surface_best(struct radeon_winsys *rws,
     return radeon_surface_best(ws->surf_man, surf);
 }
 
+static uint64_t radeon_query_timestamp(struct radeon_winsys *rws)
+{
+    struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
+    uint64_t ts = 0;
+
+    if (ws->info.drm_minor < 20 ||
+        ws->gen < R600) {
+        assert(0);
+        return 0;
+    }
+
+    radeon_get_drm_value(ws->fd, RADEON_INFO_TIMESTAMP, "timestamp",
+                         (uint32_t*)&ts);
+    return ts;
+}
+
 struct radeon_winsys *radeon_drm_winsys_create(int fd)
 {
     struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys);
@@ -407,6 +427,7 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd)
     ws->base.cs_request_feature = radeon_cs_request_feature;
     ws->base.surface_init = radeon_drm_winsys_surface_init;
     ws->base.surface_best = radeon_drm_winsys_surface_best;
+    ws->base.query_timestamp = radeon_query_timestamp;
 
     radeon_bomgr_init_functions(ws);
     radeon_drm_cs_init_functions(ws);
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 6039910..4eb57fb 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -375,6 +375,13 @@ struct radeon_winsys {
      */
     int (*surface_best)(struct radeon_winsys *ws,
                         struct radeon_surface *surf);
+
+    /**
+     * Return the current timestamp (gpu clock) on r600 and later GPUs.
+     *
+     * \param ws        The winsys this function is called from.
+     */
+    uint64_t (*query_timestamp)(struct radeon_winsys *ws);
 };
 
 #endif
-- 
1.7.9.5



More information about the mesa-dev mailing list