Reviewed-by: Alex Deucher <alexander.deucher@amd.com>tags/mesa-9.0
@@ -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; |
@@ -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; |
@@ -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); |
@@ -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 |