mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-29 08:30:42 +02:00
zink: use ring buffer to preserve last element
Previously, whenever a vertex was emitted immediately after emitting a
primitive, that vertex would not use the attributes that where assigned
last because the position variable got set.
Now the temporary attributes array is treated as a ring buffer and
whenever the position is set to 0 it's previous value is used as an
offset when accessing it. This way when a new primitive is created the
attributes at index 0 correspond to the last attributes written.
Fixes: 5a4083349f ("zink: add provoking vertex mode lowering")
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22599>
This commit is contained in:
parent
436dacf754
commit
89077b866c
1 changed files with 27 additions and 3 deletions
|
|
@ -390,10 +390,22 @@ struct lower_pv_mode_state {
|
|||
nir_variable *varyings[VARYING_SLOT_MAX];
|
||||
nir_variable *pos_counter;
|
||||
nir_variable *out_pos_counter;
|
||||
nir_variable *ring_offset;
|
||||
unsigned ring_size;
|
||||
unsigned primitive_vert_count;
|
||||
unsigned prim;
|
||||
};
|
||||
|
||||
static nir_ssa_def*
|
||||
lower_pv_mode_gs_ring_index(nir_builder *b,
|
||||
struct lower_pv_mode_state *state,
|
||||
nir_ssa_def *index)
|
||||
{
|
||||
nir_ssa_def *ring_offset = nir_load_var(b, state->ring_offset);
|
||||
return nir_imod(b, nir_iadd(b, index, ring_offset),
|
||||
nir_imm_int(b, state->ring_size));
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_pv_mode_gs_store(nir_builder *b,
|
||||
nir_intrinsic_instr *intrin,
|
||||
|
|
@ -408,8 +420,9 @@ lower_pv_mode_gs_store(nir_builder *b,
|
|||
assert(state->varyings[location]);
|
||||
assert(intrin->src[1].is_ssa);
|
||||
nir_ssa_def *pos_counter = nir_load_var(b, state->pos_counter);
|
||||
nir_ssa_def *index = lower_pv_mode_gs_ring_index(b, state, pos_counter);
|
||||
nir_store_array_var(b, state->varyings[location],
|
||||
pos_counter, intrin->src[1].ssa,
|
||||
index, intrin->src[1].ssa,
|
||||
nir_intrinsic_write_mask(intrin));
|
||||
nir_instr_remove(&intrin->instr);
|
||||
return true;
|
||||
|
|
@ -474,7 +487,8 @@ lower_pv_mode_emit_rotated_prim(nir_builder *b,
|
|||
nir_foreach_variable_with_modes(var, b->shader, nir_var_shader_out) {
|
||||
gl_varying_slot location = var->data.location;
|
||||
if (state->varyings[location]) {
|
||||
nir_ssa_def *value = nir_load_array_var(b, state->varyings[location], rotated_i);
|
||||
nir_ssa_def *index = lower_pv_mode_gs_ring_index(b, state, rotated_i);
|
||||
nir_ssa_def *value = nir_load_array_var(b, state->varyings[location], index);
|
||||
nir_store_var(b, var, value, (1u << value->num_components) - 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -519,6 +533,10 @@ lower_pv_mode_gs_end_primitive(nir_builder *b,
|
|||
nir_store_var(b, state->out_pos_counter, nir_iadd_imm(b, out_pos_counter, 1), 1);
|
||||
}
|
||||
nir_pop_loop(b, NULL);
|
||||
/* Set the ring offset such that when position 0 is
|
||||
* read we get the last value written
|
||||
*/
|
||||
nir_store_var(b, state->ring_offset, pos_counter, 1);
|
||||
nir_store_var(b, state->pos_counter, nir_imm_int(b, 0), 1);
|
||||
nir_store_var(b, state->out_pos_counter, nir_imm_int(b, 0), 1);
|
||||
|
||||
|
|
@ -579,6 +597,7 @@ lower_pv_mode_gs(nir_shader *shader, unsigned prim)
|
|||
|
||||
state.primitive_vert_count =
|
||||
lower_pv_mode_vertices_for_prim(shader->info.gs.output_primitive);
|
||||
state.ring_size = shader->info.gs.vertices_out;
|
||||
|
||||
nir_foreach_variable_with_modes(var, shader, nir_var_shader_out) {
|
||||
gl_varying_slot location = var->data.location;
|
||||
|
|
@ -588,7 +607,7 @@ lower_pv_mode_gs(nir_shader *shader, unsigned prim)
|
|||
state.varyings[location] =
|
||||
nir_local_variable_create(entry,
|
||||
glsl_array_type(var->type,
|
||||
shader->info.gs.vertices_out,
|
||||
state.ring_size,
|
||||
false),
|
||||
name);
|
||||
}
|
||||
|
|
@ -601,11 +620,16 @@ lower_pv_mode_gs(nir_shader *shader, unsigned prim)
|
|||
glsl_uint_type(),
|
||||
"__out_pos_counter");
|
||||
|
||||
state.ring_offset = nir_local_variable_create(entry,
|
||||
glsl_uint_type(),
|
||||
"__ring_offset");
|
||||
|
||||
state.prim = prim;
|
||||
|
||||
// initialize pos_counter and out_pos_counter
|
||||
nir_store_var(&b, state.pos_counter, nir_imm_int(&b, 0), 1);
|
||||
nir_store_var(&b, state.out_pos_counter, nir_imm_int(&b, 0), 1);
|
||||
nir_store_var(&b, state.ring_offset, nir_imm_int(&b, 0), 1);
|
||||
|
||||
shader->info.gs.vertices_out = (shader->info.gs.vertices_out -
|
||||
(state.primitive_vert_count - 1)) *
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue