gallium/u_threaded,st/mesa: add a merged set_vertex_elements_and_buffers call

Setting vertex elements before vertex buffers is a new requirement of gallium.

This is the only way to set the vertex elements state after vertex buffers
in st/mesa while setting the state before vertex buffers in tc_batch_execute.

A new TC call is added to set both vertex elements and vertex buffers.
Vertex buffers are filled by st/mesa first, and then the vertex elements
state is set in the same call. When TC calls it, it binds vertex elements
before vertex buffers.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27736>
This commit is contained in:
Marek Olšák 2024-02-01 00:48:59 -05:00 committed by Marge Bot
parent 2606ceacdd
commit 1638d486ff
4 changed files with 72 additions and 2 deletions

View file

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

View file

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

View file

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

View file

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