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
ShaderIO()38 ShaderIO::ShaderIO():
39 m_two_sided(false),
40 m_lds_pos(0)
41 {
42
43 }
44
ShaderInput(tgsi_semantic name)45 ShaderInput::ShaderInput(tgsi_semantic name):
46 m_name(name),
47 m_gpr(0),
48 m_uses_interpolate_at_centroid(false)
49 {
50 }
51
~ShaderInput()52 ShaderInput::~ShaderInput()
53 {
54 }
55
set_lds_pos(UNUSED int lds_pos)56 void ShaderInput::set_lds_pos(UNUSED int lds_pos)
57 {
58 }
59
ij_index() const60 int ShaderInput::ij_index() const
61 {
62 return -1;
63 }
64
interpolate() const65 bool ShaderInput::interpolate() const
66 {
67 return false;
68 }
69
lds_pos() const70 int ShaderInput::lds_pos() const
71 {
72 return 0;
73 }
74
is_varying() const75 bool ShaderInput::is_varying() const
76 {
77 return false;
78 }
79
set_uses_interpolate_at_centroid()80 void ShaderInput::set_uses_interpolate_at_centroid()
81 {
82 m_uses_interpolate_at_centroid = true;
83 }
84
set_ioinfo(r600_shader_io & io,int translated_ij_index) const85 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
set_specific_ioinfo(UNUSED r600_shader_io & io) const96 void ShaderInput::set_specific_ioinfo(UNUSED r600_shader_io& io) const
97 {
98 }
99
ShaderInputSystemValue(tgsi_semantic name,int gpr)100 ShaderInputSystemValue::ShaderInputSystemValue(tgsi_semantic name, int gpr):
101 ShaderInput(name),
102 m_gpr(gpr)
103 {
104 }
105
set_specific_ioinfo(r600_shader_io & io) const106 void ShaderInputSystemValue::set_specific_ioinfo(r600_shader_io& io) const
107 {
108 io.gpr = m_gpr;
109 io.ij_index = 0;
110 }
111
ShaderInputVarying(tgsi_semantic _name,int sid,unsigned driver_location,unsigned frac,unsigned components,tgsi_interpolate_mode interpolate,tgsi_interpolate_loc interp_loc)112 ShaderInputVarying::ShaderInputVarying(tgsi_semantic _name, int sid, unsigned driver_location,
113 unsigned frac, unsigned components,
114 tgsi_interpolate_mode interpolate,
115 tgsi_interpolate_loc interp_loc):
116 ShaderInput(_name),
117 m_driver_location(driver_location),
118 m_location_frac(frac),
119 m_sid(sid),
120 m_interpolate(interpolate),
121 m_interpolate_loc(interp_loc),
122 m_ij_index(-10),
123 m_lds_pos(0),
124 m_mask(((1 << components) - 1) << frac)
125 {
126 evaluate_spi_sid();
127
128 m_ij_index = interpolate == TGSI_INTERPOLATE_LINEAR ? 3 : 0;
129 switch (interp_loc) {
130 case TGSI_INTERPOLATE_LOC_CENTROID: m_ij_index += 2; break;
131 case TGSI_INTERPOLATE_LOC_CENTER: m_ij_index += 1; break;
132 default:
133 ;
134 }
135 }
136
ShaderInputVarying(tgsi_semantic _name,int sid,nir_variable * input)137 ShaderInputVarying::ShaderInputVarying(tgsi_semantic _name, int sid, nir_variable *input):
138 ShaderInput(_name),
139 m_driver_location(input->data.driver_location),
140 m_location_frac(input->data.location_frac),
141 m_sid(sid),
142 m_ij_index(-10),
143 m_lds_pos(0),
144 m_mask(((1 << input->type->components()) - 1) << input->data.location_frac)
145 {
146 sfn_log << SfnLog::io << __func__
147 << "name:" << _name
148 << " sid: " << sid
149 << " op: " << input->data.interpolation;
150
151 evaluate_spi_sid();
152
153 enum glsl_base_type base_type =
154 glsl_get_base_type(glsl_without_array(input->type));
155
156 switch (input->data.interpolation) {
157 case INTERP_MODE_NONE:
158 if (glsl_base_type_is_integer(base_type)) {
159 m_interpolate = TGSI_INTERPOLATE_CONSTANT;
160 break;
161 }
162
163 if (name() == TGSI_SEMANTIC_COLOR) {
164 m_interpolate = TGSI_INTERPOLATE_COLOR;
165 m_ij_index = 0;
166 break;
167 }
168 FALLTHROUGH;
169
170 case INTERP_MODE_SMOOTH:
171 assert(!glsl_base_type_is_integer(base_type));
172
173 m_interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
174 m_ij_index = 0;
175 break;
176
177 case INTERP_MODE_NOPERSPECTIVE:
178 assert(!glsl_base_type_is_integer(base_type));
179
180 m_interpolate = TGSI_INTERPOLATE_LINEAR;
181 m_ij_index = 3;
182 break;
183
184 case INTERP_MODE_FLAT:
185 m_interpolate = TGSI_INTERPOLATE_CONSTANT;
186 break;
187
188 default:
189 m_interpolate = TGSI_INTERPOLATE_CONSTANT;
190 break;
191 }
192
193 if (input->data.sample) {
194 m_interpolate_loc = TGSI_INTERPOLATE_LOC_SAMPLE;
195 } else if (input->data.centroid) {
196 m_interpolate_loc = TGSI_INTERPOLATE_LOC_CENTROID;
197 m_ij_index += 2;
198 } else {
199 m_interpolate_loc = TGSI_INTERPOLATE_LOC_CENTER;
200 m_ij_index += 1;
201 }
202 sfn_log << SfnLog::io
203 << " -> IP:" << m_interpolate
204 << " IJ:" << m_ij_index
205 << "\n";
206 }
207
is_varying() const208 bool ShaderInputVarying::is_varying() const
209 {
210 return true;
211 }
212
update_mask(int additional_comps,int frac)213 void ShaderInputVarying::update_mask(int additional_comps, int frac)
214 {
215 m_mask |= ((1 << additional_comps) - 1) << frac;
216 }
217
evaluate_spi_sid()218 void ShaderInputVarying::evaluate_spi_sid()
219 {
220 switch (name()) {
221 case TGSI_SEMANTIC_PSIZE:
222 case TGSI_SEMANTIC_EDGEFLAG:
223 case TGSI_SEMANTIC_FACE:
224 case TGSI_SEMANTIC_SAMPLEMASK:
225 assert(0 && "System value used as varying");
226 break;
227 case TGSI_SEMANTIC_POSITION:
228 m_spi_sid = 0;
229 break;
230 case TGSI_SEMANTIC_GENERIC:
231 case TGSI_SEMANTIC_TEXCOORD:
232 case TGSI_SEMANTIC_PCOORD:
233 m_spi_sid = m_sid + 1;
234 break;
235 default:
236 /* For non-generic params - pack name and sid into 8 bits */
237 m_spi_sid = (0x80 | (name() << 3) | m_sid) + 1;
238 }
239 }
240
ShaderInputVarying(tgsi_semantic name,const ShaderInputVarying & orig,size_t location)241 ShaderInputVarying::ShaderInputVarying(tgsi_semantic name,
242 const ShaderInputVarying& orig, size_t location):
243 ShaderInput(name),
244 m_driver_location(location),
245 m_location_frac(orig.location_frac()),
246
247 m_sid(orig.m_sid),
248 m_spi_sid(orig.m_spi_sid),
249 m_interpolate(orig.m_interpolate),
250 m_interpolate_loc(orig.m_interpolate_loc),
251 m_ij_index(orig.m_ij_index),
252 m_lds_pos(0),
253 m_mask(0)
254 {
255 evaluate_spi_sid();
256 }
257
interpolate() const258 bool ShaderInputVarying::interpolate() const
259 {
260 return m_interpolate > 0;
261 }
262
ij_index() const263 int ShaderInputVarying::ij_index() const
264 {
265 return m_ij_index;
266 }
267
set_lds_pos(int lds_pos)268 void ShaderInputVarying::set_lds_pos(int lds_pos)
269 {
270 m_lds_pos = lds_pos;
271 }
272
lds_pos() const273 int ShaderInputVarying::lds_pos() const
274 {
275 return m_lds_pos;
276 }
277
set_specific_ioinfo(r600_shader_io & io) const278 void ShaderInputVarying::set_specific_ioinfo(r600_shader_io& io) const
279 {
280 io.interpolate = m_interpolate;
281 io.interpolate_location = m_interpolate_loc;
282 io.sid = m_sid;
283 io.spi_sid = m_spi_sid;
284 set_color_ioinfo(io);
285 }
286
set_color_ioinfo(UNUSED r600_shader_io & io) const287 void ShaderInputVarying::set_color_ioinfo(UNUSED r600_shader_io& io) const
288 {
289 sfn_log << SfnLog::io << __func__ << " Don't set color_ioinfo\n";
290 }
291
ShaderInputColor(tgsi_semantic name,int sid,nir_variable * input)292 ShaderInputColor::ShaderInputColor(tgsi_semantic name, int sid, nir_variable *input):
293 ShaderInputVarying(name, sid, input),
294 m_back_color_input_idx(0)
295 {
296 sfn_log << SfnLog::io << __func__ << "name << " << name << " sid << " << sid << "\n";
297 }
298
ShaderInputColor(tgsi_semantic _name,int sid,unsigned driver_location,unsigned frac,unsigned components,tgsi_interpolate_mode interpolate,tgsi_interpolate_loc interp_loc)299 ShaderInputColor::ShaderInputColor(tgsi_semantic _name, int sid, unsigned driver_location,
300 unsigned frac, unsigned components, tgsi_interpolate_mode interpolate,
301 tgsi_interpolate_loc interp_loc):
302 ShaderInputVarying(_name, sid, driver_location,frac, components, interpolate, interp_loc),
303 m_back_color_input_idx(0)
304 {
305 sfn_log << SfnLog::io << __func__ << "name << " << _name << " sid << " << sid << "\n";
306 }
307
set_back_color(unsigned back_color_input_idx)308 void ShaderInputColor::set_back_color(unsigned back_color_input_idx)
309 {
310 sfn_log << SfnLog::io << "Set back color index " << back_color_input_idx << "\n";
311 m_back_color_input_idx = back_color_input_idx;
312 }
313
set_color_ioinfo(r600_shader_io & io) const314 void ShaderInputColor::set_color_ioinfo(r600_shader_io& io) const
315 {
316 sfn_log << SfnLog::io << __func__ << " set color_ioinfo " << m_back_color_input_idx << "\n";
317 io.back_color_input = m_back_color_input_idx;
318 }
319
add_input(ShaderInput * input)320 size_t ShaderIO::add_input(ShaderInput *input)
321 {
322 m_inputs.push_back(PShaderInput(input));
323 return m_inputs.size() - 1;
324 }
325
find_varying(tgsi_semantic name,int sid)326 PShaderInput ShaderIO::find_varying(tgsi_semantic name, int sid)
327 {
328 for (auto& a : m_inputs) {
329 if (a->name() == name) {
330 assert(a->is_varying());
331 auto& v = static_cast<ShaderInputVarying&>(*a);
332 if (v.sid() == sid)
333 return a;
334 }
335 }
336 return nullptr;
337 }
338
339 struct VaryingShaderIOLess {
operator ()r600::VaryingShaderIOLess340 bool operator () (PShaderInput lhs, PShaderInput rhs) const
341 {
342 const ShaderInputVarying& l = static_cast<ShaderInputVarying&>(*lhs);
343 const ShaderInputVarying& r = static_cast<ShaderInputVarying&>(*rhs);
344 return l.location() > r.location();
345 }
346 };
347
sort_varying_inputs()348 void ShaderIO::sort_varying_inputs()
349 {
350 priority_queue<PShaderInput, vector<PShaderInput>, VaryingShaderIOLess> q;
351
352 vector<int> idx;
353
354 for (auto i = 0u; i < m_inputs.size(); ++i) {
355 if (m_inputs[i]->is_varying()) {
356 q.push(m_inputs[i]);
357 idx.push_back(i);
358 }
359 }
360
361 auto next_index = idx.begin();
362 while (!q.empty()) {
363 auto si = q.top();
364 q.pop();
365 m_inputs[*next_index++] = si;
366 }
367 }
368
update_lds_pos()369 void ShaderIO::update_lds_pos()
370 {
371 m_lds_pos = -1;
372 m_ldspos.resize(m_inputs.size());
373 for (auto& i : m_inputs) {
374 if (!i->is_varying())
375 continue;
376
377 auto& v = static_cast<ShaderInputVarying&>(*i);
378 /* There are shaders that miss an input ...*/
379 if (m_ldspos.size() <= static_cast<unsigned>(v.location()))
380 m_ldspos.resize(v.location() + 1);
381 }
382
383 std::fill(m_ldspos.begin(), m_ldspos.end(), -1);
384 for (auto& i : m_inputs) {
385 if (!i->is_varying())
386 continue;
387
388 auto& v = static_cast<ShaderInputVarying&>(*i);
389 if (v.name() == TGSI_SEMANTIC_POSITION)
390 continue;
391
392 if (m_ldspos[v.location()] < 0) {
393 ++m_lds_pos;
394 m_ldspos[v.location()] = m_lds_pos;
395 }
396 v.set_lds_pos(m_lds_pos);
397 }
398 ++m_lds_pos;
399 }
400
inputs()401 std::vector<PShaderInput> &ShaderIO::inputs()
402 {
403 return m_inputs;
404 }
405
input(size_t k)406 ShaderInput& ShaderIO::input(size_t k)
407 {
408 assert(k < m_inputs.size());
409 return *m_inputs[k];
410 }
411
input(size_t driver_loc,int frac)412 ShaderInput& ShaderIO::input(size_t driver_loc, int frac)
413 {
414 for (auto& i: m_inputs) {
415 if (!i->is_varying())
416 continue;
417
418 auto& v = static_cast<ShaderInputVarying&>(*i);
419 if (v.location() == driver_loc)
420 return v;
421 }
422 return input(driver_loc);
423 }
424
set_two_sided()425 void ShaderIO::set_two_sided()
426 {
427 m_two_sided = true;
428 }
429
430 std::pair<unsigned, unsigned>
r600_get_varying_semantic(unsigned varying_location)431 r600_get_varying_semantic(unsigned varying_location)
432 {
433 std::pair<unsigned, unsigned> result;
434 tgsi_get_gl_varying_semantic(static_cast<gl_varying_slot>(varying_location),
435 true, &result.first, &result.second);
436
437 if (result.first == TGSI_SEMANTIC_GENERIC) {
438 result.second += 9;
439 } else if (result.first == TGSI_SEMANTIC_PCOORD) {
440 result.second = 8;
441 }
442 return result;
443 }
444
445
446
447 }
448
449