intel: Wait on the last swapbuffers to complete before queuing a new one.
authorBrian Paul <brianp@vmware.com>
Tue, 4 Aug 2009 15:22:15 +0000 (09:22 -0600)
committerBrian Paul <brianp@vmware.com>
Tue, 4 Aug 2009 15:22:15 +0000 (09:22 -0600)
This fixes jerkiness in doom3 and other apps since the kernel change to
throttle less absurdly, which led to a thundering herd of frames.

Because this is a rather minimal fix, there is at least one downside: If
the whole scene completes in one batchbuffer, we'll end up stalling the GPU.

Thanks to Michel Dänzer for suggesting using glFlush to signal frame end
instead of going to all the effort of adding a new DRI2 extension.

(cherry picked from master, commit 0828579a658af01a64b5e699175dc9bbbedcd685)

src/mesa/drivers/dri/intel/intel_batchbuffer.c
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h

index 29dc05c518e4a8c099b6da2b37e5501e09651ddb..82a92a9f454bd5c548681194d2050f0fe78b243e 100644 (file)
@@ -197,6 +197,11 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
    GLuint used = batch->ptr - batch->map;
    GLboolean was_locked = intel->locked;
 
+   if (intel->first_post_swapbuffers_batch == NULL) {
+      intel->first_post_swapbuffers_batch = intel->batch->buf;
+      drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
+   }
+
    if (used == 0) {
       batch->cliprect_mode = IGNORE_CLIPRECTS;
       return;
index 9db5b5464330979d57609aaae1f72251ffd46a5b..a40951abe398f577c7398995ea24d2ac16fa1dc6 100644 (file)
@@ -521,7 +521,27 @@ intelFlush(GLcontext * ctx)
 static void
 intel_glFlush(GLcontext *ctx)
 {
+   struct intel_context *intel = intel_context(ctx);
+
    intel_flush(ctx, GL_TRUE);
+
+   /* We're using glFlush as an indicator that a frame is done, which is
+    * what DRI2 does before calling SwapBuffers (and means we should catch
+    * people doing front-buffer rendering, as well)..
+    *
+    * Wait for the swapbuffers before the one we just emitted, so we don't
+    * get too many swaps outstanding for apps that are GPU-heavy but not
+    * CPU-heavy.
+    *
+    * Unfortunately, we don't have a handle to the batch containing the swap,
+    * and getting our hands on that doesn't seem worth it, so we just us the
+    * first batch we emitted after the last swap.
+    */
+   if (intel->first_post_swapbuffers_batch != NULL) {
+      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
+      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
+      intel->first_post_swapbuffers_batch = NULL;
+   }
 }
 
 void
@@ -787,6 +807,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
       intel->prim.vb = NULL;
       dri_bo_unreference(intel->prim.vb_bo);
       intel->prim.vb_bo = NULL;
+      dri_bo_unreference(intel->first_post_swapbuffers_batch);
+      intel->first_post_swapbuffers_batch = NULL;
 
       if (release_texture_heaps) {
          /* This share group is about to go away, free our private
index b5cf7e6648e8056577d4279019b414a2536e77c6..b3db561fd5b6fdb4ec43f64411b9b330a7c603b9 100644 (file)
@@ -191,6 +191,7 @@ struct intel_context
    GLboolean ttm;
 
    struct intel_batchbuffer *batch;
+   drm_intel_bo *first_post_swapbuffers_batch;
    GLboolean no_batch_wrap;
    unsigned batch_id;