1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 * Copyright © 2023 Valve Corporation
5 *
6 * SPDX-License-Identifier: MIT
7 */
8
9 #include "nir.h"
10 #include "nir_builder.h"
11 #include "radv_nir.h"
12
13 static nir_variable *
find_layer_out_var(nir_shader * nir)14 find_layer_out_var(nir_shader *nir)
15 {
16 nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_out, VARYING_SLOT_LAYER);
17 if (var != NULL)
18 return var;
19
20 var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "layer id");
21 var->data.location = VARYING_SLOT_LAYER;
22 var->data.interpolation = INTERP_MODE_NONE;
23
24 return var;
25 }
26
27 bool
radv_nir_export_multiview(nir_shader * nir)28 radv_nir_export_multiview(nir_shader *nir)
29 {
30 nir_function_impl *impl = nir_shader_get_entrypoint(nir);
31 bool progress = false;
32
33 nir_builder b = nir_builder_create(impl);
34
35 /* This pass is not suitable for mesh shaders, because it can't know the mapping between API mesh
36 * shader invocations and output primitives. Needs to be handled in ac_nir_lower_ngg.
37 */
38 assert(nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_TESS_EVAL ||
39 nir->info.stage == MESA_SHADER_GEOMETRY);
40
41 /* Iterate in reverse order since there should be only one deref store to POS after
42 * lower_io_to_temporaries for vertex shaders and inject the layer there. For geometry shaders,
43 * the layer is injected right before every emit_vertex_with_counter.
44 */
45 nir_variable *layer = NULL;
46 nir_foreach_block_reverse (block, impl) {
47 nir_foreach_instr_reverse (instr, block) {
48 if (instr->type != nir_instr_type_intrinsic)
49 continue;
50
51 if (nir->info.stage == MESA_SHADER_GEOMETRY) {
52 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
53 if (intr->intrinsic != nir_intrinsic_emit_vertex_with_counter)
54 continue;
55
56 b.cursor = nir_before_instr(instr);
57 } else {
58 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
59 if (intr->intrinsic != nir_intrinsic_store_deref)
60 continue;
61
62 nir_variable *var = nir_intrinsic_get_var(intr, 0);
63 if (var->data.mode != nir_var_shader_out || var->data.location != VARYING_SLOT_POS)
64 continue;
65
66 b.cursor = nir_after_instr(instr);
67 }
68
69 if (!layer)
70 layer = find_layer_out_var(nir);
71
72 nir_store_var(&b, layer, nir_load_view_index(&b), 1);
73
74 /* Update outputs_written to reflect that the pass added a new output. */
75 nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_LAYER);
76
77 progress = true;
78 if (nir->info.stage == MESA_SHADER_VERTEX)
79 break;
80 }
81 if (nir->info.stage == MESA_SHADER_VERTEX && progress)
82 break;
83 }
84
85 if (progress)
86 nir_metadata_preserve(impl, nir_metadata_control_flow);
87 else
88 nir_metadata_preserve(impl, nir_metadata_all);
89
90 return progress;
91 }
92