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

Alex Deucher alexdeucher at gmail.com
Mon Aug 13 08:00:58 PDT 2012


On Sun, Aug 12, 2012 at 11:54 AM, Marek Olšák <maraeo at gmail.com> wrote:
> ---
>  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(-)

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

>
> 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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list