From 2b81e31d4488ada643560a640aa4c0f6372e9ca7 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Mon, 2 May 2016 18:17:48 -0700 Subject: [PATCH] svga: fix vertex buffer references in the hw state This patch fixes three issues with vertex buffer references: (1) Instead of copy the vertex buffer resource handles to the hw state in the context structure, use pipe_resource_reference to properly reference the vertex buffer resources in the context. (2) Make sure to unbind those unused vertex buffer resources. (3) Force to rebind the vertex buffer resources at the first draw of each command buffer to make sure the vertex buffer resources are paged in. Reviewed-by: Brian Paul --- src/gallium/drivers/svga/svga_context.c | 5 ++ src/gallium/drivers/svga/svga_context.h | 4 +- src/gallium/drivers/svga/svga_draw.c | 79 ++++++++++++++------- src/gallium/drivers/svga/svga_pipe_vertex.c | 3 + 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index 32dc209b619..fa6406c9f89 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -241,6 +241,8 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen, svga->state.hw_draw.vs = NULL; svga->state.hw_draw.gs = NULL; svga->state.hw_draw.fs = NULL; + + /* Initialize the currently bound buffer resources */ memset(svga->state.hw_draw.constbuf, 0, sizeof(svga->state.hw_draw.constbuf)); memset(svga->state.hw_draw.default_constbuf_size, 0, @@ -248,6 +250,9 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen, memset(svga->state.hw_draw.enabled_constbufs, 0, sizeof(svga->state.hw_draw.enabled_constbufs)); svga->state.hw_draw.ib = NULL; + svga->state.hw_draw.num_vbuffers = 0; + memset(svga->state.hw_draw.vbuffers, 0, + sizeof(svga->state.hw_draw.vbuffers)); /* Create a no-operation blend state which we will bind whenever the * requested blend state is impossible (e.g. due to having an integer diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 01f290eebfe..4f1c07ec4b1 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -357,8 +357,8 @@ struct svga_hw_draw_state SVGA3dPrimitiveType topology; /** Vertex buffer state */ - SVGA3dVertexBuffer vbuffers[PIPE_MAX_ATTRIBS]; - struct svga_winsys_surface *vbuffer_handles[PIPE_MAX_ATTRIBS]; + SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS]; + struct pipe_resource *vbuffers[PIPE_MAX_ATTRIBS]; unsigned num_vbuffers; struct pipe_resource *ib; /**< index buffer for drawing */ diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c index b6de7af80a8..872dd7f8954 100644 --- a/src/gallium/drivers/svga/svga_draw.c +++ b/src/gallium/drivers/svga/svga_draw.c @@ -436,12 +436,14 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, unsigned start_instance, unsigned instance_count) { struct svga_context *svga = hwtnl->svga; - struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX]; + struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX]; + struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX]; struct svga_winsys_surface *ib_handle; const unsigned vbuf_count = hwtnl->cmd.vbuf_count; enum pipe_error ret; unsigned i; boolean rebind_ib = FALSE; + boolean rebind_vbuf = FALSE; assert(svga_have_vgpu10(svga)); assert(hwtnl->cmd.prim_count == 0); @@ -467,6 +469,9 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, /* Force rebinding the index buffer when needed */ rebind_ib = TRUE; + + /* Force rebinding the vertex buffers */ + rebind_vbuf = TRUE; } ret = validate_sampler_resources(svga); @@ -483,16 +488,23 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, if (sbuf) { assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); - vb_handle[i] = svga_buffer_handle(svga, &sbuf->b.b); - if (vb_handle[i] == NULL) + vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b.b); + if (vbuffer_handles[i] == NULL) return PIPE_ERROR_OUT_OF_MEMORY; + vbuffers[i] = &sbuf->b.b; } else { - vb_handle[i] = NULL; + vbuffers[i] = NULL; + vbuffer_handles[i] = NULL; } } - /* Get handles for the index buffers */ + for (; i < svga->state.hw_draw.num_vbuffers; i++) { + vbuffers[i] = NULL; + vbuffer_handles[i] = NULL; + } + + /* Get handle for the index buffer */ if (ib) { struct svga_buffer *sbuf = svga_buffer(ib); @@ -519,33 +531,50 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, /* setup vertex buffers */ { - SVGA3dVertexBuffer buffers[PIPE_MAX_ATTRIBS]; + SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS]; + + memset(vbuffer_attrs, 0, sizeof(vbuffer_attrs)); for (i = 0; i < vbuf_count; i++) { - buffers[i].stride = hwtnl->cmd.vbufs[i].stride; - buffers[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; + vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride; + vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; } - if (vbuf_count > 0) { - /* If we haven't yet emitted a drawing command or if any - * vertex buffer state is changing, issue that state now. + + /* If we haven't yet emitted a drawing command or if any + * vertex buffer state is changing, issue that state now. + */ + if (rebind_vbuf || + ((hwtnl->cmd.swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) == 0) || + vbuf_count != svga->state.hw_draw.num_vbuffers || + memcmp(vbuffer_attrs, svga->state.hw_draw.vbuffer_attrs, + vbuf_count * sizeof(vbuffer_attrs[0])) || + memcmp(vbuffers, svga->state.hw_draw.vbuffers, + vbuf_count * sizeof(vbuffers[0]))) { + + unsigned num_vbuffers; + + /* get the max of the current bound vertex buffers count and + * the to-be-bound vertex buffers count, so as to unbind + * the unused vertex buffers. */ - if (((hwtnl->cmd.swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) == 0) || - vbuf_count != svga->state.hw_draw.num_vbuffers || - memcmp(buffers, svga->state.hw_draw.vbuffers, - vbuf_count * sizeof(buffers[0])) || - memcmp(vb_handle, svga->state.hw_draw.vbuffer_handles, - vbuf_count * sizeof(vb_handle[0]))) { - ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, vbuf_count, + num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers); + + if (num_vbuffers > 0) { + + ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, num_vbuffers, 0, /* startBuffer */ - buffers, vb_handle); + vbuffer_attrs, + vbuffer_handles); if (ret != PIPE_OK) return ret; - svga->state.hw_draw.num_vbuffers = vbuf_count; - memcpy(svga->state.hw_draw.vbuffers, buffers, - vbuf_count * sizeof(buffers[0])); - memcpy(svga->state.hw_draw.vbuffer_handles, vb_handle, - vbuf_count * sizeof(vb_handle[0])); + svga->state.hw_draw.num_vbuffers = num_vbuffers; + memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs, + num_vbuffers * sizeof(vbuffer_attrs[0])); + for (i = 0; i < num_vbuffers; i++) { + pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], + vbuffers[i]); + } } } } @@ -610,8 +639,8 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, SVGA3D_FORMAT_INVALID, 0); if (ret != PIPE_OK) return ret; - svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID; pipe_resource_reference(&svga->state.hw_draw.ib, NULL); + svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID; } assert(svga->state.hw_draw.ib == NULL); diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 4692f766546..075cf5f91bf 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -329,6 +329,9 @@ void svga_cleanup_vertex_state( struct svga_context *svga ) pipe_resource_reference(&svga->curr.vb[i].buffer, NULL); pipe_resource_reference(&svga->state.hw_draw.ib, NULL); + + for (i = 0; i < svga->state.hw_draw.num_vbuffers; i++) + pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], NULL); } -- 2.30.2