- 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]));
+ if (num_vbuffers > 0) {
+ SVGA3dVertexBuffer *pbufAttrs = vbuffer_attrs;
+ struct svga_winsys_surface **pbufHandles = vbuffer_handles;
+ unsigned numVBuf = 0;
+
+ /* Loop through the vertex buffer lists to only emit
+ * those vertex buffers that are not already in the
+ * corresponding entries in the device's vertex buffer list.
+ */
+ for (i = 0; i < num_vbuffers; i++) {
+ boolean emit;
+
+ emit = vertex_buffers_equal(1,
+ &vbuffer_attrs[i],
+ &vbuffers[i],
+ &svga->state.hw_draw.vbuffer_attrs[i],
+ &svga->state.hw_draw.vbuffers[i]);
+
+ if (!emit && i == num_vbuffers-1) {
+ /* Include the last vertex buffer in the next emit
+ * if it is different.
+ */
+ emit = TRUE;
+ numVBuf++;
+ i++;
+ }
+
+ if (emit) {
+ /* numVBuf can only be 0 if the first vertex buffer
+ * is the same as the one in the device's list.
+ * In this case, there is nothing to send yet.
+ */
+ if (numVBuf) {
+ ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc,
+ numVBuf,
+ i - numVBuf,
+ pbufAttrs, pbufHandles);
+ if (ret != PIPE_OK)
+ return ret;
+ }
+ pbufAttrs += (numVBuf + 1);
+ pbufHandles += (numVBuf + 1);
+ numVBuf = 0;
+ }
+ else
+ numVBuf++;
+ }
+
+ /* save the number of vertex buffers sent to the device, not
+ * including trailing unbound vertex buffers.
+ */
+ svga->state.hw_draw.num_vbuffers = last_vbuf + 1;
+ 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++) {
+ if (vbuffer_handles[i] && !last_command_was_draw(svga)) {
+ ret = svga->swc->resource_rebind(svga->swc, vbuffer_handles[i],
+ NULL, SVGA_RELOC_READ);
+ if (ret != PIPE_OK)
+ return ret;
+ }