mesa/st: Implement GL_TIME_ELAPSED w/ PIPE_QUERY_TIMESTAMP.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 9 Dec 2012 10:08:13 +0000 (10:08 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 20 Dec 2012 16:33:49 +0000 (16:33 +0000)
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>
src/mesa/state_tracker/st_cb_queryobj.c
src/mesa/state_tracker/st_cb_queryobj.h
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_extensions.c

index b10fd9335eda1ae0ed33ed948595be553a4bbb31..98b61f5761bf5defc1453b0282a1d34a14d33dc0 100644 (file)
@@ -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:
-      type = PIPE_QUERY_TIME_ELAPSED;
+   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 */
-      pipe->destroy_query(pipe, stq->pq);
-      stq->pq = NULL;
+      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 (!stq->pq) {
-      stq->pq = pipe->create_query(pipe, type);
-      stq->type = type;
+   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;
+      }
+      pipe->begin_query(pipe, stq->pq);
    }
-
    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));
 
-   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);
 }
 
 
index 03487b153170ea9a376431c5ac2bc9434ca71b30..d5b107532459877b996e944aea7fdbb88a793da4 100644 (file)
@@ -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 */
 };
 
index eeb7f0c4fd6b05f97006b1d98324e0937e9b5883..2be74b45262f2396572a3df1c6389ec9ff6271f8 100644 (file)
@@ -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.
index f7deb9c60834bf826f068ae09bd629f0a6771339..e7cf4f3bb8c6b1c2903d8679c5b7df960820935a 100644 (file)
@@ -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 &&