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