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 assert(s->info.io_lowered);
24 nir_function_impl *impl = nir_shader_get_entrypoint(s);
25 nir_builder b = nir_builder_at(nir_before_impl(impl));
26
27 nir_def *mvp[4];
28 for (int i = 0; i < 4; i++) {
29 gl_state_index16 tokens[STATE_LENGTH] = {
30 aos ? STATE_MVP_MATRIX : STATE_MVP_MATRIX_TRANSPOSE, 0, i, i};
31 nir_variable *var = st_nir_state_variable_create(s, glsl_vec4_type(), tokens);
32 _mesa_add_state_reference(paramList, tokens);
33 mvp[i] = nir_load_var(&b, var);
34 }
35
36 nir_def *result;
37 nir_def *in_pos = nir_load_input(&b, 4, 32, nir_imm_int(&b, 0),
38 .io_semantics.location = VERT_ATTRIB_POS);
39
40 if (aos) {
41 nir_def *chans[4];
42 for (int i = 0; i < 4; i++)
43 chans[i] = nir_fdot4(&b, mvp[i], in_pos);
44 result = nir_vec4(&b, chans[0], chans[1], chans[2], chans[3]);
45 } else {
46 result = nir_fmul(&b, mvp[0], nir_channel(&b, in_pos, 0));
47 for (int i = 1; i < 4; i++)
48 result = nir_fmad(&b, mvp[i], nir_channel(&b, in_pos, i), result);
49 }
50
51 nir_store_output(&b, result, nir_imm_int(&b, 0),
52 .io_semantics.location = VARYING_SLOT_POS);
53 nir_metadata_preserve(b.impl, nir_metadata_control_flow);
54
55 return true;
56 }
57