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:

committed by
José Fonseca

parent
9976216bf6
commit
3160b0b9fc
@@ -72,6 +72,11 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
|
||||
stq->pq = NULL;
|
||||
}
|
||||
|
||||
if (stq->pq_begin) {
|
||||
pipe->destroy_query(pipe, stq->pq_begin);
|
||||
stq->pq_begin = NULL;
|
||||
}
|
||||
|
||||
free(stq);
|
||||
}
|
||||
|
||||
@@ -79,7 +84,8 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
|
||||
static void
|
||||
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);
|
||||
unsigned type;
|
||||
|
||||
@@ -98,29 +104,46 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
|
||||
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
|
||||
type = PIPE_QUERY_PRIMITIVES_EMITTED;
|
||||
break;
|
||||
case GL_TIME_ELAPSED_EXT:
|
||||
case GL_TIME_ELAPSED:
|
||||
if (st->has_time_elapsed)
|
||||
type = PIPE_QUERY_TIME_ELAPSED;
|
||||
else
|
||||
type = PIPE_QUERY_TIMESTAMP;
|
||||
break;
|
||||
default:
|
||||
assert(0 && "unexpected query target in st_BeginQuery()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stq->pq && stq->type != type) {
|
||||
if (stq->type != type) {
|
||||
/* free old query of different type */
|
||||
if (stq->pq) {
|
||||
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 */
|
||||
}
|
||||
|
||||
if (q->Target == GL_TIME_ELAPSED &&
|
||||
type == PIPE_QUERY_TIMESTAMP) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
assert(stq->type == type);
|
||||
|
||||
pipe->begin_query(pipe, stq->pq);
|
||||
}
|
||||
assert(stq->type == type);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +155,9 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
|
||||
|
||||
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->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
|
||||
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);
|
||||
|
||||
while (!stq->base.Ready &&
|
||||
!pipe->get_query_result(pipe,
|
||||
stq->pq,
|
||||
TRUE,
|
||||
(void*)&q->Result))
|
||||
!get_query_result(pipe, stq, TRUE))
|
||||
{
|
||||
/* 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 st_query_object *stq = st_query_object(q);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -39,6 +39,10 @@ struct st_query_object
|
||||
{
|
||||
struct gl_query_object base;
|
||||
struct pipe_query *pq;
|
||||
|
||||
/* Begin TIMESTAMP query for GL_TIME_ELAPSED_EXT queries */
|
||||
struct pipe_query *pq_begin;
|
||||
|
||||
unsigned type; /**< PIPE_QUERY_x */
|
||||
};
|
||||
|
||||
|
@@ -83,6 +83,7 @@ struct st_context
|
||||
GLboolean clamp_frag_color_in_shader;
|
||||
GLboolean clamp_vert_color_in_shader;
|
||||
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 glViewpport calls, this is set via a option.
|
||||
|
@@ -371,6 +371,7 @@ void st_init_extensions(struct st_context *st)
|
||||
{ o(ARB_shader_texture_lod), PIPE_CAP_SM3 },
|
||||
{ o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP },
|
||||
{ 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_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_mirror_clamp), PIPE_CAP_TEXTURE_MIRROR_CLAMP },
|
||||
{ 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(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)
|
||||
ctx->Extensions.ARB_blend_func_extended = GL_TRUE;
|
||||
|
||||
if (screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED) &&
|
||||
screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP)) {
|
||||
ctx->Extensions.ARB_timer_query = GL_TRUE;
|
||||
st->has_time_elapsed =
|
||||
screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
|
||||
|
||||
if (st->has_time_elapsed ||
|
||||
ctx->Extensions.ARB_timer_query) {
|
||||
ctx->Extensions.EXT_timer_query = GL_TRUE;
|
||||
}
|
||||
|
||||
if (ctx->Extensions.ARB_transform_feedback2 &&
|
||||
|
Reference in New Issue
Block a user