r600g: implement timestamp query and get_timestamp hook
authorMarek Olšák <maraeo@gmail.com>
Thu, 5 Jul 2012 18:06:41 +0000 (20:06 +0200)
committerMarek Olšák <maraeo@gmail.com>
Wed, 15 Aug 2012 17:20:58 +0000 (19:20 +0200)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_query.c
src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
src/gallium/winsys/radeon/drm/radeon_winsys.h

index 3960cd0d48a7e14e4a314f3acbf157620baedbe7..cf2983315b2e1f8a26e434bd3215759bc8dc683e 100644 (file)
@@ -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;
index 90b7a66d614b1caf34fa79dcdc2c84ba107d3a5f..440b8c9d186b837b81eebca2f5f4517efe0e0274 100644 (file)
@@ -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;
index c9c6932c862c3e2c96098d04edd5768cb8d3d5db..c03dd045edf0f3019c103ccac754d6c608bbf25f 100644 (file)
 #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);
index 6039910f870c100c8a7e9722e4ac155169a3033a..4eb57fb125975811a03ea57619c77a37af503ba9 100644 (file)
@@ -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