svga: fix vertex buffer references in the hw state
authorCharmaine Lee <charmainel@vmware.com>
Tue, 3 May 2016 01:17:48 +0000 (18:17 -0700)
committerBrian Paul <brianp@vmware.com>
Thu, 23 Jun 2016 13:31:20 +0000 (07:31 -0600)
This patch fixes three issues with vertex buffer references:
(1) Instead of copy the vertex buffer resource handles to the hw state
    in the context structure, use pipe_resource_reference to properly
    reference the vertex buffer resources in the context.

(2) Make sure to unbind those unused vertex buffer resources.

(3) Force to rebind the vertex buffer resources at the first draw of each
    command buffer to make sure the vertex buffer resources are paged in.

Reviewed-by: Brian Paul <brianp@vmware.com>
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_vertex.c

index 32dc209b6192136cd305d8c3d4040b82c898ca68..fa6406c9f89233ebaad73b15f2d28064c50b3adf 100644 (file)
@@ -241,6 +241,8 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
    svga->state.hw_draw.vs = NULL;
    svga->state.hw_draw.gs = NULL;
    svga->state.hw_draw.fs = NULL;
+
+   /* Initialize the currently bound buffer resources */
    memset(svga->state.hw_draw.constbuf, 0,
           sizeof(svga->state.hw_draw.constbuf));
    memset(svga->state.hw_draw.default_constbuf_size, 0,
@@ -248,6 +250,9 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
    memset(svga->state.hw_draw.enabled_constbufs, 0,
           sizeof(svga->state.hw_draw.enabled_constbufs));
    svga->state.hw_draw.ib = NULL;
+   svga->state.hw_draw.num_vbuffers = 0;
+   memset(svga->state.hw_draw.vbuffers, 0,
+          sizeof(svga->state.hw_draw.vbuffers));
 
    /* Create a no-operation blend state which we will bind whenever the
     * requested blend state is impossible (e.g. due to having an integer
index 01f290eebfe64a82b417ad8186c2e47616893a1e..4f1c07ec4b1af21f50ccab61a04c99f123b4b999 100644 (file)
@@ -357,8 +357,8 @@ struct svga_hw_draw_state
    SVGA3dPrimitiveType topology;
 
    /** Vertex buffer state */
-   SVGA3dVertexBuffer vbuffers[PIPE_MAX_ATTRIBS];
-   struct svga_winsys_surface *vbuffer_handles[PIPE_MAX_ATTRIBS];
+   SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS];
+   struct pipe_resource *vbuffers[PIPE_MAX_ATTRIBS];
    unsigned num_vbuffers;
 
    struct pipe_resource *ib;  /**< index buffer for drawing */
index b6de7af80a89fc3ad7f45c758635bb1caf64f292..872dd7f89540126d08196b07dbf4807802f099cc 100644 (file)
@@ -436,12 +436,14 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
             unsigned start_instance, unsigned instance_count)
 {
    struct svga_context *svga = hwtnl->svga;
-   struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
+   struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX];
+   struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX];
    struct svga_winsys_surface *ib_handle;
    const unsigned vbuf_count = hwtnl->cmd.vbuf_count;
    enum pipe_error ret;
    unsigned i;
    boolean rebind_ib = FALSE;
+   boolean rebind_vbuf = FALSE;
 
    assert(svga_have_vgpu10(svga));
    assert(hwtnl->cmd.prim_count == 0);
@@ -467,6 +469,9 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
 
       /* Force rebinding the index buffer when needed */
       rebind_ib = TRUE;
+
+      /* Force rebinding the vertex buffers */
+      rebind_vbuf = TRUE;
    }
 
    ret = validate_sampler_resources(svga);
@@ -483,16 +488,23 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
 
       if (sbuf) {
          assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
-         vb_handle[i] = svga_buffer_handle(svga, &sbuf->b.b);
-         if (vb_handle[i] == NULL)
+         vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b.b);
+         if (vbuffer_handles[i] == NULL)
             return PIPE_ERROR_OUT_OF_MEMORY;
+         vbuffers[i] = &sbuf->b.b;
       }
       else {
-         vb_handle[i] = NULL;
+         vbuffers[i] = NULL;
+         vbuffer_handles[i] = NULL;
       }
    }
 
-   /* Get handles for the index buffers */
+   for (; i < svga->state.hw_draw.num_vbuffers; i++) {
+      vbuffers[i] = NULL;
+      vbuffer_handles[i] = NULL;
+   }
+
+   /* Get handle for the index buffer */
    if (ib) {
       struct svga_buffer *sbuf = svga_buffer(ib);
 
@@ -519,33 +531,50 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
 
    /* setup vertex buffers */
    {
-      SVGA3dVertexBuffer buffers[PIPE_MAX_ATTRIBS];
+      SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS];
+
+      memset(vbuffer_attrs, 0, sizeof(vbuffer_attrs));
 
       for (i = 0; i < vbuf_count; i++) {
-         buffers[i].stride = hwtnl->cmd.vbufs[i].stride;
-         buffers[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
+         vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride;
+         vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
       }
-      if (vbuf_count > 0) {
-         /* If we haven't yet emitted a drawing command or if any
-          * vertex buffer state is changing, issue that state now.
+
+      /* If we haven't yet emitted a drawing command or if any
+       * vertex buffer state is changing, issue that state now.
+       */
+      if (rebind_vbuf ||
+          ((hwtnl->cmd.swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) == 0) ||
+          vbuf_count != svga->state.hw_draw.num_vbuffers ||
+          memcmp(vbuffer_attrs, svga->state.hw_draw.vbuffer_attrs,
+                 vbuf_count * sizeof(vbuffer_attrs[0])) ||
+          memcmp(vbuffers, svga->state.hw_draw.vbuffers,
+                 vbuf_count * sizeof(vbuffers[0]))) {
+
+         unsigned num_vbuffers;
+
+         /* get the max of the current bound vertex buffers count and
+          * the to-be-bound vertex buffers count, so as to unbind
+          * the unused vertex buffers.
           */
-         if (((hwtnl->cmd.swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) == 0) ||
-             vbuf_count != svga->state.hw_draw.num_vbuffers ||
-             memcmp(buffers, svga->state.hw_draw.vbuffers,
-                    vbuf_count * sizeof(buffers[0])) ||
-             memcmp(vb_handle, svga->state.hw_draw.vbuffer_handles,
-                    vbuf_count * sizeof(vb_handle[0]))) {
-            ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, vbuf_count,
+         num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers);
+
+         if (num_vbuffers > 0) {
+
+            ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, num_vbuffers,
                                                  0,    /* startBuffer */
-                                                 buffers, vb_handle);
+                                                 vbuffer_attrs,
+                                                 vbuffer_handles);
             if (ret != PIPE_OK)
                return ret;
 
-            svga->state.hw_draw.num_vbuffers = vbuf_count;
-            memcpy(svga->state.hw_draw.vbuffers, buffers,
-                   vbuf_count * sizeof(buffers[0]));
-            memcpy(svga->state.hw_draw.vbuffer_handles, vb_handle,
-                   vbuf_count * sizeof(vb_handle[0]));
+            svga->state.hw_draw.num_vbuffers = num_vbuffers;
+            memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs,
+                   num_vbuffers * sizeof(vbuffer_attrs[0]));
+            for (i = 0; i < num_vbuffers; i++) {
+               pipe_resource_reference(&svga->state.hw_draw.vbuffers[i],
+                                       vbuffers[i]);
+            }
          }
       }
    }
@@ -610,8 +639,8 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
                                             SVGA3D_FORMAT_INVALID, 0);
          if (ret != PIPE_OK)
             return ret;
-         svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID;
          pipe_resource_reference(&svga->state.hw_draw.ib, NULL);
+         svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID;
       }
 
       assert(svga->state.hw_draw.ib == NULL);
index 4692f76654635241396f48d4b75dcd422a0816a7..075cf5f91bf1effca6c8a2de97974e7aa8621c48 100644 (file)
@@ -329,6 +329,9 @@ void svga_cleanup_vertex_state( struct svga_context *svga )
       pipe_resource_reference(&svga->curr.vb[i].buffer, NULL);
 
    pipe_resource_reference(&svga->state.hw_draw.ib, NULL);
+
+   for (i = 0; i < svga->state.hw_draw.num_vbuffers; i++)
+      pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], NULL);
 }