xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/nak_nir_lower_gs_intrinsics.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2023 Collabora, Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "nak_private.h"
7 #include "nir_builder.h"
8 #include "nir_format_convert.h"
9 
10 
11 struct state {
12    nir_builder *builder;
13    nir_variable *handle_var;
14    bool progress;
15 };
16 
17 static void
rewrite_emit_vertex(nir_intrinsic_instr * intr,struct state * state)18 rewrite_emit_vertex(nir_intrinsic_instr *intr, struct state *state)
19 {
20    nir_builder *b = state->builder;
21    const unsigned stream = nir_intrinsic_stream_id(intr);
22 
23    b->cursor = nir_before_instr(&intr->instr);
24 
25    nir_def *gs_handle = nir_load_var(b, state->handle_var);
26    nir_def *gs_handle_out = nir_emit_vertex_nv(b, 32, gs_handle, stream);
27 
28    nir_store_var(b, state->handle_var, gs_handle_out, 0x1);
29 
30    nir_instr_remove(&intr->instr);
31 
32    state->progress = true;
33 }
34 
35 static void
rewrite_end_primitive(nir_intrinsic_instr * intr,struct state * state)36 rewrite_end_primitive(nir_intrinsic_instr *intr, struct state *state)
37 {
38    nir_builder *b = state->builder;
39    const unsigned stream = nir_intrinsic_stream_id(intr);
40 
41    b->cursor = nir_before_instr(&intr->instr);
42 
43    nir_def *gs_handle = nir_load_var(b, state->handle_var);
44    nir_def *gs_handle_out = nir_end_primitive_nv(b, 32, gs_handle, stream);
45 
46    nir_store_var(b, state->handle_var, gs_handle_out, 0x1);
47 
48    nir_instr_remove(&intr->instr);
49 
50    state->progress = true;
51 }
52 
53 static void
rewrite_ast_nv(nir_intrinsic_instr * intr,struct state * state)54 rewrite_ast_nv(nir_intrinsic_instr *intr, struct state *state)
55 {
56    nir_builder *b = state->builder;
57 
58    b->cursor = nir_before_instr(&intr->instr);
59 
60    nir_src *vtx = &intr->src[1];
61    nir_def *gs_handle = nir_load_var(b, state->handle_var);
62    nir_src_rewrite(vtx, gs_handle);
63 
64    state->progress = true;
65 }
66 
67 static void
append_final_primitive_nv(nir_block * end_block,struct state * state)68 append_final_primitive_nv(nir_block *end_block, struct state *state)
69 {
70    nir_builder *b = state->builder;
71 
72    set_foreach(end_block->predecessors, entry) {
73       nir_block *pred = (nir_block *)entry->key;
74       b->cursor = nir_after_block_before_jump(pred);
75 
76       nir_def *gs_handle = nir_load_var(b, state->handle_var);
77       nir_final_primitive_nv(b, gs_handle);
78 
79       state->progress = true;
80    }
81 }
82 
83 bool
nak_nir_lower_gs_intrinsics(nir_shader * nir)84 nak_nir_lower_gs_intrinsics(nir_shader *nir)
85 {
86    struct state state;
87 
88    state.progress = false;
89    nir_function_impl *impl = nir_shader_get_entrypoint(nir);
90    nir_builder builder = nir_builder_at(nir_before_impl(impl));
91 
92    state.builder = &builder;
93 
94    state.handle_var = nir_local_variable_create(impl, glsl_uint_type(), "gs_handle");
95    nir_store_var(&builder, state.handle_var, nir_imm_int(&builder, 0), 0x1);
96 
97    nir_foreach_block_safe(block, impl) {
98       nir_foreach_instr_safe(instr, block) {
99          if (instr->type != nir_instr_type_intrinsic)
100             continue;
101 
102          nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
103 
104          switch (intr->intrinsic) {
105          case nir_intrinsic_emit_vertex:
106             rewrite_emit_vertex(intr, &state);
107             break;
108          case nir_intrinsic_end_primitive:
109             rewrite_end_primitive(intr, &state);
110             break;
111          case nir_intrinsic_ast_nv:
112             rewrite_ast_nv(intr, &state);
113             break;
114          default:
115             break;
116          }
117       }
118    }
119 
120    append_final_primitive_nv(impl->end_block, &state);
121 
122    nir_metadata_preserve(impl, nir_metadata_none);
123 
124    return state.progress;
125 }