xref: /aosp_15_r20/external/mesa3d/src/mesa/state_tracker/st_nir_lower_position_invariant.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2023 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "nir_builder.h"
7 #include "nir_builtin_builder.h"
8 #include "st_nir.h"
9 
10 /**
11  * Emits the implicit "gl_Position = gl_ModelViewProjection * gl_Vertex" for
12  * ARB_vertex_program's ARB_position_invariant option, which must match the
13  * behavior of the fixed function vertex shader.
14  *
15  * The "aos" flag is
16  * ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS, used by
17  * both FF VS and ARB_vp.
18  */
19 bool
st_nir_lower_position_invariant(struct nir_shader * s,bool aos,struct gl_program_parameter_list * paramList)20 st_nir_lower_position_invariant(struct nir_shader *s, bool aos,
21                                 struct gl_program_parameter_list *paramList)
22 {
23    nir_function_impl *impl = nir_shader_get_entrypoint(s);
24    nir_builder b = nir_builder_at(nir_before_impl(impl));
25 
26    nir_def *mvp[4];
27    for (int i = 0; i < 4; i++) {
28       gl_state_index16 tokens[STATE_LENGTH] = {
29           aos ? STATE_MVP_MATRIX : STATE_MVP_MATRIX_TRANSPOSE, 0, i, i};
30       nir_variable *var = st_nir_state_variable_create(s, glsl_vec4_type(), tokens);
31       _mesa_add_state_reference(paramList, tokens);
32       mvp[i] = nir_load_var(&b, var);
33    }
34 
35    nir_def *result;
36    nir_def *in_pos = nir_load_var(&b, nir_get_variable_with_location(s, nir_var_shader_in,
37                                                                          VERT_ATTRIB_POS, glsl_vec4_type()));
38    s->info.inputs_read |= VERT_BIT_POS;
39    if (aos) {
40       nir_def *chans[4];
41       for (int i = 0; i < 4; i++)
42          chans[i] = nir_fdot4(&b, mvp[i], in_pos);
43       result = nir_vec4(&b, chans[0], chans[1], chans[2], chans[3]);
44    } else {
45       result = nir_fmul(&b, mvp[0], nir_channel(&b, in_pos, 0));
46       for (int i = 1; i < 4; i++)
47          result = nir_fmad(&b, mvp[i], nir_channel(&b, in_pos, i), result);
48    }
49    nir_store_var(&b, nir_get_variable_with_location(s, nir_var_shader_out,
50                                                     VARYING_SLOT_POS, glsl_vec4_type()), result, 0xf);
51    s->info.outputs_written |= VARYING_BIT_POS;
52 
53    nir_metadata_preserve(b.impl, nir_metadata_control_flow);
54 
55    return true;
56 }
57