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 <brianp@vmware.com>
This commit is contained in:
Charmaine Lee 2016-05-02 18:17:48 -07:00 committed by Brian Paul
parent a1d74f5528
commit 2b81e31d44
4 changed files with 64 additions and 27 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}