r600g: Implement timer queries.

This commit is contained in:
Mathias Fröhlich 2011-01-23 22:35:13 +01:00 committed by Alex Deucher
parent e7ec532735
commit 90c2fd8640
5 changed files with 78 additions and 14 deletions

View file

@ -113,6 +113,7 @@ struct r600_tiling_info {
enum radeon_family r600_get_family(struct radeon *rw);
enum chip_class r600_get_family_class(struct radeon *radeon);
struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon);
unsigned r600_get_clock_crystal_freq(struct radeon *radeon);
/* r600_bo.c */
struct r600_bo;

View file

@ -283,7 +283,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
return 1;
/* Unsupported features (boolean caps). */
case PIPE_CAP_TIMER_QUERY:
case PIPE_CAP_STREAM_OUTPUT:
case PIPE_CAP_PRIMITIVE_RESTART:
case PIPE_CAP_INDEP_BLEND_FUNC: /* FIXME allow this */
@ -318,6 +317,10 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 0;
/* Timer queries, present when the clock frequency is non zero. */
case PIPE_CAP_TIMER_QUERY:
return r600_get_clock_crystal_freq(rscreen->radeon) != 0;
default:
R600_ERR("r600: unknown param %d\n", param);
return 0;

View file

@ -41,6 +41,10 @@
#define RADEON_INFO_TILING_CONFIG 0x6
#endif
#ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ
#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9
#endif
enum radeon_family r600_get_family(struct radeon *r600)
{
return r600->family;
@ -56,6 +60,11 @@ struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
return &radeon->tiling_info;
}
unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
{
return radeon->clock_crystal_freq;
}
static int radeon_get_device(struct radeon *radeon)
{
struct drm_radeon_info info;
@ -124,6 +133,24 @@ static int radeon_drm_get_tiling(struct radeon *radeon)
return 0;
}
static int radeon_get_clock_crystal_freq(struct radeon *radeon)
{
struct drm_radeon_info info;
uint32_t clock_crystal_freq;
int r;
radeon->device = 0;
info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ;
info.value = (uintptr_t)&clock_crystal_freq;
r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
sizeof(struct drm_radeon_info));
if (r)
return r;
radeon->clock_crystal_freq = clock_crystal_freq;
return 0;
}
static int radeon_init_fence(struct radeon *radeon)
{
radeon->fence = 1;
@ -205,6 +232,9 @@ static struct radeon *radeon_new(int fd, unsigned device)
if (radeon_drm_get_tiling(radeon))
return NULL;
}
/* get the GPU counter frequency, failure is non fatal */
radeon_get_clock_crystal_freq(radeon);
radeon->bomgr = r600_bomgr_create(radeon, 1000000);
if (radeon->bomgr == NULL) {
return NULL;

View file

@ -1263,7 +1263,8 @@ static boolean r600_query_result(struct r600_context *ctx, struct r600_query *qu
for (i = 0; i < query->num_results; i += 4) {
start = (u64)results[i] | (u64)results[i + 1] << 32;
end = (u64)results[i + 2] | (u64)results[i + 3] << 32;
if ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) {
if (((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL))
|| query->type == PIPE_QUERY_TIME_ELAPSED) {
query->result += end - start;
}
}
@ -1275,8 +1276,15 @@ static boolean r600_query_result(struct r600_context *ctx, struct r600_query *qu
void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
{
/* query request needs 6 dwords for begin + 6 dwords for end */
if ((12 + ctx->pm4_cdwords) > ctx->pm4_ndwords) {
unsigned required_space;
/* query request needs 6/8 dwords for begin + 6/8 dwords for end */
if (query->type == PIPE_QUERY_TIME_ELAPSED)
required_space = 16;
else
required_space = 12;
if ((required_space + ctx->pm4_cdwords) > ctx->pm4_ndwords) {
/* need to flush */
r600_context_flush(ctx);
}
@ -1288,10 +1296,19 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
}
/* emit begin query */
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = 0;
if (query->type == PIPE_QUERY_TIME_ELAPSED) {
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = (3 << 29);
ctx->pm4[ctx->pm4_cdwords++] = 0;
ctx->pm4[ctx->pm4_cdwords++] = 0;
} else {
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = 0;
}
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0);
ctx->pm4[ctx->pm4_cdwords++] = 0;
r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer);
@ -1304,10 +1321,19 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
void r600_query_end(struct r600_context *ctx, struct r600_query *query)
{
/* emit begin query */
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = 0;
if (query->type == PIPE_QUERY_TIME_ELAPSED) {
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = (3 << 29);
ctx->pm4[ctx->pm4_cdwords++] = 0;
ctx->pm4[ctx->pm4_cdwords++] = 0;
} else {
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer);
ctx->pm4[ctx->pm4_cdwords++] = 0;
}
ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0);
ctx->pm4[ctx->pm4_cdwords++] = 0;
r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer);
@ -1322,7 +1348,7 @@ struct r600_query *r600_context_query_create(struct r600_context *ctx, unsigned
{
struct r600_query *query;
if (query_type != PIPE_QUERY_OCCLUSION_COUNTER)
if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && query_type != PIPE_QUERY_TIME_ELAPSED)
return NULL;
query = calloc(1, sizeof(struct r600_query));
@ -1366,7 +1392,10 @@ boolean r600_context_query_result(struct r600_context *ctx,
}
if (!r600_query_result(ctx, query, wait))
return FALSE;
*result = query->result;
if (query->type == PIPE_QUERY_TIME_ELAPSED)
*result = (1000000*query->result)/r600_get_clock_crystal_freq(ctx->radeon);
else
*result = query->result;
query->result = 0;
return TRUE;
}

View file

@ -49,6 +49,7 @@ struct radeon {
unsigned fence;
unsigned *cfence;
struct r600_bo *fence_bo;
unsigned clock_crystal_freq;
};
struct r600_reg {