1 /* -*- mesa-c++ -*-
2 * Copyright 2022 Collabora LTD
3 * Author: Gert Wollny <[email protected]>
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "sfn_shader_tess.h"
8
9 #include "sfn_instr_export.h"
10 #include "sfn_shader_vs.h"
11
12 #include <sstream>
13
14 namespace r600 {
15
16 using std::string;
17
TCSShader(const r600_shader_key & key)18 TCSShader::TCSShader(const r600_shader_key& key):
19 Shader("TCS", key.tcs.first_atomic_counter),
20 m_tcs_prim_mode(key.tcs.prim_mode)
21 {
22 }
23
24 bool
do_scan_instruction(nir_instr * instr)25 TCSShader::do_scan_instruction(nir_instr *instr)
26 {
27 if (instr->type != nir_instr_type_intrinsic)
28 return false;
29
30 nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
31
32 switch (ii->intrinsic) {
33 case nir_intrinsic_load_primitive_id:
34 m_sv_values.set(es_primitive_id);
35 break;
36 case nir_intrinsic_load_invocation_id:
37 m_sv_values.set(es_invocation_id);
38 break;
39 case nir_intrinsic_load_tcs_rel_patch_id_r600:
40 m_sv_values.set(es_rel_patch_id);
41 break;
42 case nir_intrinsic_load_tcs_tess_factor_base_r600:
43 m_sv_values.set(es_tess_factor_base);
44 break;
45 default:
46 return false;
47 ;
48 }
49 return true;
50 }
51
52 int
do_allocate_reserved_registers()53 TCSShader::do_allocate_reserved_registers()
54 {
55 if (m_sv_values.test(es_primitive_id)) {
56 m_primitive_id = value_factory().allocate_pinned_register(0, 0);
57 }
58
59 if (m_sv_values.test(es_invocation_id)) {
60 m_invocation_id = value_factory().allocate_pinned_register(0, 2);
61 }
62
63 if (m_sv_values.test(es_rel_patch_id)) {
64 m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);
65 }
66
67 if (m_sv_values.test(es_tess_factor_base)) {
68 m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
69 }
70
71 return value_factory().next_register_index();
72 ;
73 }
74
75 bool
process_stage_intrinsic(nir_intrinsic_instr * instr)76 TCSShader::process_stage_intrinsic(nir_intrinsic_instr *instr)
77 {
78 switch (instr->intrinsic) {
79 case nir_intrinsic_load_tcs_rel_patch_id_r600:
80 return emit_simple_mov(instr->def, 0, m_rel_patch_id);
81 case nir_intrinsic_load_invocation_id:
82 return emit_simple_mov(instr->def, 0, m_invocation_id);
83 case nir_intrinsic_load_primitive_id:
84 return emit_simple_mov(instr->def, 0, m_primitive_id);
85 case nir_intrinsic_load_tcs_tess_factor_base_r600:
86 return emit_simple_mov(instr->def, 0, m_tess_factor_base);
87 case nir_intrinsic_store_tf_r600:
88 return store_tess_factor(instr);
89 default:
90 return false;
91 }
92 }
93
94 bool
store_tess_factor(nir_intrinsic_instr * instr)95 TCSShader::store_tess_factor(nir_intrinsic_instr *instr)
96 {
97 auto value0 = value_factory().src_vec4(instr->src[0], pin_group, {0, 1, 7, 7});
98 emit_instruction(new WriteTFInstr(value0));
99 return true;
100 }
101
102 void
do_get_shader_info(r600_shader * sh_info)103 TCSShader::do_get_shader_info(r600_shader *sh_info)
104 {
105 sh_info->processor_type = PIPE_SHADER_TESS_CTRL;
106 sh_info->tcs_prim_mode = m_tcs_prim_mode;
107 }
108
109 bool
read_prop(std::istream & is)110 TCSShader::read_prop(std::istream& is)
111 {
112 string value;
113 is >> value;
114
115 ASSERTED auto splitpos = value.find(':');
116 assert(splitpos != string::npos);
117
118 std::istringstream ival(value);
119 string name;
120 string val;
121
122 std::getline(ival, name, ':');
123
124 if (name == "TCS_PRIM_MODE")
125 ival >> m_tcs_prim_mode;
126 else
127 return false;
128 return true;
129 }
130
131 void
do_print_properties(std::ostream & os) const132 TCSShader::do_print_properties(std::ostream& os) const
133 {
134 os << "PROP TCS_PRIM_MODE:" << m_tcs_prim_mode << "\n";
135 }
136
TESShader(const pipe_stream_output_info * so_info,const r600_shader * gs_shader,const r600_shader_key & key)137 TESShader::TESShader(const pipe_stream_output_info *so_info,
138 const r600_shader *gs_shader,
139 const r600_shader_key& key):
140 VertexStageShader("TES", key.tes.first_atomic_counter),
141 m_vs_as_gs_a(key.vs.as_gs_a),
142 m_tes_as_es(key.tes.as_es)
143 {
144 if (key.tes.as_es)
145 m_export_processor = new VertexExportForGS(this, gs_shader);
146 else
147 m_export_processor = new VertexExportForFs(this, so_info, key);
148 }
149
150 bool
do_scan_instruction(nir_instr * instr)151 TESShader::do_scan_instruction(nir_instr *instr)
152 {
153 if (instr->type != nir_instr_type_intrinsic)
154 return false;
155
156 auto intr = nir_instr_as_intrinsic(instr);
157
158 switch (intr->intrinsic) {
159 case nir_intrinsic_load_tess_coord_xy:
160 m_sv_values.set(es_tess_coord);
161 break;
162 case nir_intrinsic_load_primitive_id:
163 m_sv_values.set(es_primitive_id);
164 break;
165 case nir_intrinsic_load_tcs_rel_patch_id_r600:
166 m_sv_values.set(es_rel_patch_id);
167 break;
168 case nir_intrinsic_store_output: {
169 int driver_location = nir_intrinsic_base(intr);
170 auto location = static_cast<gl_varying_slot>(nir_intrinsic_io_semantics(intr).location);
171 auto write_mask = nir_intrinsic_write_mask(intr);
172
173 if (location == VARYING_SLOT_LAYER)
174 write_mask = 4;
175
176 ShaderOutput output(driver_location, write_mask, location);
177
178 add_output(output);
179 break;
180 }
181 default:
182 return false;
183 }
184 return true;
185 }
186
187 int
do_allocate_reserved_registers()188 TESShader::do_allocate_reserved_registers()
189 {
190 if (m_sv_values.test(es_tess_coord)) {
191 m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
192 m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
193 }
194
195 if (m_sv_values.test(es_rel_patch_id)) {
196 m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
197 }
198
199 if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
200 m_primitive_id = value_factory().allocate_pinned_register(0, 3);
201 }
202 return value_factory().next_register_index();
203 }
204
205 bool
process_stage_intrinsic(nir_intrinsic_instr * intr)206 TESShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
207 {
208 switch (intr->intrinsic) {
209 case nir_intrinsic_load_tess_coord_xy:
210 return emit_simple_mov(intr->def, 0, m_tess_coord[0], pin_none) &&
211 emit_simple_mov(intr->def, 1, m_tess_coord[1], pin_none);
212 case nir_intrinsic_load_primitive_id:
213 return emit_simple_mov(intr->def, 0, m_primitive_id);
214 case nir_intrinsic_load_tcs_rel_patch_id_r600:
215 return emit_simple_mov(intr->def, 0, m_rel_patch_id);
216 case nir_intrinsic_store_output:
217 return m_export_processor->store_output(*intr);
218 default:
219 return false;
220 }
221 }
222
223 void
do_get_shader_info(r600_shader * sh_info)224 TESShader::do_get_shader_info(r600_shader *sh_info)
225 {
226 sh_info->processor_type = PIPE_SHADER_TESS_EVAL;
227 m_export_processor->get_shader_info(sh_info);
228 }
229
230 void
do_finalize()231 TESShader::do_finalize()
232 {
233 m_export_processor->finalize();
234 }
235
236 bool
read_prop(std::istream & is)237 TESShader::TESShader::read_prop(std::istream& is)
238 {
239 (void)is;
240 return true;
241 }
242
243 void
do_print_properties(std::ostream & os) const244 TESShader::do_print_properties(std::ostream& os) const
245 {
246 (void)os;
247 }
248
249 } // namespace r600
250