r600/sfn: Add tesselation shaders
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_shaderio.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018 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_shaderio.h"
28 #include "sfn_debug.h"
29 #include "tgsi/tgsi_from_mesa.h"
30
31 #include <queue>
32
33 namespace r600 {
34
35 using std::vector;
36 using std::priority_queue;
37
38 ShaderIO::ShaderIO():
39 m_two_sided(false),
40 m_lds_pos(0)
41 {
42
43 }
44
45 ShaderInput::ShaderInput(tgsi_semantic name):
46 m_name(name),
47 m_gpr(0),
48 m_uses_interpolate_at_centroid(false)
49 {
50 }
51
52 ShaderInput::~ShaderInput()
53 {
54 }
55
56 void ShaderInput::set_lds_pos(UNUSED int lds_pos)
57 {
58 }
59
60 int ShaderInput::ij_index() const
61 {
62 return -1;
63 }
64
65 bool ShaderInput::interpolate() const
66 {
67 return false;
68 }
69
70 int ShaderInput::lds_pos() const
71 {
72 return 0;
73 }
74
75 bool ShaderInput::is_varying() const
76 {
77 return false;
78 }
79
80 void ShaderInput::set_uses_interpolate_at_centroid()
81 {
82 m_uses_interpolate_at_centroid = true;
83 }
84
85 void ShaderInput::set_ioinfo(r600_shader_io& io, int translated_ij_index) const
86 {
87 io.name = m_name;
88 io.gpr = m_gpr;
89 io.ij_index = translated_ij_index;
90 io.lds_pos = lds_pos();
91 io.uses_interpolate_at_centroid = m_uses_interpolate_at_centroid;
92
93 set_specific_ioinfo(io);
94 }
95
96 void ShaderInput::set_specific_ioinfo(UNUSED r600_shader_io& io) const
97 {
98 }
99
100 ShaderInputSystemValue::ShaderInputSystemValue(tgsi_semantic name, int gpr):
101 ShaderInput(name),
102 m_gpr(gpr)
103 {
104 }
105
106 void ShaderInputSystemValue::set_specific_ioinfo(r600_shader_io& io) const
107 {
108 io.gpr = m_gpr;
109 io.ij_index = 0;
110 }
111
112 ShaderInputVarying::ShaderInputVarying(tgsi_semantic _name, int sid, nir_variable *input):
113 ShaderInput(_name),
114 m_driver_location(input->data.driver_location),
115 m_location_frac(input->data.location_frac),
116 m_sid(sid),
117 m_ij_index(-10),
118 m_mask((1 << input->type->components()) - 1)
119 {
120 sfn_log << SfnLog::io << __func__
121 << "name:" << _name
122 << " sid: " << sid
123 << " op: " << input->data.interpolation;
124
125 evaluate_spi_sid();
126
127 enum glsl_base_type base_type =
128 glsl_get_base_type(glsl_without_array(input->type));
129
130 switch (input->data.interpolation) {
131 case INTERP_MODE_NONE:
132 if (glsl_base_type_is_integer(base_type)) {
133 m_interpolate = TGSI_INTERPOLATE_CONSTANT;
134 break;
135 }
136
137 if (name() == TGSI_SEMANTIC_COLOR) {
138 m_interpolate = TGSI_INTERPOLATE_COLOR;
139 m_ij_index = 0;
140 break;
141 }
142 /* fall-through */
143
144 case INTERP_MODE_SMOOTH:
145 assert(!glsl_base_type_is_integer(base_type));
146
147 m_interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
148 m_ij_index = 0;
149 break;
150
151 case INTERP_MODE_NOPERSPECTIVE:
152 assert(!glsl_base_type_is_integer(base_type));
153
154 m_interpolate = TGSI_INTERPOLATE_LINEAR;
155 m_ij_index = 3;
156 break;
157
158 case INTERP_MODE_FLAT:
159 m_interpolate = TGSI_INTERPOLATE_CONSTANT;
160 break;
161 }
162
163 if (input->data.sample) {
164 m_interpolate_loc = TGSI_INTERPOLATE_LOC_SAMPLE;
165 } else if (input->data.centroid) {
166 m_interpolate_loc = TGSI_INTERPOLATE_LOC_CENTROID;
167 m_ij_index += 2;
168 } else {
169 m_interpolate_loc = TGSI_INTERPOLATE_LOC_CENTER;
170 m_ij_index += 1;
171 }
172 sfn_log << SfnLog::io
173 << " -> IP:" << m_interpolate
174 << " IJ:" << m_ij_index
175 << "\n";
176 }
177
178 bool ShaderInputVarying::is_varying() const
179 {
180 return true;
181 }
182
183 void ShaderInputVarying::update_mask(int additional_comps)
184 {
185 m_mask |= additional_comps;
186 }
187
188 void ShaderInputVarying::evaluate_spi_sid()
189 {
190 switch (name()) {
191 case TGSI_SEMANTIC_POSITION:
192 case TGSI_SEMANTIC_PSIZE:
193 case TGSI_SEMANTIC_EDGEFLAG:
194 case TGSI_SEMANTIC_FACE:
195 case TGSI_SEMANTIC_SAMPLEMASK:
196 assert(0 && "System value used as varying");
197 break;
198 case TGSI_SEMANTIC_GENERIC:
199 m_spi_sid = m_sid + 1;
200 break;
201 default:
202 /* For non-generic params - pack name and sid into 8 bits */
203 m_spi_sid = (0x80 | (name() << 3) | m_sid) + 1;
204 }
205 }
206
207 ShaderInputVarying::ShaderInputVarying(tgsi_semantic name,
208 const ShaderInputVarying& orig, size_t location):
209 ShaderInput(name),
210 m_driver_location(location),
211 m_location_frac(orig.location_frac()),
212
213 m_sid(orig.m_sid),
214 m_spi_sid(orig.m_spi_sid),
215 m_interpolate(orig.m_interpolate),
216 m_interpolate_loc(orig.m_interpolate_loc),
217 m_ij_index(orig.m_ij_index),
218 m_lds_pos(0)
219 {
220 evaluate_spi_sid();
221 }
222
223 bool ShaderInputVarying::interpolate() const
224 {
225 return m_interpolate > 0;
226 }
227
228 int ShaderInputVarying::ij_index() const
229 {
230 return m_ij_index;
231 }
232
233 void ShaderInputVarying::set_lds_pos(int lds_pos)
234 {
235 m_lds_pos = lds_pos;
236 }
237
238 int ShaderInputVarying::lds_pos() const
239 {
240 return m_lds_pos;
241 }
242
243 void ShaderInputVarying::set_specific_ioinfo(r600_shader_io& io) const
244 {
245 io.interpolate = m_interpolate;
246 io.interpolate_location = m_interpolate_loc;
247 io.sid = m_sid;
248 io.spi_sid = m_spi_sid;
249 set_color_ioinfo(io);
250 }
251
252 void ShaderInputVarying::set_color_ioinfo(UNUSED r600_shader_io& io) const
253 {
254 sfn_log << SfnLog::io << __func__ << " Don't set color_ioinfo\n";
255 }
256
257 ShaderInputColor::ShaderInputColor(tgsi_semantic name, int sid, nir_variable *input):
258 ShaderInputVarying(name, sid, input),
259 m_back_color_input_idx(0)
260 {
261 sfn_log << SfnLog::io << __func__ << "name << " << name << " sid << " << sid << "\n";
262 }
263
264 void ShaderInputColor::set_back_color(unsigned back_color_input_idx)
265 {
266 sfn_log << SfnLog::io << "Set back color index " << back_color_input_idx << "\n";
267 m_back_color_input_idx = back_color_input_idx;
268 }
269
270 void ShaderInputColor::set_color_ioinfo(r600_shader_io& io) const
271 {
272 sfn_log << SfnLog::io << __func__ << " set color_ioinfo " << m_back_color_input_idx << "\n";
273 io.back_color_input = m_back_color_input_idx;
274 }
275
276 size_t ShaderIO::add_input(ShaderInput *input)
277 {
278 m_inputs.push_back(PShaderInput(input));
279 return m_inputs.size() - 1;
280 }
281
282 PShaderInput ShaderIO::find_varying(tgsi_semantic name, int sid, int frac)
283 {
284 for (auto& a : m_inputs) {
285 if (a->name() == name) {
286 assert(a->is_varying());
287 auto& v = static_cast<ShaderInputVarying&>(*a);
288 if (v.sid() == sid && (v.location_frac() == frac))
289 return a;
290 }
291 }
292 return nullptr;
293 }
294
295 struct VaryingShaderIOLess {
296 bool operator () (PShaderInput lhs, PShaderInput rhs) const
297 {
298 const ShaderInputVarying& l = static_cast<ShaderInputVarying&>(*lhs);
299 const ShaderInputVarying& r = static_cast<ShaderInputVarying&>(*rhs);
300 return l.location() > r.location();
301 }
302 };
303
304 void ShaderIO::sort_varying_inputs()
305 {
306 priority_queue<PShaderInput, vector<PShaderInput>, VaryingShaderIOLess> q;
307
308 vector<int> idx;
309
310 for (auto i = 0u; i < m_inputs.size(); ++i) {
311 if (m_inputs[i]->is_varying()) {
312 q.push(m_inputs[i]);
313 idx.push_back(i);
314 }
315 }
316
317 auto next_index = idx.begin();
318 while (!q.empty()) {
319 auto si = q.top();
320 q.pop();
321 m_inputs[*next_index++] = si;
322 }
323 }
324
325 void ShaderIO::update_lds_pos()
326 {
327 m_lds_pos = -1;
328 m_ldspos.resize(m_inputs.size());
329 for (auto& i : m_inputs) {
330 if (!i->is_varying())
331 continue;
332
333 auto& v = static_cast<ShaderInputVarying&>(*i);
334 /* There are shaders that miss an input ...*/
335 if (m_ldspos.size() <= static_cast<unsigned>(v.location()))
336 m_ldspos.resize(v.location() + 1);
337 }
338
339 std::fill(m_ldspos.begin(), m_ldspos.end(), -1);
340 for (auto& i : m_inputs) {
341 if (!i->is_varying())
342 continue;
343
344 auto& v = static_cast<ShaderInputVarying&>(*i);
345 if (m_ldspos[v.location()] < 0) {
346 ++m_lds_pos;
347 m_ldspos[v.location()] = m_lds_pos;
348 }
349 v.set_lds_pos(m_lds_pos);
350 }
351 ++m_lds_pos;
352 }
353
354 std::vector<PShaderInput> &ShaderIO::inputs()
355 {
356 return m_inputs;
357 }
358
359 ShaderInput& ShaderIO::input(size_t k)
360 {
361 assert(k < m_inputs.size());
362 return *m_inputs[k];
363 }
364
365 ShaderInput& ShaderIO::input(size_t driver_loc, int frac)
366 {
367 for (auto& i: m_inputs) {
368 if (!i->is_varying())
369 continue;
370
371 auto& v = static_cast<ShaderInputVarying&>(*i);
372 if (v.location() == driver_loc && v.location_frac() == frac)
373 return v;
374 }
375 return input(driver_loc);
376 }
377
378 void ShaderIO::set_two_sided()
379 {
380 m_two_sided = true;
381 }
382
383 }
384