1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2022 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "sfn_shader_tess.h"
28
29 #include "sfn_instr_export.h"
30 #include "sfn_shader_vs.h"
31
32 #include <sstream>
33
34 namespace r600 {
35
36 using std::string;
37
TCSShader(const r600_shader_key & key)38 TCSShader::TCSShader(const r600_shader_key& key):
39 Shader("TCS", key.tcs.first_atomic_counter),
40 m_tcs_prim_mode(key.tcs.prim_mode)
41 {
42 }
43
44 bool
do_scan_instruction(nir_instr * instr)45 TCSShader::do_scan_instruction(nir_instr *instr)
46 {
47 if (instr->type != nir_instr_type_intrinsic)
48 return false;
49
50 nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
51
52 switch (ii->intrinsic) {
53 case nir_intrinsic_load_primitive_id:
54 m_sv_values.set(es_primitive_id);
55 break;
56 case nir_intrinsic_load_invocation_id:
57 m_sv_values.set(es_invocation_id);
58 break;
59 case nir_intrinsic_load_tcs_rel_patch_id_r600:
60 m_sv_values.set(es_rel_patch_id);
61 break;
62 case nir_intrinsic_load_tcs_tess_factor_base_r600:
63 m_sv_values.set(es_tess_factor_base);
64 break;
65 default:
66 return false;
67 ;
68 }
69 return true;
70 }
71
72 int
do_allocate_reserved_registers()73 TCSShader::do_allocate_reserved_registers()
74 {
75 if (m_sv_values.test(es_primitive_id)) {
76 m_primitive_id = value_factory().allocate_pinned_register(0, 0);
77 }
78
79 if (m_sv_values.test(es_invocation_id)) {
80 m_invocation_id = value_factory().allocate_pinned_register(0, 2);
81 }
82
83 if (m_sv_values.test(es_rel_patch_id)) {
84 m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);
85 }
86
87 if (m_sv_values.test(es_tess_factor_base)) {
88 m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
89 }
90
91 return value_factory().next_register_index();
92 ;
93 }
94
95 bool
process_stage_intrinsic(nir_intrinsic_instr * instr)96 TCSShader::process_stage_intrinsic(nir_intrinsic_instr *instr)
97 {
98 switch (instr->intrinsic) {
99 case nir_intrinsic_load_tcs_rel_patch_id_r600:
100 return emit_simple_mov(instr->def, 0, m_rel_patch_id);
101 case nir_intrinsic_load_invocation_id:
102 return emit_simple_mov(instr->def, 0, m_invocation_id);
103 case nir_intrinsic_load_primitive_id:
104 return emit_simple_mov(instr->def, 0, m_primitive_id);
105 case nir_intrinsic_load_tcs_tess_factor_base_r600:
106 return emit_simple_mov(instr->def, 0, m_tess_factor_base);
107 case nir_intrinsic_store_tf_r600:
108 return store_tess_factor(instr);
109 default:
110 return false;
111 }
112 }
113
114 bool
store_tess_factor(nir_intrinsic_instr * instr)115 TCSShader::store_tess_factor(nir_intrinsic_instr *instr)
116 {
117 auto value0 = value_factory().src_vec4(instr->src[0], pin_group, {0, 1, 7, 7});
118 emit_instruction(new WriteTFInstr(value0));
119 return true;
120 }
121
122 void
do_get_shader_info(r600_shader * sh_info)123 TCSShader::do_get_shader_info(r600_shader *sh_info)
124 {
125 sh_info->processor_type = PIPE_SHADER_TESS_CTRL;
126 sh_info->tcs_prim_mode = m_tcs_prim_mode;
127 }
128
129 bool
read_prop(std::istream & is)130 TCSShader::read_prop(std::istream& is)
131 {
132 string value;
133 is >> value;
134
135 ASSERTED auto splitpos = value.find(':');
136 assert(splitpos != string::npos);
137
138 std::istringstream ival(value);
139 string name;
140 string val;
141
142 std::getline(ival, name, ':');
143
144 if (name == "TCS_PRIM_MODE")
145 ival >> m_tcs_prim_mode;
146 else
147 return false;
148 return true;
149 }
150
151 void
do_print_properties(std::ostream & os) const152 TCSShader::do_print_properties(std::ostream& os) const
153 {
154 os << "PROP TCS_PRIM_MODE:" << m_tcs_prim_mode << "\n";
155 }
156
TESShader(const pipe_stream_output_info * so_info,const r600_shader * gs_shader,const r600_shader_key & key)157 TESShader::TESShader(const pipe_stream_output_info *so_info,
158 const r600_shader *gs_shader,
159 const r600_shader_key& key):
160 VertexStageShader("TES", key.tes.first_atomic_counter),
161 m_vs_as_gs_a(key.vs.as_gs_a),
162 m_tes_as_es(key.tes.as_es)
163 {
164 if (key.tes.as_es)
165 m_export_processor = new VertexExportForGS(this, gs_shader);
166 else
167 m_export_processor = new VertexExportForFs(this, so_info, key);
168 }
169
170 bool
do_scan_instruction(nir_instr * instr)171 TESShader::do_scan_instruction(nir_instr *instr)
172 {
173 if (instr->type != nir_instr_type_intrinsic)
174 return false;
175
176 auto intr = nir_instr_as_intrinsic(instr);
177
178 switch (intr->intrinsic) {
179 case nir_intrinsic_load_tess_coord_xy:
180 m_sv_values.set(es_tess_coord);
181 break;
182 case nir_intrinsic_load_primitive_id:
183 m_sv_values.set(es_primitive_id);
184 break;
185 case nir_intrinsic_load_tcs_rel_patch_id_r600:
186 m_sv_values.set(es_rel_patch_id);
187 break;
188 case nir_intrinsic_store_output: {
189 int driver_location = nir_intrinsic_base(intr);
190 auto location = static_cast<gl_varying_slot>(nir_intrinsic_io_semantics(intr).location);
191 auto write_mask = nir_intrinsic_write_mask(intr);
192
193 if (location == VARYING_SLOT_LAYER)
194 write_mask = 4;
195
196 ShaderOutput output(driver_location, write_mask, location);
197
198 add_output(output);
199 break;
200 }
201 default:
202 return false;
203 }
204 return true;
205 }
206
207 int
do_allocate_reserved_registers()208 TESShader::do_allocate_reserved_registers()
209 {
210 if (m_sv_values.test(es_tess_coord)) {
211 m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
212 m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
213 }
214
215 if (m_sv_values.test(es_rel_patch_id)) {
216 m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
217 }
218
219 if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
220 m_primitive_id = value_factory().allocate_pinned_register(0, 3);
221 }
222 return value_factory().next_register_index();
223 }
224
225 bool
process_stage_intrinsic(nir_intrinsic_instr * intr)226 TESShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
227 {
228 switch (intr->intrinsic) {
229 case nir_intrinsic_load_tess_coord_xy:
230 return emit_simple_mov(intr->def, 0, m_tess_coord[0], pin_none) &&
231 emit_simple_mov(intr->def, 1, m_tess_coord[1], pin_none);
232 case nir_intrinsic_load_primitive_id:
233 return emit_simple_mov(intr->def, 0, m_primitive_id);
234 case nir_intrinsic_load_tcs_rel_patch_id_r600:
235 return emit_simple_mov(intr->def, 0, m_rel_patch_id);
236 case nir_intrinsic_store_output:
237 return m_export_processor->store_output(*intr);
238 default:
239 return false;
240 }
241 }
242
243 void
do_get_shader_info(r600_shader * sh_info)244 TESShader::do_get_shader_info(r600_shader *sh_info)
245 {
246 sh_info->processor_type = PIPE_SHADER_TESS_EVAL;
247 m_export_processor->get_shader_info(sh_info);
248 }
249
250 void
do_finalize()251 TESShader::do_finalize()
252 {
253 m_export_processor->finalize();
254 }
255
256 bool
read_prop(std::istream & is)257 TESShader::TESShader::read_prop(std::istream& is)
258 {
259 (void)is;
260 return true;
261 }
262
263 void
do_print_properties(std::ostream & os) const264 TESShader::do_print_properties(std::ostream& os) const
265 {
266 (void)os;
267 }
268
269 } // namespace r600
270