diff options
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 18cc804d0c9..4add087888f 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 4448b7d0308..39aa530a672 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 40429a8dc80..d18d026bfa1 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 f718f24c905..877ae5499a1 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); |