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 33namespace r600 { 34 35using std::vector; 36using std::priority_queue; 37 38ShaderIO::ShaderIO(): 39 m_two_sided(false), 40 m_lds_pos(0) 41{ 42 43} 44 45ShaderInput::ShaderInput(tgsi_semantic name): 46 m_name(name), 47 m_gpr(0), 48 m_uses_interpolate_at_centroid(false) 49{ 50} 51 52ShaderInput::~ShaderInput() 53{ 54} 55 56void ShaderInput::set_lds_pos(UNUSED int lds_pos) 57{ 58} 59 60int ShaderInput::ij_index() const 61{ 62 return -1; 63} 64 65bool ShaderInput::interpolate() const 66{ 67 return false; 68} 69 70int ShaderInput::lds_pos() const 71{ 72 return 0; 73} 74 75bool ShaderInput::is_varying() const 76{ 77 return false; 78} 79 80void ShaderInput::set_uses_interpolate_at_centroid() 81{ 82 m_uses_interpolate_at_centroid = true; 83} 84 85void 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 96void ShaderInput::set_specific_ioinfo(UNUSED r600_shader_io& io) const 97{ 98} 99 100ShaderInputSystemValue::ShaderInputSystemValue(tgsi_semantic name, int gpr): 101 ShaderInput(name), 102 m_gpr(gpr) 103{ 104} 105 106void ShaderInputSystemValue::set_specific_ioinfo(r600_shader_io& io) const 107{ 108 io.gpr = m_gpr; 109 io.ij_index = 0; 110} 111 112ShaderInputVarying::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 137ShaderInputVarying::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 208bool ShaderInputVarying::is_varying() const 209{ 210 return true; 211} 212 213void ShaderInputVarying::update_mask(int additional_comps, int frac) 214{ 215 m_mask |= ((1 << additional_comps) - 1) << frac; 216} 217 218void 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 241ShaderInputVarying::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 258bool ShaderInputVarying::interpolate() const 259{ 260 return m_interpolate > 0; 261} 262 263int ShaderInputVarying::ij_index() const 264{ 265 return m_ij_index; 266} 267 268void ShaderInputVarying::set_lds_pos(int lds_pos) 269{ 270 m_lds_pos = lds_pos; 271} 272 273int ShaderInputVarying::lds_pos() const 274{ 275 return m_lds_pos; 276} 277 278void 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 287void 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 292ShaderInputColor::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 299ShaderInputColor::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 308void 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 314void 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 320size_t ShaderIO::add_input(ShaderInput *input) 321{ 322 m_inputs.push_back(PShaderInput(input)); 323 return m_inputs.size() - 1; 324} 325 326PShaderInput 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 339struct VaryingShaderIOLess { 340 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 348void 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 369void 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 401std::vector<PShaderInput> &ShaderIO::inputs() 402{ 403 return m_inputs; 404} 405 406ShaderInput& ShaderIO::input(size_t k) 407{ 408 assert(k < m_inputs.size()); 409 return *m_inputs[k]; 410} 411 412ShaderInput& 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 425void ShaderIO::set_two_sided() 426{ 427 m_two_sided = true; 428} 429 430std::pair<unsigned, unsigned> 431r600_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