From 44f14ebd7b9ba7186342039d2602fdd6ea5077f5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 5 Jul 2012 20:06:41 +0200 Subject: [PATCH] r600g: implement timestamp query and get_timestamp hook Reviewed-by: Alex Deucher --- src/gallium/drivers/r600/r600_pipe.c | 13 +++++++++++- src/gallium/drivers/r600/r600_query.c | 17 ++++++++++++++- .../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 3960cd0d48a..cf2983315b2 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 90b7a66d614..440b8c9d186 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 c9c6932c862..c03dd045edf 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 6039910f870..4eb57fb1259 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 -- 2.30.2