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 }