summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Fröhlich <Mathias.Froehlich@web.de>2011-01-23 22:35:13 +0100
committerAlex Deucher <alexdeucher@gmail.com>2011-01-25 14:18:19 -0500
commit90c2fd86407999475ff6accecf36e5a2c75feb9b (patch)
tree0a0085852f6888ec55bb580eac3dc539ef95fa0c
parente7ec53273547335863b2377bea9d35aa9c114c6b (diff)
r600g: Implement timer queries.
-rw-r--r--src/gallium/drivers/r600/r600.h1
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c5
-rw-r--r--src/gallium/winsys/r600/drm/r600_drm.c30
-rw-r--r--src/gallium/winsys/r600/drm/r600_hw_context.c55
-rw-r--r--src/gallium/winsys/r600/drm/r600_priv.h1
5 files changed, 78 insertions, 14 deletions
diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index a852bef615..b8888bede2 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -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;
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 53d2c10c56..1ee327f16a 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -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;
diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c
index 6fc147fb6f..3c7e9aa449 100644
--- a/src/gallium/winsys/r600/drm/r600_drm.c
+++ b/src/gallium/winsys/r600/drm/r600_drm.c
@@ -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;
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index 96e409015c..6b7e4d886f 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -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;
}
diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h
index a38a6481b4..2d91cd97d6 100644
--- a/src/gallium/winsys/r600/drm/r600_priv.h
+++ b/src/gallium/winsys/r600/drm/r600_priv.h
@@ -49,6 +49,7 @@ struct radeon {
unsigned fence;
unsigned *cfence;
struct r600_bo *fence_bo;
+ unsigned clock_crystal_freq;
};
struct r600_reg {