X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_draw.c;h=600df89200661960485ef60ffdb8f02c3763bb59;hb=ca531aeeb120cdda966120a17cdf50aa14c3129b;hp=80526ed4d1578c5e3c2424bd104a1a3f66d0cde0;hpb=f0993f81c7fab4ceb99b010d8ee2facbf4fdc737;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c index 80526ed4d15..600df892006 100644 --- a/src/gallium/drivers/svga/svga_draw.c +++ b/src/gallium/drivers/svga/svga_draw.c @@ -436,11 +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); @@ -458,6 +461,17 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, ret = svga_rebind_shaders(svga); if (ret != PIPE_OK) return ret; + + /* Rebind stream output targets */ + ret = svga_rebind_stream_output_targets(svga); + if (ret != PIPE_OK) + return ret; + + /* Force rebinding the index buffer when needed */ + rebind_ib = TRUE; + + /* Force rebinding the vertex buffers */ + rebind_vbuf = TRUE; } ret = validate_sampler_resources(svga); @@ -474,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); @@ -510,33 +531,61 @@ 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]); + } + } + } + else { + /* Even though we can avoid emitting the redundant SetVertexBuffers + * command, we still need to reference the vertex buffers surfaces. + */ + for (i = 0; i < vbuf_count; i++) { + ret = svga->swc->resource_rebind(svga->swc, vbuffer_handles[i], + NULL, SVGA_RELOC_READ); + if (ret != PIPE_OK) + return ret; } } } @@ -555,18 +604,31 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth); /* setup index buffer */ - if (ib_handle != svga->state.hw_draw.ib || + if (rebind_ib || + ib != svga->state.hw_draw.ib || indexFormat != svga->state.hw_draw.ib_format || range->indexArray.offset != svga->state.hw_draw.ib_offset) { + + assert(indexFormat != SVGA3D_FORMAT_INVALID); ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle, indexFormat, range->indexArray.offset); if (ret != PIPE_OK) return ret; - svga->state.hw_draw.ib = ib_handle; + + pipe_resource_reference(&svga->state.hw_draw.ib, ib); svga->state.hw_draw.ib_format = indexFormat; svga->state.hw_draw.ib_offset = range->indexArray.offset; } + else { + /* Even though we can avoid emitting the redundant SetIndexBuffer + * command, we still need to reference the index buffer surface. + */ + ret = svga->swc->resource_rebind(svga->swc, ib_handle, + NULL, SVGA_RELOC_READ); + if (ret != PIPE_OK) + return ret; + } if (instance_count > 1) { ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc, @@ -590,6 +652,19 @@ draw_vgpu10(struct svga_hwtnl *hwtnl, } else { /* non-indexed drawing */ + if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID || + svga->state.hw_draw.ib != NULL) { + /* Unbind previously bound index buffer */ + ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL, + SVGA3D_FORMAT_INVALID, 0); + if (ret != PIPE_OK) + return ret; + 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); + if (instance_count > 1) { ret = SVGA3D_vgpu10_DrawInstanced(svga->swc, vcount, @@ -751,17 +826,14 @@ check_draw_params(struct svga_hwtnl *hwtnl, assert(range->indexWidth == range->indexArray.stride); if (ib) { - unsigned size = ib->width0; - unsigned offset = range->indexArray.offset; - unsigned stride = range->indexArray.stride; - unsigned count; + MAYBE_UNUSED unsigned size = ib->width0; + MAYBE_UNUSED unsigned offset = range->indexArray.offset; + MAYBE_UNUSED unsigned stride = range->indexArray.stride; + MAYBE_UNUSED unsigned count; assert(size); assert(offset < size); assert(stride); - (void) size; - (void) offset; - (void) stride; switch (range->primType) { case SVGA3D_PRIMITIVE_POINTLIST: