svga: Rebind framebuffer and tss bindings strictly when necessary.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 7 Apr 2011 15:54:37 +0000 (16:54 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 12 Apr 2011 11:00:49 +0000 (12:00 +0100)
The earlier change to ensure rendertargets and textures are always
rebound at every command buffer start had the downside of making
successive flushes no longer no-ops, as a command buffer with merely
the rebinding commands were being unnecessarily sent to the vGPU.

This change only re-emits the bindings when necessary, by keeping track
of the need to rebind outside of the dirty state update mechanism.

src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_draw.c
src/gallium/drivers/svga/svga_pipe_clear.c
src/gallium/drivers/svga/svga_state_framebuffer.c
src/gallium/drivers/svga/svga_state_tss.c

index 4782b4bf70ebc6208c3b20763dfdfcababb97cbf..dbbc249258d41471ce358d1f9aedb3913fee31e7 100644 (file)
@@ -204,7 +204,6 @@ void svga_context_flush( struct svga_context *svga,
 {
    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
    struct pipe_fence_handle *fence = NULL;
-   enum pipe_error ret;
 
    svga->curr.nr_fbs = 0;
 
@@ -219,25 +218,11 @@ void svga_context_flush( struct svga_context *svga,
 
    svga_screen_cache_flush(svgascreen, fence);
 
-   /* To force the reemission of rendertargets and texture bindings at
-    * the beginning of every command buffer.
-    */
-   svga->dirty |= SVGA_NEW_COMMAND_BUFFER;
-
-   /*
-    * We must reemit the surface bindings here, because svga_update_state
-    * will always flush the primitives before processing the
-    * SVGA_NEW_COMMAND_BUFFER state change.
-    *
-    * TODO: Refactor this.
+   /* To force the re-emission of rendertargets and texture sampler bindings on
+    * the next command buffer.
     */
-   ret = svga_reemit_framebuffer_bindings(svga);
-   assert(ret == PIPE_OK);
-
-   ret = svga_reemit_tss_bindings(svga);
-   assert(ret == PIPE_OK);
-
-   svga->dirty &= ~SVGA_NEW_COMMAND_BUFFER;
+   svga->rebind.rendertargets = TRUE;
+   svga->rebind.texture_samplers = TRUE;
 
    if (SVGA_DEBUG & DEBUG_SYNC) {
       if (fence)
index 7b36a3606e06c23e3db4dac13151bd7c1f961637..eca529d262e37aa375de49189698d1f255b1940d 100644 (file)
@@ -358,6 +358,11 @@ struct svga_context
    struct svga_state curr;      /* state from the state tracker */
    unsigned dirty;              /* statechanges since last update_state() */
 
+   struct {
+      unsigned rendertargets:1;
+      unsigned texture_samplers:1;
+   } rebind;
+
    struct u_upload_mgr *upload_ib;
    struct u_upload_mgr *upload_vb;
    struct svga_hwtnl *hwtnl;
@@ -402,7 +407,6 @@ struct svga_context
 #define SVGA_NEW_ZERO_STRIDE         0x2000000
 #define SVGA_NEW_TEXTURE_FLAGS       0x4000000
 #define SVGA_NEW_STENCIL_REF         0x8000000
-#define SVGA_NEW_COMMAND_BUFFER      0x10000000
 
 
 
index 2c873a0f7ac276fc65ccb80c0c12df6ef20fecb2..d8af615ede153a35a95bc2df4b92ee992e168119 100644 (file)
@@ -170,6 +170,20 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
          ib_handle[i] = handle;
       }
 
+      if (svga->rebind.rendertargets) {
+         ret = svga_reemit_framebuffer_bindings(svga);
+         if (ret != PIPE_OK) {
+            return ret;
+         }
+      }
+
+      if (svga->rebind.texture_samplers) {
+         ret = svga_reemit_tss_bindings(svga);
+         if (ret != PIPE_OK) {
+            return ret;
+         }
+      }
+
       SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
                svga->curr.framebuffer.cbufs[0] ?
                svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
index 41f239c1a85ce63b10baa372fee01cf68577eedf..b288c3eb2a6d73c502a13424fbcca4a3c1872802 100644 (file)
@@ -52,6 +52,13 @@ try_clear(struct svga_context *svga,
    if (ret)
       return ret;
 
+   if (svga->rebind.rendertargets) {
+      ret = svga_reemit_framebuffer_bindings(svga);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+   }
+
    if ((buffers & PIPE_CLEAR_COLOR) && fb->cbufs[0]) {
       flags |= SVGA3D_CLEAR_COLOR;
       util_pack_color(rgba, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
index 47bdc253d7bc7dc3c62bc42056c8bbca997e40c5..cc4819431add5e02b4414be95aec062935edc038 100644 (file)
@@ -43,7 +43,7 @@ static int emit_framebuffer( struct svga_context *svga,
 {
    const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
-   boolean reemit = !!(dirty & SVGA_NEW_COMMAND_BUFFER);
+   boolean reemit = svga->rebind.rendertargets;
    unsigned i;
    enum pipe_error ret;
 
@@ -88,6 +88,7 @@ static int emit_framebuffer( struct svga_context *svga,
       pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
    }
 
+   svga->rebind.rendertargets = FALSE;
 
    return 0;
 }
@@ -108,6 +109,8 @@ svga_reemit_framebuffer_bindings(struct svga_context *svga)
    unsigned i;
    enum pipe_error ret;
 
+   assert(svga->rebind.rendertargets);
+
    for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, 8); ++i) {
       if (hw->cbufs[i]) {
          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, hw->cbufs[i]);
@@ -138,6 +141,8 @@ svga_reemit_framebuffer_bindings(struct svga_context *svga)
       }
    }
 
+   svga->rebind.rendertargets = FALSE;
+
    return PIPE_OK;
 }
 
@@ -145,8 +150,7 @@ svga_reemit_framebuffer_bindings(struct svga_context *svga)
 struct svga_tracked_state svga_hw_framebuffer = 
 {
    "hw framebuffer state",
-   SVGA_NEW_FRAME_BUFFER |
-   SVGA_NEW_COMMAND_BUFFER,
+   SVGA_NEW_FRAME_BUFFER,
    emit_framebuffer
 };
 
index c502506b93bd444258514cd6f98c8172f55055d5..8b11a2a425ed452ebe92d84a6bec38dd28500d11 100644 (file)
@@ -66,7 +66,7 @@ static int
 update_tss_binding(struct svga_context *svga, 
                    unsigned dirty )
 {
-   boolean reemit = !!(dirty & SVGA_NEW_COMMAND_BUFFER);
+   boolean reemit = svga->rebind.texture_samplers;
    unsigned i;
    unsigned count = MAX2( svga->curr.num_sampler_views,
                           svga->state.hw_draw.num_views );
@@ -159,6 +159,8 @@ update_tss_binding(struct svga_context *svga,
       SVGA_FIFOCommitAll( svga->swc );
    }
 
+   svga->rebind.texture_samplers = FALSE;
+
    return 0;
 
 fail:
@@ -181,6 +183,8 @@ svga_reemit_tss_bindings(struct svga_context *svga)
    enum pipe_error ret;
    struct bind_queue queue;
 
+   assert(svga->rebind.texture_samplers);
+
    queue.bind_count = 0;
 
    for (i = 0; i < svga->state.hw_draw.num_views; i++) {
@@ -220,6 +224,8 @@ svga_reemit_tss_bindings(struct svga_context *svga)
       SVGA_FIFOCommitAll(svga->swc);
    }
 
+   svga->rebind.texture_samplers = FALSE;
+
    return PIPE_OK;
 }
 
@@ -227,8 +233,7 @@ svga_reemit_tss_bindings(struct svga_context *svga)
 struct svga_tracked_state svga_hw_tss_binding = {
    "texture binding emit",
    SVGA_NEW_TEXTURE_BINDING |
-   SVGA_NEW_SAMPLER |
-   SVGA_NEW_COMMAND_BUFFER,
+   SVGA_NEW_SAMPLER,
    update_tss_binding
 };