svga: Flush the hwtnl primitives before writing to buffers.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 27 Oct 2011 18:09:25 +0000 (19:09 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Mon, 31 Oct 2011 15:22:09 +0000 (15:22 +0000)
svga keeps a small queue of similar primitive draws in order to coalesce
them into a single draw primitive command.

But the buffers referred in primitives not yet emitted were being ignored
in the considerations to flush or not the context.

This fixes piglit vbo-map-remap, vbo-subdata-sync, vbo-subdata-zero, and
Seeker.

Based on investigation and patch from Brian Paul.

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_draw.h
src/gallium/drivers/svga/svga_resource_buffer.c

index 9f4f8a47def7d3fded52b4537e4f2a553b34086f..cbeb424fff5d5e789ad6c1d72df50b99be9fcf1b 100644 (file)
@@ -259,6 +259,20 @@ void svga_hwtnl_flush_retry( struct svga_context *svga )
 }
 
 
+/**
+ * Flush the primitive queue if this buffer is referred.
+ *
+ * Otherwise DMA commands on the referred buffer will be emitted too late.
+ */
+void svga_hwtnl_flush_buffer( struct svga_context *svga,
+                              struct pipe_resource *buffer )
+{
+   if (svga_hwtnl_is_buffer_referred(svga->hwtnl, buffer)) {
+      svga_hwtnl_flush_retry(svga);
+   }
+}
+
+
 /* Emit all operations pending on host surfaces.
  */ 
 void svga_surfaces_flush(struct svga_context *svga)
index a03a81749bbdbc80ec0d5f013f0dd4ff01985abd..07d3c5f2c25a5f7d61f5a8d0ac328fe3999785bb 100644 (file)
@@ -454,6 +454,8 @@ void svga_context_flush( struct svga_context *svga,
                          struct pipe_fence_handle **pfence );
 
 void svga_hwtnl_flush_retry( struct svga_context *svga );
+void svga_hwtnl_flush_buffer( struct svga_context *svga,
+                              struct pipe_resource *buffer );
 
 void svga_surfaces_flush(struct svga_context *svga);
 
index 51869995c7e8f1dbf4d4808292a1f1cdc27302e7..c43d1a3443f37f9d2f07d94ba7245f01eda2d30b 100644 (file)
@@ -128,6 +128,39 @@ void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
 }
 
 
+/**
+ * Determine whether the specified buffer is referred in the primitive queue,
+ * for which no commands have been written yet.
+ */
+boolean
+svga_hwtnl_is_buffer_referred( struct svga_hwtnl *hwtnl,
+                               struct pipe_resource *buffer)
+{
+   unsigned i;
+
+   if (svga_buffer_is_user_buffer(buffer)) {
+      return FALSE;
+   }
+
+   if (!hwtnl->cmd.prim_count) {
+      return FALSE;
+   }
+
+   for (i = 0; i < hwtnl->cmd.vdecl_count; ++i) {
+      if (hwtnl->cmd.vdecl_vb[i] == buffer) {
+         return TRUE;
+      }
+   }
+
+   for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
+      if (hwtnl->cmd.prim_ib[i] == buffer) {
+         return TRUE;
+      }
+   }
+
+   return FALSE;
+}
+
 
 enum pipe_error
 svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
index 1dac17421e1d06cb7e9a0e3ff41a75e2a2e69715..31bea5243848873972e7ae85211e656c788053e2 100644 (file)
@@ -76,6 +76,10 @@ svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
                                 unsigned start, 
                                 unsigned count );
 
+boolean
+svga_hwtnl_is_buffer_referred( struct svga_hwtnl *hwtnl,
+                               struct pipe_resource *buffer );
+
 enum pipe_error
 svga_hwtnl_flush( struct svga_hwtnl *hwtnl );
 
index 34ab9e143e68a10f4b0b6f827a81fb4e86979c1c..fa713ee88adda16c864983942dcfee6276e6faf1 100644 (file)
@@ -87,10 +87,13 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
    if (usage & PIPE_TRANSFER_WRITE) {
       if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
          /*
-          * Finish writing any pending DMA commands, and tell the host to discard
-          * the buffer contents on the next DMA operation.
+          * Flush any pending primitives, finish writing any pending DMA
+          * commands, and tell the host to discard the buffer contents on
+          * the next DMA operation.
           */
 
+         svga_hwtnl_flush_buffer(svga, resource);
+
          if (sbuf->dma.pending) {
             svga_buffer_upload_flush(svga, sbuf);
 
@@ -117,10 +120,12 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
          }
       } else {
          /*
-          * Synchronizing, so finish writing any pending DMA command, and
-          * ensure the next DMA will be done in order.
+          * Synchronizing, so flush any pending primitives, finish writing any
+          * pending DMA command, and ensure the next DMA will be done in order.
           */
 
+         svga_hwtnl_flush_buffer(svga, resource);
+
          if (sbuf->dma.pending) {
             svga_buffer_upload_flush(svga, sbuf);