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