diff options
author | José Fonseca <[email protected]> | 2011-10-27 19:09:25 +0100 |
---|---|---|
committer | José Fonseca <[email protected]> | 2011-10-31 15:22:09 +0000 |
commit | 1e9d8934a1a56e888f07a3571038a3f9205a72ae (patch) | |
tree | 591ef7bb8913783c60f7323cc9cfa4a4242759a6 | |
parent | c04b9d1d561cc3a1300e65bd410f33dfff6fe1e0 (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 <[email protected]>
-rw-r--r-- | src/gallium/drivers/svga/svga_context.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_draw.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_draw.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer.c | 13 |
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); |