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_instruction_fetch.h" 28 29#include "gallium/drivers/r600/r600_pipe.h" 30 31namespace r600 { 32 33/* refactor this to add status create methods for specific tasks */ 34FetchInstruction::FetchInstruction(EVFetchInstr op, 35 EVFetchType type, 36 GPRVector dst, 37 PValue src, int offset, 38 int buffer_id, PValue buffer_offset, 39 EBufferIndexMode cp_rel, 40 bool use_const_field): 41 Instruction(vtx), 42 m_vc_opcode(op), 43 m_fetch_type(type), 44 m_endian_swap(vtx_es_none), 45 m_src(src), 46 m_dst(dst), 47 m_offset(offset), 48 m_is_mega_fetch(1), 49 m_mega_fetch_count(16), 50 m_buffer_id(buffer_id), 51 m_semantic_id(0), 52 m_buffer_index_mode(cp_rel), 53 m_flags(0), 54 m_uncached(false), 55 m_indexed(false), 56 m_array_base(0), 57 m_array_size(0), 58 m_elm_size(0), 59 m_buffer_offset(buffer_offset), 60 m_dest_swizzle({0,1,2,3}) 61{ 62 if (use_const_field) { 63 m_flags.set(vtx_use_const_field); 64 m_data_format = fmt_invalid; 65 m_num_format = vtx_nf_norm; 66 } else { 67 m_flags.set(vtx_format_comp_signed); 68 m_data_format = fmt_32_32_32_32_float; 69 m_num_format = vtx_nf_scaled; 70 } 71 72 add_remappable_src_value(&m_src); 73 add_remappable_src_value(&m_buffer_offset); 74 75 add_remappable_dst_value(&m_dst); 76} 77 78/* Resource query */ 79FetchInstruction::FetchInstruction(EVFetchInstr vc_opcode, 80 EVFetchType fetch_type, 81 EVTXDataFormat data_format, 82 EVFetchNumFormat num_format, 83 EVFetchEndianSwap endian_swap, 84 const PValue src, 85 const GPRVector dst, 86 uint32_t offset, 87 bool is_mega_fetch, 88 uint32_t mega_fetch_count, 89 uint32_t buffer_id, 90 uint32_t semantic_id, 91 92 EBufferIndexMode buffer_index_mode, 93 bool uncached, 94 bool indexed, 95 int array_base, 96 int array_size, 97 int elm_size, 98 PValue buffer_offset, 99 const std::array<int, 4>& dest_swizzle): 100 Instruction(vtx), 101 m_vc_opcode(vc_opcode), 102 m_fetch_type(fetch_type), 103 m_data_format(data_format), 104 m_num_format(num_format), 105 m_endian_swap(endian_swap), 106 m_src(src), 107 m_dst(dst), 108 m_offset(offset), 109 m_is_mega_fetch(is_mega_fetch), 110 m_mega_fetch_count(mega_fetch_count), 111 m_buffer_id(buffer_id), 112 m_semantic_id(semantic_id), 113 m_buffer_index_mode(buffer_index_mode), 114 m_uncached(uncached), 115 m_indexed(indexed), 116 m_array_base(array_base), 117 m_array_size(array_size), 118 m_elm_size(elm_size), 119 m_buffer_offset(buffer_offset), 120 m_dest_swizzle(dest_swizzle) 121{ 122 add_remappable_src_value(&m_src); 123 add_remappable_dst_value(&m_dst); 124 add_remappable_src_value(&m_buffer_offset); 125} 126 127FetchInstruction::FetchInstruction(GPRVector dst, 128 PValue src, 129 int buffer_id, PValue buffer_offset, 130 EVTXDataFormat format, 131 EVFetchNumFormat num_format): 132 Instruction(vtx), 133 m_vc_opcode(vc_fetch), 134 m_fetch_type(no_index_offset), 135 m_data_format(format), 136 m_num_format(num_format), 137 m_endian_swap(vtx_es_none), 138 m_src(src), 139 m_dst(dst), 140 m_offset(0), 141 m_is_mega_fetch(0), 142 m_mega_fetch_count(0), 143 m_buffer_id(buffer_id), 144 m_semantic_id(0), 145 m_buffer_index_mode(bim_none), 146 m_flags(0), 147 m_uncached(false), 148 m_indexed(false), 149 m_array_base(0), 150 m_array_size(0), 151 m_elm_size(1), 152 m_buffer_offset(buffer_offset), 153 m_dest_swizzle({0,1,2,3}) 154{ 155 m_flags.set(vtx_format_comp_signed); 156 157 add_remappable_src_value(&m_src); 158 add_remappable_dst_value(&m_dst); 159 add_remappable_src_value(&m_buffer_offset); 160} 161 162 163/* Resource query */ 164FetchInstruction::FetchInstruction(GPRVector dst, 165 PValue src, 166 int buffer_id, 167 EBufferIndexMode cp_rel): 168 Instruction(vtx), 169 m_vc_opcode(vc_get_buf_resinfo), 170 m_fetch_type(no_index_offset), 171 m_data_format(fmt_32_32_32_32), 172 m_num_format(vtx_nf_norm), 173 m_endian_swap(vtx_es_none), 174 m_src(src), 175 m_dst(dst), 176 m_offset(0), 177 m_is_mega_fetch(0), 178 m_mega_fetch_count(16), 179 m_buffer_id(buffer_id), 180 m_semantic_id(0), 181 m_buffer_index_mode(cp_rel), 182 m_flags(0), 183 m_uncached(false), 184 m_indexed(false), 185 m_array_base(0), 186 m_array_size(0), 187 m_elm_size(0), 188 m_dest_swizzle({0,1,2,3}) 189{ 190 m_flags.set(vtx_format_comp_signed); 191 add_remappable_src_value(&m_src); 192 add_remappable_dst_value(&m_dst); 193 add_remappable_src_value(&m_buffer_offset); 194} 195 196FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int scratch_size): 197 Instruction(vtx), 198 m_vc_opcode(vc_read_scratch), 199 m_fetch_type(vertex_data), 200 m_data_format(fmt_32_32_32_32), 201 m_num_format(vtx_nf_int), 202 m_endian_swap(vtx_es_none), 203 m_dst(dst), 204 m_offset(0), 205 m_is_mega_fetch(0), 206 m_mega_fetch_count(16), 207 m_buffer_id(0), 208 m_semantic_id(0), 209 m_buffer_index_mode(bim_none), 210 m_flags(0), 211 m_uncached(true), 212 m_array_base(0), 213 m_array_size(0), 214 m_elm_size(3), 215 m_dest_swizzle({0,1,2,3}) 216{ 217 if (src->type() == Value::literal) { 218 const auto& lv = static_cast<const LiteralValue&>(*src); 219 m_array_base = lv.value(); 220 m_indexed = false; 221 m_src.reset(new GPRValue(0,0)); 222 m_array_size = 0; 223 } else { 224 m_array_base = 0; 225 m_src = src; 226 m_indexed = true; 227 m_array_size = scratch_size - 1; 228 } 229 add_remappable_src_value(&m_src); 230 add_remappable_dst_value(&m_dst); 231 add_remappable_src_value(&m_buffer_offset); 232} 233 234void FetchInstruction::replace_values(const ValueSet& candidates, PValue new_value) 235{ 236 if (!m_src) 237 return; 238 for (auto c: candidates) { 239 for (int i = 0; i < 4; ++i) { 240 if (*c == *m_dst.reg_i(i)) 241 m_dst.set_reg_i(i, new_value); 242 } 243 if (*m_src == *c) 244 m_src = new_value; 245 } 246} 247 248 249bool FetchInstruction::is_equal_to(const Instruction& lhs) const 250{ 251 auto& l = static_cast<const FetchInstruction&>(lhs); 252 if (m_src) { 253 if (!l.m_src) 254 return false; 255 if (*m_src != *l.m_src) 256 return false; 257 } else { 258 if (l.m_src) 259 return false; 260 } 261 262 return m_vc_opcode == l.m_vc_opcode && 263 m_fetch_type == l.m_fetch_type && 264 m_data_format == l.m_data_format && 265 m_num_format == l.m_num_format && 266 m_endian_swap == l.m_endian_swap && 267 m_dst == l.m_dst && 268 m_offset == l.m_offset && 269 m_buffer_id == l.m_buffer_id && 270 m_semantic_id == l.m_semantic_id && 271 m_buffer_index_mode == l.m_buffer_index_mode && 272 m_flags == l.m_flags && 273 m_indexed == l.m_indexed && 274 m_uncached == l.m_uncached; 275} 276 277void FetchInstruction::set_format(EVTXDataFormat fmt) 278{ 279 m_data_format = fmt; 280} 281 282 283void FetchInstruction::set_dest_swizzle(const std::array<int,4>& swz) 284{ 285 m_dest_swizzle = swz; 286} 287 288void FetchInstruction::prelude_append(Instruction *instr) 289{ 290 assert(instr); 291 m_prelude.push_back(PInstruction(instr)); 292} 293 294const std::vector<PInstruction>& FetchInstruction::prelude() const 295{ 296 return m_prelude; 297} 298 299LoadFromScratch::LoadFromScratch(GPRVector dst, PValue src, int scratch_size): 300 FetchInstruction(dst, src, scratch_size) 301{ 302} 303 304FetchGDSOpResult::FetchGDSOpResult(const GPRVector dst, const PValue src): 305 FetchInstruction(vc_fetch, 306 no_index_offset, 307 fmt_32, 308 vtx_nf_int, 309 vtx_es_none, 310 src, 311 dst, 312 0, 313 false, 314 0xf, 315 R600_IMAGE_IMMED_RESOURCE_OFFSET, 316 0, 317 bim_none, 318 false, 319 false, 320 0, 321 0, 322 0, 323 PValue(), 324 {0,7,7,7}) 325{ 326 set_flag(vtx_srf_mode); 327 set_flag(vtx_vpm); 328} 329 330FetchTCSIOParam::FetchTCSIOParam(GPRVector dst, PValue src, int offset): 331 FetchInstruction(vc_fetch, 332 no_index_offset, 333 fmt_32_32_32_32, 334 vtx_nf_scaled, 335 vtx_es_none, 336 src, 337 dst, 338 offset, 339 false, 340 16, 341 R600_LDS_INFO_CONST_BUFFER, 342 0, 343 bim_none, 344 false, 345 false, 346 0, 347 0, 348 0, 349 PValue(), 350 {0,1,2,3}) 351{ 352 set_flag(vtx_srf_mode); 353 set_flag(vtx_format_comp_signed); 354} 355 356 357static const char *fmt_descr[64] = { 358 "INVALID", 359 "8", 360 "4_4", 361 "3_3_2", 362 "RESERVED_4", 363 "16", 364 "16F", 365 "8_8", 366 "5_6_5", 367 "6_5_5", 368 "1_5_5_5", 369 "4_4_4_4", 370 "5_5_5_1", 371 "32", 372 "32F", 373 "16_16", 374 "16_16F", 375 "8_24", 376 "8_24F", 377 "24_8", 378 "24_8F", 379 "10_11_11", 380 "10_11_11F", 381 "11_11_10", 382 "11_11_10F", 383 "2_10_10_10", 384 "8_8_8_8", 385 "10_10_10_2", 386 "X24_8_32F", 387 "32_32", 388 "32_32F", 389 "16_16_16_16", 390 "16_16_16_16F", 391 "RESERVED_33", 392 "32_32_32_32", 393 "32_32_32_32F", 394 "RESERVED_36", 395 "1", 396 "1_REVERSED", 397 "GB_GR", 398 "BG_RG", 399 "32_AS_8", 400 "32_AS_8_8", 401 "5_9_9_9_SHAREDEXP", 402 "8_8_8", 403 "16_16_16", 404 "16_16_16F", 405 "32_32_32", 406 "32_32_32F", 407 "BC1", 408 "BC2", 409 "BC3", 410 "BC4", 411 "BC5", 412 "APC0", 413 "APC1", 414 "APC2", 415 "APC3", 416 "APC4", 417 "APC5", 418 "APC6", 419 "APC7", 420 "CTX1", 421 "RESERVED_63" 422}; 423 424 425void FetchInstruction::do_print(std::ostream& os) const 426{ 427 static const std::string num_format_char[] = {"norm", "int", "scaled"}; 428 static const std::string endian_swap_code[] = { 429 "noswap", "8in16", "8in32" 430 }; 431 static const char buffer_index_mode_char[] = "_01E"; 432 static const char *flag_string[] = {"WQM", "CF", "signed", "no_zero", 433 "nostride", "AC", "TC", "VPM"}; 434 switch (m_vc_opcode) { 435 case vc_fetch: 436 os << "Fetch " << m_dst; 437 break; 438 case vc_semantic: 439 os << "Fetch Semantic ID:" << m_semantic_id; 440 break; 441 case vc_get_buf_resinfo: 442 os << "Fetch BufResinfo:" << m_dst; 443 break; 444 case vc_read_scratch: 445 os << "MEM_READ_SCRATCH:" << m_dst; 446 break; 447 default: 448 os << "Fetch ERROR"; 449 return; 450 } 451 452 os << ", " << *m_src; 453 454 if (m_offset) 455 os << "+" << m_offset; 456 457 os << " BUFID:" << m_buffer_id 458 << " FMT:(" << fmt_descr[m_data_format] 459 << " " << num_format_char[m_num_format] 460 << " " << endian_swap_code[m_endian_swap] 461 << ")"; 462 if (m_buffer_index_mode > 0) 463 os << " IndexMode:" << buffer_index_mode_char[m_buffer_index_mode]; 464 465 466 if (m_is_mega_fetch) 467 os << " MFC:" << m_mega_fetch_count; 468 else 469 os << " mfc*:" << m_mega_fetch_count; 470 471 if (m_flags.any()) { 472 os << " Flags:"; 473 for( int i = 0; i < vtx_unknown; ++i) { 474 if (m_flags.test(i)) 475 os << ' ' << flag_string[i]; 476 } 477 } 478} 479 480} 481