diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index dc2b9f47a7b..c0a434c2c3b 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -2110,6 +2110,54 @@ tc_add_set_vertex_buffers_call(struct pipe_context *_pipe, unsigned count) return p->slot; } +struct tc_vertex_elements_and_buffers { + struct tc_call_base base; + uint8_t count; + void *velems_state; + struct pipe_vertex_buffer slot[0]; /* more will be allocated if needed */ +}; + +static uint16_t +tc_call_set_vertex_elements_and_buffers(struct pipe_context *pipe, void *call) +{ + struct tc_vertex_elements_and_buffers *p = + (struct tc_vertex_elements_and_buffers *)call; + unsigned count = p->count; + + for (unsigned i = 0; i < count; i++) + tc_assert(!p->slot[i].is_user_buffer); + + if (p->velems_state) + pipe->bind_vertex_elements_state(pipe, p->velems_state); + + pipe->set_vertex_buffers(pipe, count, p->slot); + return p->base.num_slots; +} + +/** + * Same as tc_add_set_vertex_buffers_call, but the caller should call + * tc_set_vertex_elements_for_call with the return value to set the vertex + * elements state. The vertex elements state will be bound before vertex + * buffers. + */ +struct pipe_vertex_buffer * +tc_add_set_vertex_elements_and_buffers_call(struct pipe_context *_pipe, + unsigned count) +{ + struct threaded_context *tc = threaded_context(_pipe); + + /* We don't need to unbind trailing buffers because we never touch bindings + * after num_vertex_buffers. + */ + tc->num_vertex_buffers = count; + + struct tc_vertex_elements_and_buffers *p = + tc_add_slot_based_call(tc, TC_CALL_set_vertex_elements_and_buffers, + tc_vertex_elements_and_buffers, count); + p->count = count; + return p->slot; +} + struct tc_stream_outputs { struct tc_call_base base; uint8_t count; diff --git a/src/gallium/auxiliary/util/u_threaded_context.h b/src/gallium/auxiliary/util/u_threaded_context.h index 9b329ba3f33..3d2f5a93eab 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.h +++ b/src/gallium/auxiliary/util/u_threaded_context.h @@ -712,6 +712,10 @@ tc_add_draw_single_call(struct pipe_context *_pipe, struct pipe_vertex_buffer * tc_add_set_vertex_buffers_call(struct pipe_context *_pipe, unsigned count); +struct pipe_vertex_buffer * +tc_add_set_vertex_elements_and_buffers_call(struct pipe_context *_pipe, + unsigned count); + void tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, unsigned drawid_offset, @@ -834,6 +838,19 @@ tc_track_vertex_buffer(struct pipe_context *_pipe, unsigned index, } } +/** + * "buffers" must be a result of tc_add_set_vertex_elements_and_buffers_call. + * This sets the vertex elements state for it. It will be bound before vertex + * buffers. + */ +static inline void +tc_set_vertex_elements_for_call(struct pipe_vertex_buffer *buffers, + void *state) +{ + void **ptr = (void**)buffers; + ptr[-1] = state; +} + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/util/u_threaded_context_calls.h b/src/gallium/auxiliary/util/u_threaded_context_calls.h index 53578dc9079..936e6b0d473 100644 --- a/src/gallium/auxiliary/util/u_threaded_context_calls.h +++ b/src/gallium/auxiliary/util/u_threaded_context_calls.h @@ -10,6 +10,7 @@ */ CALL(draw_single) CALL(set_vertex_buffers) +CALL(set_vertex_elements_and_buffers) CALL(set_constant_buffer) CALL(bind_rasterizer_state) CALL(buffer_unmap) diff --git a/src/mesa/state_tracker/st_atom_array.cpp b/src/mesa/state_tracker/st_atom_array.cpp index faa2d626de9..c10342ae57a 100644 --- a/src/mesa/state_tracker/st_atom_array.cpp +++ b/src/mesa/state_tracker/st_atom_array.cpp @@ -432,7 +432,10 @@ st_update_array_templ(struct st_context *st, /* Add up to 1 vertex buffer for zero-stride vertex attribs. */ num_vbuffers_tc += ALLOW_ZERO_STRIDE_ATTRIBS && inputs_read & ~enabled_arrays; - vbuffer = tc_add_set_vertex_buffers_call(st->pipe, num_vbuffers_tc); + vbuffer = UPDATE_VELEMS ? + tc_add_set_vertex_elements_and_buffers_call(st->pipe, + num_vbuffers_tc) : + tc_add_set_vertex_buffers_call(st->pipe, num_vbuffers_tc); } else { vbuffer = vbuffer_local; } @@ -464,7 +467,8 @@ st_update_array_templ(struct st_context *st, /* Set vertex buffers and elements. */ if (FILL_TC_SET_VB) { - cso_set_vertex_elements(cso, &velements); + void *state = cso_get_vertex_elements_for_bind(cso, &velements); + tc_set_vertex_elements_for_call(vbuffer, state); } else { cso_set_vertex_buffers_and_elements(cso, &velements, num_vbuffers, uses_user_vertex_buffers, vbuffer);