mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 07:18:17 +02:00
nir/lower_clip: implement ClipVertex lowering for GS + lowered IO correctly
This is currently needed to fix d3d12 for st_unlower_io_to_vars. The idea is to track the current value of ClipVertex in a temporary variable, and for every emit_vertex, we load the ClipVertex value from the temporary (which matches the stored value) and insert new CLIP_DIST stores before emit_vertex. Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32363>
This commit is contained in:
parent
a648acc287
commit
c50c9e9bf9
1 changed files with 68 additions and 11 deletions
|
|
@ -150,10 +150,6 @@ load_clipdist_input(nir_builder *b, nir_variable *in, int location_offset,
|
|||
val[3] = nir_channel(b, load, 3);
|
||||
}
|
||||
|
||||
/* TODO: maybe this would be a useful helper?
|
||||
* NOTE: assumes each output is written exactly once (and unconditionally)
|
||||
* so if needed nir_lower_outputs_to_temporaries()
|
||||
*/
|
||||
static nir_def *
|
||||
find_output(nir_builder *b, unsigned location)
|
||||
{
|
||||
|
|
@ -271,6 +267,9 @@ struct lower_clip_state {
|
|||
unsigned ucp_enables;
|
||||
bool use_clipdist_array;
|
||||
const gl_state_index16 (*clipplane_state_tokens)[STATE_LENGTH];
|
||||
|
||||
/* This holds the current CLIP_VERTEX value for GS. */
|
||||
nir_variable *clipvertex_gs_temp;
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -318,9 +317,15 @@ static void
|
|||
lower_clip_vertex_intrin(nir_builder *b, const struct lower_clip_state *state)
|
||||
{
|
||||
nir_def *clipdist[MAX_CLIP_PLANES] = {NULL};
|
||||
nir_def *cv =
|
||||
find_output(b, b->shader->info.outputs_written & VARYING_BIT_CLIP_VERTEX ?
|
||||
VARYING_SLOT_CLIP_VERTEX : VARYING_SLOT_POS);
|
||||
nir_def *cv;
|
||||
|
||||
if (state->clipvertex_gs_temp) {
|
||||
cv = nir_load_deref(b, nir_build_deref_var(b, state->clipvertex_gs_temp));
|
||||
} else {
|
||||
cv = find_output(b, b->shader->info.outputs_written &
|
||||
VARYING_BIT_CLIP_VERTEX ?
|
||||
VARYING_SLOT_CLIP_VERTEX : VARYING_SLOT_POS);
|
||||
}
|
||||
|
||||
for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
|
||||
if (state->ucp_enables & (1 << plane)) {
|
||||
|
|
@ -423,6 +428,10 @@ nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* GS lowering
|
||||
*/
|
||||
|
||||
static bool
|
||||
lower_clip_vertex_gs(nir_builder *b, nir_intrinsic_instr *intr, void *opaque)
|
||||
{
|
||||
|
|
@ -443,9 +452,49 @@ lower_clip_vertex_gs(nir_builder *b, nir_intrinsic_instr *intr, void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GS lowering
|
||||
/* Track the CLIP_VERTEX or POS value in a local variable, so that we can
|
||||
* retrieve it at emit_vertex.
|
||||
*/
|
||||
static bool
|
||||
save_clipvertex_to_temp_gs(nir_builder *b, nir_intrinsic_instr *intr,
|
||||
void *opaque)
|
||||
{
|
||||
const struct lower_clip_state *state =
|
||||
(const struct lower_clip_state *)opaque;
|
||||
gl_varying_slot clip_output_slot =
|
||||
b->shader->info.outputs_written & VARYING_BIT_CLIP_VERTEX ?
|
||||
VARYING_SLOT_CLIP_VERTEX : VARYING_SLOT_POS;
|
||||
|
||||
if (intr->intrinsic != nir_intrinsic_store_output ||
|
||||
nir_intrinsic_io_semantics(intr).location != clip_output_slot)
|
||||
return false;
|
||||
|
||||
b->cursor = nir_before_instr(&intr->instr);
|
||||
|
||||
unsigned component = nir_intrinsic_component(intr);
|
||||
unsigned writemask = nir_intrinsic_write_mask(intr);
|
||||
nir_def *value = intr->src[0].ssa;
|
||||
|
||||
/* Shift vector elements to the right by component. */
|
||||
if (component) {
|
||||
unsigned swizzle[4] = {0};
|
||||
|
||||
for (unsigned i = 1; i < value->num_components; i++)
|
||||
swizzle[component + i] = i;
|
||||
value = nir_swizzle(b, value, swizzle,
|
||||
component + value->num_components);
|
||||
}
|
||||
|
||||
nir_store_deref(b, nir_build_deref_var(b, state->clipvertex_gs_temp),
|
||||
nir_pad_vec4(b, value), writemask << component);
|
||||
|
||||
/* Remove the CLIP_VERTEX store because it will be replaced by CLIP_DIST
|
||||
* stores.
|
||||
*/
|
||||
if (clip_output_slot == VARYING_SLOT_CLIP_VERTEX)
|
||||
nir_instr_remove(&intr->instr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
|
||||
|
|
@ -467,8 +516,16 @@ nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables,
|
|||
|
||||
shader->info.clip_distance_array_size = util_last_bit(ucp_enables);
|
||||
|
||||
/* insert CLIPDIST outputs */
|
||||
if (!shader->info.io_lowered) {
|
||||
if (shader->info.io_lowered) {
|
||||
/* Track the current value of CLIP_VERTEX or POS in a local variable. */
|
||||
state.clipvertex_gs_temp =
|
||||
nir_local_variable_create(nir_shader_get_entrypoint(shader),
|
||||
glsl_vec4_type(), "clipvertex_gs_temp");
|
||||
if (!nir_shader_intrinsics_pass(shader, save_clipvertex_to_temp_gs,
|
||||
nir_metadata_control_flow, &state))
|
||||
return false;
|
||||
} else {
|
||||
/* insert CLIPDIST outputs */
|
||||
create_clipdist_vars(shader, state.out, ucp_enables, true,
|
||||
use_clipdist_array);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue