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,nir_variable * input)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 
is_varying() const178 bool ShaderInputVarying::is_varying() const
179 {
180    return true;
181 }
182 
update_mask(int additional_comps)183 void ShaderInputVarying::update_mask(int additional_comps)
184 {
185    m_mask |= additional_comps;
186 }
187 
evaluate_spi_sid()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    case TGSI_SEMANTIC_TEXCOORD:
200    case TGSI_SEMANTIC_PCOORD:
201       m_spi_sid = m_sid + 1;
202       break;
203    default:
204       /* For non-generic params - pack name and sid into 8 bits */
205       m_spi_sid = (0x80 | (name() << 3) | m_sid) + 1;
206    }
207 }
208 
ShaderInputVarying(tgsi_semantic name,const ShaderInputVarying & orig,size_t location)209 ShaderInputVarying::ShaderInputVarying(tgsi_semantic name,
210                                        const ShaderInputVarying& orig, size_t location):
211    ShaderInput(name),
212    m_driver_location(location),
213    m_location_frac(orig.location_frac()),
214 
215    m_sid(orig.m_sid),
216    m_spi_sid(orig.m_spi_sid),
217    m_interpolate(orig.m_interpolate),
218    m_interpolate_loc(orig.m_interpolate_loc),
219    m_ij_index(orig.m_ij_index),
220    m_lds_pos(0)
221 {
222    evaluate_spi_sid();
223 }
224 
interpolate() const225 bool ShaderInputVarying::interpolate() const
226 {
227    return m_interpolate > 0;
228 }
229 
ij_index() const230 int ShaderInputVarying::ij_index() const
231 {
232    return m_ij_index;
233 }
234 
set_lds_pos(int lds_pos)235 void ShaderInputVarying::set_lds_pos(int lds_pos)
236 {
237    m_lds_pos = lds_pos;
238 }
239 
lds_pos() const240 int ShaderInputVarying::lds_pos() const
241 {
242    return m_lds_pos;
243 }
244 
set_specific_ioinfo(r600_shader_io & io) const245 void ShaderInputVarying::set_specific_ioinfo(r600_shader_io& io) const
246 {
247    io.interpolate = m_interpolate;
248    io.interpolate_location = m_interpolate_loc;
249    io.sid = m_sid;
250    io.spi_sid = m_spi_sid;
251    set_color_ioinfo(io);
252 }
253 
set_color_ioinfo(UNUSED r600_shader_io & io) const254 void ShaderInputVarying::set_color_ioinfo(UNUSED r600_shader_io& io) const
255 {
256    sfn_log << SfnLog::io << __func__ << " Don't set color_ioinfo\n";
257 }
258 
ShaderInputColor(tgsi_semantic name,int sid,nir_variable * input)259 ShaderInputColor::ShaderInputColor(tgsi_semantic name, int sid, nir_variable *input):
260    ShaderInputVarying(name, sid, input),
261    m_back_color_input_idx(0)
262 {
263    sfn_log << SfnLog::io << __func__ << "name << " << name << " sid << " << sid << "\n";
264 }
265 
set_back_color(unsigned back_color_input_idx)266 void ShaderInputColor::set_back_color(unsigned back_color_input_idx)
267 {
268    sfn_log << SfnLog::io << "Set back color index " << back_color_input_idx << "\n";
269    m_back_color_input_idx = back_color_input_idx;
270 }
271 
set_color_ioinfo(r600_shader_io & io) const272 void ShaderInputColor::set_color_ioinfo(r600_shader_io& io) const
273 {
274    sfn_log << SfnLog::io << __func__ << " set color_ioinfo " << m_back_color_input_idx << "\n";
275    io.back_color_input = m_back_color_input_idx;
276 }
277 
add_input(ShaderInput * input)278 size_t ShaderIO::add_input(ShaderInput *input)
279 {
280    m_inputs.push_back(PShaderInput(input));
281    return m_inputs.size() - 1;
282 }
283 
find_varying(tgsi_semantic name,int sid,int frac)284 PShaderInput ShaderIO::find_varying(tgsi_semantic name, int sid, int frac)
285 {
286    for (auto& a : m_inputs) {
287       if (a->name() == name) {
288          assert(a->is_varying());
289          auto& v = static_cast<ShaderInputVarying&>(*a);
290          if (v.sid() == sid && (v.location_frac() == frac))
291             return a;
292       }
293    }
294    return nullptr;
295 }
296 
297 struct VaryingShaderIOLess {
operator ()r600::VaryingShaderIOLess298    bool operator () (PShaderInput lhs, PShaderInput rhs) const
299    {
300       const ShaderInputVarying& l = static_cast<ShaderInputVarying&>(*lhs);
301       const ShaderInputVarying& r = static_cast<ShaderInputVarying&>(*rhs);
302       return l.location() > r.location();
303    }
304 };
305 
sort_varying_inputs()306 void ShaderIO::sort_varying_inputs()
307 {
308    priority_queue<PShaderInput, vector<PShaderInput>, VaryingShaderIOLess> q;
309 
310    vector<int> idx;
311 
312    for (auto i = 0u; i < m_inputs.size(); ++i) {
313       if (m_inputs[i]->is_varying()) {
314          q.push(m_inputs[i]);
315          idx.push_back(i);
316       }
317    }
318 
319    auto next_index = idx.begin();
320    while (!q.empty()) {
321       auto si = q.top();
322       q.pop();
323       m_inputs[*next_index++] = si;
324    }
325 }
326 
update_lds_pos()327 void ShaderIO::update_lds_pos()
328 {
329    m_lds_pos = -1;
330    m_ldspos.resize(m_inputs.size());
331    for (auto& i : m_inputs) {
332       if (!i->is_varying())
333          continue;
334 
335       auto& v = static_cast<ShaderInputVarying&>(*i);
336       /* There are shaders that miss an input ...*/
337       if (m_ldspos.size() <= static_cast<unsigned>(v.location()))
338           m_ldspos.resize(v.location() + 1);
339    }
340 
341    std::fill(m_ldspos.begin(), m_ldspos.end(), -1);
342    for (auto& i : m_inputs) {
343       if (!i->is_varying())
344          continue;
345 
346       auto& v = static_cast<ShaderInputVarying&>(*i);
347       if (m_ldspos[v.location()] < 0) {
348          ++m_lds_pos;
349          m_ldspos[v.location()] = m_lds_pos;
350       }
351       v.set_lds_pos(m_lds_pos);
352    }
353    ++m_lds_pos;
354 }
355 
inputs()356 std::vector<PShaderInput> &ShaderIO::inputs()
357 {
358    return m_inputs;
359 }
360 
input(size_t k)361 ShaderInput& ShaderIO::input(size_t k)
362 {
363    assert(k < m_inputs.size());
364    return *m_inputs[k];
365 }
366 
input(size_t driver_loc,int frac)367 ShaderInput& ShaderIO::input(size_t driver_loc, int frac)
368 {
369    for (auto& i: m_inputs) {
370       if (!i->is_varying())
371          continue;
372 
373       auto& v = static_cast<ShaderInputVarying&>(*i);
374       if (v.location() == driver_loc && v.location_frac() == frac)
375          return v;
376    }
377    return input(driver_loc);
378 }
379 
set_two_sided()380 void ShaderIO::set_two_sided()
381 {
382    m_two_sided = true;
383 }
384 
385 std::pair<unsigned, unsigned>
r600_get_varying_semantic(unsigned varying_location)386 r600_get_varying_semantic(unsigned varying_location)
387 {
388    std::pair<unsigned, unsigned> result;
389    tgsi_get_gl_varying_semantic(static_cast<gl_varying_slot>(varying_location),
390                                 true, &result.first, &result.second);
391 
392    if (result.first == TGSI_SEMANTIC_GENERIC) {
393       result.second += 9;
394    } else if (result.first == TGSI_SEMANTIC_PCOORD) {
395       result.second = 8;
396    }
397    return result;
398 }
399 
400 
401 
402 }
403 
404