summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2011-10-27 19:09:25 +0100
committerJosé Fonseca <jfonseca@vmware.com>2011-10-31 15:22:09 +0000
commit1e9d8934a1a56e888f07a3571038a3f9205a72ae (patch)
tree591ef7bb8913783c60f7323cc9cfa4a4242759a6
parentc04b9d1d561cc3a1300e65bd410f33dfff6fe1e0 (diff)
svga: Flush the hwtnl primitives before writing to buffers.
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>
-rw-r--r--src/gallium/drivers/svga/svga_context.c14
-rw-r--r--src/gallium/drivers/svga/svga_context.h2
-rw-r--r--src/gallium/drivers/svga/svga_draw.c33
-rw-r--r--src/gallium/drivers/svga/svga_draw.h4
-rw-r--r--src/gallium/drivers/svga/svga_resource_buffer.c13
5 files changed, 62 insertions, 4 deletions
diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
index 9f4f8a47def..cbeb424fff5 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -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)
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index a03a81749bb..07d3c5f2c25 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c
index 51869995c7e..c43d1a3443f 100644
--- a/src/gallium/drivers/svga/svga_draw.c
+++ b/src/gallium/drivers/svga/svga_draw.c
@@ -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 )
diff --git a/src/gallium/drivers/svga/svga_draw.h b/src/gallium/drivers/svga/svga_draw.h
index 1dac17421e1..31bea524384 100644
--- a/src/gallium/drivers/svga/svga_draw.h
+++ b/src/gallium/drivers/svga/svga_draw.h
@@ -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 );
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
index 34ab9e143e6..fa713ee88ad 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer.c
@@ -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);