From 1e9d8934a1a56e888f07a3571038a3f9205a72ae Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 27 Oct 2011 19:09:25 +0100 Subject: [PATCH] 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 --- src/gallium/drivers/svga/svga_context.c | 14 +++++++++++ src/gallium/drivers/svga/svga_context.h | 2 ++ src/gallium/drivers/svga/svga_draw.c | 33 +++++++++++++++++++++++++ src/gallium/drivers/svga/svga_draw.h | 4 +++ 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 9f4f8a4..cbeb424 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 a03a817..07d3c5f 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 5186999..c43d1a3 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 1dac174..31bea52 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 34ab9e1..fa713ee 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); -- 2.7.4