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. */
/* 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;
}
}
+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);
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;
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:
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;
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:
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:
* {
}
/* 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;
#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.
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);
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);
*/
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