From 7abfb0b0d50798a476907d4b2f47db05a314cb49 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Tue, 15 Nov 2016 10:15:46 -0800 Subject: [PATCH] svga: do not unconditionally enable streamout bind flag Currently we unconditionally enable streamout bind flag at buffer resource creation time. This is not necessary if the buffer is never used as a streamout buffer. With this patch, we enable streamout bind flag as indicated by the state tracker. If the buffer is later bound to streamout and does not already has streamout bind flag enabled, we will recreate the buffer with the new set of bind flags. Buffer content will be copied from the old buffer to the new one. Tested with MTT piglit, Nature, Tropics, Lightsmark. v2: Fix bind flags check as suggested by Brian. Reviewed-by: Brian Paul Reviewed-by: Jose Fonseca --- src/gallium/drivers/svga/svga_pipe_streamout.c | 8 +-- src/gallium/drivers/svga/svga_resource_buffer.c | 14 ++--- .../drivers/svga/svga_resource_buffer_upload.c | 62 +++++++++++++++++++++- .../drivers/svga/svga_resource_buffer_upload.h | 5 ++ 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/svga/svga_pipe_streamout.c b/src/gallium/drivers/svga/svga_pipe_streamout.c index 18cc804..4add087 100644 --- a/src/gallium/drivers/svga/svga_pipe_streamout.c +++ b/src/gallium/drivers/svga/svga_pipe_streamout.c @@ -276,14 +276,14 @@ svga_set_stream_output_targets(struct pipe_context *pipe, for (i = 0; i < num_targets; i++) { struct svga_stream_output_target *sot = svga_stream_output_target(targets[i]); - struct svga_buffer *sbuf = svga_buffer(sot->base.buffer); unsigned size; - assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT); - (void) sbuf; - svga->so_surfaces[i] = svga_buffer_handle(svga, sot->base.buffer, PIPE_BIND_STREAM_OUTPUT); + + assert(svga_buffer(sot->base.buffer)->key.flags + & SVGA3D_SURFACE_BIND_STREAM_OUTPUT); + svga->so_targets[i] = &sot->base; soBindings[i].offset = sot->base.buffer_offset; diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index 4448b7d..39aa530 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -427,20 +427,22 @@ svga_buffer_create(struct pipe_screen *screen, if (svga_buffer_needs_hw_storage(bind_flags)) { - /* If the buffer will be used for vertex/index/stream data, set all - * the flags so that the buffer will be accepted for all those uses. + /* If the buffer will be used for vertex/index/stream data, set + * the vertex/index bind flags as well so that the buffer will be + * accepted for those uses. * Note that the PIPE_BIND_ flags we get from the state tracker are * just a hint about how the buffer may be used. And OpenGL buffer * object may be used for many different things. + * Also note that we do not unconditionally set the streamout + * bind flag since streamout buffer is an output buffer and + * might have performance implication. */ if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) { - /* Not a constant buffer. The buffer may be used for vertex data, - * indexes or stream-out. + /* Not a constant buffer. The buffer may be used for vertex data + * or indexes. */ bind_flags |= (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER); - if (ss->sws->have_vgpu10) - bind_flags |= PIPE_BIND_STREAM_OUTPUT; } if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK) diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c index 40429a8..d18d026 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c @@ -213,6 +213,53 @@ svga_buffer_create_host_surface(struct svga_screen *ss, } +/** + * Recreates a host surface with the new bind flags. + */ +enum pipe_error +svga_buffer_recreate_host_surface(struct svga_context *svga, + struct svga_buffer *sbuf, + unsigned bind_flags) +{ + struct svga_screen *ss = svga_screen(sbuf->b.b.screen); + struct svga_winsys_surface *old_handle; + struct svga_host_surface_cache_key old_key; + enum pipe_error ret = PIPE_OK; + + assert(sbuf->bind_flags != bind_flags); + + /* Flush any pending upload first */ + svga_buffer_upload_flush(svga, sbuf); + + /* Save the old resource handle and key */ + old_handle = sbuf->handle; + old_key = sbuf->key; + sbuf->handle = NULL; + + /* Create a new resource with the required bind_flags */ + ret = svga_buffer_create_host_surface(ss, sbuf, bind_flags); + if (ret == PIPE_OK) { + /* Copy the surface data */ + assert(sbuf->handle); + ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle, + 0, 0, sbuf->b.b.width0); + if (ret != PIPE_OK) { + svga_context_flush(svga, NULL); + ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle, + 0, 0, sbuf->b.b.width0); + assert(ret == PIPE_OK); + } + } + + /* Set the new bind flags for this buffer resource */ + sbuf->bind_flags = bind_flags; + + /* Destroy the old resource handle */ + svga_screen_surface_destroy(ss, &old_key, &old_handle); + + return ret; +} + void svga_buffer_destroy_host_surface(struct svga_screen *ss, struct svga_buffer *sbuf) @@ -791,7 +838,20 @@ svga_buffer_handle(struct svga_context *svga, struct pipe_resource *buf, assert(!sbuf->user); - if (!sbuf->handle) { + if (sbuf->handle) { + if ((sbuf->bind_flags & tobind_flags) != tobind_flags) { + /* If the allocated resource's bind flags do not include the + * requested bind flags, create a new resource to include the + * new bind flags, and do a BufferCopy from the old resource to + * the new one. + */ + assert(svga_have_vgpu10(svga)); + ret = svga_buffer_recreate_host_surface(svga, sbuf, + sbuf->bind_flags|tobind_flags); + if (ret != PIPE_OK) + return NULL; + } + } else { /* This call will set sbuf->handle */ if (svga_have_gb_objects(svga)) { ret = svga_buffer_update_hw(svga, sbuf, sbuf->bind_flags); diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.h b/src/gallium/drivers/svga/svga_resource_buffer_upload.h index f718f24..877ae54 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.h +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.h @@ -50,6 +50,11 @@ svga_buffer_create_host_surface(struct svga_screen *ss, struct svga_buffer *sbuf, unsigned bind_flags); +enum pipe_error +svga_buffer_recreate_host_surface(struct svga_context *svga, + struct svga_buffer *sbuf, + unsigned bind_flags); + void svga_buffer_destroy_host_surface(struct svga_screen *ss, struct svga_buffer *sbuf); -- 2.7.4