mesa/st: Implement GL_TIME_ELAPSED w/ PIPE_QUERY_TIMESTAMP.

ARB/EXT_timer_query's definition of GL_TIME_ELAPSED match precisely the
subtraction of two GL_TIMESTAMP queries.

And for a lot of drivers, that's precisely how they have to implement
internally -- by emitting two hardware timestamp queries.

So, to simplify driver implementation, simply allow doing so in the state
tracker.

Eventually if no driver implements PIPE_QUERY_TIME_ELAPSED then we could
retire it.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Marek Olšák <maraeo@gmail.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
José Fonseca
2012-12-09 10:08:13 +00:00
committed by José Fonseca
parent 9976216bf6
commit 3160b0b9fc
4 changed files with 79 additions and 22 deletions

View File

@@ -72,6 +72,11 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
stq->pq = NULL; stq->pq = NULL;
} }
if (stq->pq_begin) {
pipe->destroy_query(pipe, stq->pq_begin);
stq->pq_begin = NULL;
}
free(stq); free(stq);
} }
@@ -79,7 +84,8 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
static void static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q) st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{ {
struct pipe_context *pipe = st_context(ctx)->pipe; struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct st_query_object *stq = st_query_object(q); struct st_query_object *stq = st_query_object(q);
unsigned type; unsigned type;
@@ -98,29 +104,46 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
type = PIPE_QUERY_PRIMITIVES_EMITTED; type = PIPE_QUERY_PRIMITIVES_EMITTED;
break; break;
case GL_TIME_ELAPSED_EXT: case GL_TIME_ELAPSED:
type = PIPE_QUERY_TIME_ELAPSED; if (st->has_time_elapsed)
type = PIPE_QUERY_TIME_ELAPSED;
else
type = PIPE_QUERY_TIMESTAMP;
break; break;
default: default:
assert(0 && "unexpected query target in st_BeginQuery()"); assert(0 && "unexpected query target in st_BeginQuery()");
return; return;
} }
if (stq->pq && stq->type != type) { if (stq->type != type) {
/* free old query of different type */ /* free old query of different type */
pipe->destroy_query(pipe, stq->pq); if (stq->pq) {
stq->pq = NULL; pipe->destroy_query(pipe, stq->pq);
stq->pq = NULL;
}
if (stq->pq_begin) {
pipe->destroy_query(pipe, stq->pq_begin);
stq->pq_begin = NULL;
}
stq->type = PIPE_QUERY_TYPES; /* an invalid value */ stq->type = PIPE_QUERY_TYPES; /* an invalid value */
} }
if (!stq->pq) { if (q->Target == GL_TIME_ELAPSED &&
stq->pq = pipe->create_query(pipe, type); type == PIPE_QUERY_TIMESTAMP) {
stq->type = type; /* Determine time elapsed by emitting two timestamp queries. */
if (!stq->pq_begin) {
stq->pq_begin = pipe->create_query(pipe, type);
stq->type = type;
}
pipe->end_query(pipe, stq->pq_begin);
} else {
if (!stq->pq) {
stq->pq = pipe->create_query(pipe, type);
stq->type = type;
}
pipe->begin_query(pipe, stq->pq);
} }
assert(stq->type == type); assert(stq->type == type);
pipe->begin_query(pipe, stq->pq);
} }
@@ -132,7 +155,9 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
st_flush_bitmap_cache(st_context(ctx)); st_flush_bitmap_cache(st_context(ctx));
if (q->Target == GL_TIMESTAMP && !stq->pq) { if ((q->Target == GL_TIMESTAMP ||
q->Target == GL_TIME_ELAPSED) &&
!stq->pq) {
stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP); stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
stq->type = PIPE_QUERY_TIMESTAMP; stq->type = PIPE_QUERY_TIMESTAMP;
} }
@@ -141,6 +166,33 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
} }
static boolean
get_query_result(struct pipe_context *pipe,
struct st_query_object *stq,
boolean wait)
{
if (!pipe->get_query_result(pipe,
stq->pq,
wait,
(void *)&stq->base.Result)) {
return FALSE;
}
if (stq->base.Target == GL_TIME_ELAPSED &&
stq->type == PIPE_QUERY_TIMESTAMP) {
/* Calculate the elapsed time from the two timestamp queries */
GLuint64EXT Result0 = 0;
assert(stq->pq_begin);
pipe->get_query_result(pipe, stq->pq_begin, TRUE, (void *)&Result0);
stq->base.Result -= Result0;
} else {
assert(!stq->pq_begin);
}
return TRUE;
}
static void static void
st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q) st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
{ {
@@ -151,10 +203,7 @@ st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
assert(!stq->base.Ready); assert(!stq->base.Ready);
while (!stq->base.Ready && while (!stq->base.Ready &&
!pipe->get_query_result(pipe, !get_query_result(pipe, stq, TRUE))
stq->pq,
TRUE,
(void*)&q->Result))
{ {
/* nothing */ /* nothing */
} }
@@ -169,7 +218,7 @@ st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q)
struct pipe_context *pipe = st_context(ctx)->pipe; struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q); struct st_query_object *stq = st_query_object(q);
assert(!q->Ready); /* we should not get called if Ready is TRUE */ assert(!q->Ready); /* we should not get called if Ready is TRUE */
q->Ready = pipe->get_query_result(pipe, stq->pq, FALSE, (void*)&q->Result); q->Ready = get_query_result(pipe, stq, FALSE);
} }

View File

@@ -39,6 +39,10 @@ struct st_query_object
{ {
struct gl_query_object base; struct gl_query_object base;
struct pipe_query *pq; struct pipe_query *pq;
/* Begin TIMESTAMP query for GL_TIME_ELAPSED_EXT queries */
struct pipe_query *pq_begin;
unsigned type; /**< PIPE_QUERY_x */ unsigned type; /**< PIPE_QUERY_x */
}; };

View File

@@ -83,6 +83,7 @@ struct st_context
GLboolean clamp_frag_color_in_shader; GLboolean clamp_frag_color_in_shader;
GLboolean clamp_vert_color_in_shader; GLboolean clamp_vert_color_in_shader;
boolean has_stencil_export; /**< can do shader stencil export? */ boolean has_stencil_export; /**< can do shader stencil export? */
boolean has_time_elapsed;
/* On old libGL's for linux we need to invalidate the drawables /* On old libGL's for linux we need to invalidate the drawables
* on glViewpport calls, this is set via a option. * on glViewpport calls, this is set via a option.

View File

@@ -371,6 +371,7 @@ void st_init_extensions(struct st_context *st)
{ o(ARB_shader_texture_lod), PIPE_CAP_SM3 }, { o(ARB_shader_texture_lod), PIPE_CAP_SM3 },
{ o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP }, { o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP },
{ o(ARB_texture_non_power_of_two), PIPE_CAP_NPOT_TEXTURES }, { o(ARB_texture_non_power_of_two), PIPE_CAP_NPOT_TEXTURES },
{ o(ARB_timer_query), PIPE_CAP_QUERY_TIMESTAMP },
{ o(ARB_transform_feedback2), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME }, { o(ARB_transform_feedback2), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
{ o(ARB_transform_feedback3), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME }, { o(ARB_transform_feedback3), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
@@ -382,7 +383,6 @@ void st_init_extensions(struct st_context *st)
{ o(EXT_texture_filter_anisotropic), PIPE_CAP_ANISOTROPIC_FILTER }, { o(EXT_texture_filter_anisotropic), PIPE_CAP_ANISOTROPIC_FILTER },
{ o(EXT_texture_mirror_clamp), PIPE_CAP_TEXTURE_MIRROR_CLAMP }, { o(EXT_texture_mirror_clamp), PIPE_CAP_TEXTURE_MIRROR_CLAMP },
{ o(EXT_texture_swizzle), PIPE_CAP_TEXTURE_SWIZZLE }, { o(EXT_texture_swizzle), PIPE_CAP_TEXTURE_SWIZZLE },
{ o(EXT_timer_query), PIPE_CAP_QUERY_TIME_ELAPSED },
{ o(EXT_transform_feedback), PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS }, { o(EXT_transform_feedback), PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS },
{ o(AMD_seamless_cubemap_per_texture), PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE }, { o(AMD_seamless_cubemap_per_texture), PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE },
@@ -652,9 +652,12 @@ void st_init_extensions(struct st_context *st)
if (ctx->Const.MaxDualSourceDrawBuffers > 0) if (ctx->Const.MaxDualSourceDrawBuffers > 0)
ctx->Extensions.ARB_blend_func_extended = GL_TRUE; ctx->Extensions.ARB_blend_func_extended = GL_TRUE;
if (screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED) && st->has_time_elapsed =
screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP)) { screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
ctx->Extensions.ARB_timer_query = GL_TRUE;
if (st->has_time_elapsed ||
ctx->Extensions.ARB_timer_query) {
ctx->Extensions.EXT_timer_query = GL_TRUE;
} }
if (ctx->Extensions.ARB_transform_feedback2 && if (ctx->Extensions.ARB_transform_feedback2 &&