1 /* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 */ 26 27 /** 28 **************************************************************************************************** 29 * @file siaddrlib.cpp 30 * @brief Contains the implementation for the SiLib class. 31 **************************************************************************************************** 32 */ 33 34 #include "siaddrlib.h" 35 #include "si_gb_reg.h" 36 37 #include "amdgpu_asic_addr.h" 38 39 //////////////////////////////////////////////////////////////////////////////////////////////////// 40 //////////////////////////////////////////////////////////////////////////////////////////////////// 41 namespace Addr 42 { 43 44 /** 45 **************************************************************************************************** 46 * SiHwlInit 47 * 48 * @brief 49 * Creates an SiLib object. 50 * 51 * @return 52 * Returns an SiLib object pointer. 53 **************************************************************************************************** 54 */ 55 Lib* SiHwlInit(const Client* pClient) 56 { 57 return V1::SiLib::CreateObj(pClient); 58 } 59 60 namespace V1 61 { 62 63 // We don't support MSAA for equation 64 const BOOL_32 SiLib::m_EquationSupport[SiLib::TileTableSize][SiLib::MaxNumElementBytes] = 65 { 66 {TRUE, TRUE, TRUE, FALSE, FALSE}, // 0, non-AA compressed depth or any stencil 67 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 1, 2xAA/4xAA compressed depth with or without stencil 68 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 2, 8xAA compressed depth with or without stencil 69 {FALSE, TRUE, FALSE, FALSE, FALSE}, // 3, 16 bpp depth PRT (non-MSAA), don't support uncompressed depth 70 {TRUE, TRUE, TRUE, FALSE, FALSE}, // 4, 1D depth 71 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 5, 16 bpp depth PRT (4xMSAA) 72 {FALSE, FALSE, TRUE, FALSE, FALSE}, // 6, 32 bpp depth PRT (non-MSAA) 73 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 7, 32 bpp depth PRT (4xMSAA) 74 {TRUE, TRUE, TRUE, TRUE, TRUE }, // 8, Linear 75 {TRUE, TRUE, TRUE, TRUE, TRUE }, // 9, 1D display 76 {TRUE, FALSE, FALSE, FALSE, FALSE}, // 10, 8 bpp color (displayable) 77 {FALSE, TRUE, FALSE, FALSE, FALSE}, // 11, 16 bpp color (displayable) 78 {FALSE, FALSE, TRUE, TRUE, FALSE}, // 12, 32/64 bpp color (displayable) 79 {TRUE, TRUE, TRUE, TRUE, TRUE }, // 13, 1D thin 80 {TRUE, FALSE, FALSE, FALSE, FALSE}, // 14, 8 bpp color non-displayable 81 {FALSE, TRUE, FALSE, FALSE, FALSE}, // 15, 16 bpp color non-displayable 82 {FALSE, FALSE, TRUE, FALSE, FALSE}, // 16, 32 bpp color non-displayable 83 {FALSE, FALSE, FALSE, TRUE, TRUE }, // 17, 64/128 bpp color non-displayable 84 {TRUE, TRUE, TRUE, TRUE, TRUE }, // 18, 1D THICK 85 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 19, 2D XTHICK 86 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 20, 2D THICK 87 {TRUE, FALSE, FALSE, FALSE, FALSE}, // 21, 8 bpp 2D PRTs (non-MSAA) 88 {FALSE, TRUE, FALSE, FALSE, FALSE}, // 22, 16 bpp 2D PRTs (non-MSAA) 89 {FALSE, FALSE, TRUE, FALSE, FALSE}, // 23, 32 bpp 2D PRTs (non-MSAA) 90 {FALSE, FALSE, FALSE, TRUE, FALSE}, // 24, 64 bpp 2D PRTs (non-MSAA) 91 {FALSE, FALSE, FALSE, FALSE, TRUE }, // 25, 128bpp 2D PRTs (non-MSAA) 92 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 26, none 93 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 27, none 94 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 28, none 95 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 29, none 96 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 30, 64bpp 2D PRTs (4xMSAA) 97 {FALSE, FALSE, FALSE, FALSE, FALSE}, // 31, none 98 }; 99 100 /** 101 **************************************************************************************************** 102 * SiLib::SiLib 103 * 104 * @brief 105 * Constructor 106 * 107 **************************************************************************************************** 108 */ 109 SiLib::SiLib(const Client* pClient) 110 : 111 EgBasedLib(pClient), 112 m_noOfEntries(0), 113 m_numEquations(0) 114 { 115 m_class = SI_ADDRLIB; 116 memset(&m_settings, 0, sizeof(m_settings)); 117 } 118 119 /** 120 **************************************************************************************************** 121 * SiLib::~SiLib 122 * 123 * @brief 124 * Destructor 125 **************************************************************************************************** 126 */ 127 SiLib::~SiLib() 128 { 129 } 130 131 /** 132 **************************************************************************************************** 133 * SiLib::HwlGetPipes 134 * 135 * @brief 136 * Get number pipes 137 * @return 138 * num pipes 139 **************************************************************************************************** 140 */ 141 UINT_32 SiLib::HwlGetPipes( 142 const ADDR_TILEINFO* pTileInfo ///< [in] Tile info 143 ) const 144 { 145 UINT_32 numPipes; 146 147 if (pTileInfo) 148 { 149 numPipes = GetPipePerSurf(pTileInfo->pipeConfig); 150 } 151 else 152 { 153 ADDR_ASSERT_ALWAYS(); 154 numPipes = m_pipes; // Suppose we should still have a global pipes 155 } 156 157 return numPipes; 158 } 159 160 /** 161 **************************************************************************************************** 162 * SiLib::GetPipePerSurf 163 * @brief 164 * get pipe num base on inputing tileinfo->pipeconfig 165 * @return 166 * pipe number 167 **************************************************************************************************** 168 */ 169 UINT_32 SiLib::GetPipePerSurf( 170 AddrPipeCfg pipeConfig ///< [in] pipe config 171 ) const 172 { 173 UINT_32 numPipes = 0; 174 175 switch (pipeConfig) 176 { 177 case ADDR_PIPECFG_P2: 178 numPipes = 2; 179 break; 180 case ADDR_PIPECFG_P4_8x16: 181 case ADDR_PIPECFG_P4_16x16: 182 case ADDR_PIPECFG_P4_16x32: 183 case ADDR_PIPECFG_P4_32x32: 184 numPipes = 4; 185 break; 186 case ADDR_PIPECFG_P8_16x16_8x16: 187 case ADDR_PIPECFG_P8_16x32_8x16: 188 case ADDR_PIPECFG_P8_32x32_8x16: 189 case ADDR_PIPECFG_P8_16x32_16x16: 190 case ADDR_PIPECFG_P8_32x32_16x16: 191 case ADDR_PIPECFG_P8_32x32_16x32: 192 case ADDR_PIPECFG_P8_32x64_32x32: 193 numPipes = 8; 194 break; 195 case ADDR_PIPECFG_P16_32x32_8x16: 196 case ADDR_PIPECFG_P16_32x32_16x16: 197 numPipes = 16; 198 break; 199 default: 200 ADDR_ASSERT(!"Invalid pipe config"); 201 numPipes = m_pipes; 202 } 203 return numPipes; 204 } 205 206 /** 207 **************************************************************************************************** 208 * SiLib::ComputeBankEquation 209 * 210 * @brief 211 * Compute bank equation 212 * 213 * @return 214 * If equation can be computed 215 **************************************************************************************************** 216 */ 217 ADDR_E_RETURNCODE SiLib::ComputeBankEquation( 218 UINT_32 log2BytesPP, ///< [in] log2 of bytes per pixel 219 UINT_32 threshX, ///< [in] threshold for x channel 220 UINT_32 threshY, ///< [in] threshold for y channel 221 ADDR_TILEINFO* pTileInfo, ///< [in] tile info 222 ADDR_EQUATION* pEquation ///< [out] bank equation 223 ) const 224 { 225 ADDR_E_RETURNCODE retCode = ADDR_OK; 226 227 UINT_32 pipes = HwlGetPipes(pTileInfo); 228 UINT_32 bankXStart = 3 + Log2(pipes) + Log2(pTileInfo->bankWidth); 229 UINT_32 bankYStart = 3 + Log2(pTileInfo->bankHeight); 230 231 ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, log2BytesPP + bankXStart); 232 ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, log2BytesPP + bankXStart + 1); 233 ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, log2BytesPP + bankXStart + 2); 234 ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, log2BytesPP + bankXStart + 3); 235 ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, bankYStart); 236 ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, bankYStart + 1); 237 ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, bankYStart + 2); 238 ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, bankYStart + 3); 239 240 x3.value = (threshX > bankXStart) ? x3.value : 0; 241 x4.value = (threshX > bankXStart + 1) ? x4.value : 0; 242 x5.value = (threshX > bankXStart + 2) ? x5.value : 0; 243 x6.value = (threshX > bankXStart + 3) ? x6.value : 0; 244 y3.value = (threshY > bankYStart) ? y3.value : 0; 245 y4.value = (threshY > bankYStart + 1) ? y4.value : 0; 246 y5.value = (threshY > bankYStart + 2) ? y5.value : 0; 247 y6.value = (threshY > bankYStart + 3) ? y6.value : 0; 248 249 switch (pTileInfo->banks) 250 { 251 case 16: 252 if (pTileInfo->macroAspectRatio == 1) 253 { 254 pEquation->addr[0] = y6; 255 pEquation->xor1[0] = x3; 256 pEquation->addr[1] = y5; 257 pEquation->xor1[1] = y6; 258 pEquation->xor2[1] = x4; 259 pEquation->addr[2] = y4; 260 pEquation->xor1[2] = x5; 261 pEquation->addr[3] = y3; 262 pEquation->xor1[3] = x6; 263 } 264 else if (pTileInfo->macroAspectRatio == 2) 265 { 266 pEquation->addr[0] = x3; 267 pEquation->xor1[0] = y6; 268 pEquation->addr[1] = y5; 269 pEquation->xor1[1] = y6; 270 pEquation->xor2[1] = x4; 271 pEquation->addr[2] = y4; 272 pEquation->xor1[2] = x5; 273 pEquation->addr[3] = y3; 274 pEquation->xor1[3] = x6; 275 } 276 else if (pTileInfo->macroAspectRatio == 4) 277 { 278 pEquation->addr[0] = x3; 279 pEquation->xor1[0] = y6; 280 pEquation->addr[1] = x4; 281 pEquation->xor1[1] = y5; 282 pEquation->xor2[1] = y6; 283 pEquation->addr[2] = y4; 284 pEquation->xor1[2] = x5; 285 pEquation->addr[3] = y3; 286 pEquation->xor1[3] = x6; 287 } 288 else if (pTileInfo->macroAspectRatio == 8) 289 { 290 pEquation->addr[0] = x3; 291 pEquation->xor1[0] = y6; 292 pEquation->addr[1] = x4; 293 pEquation->xor1[1] = y5; 294 pEquation->xor2[1] = y6; 295 pEquation->addr[2] = x5; 296 pEquation->xor1[2] = y4; 297 pEquation->addr[3] = y3; 298 pEquation->xor1[3] = x6; 299 } 300 else 301 { 302 ADDR_ASSERT_ALWAYS(); 303 } 304 pEquation->numBits = 4; 305 break; 306 case 8: 307 if (pTileInfo->macroAspectRatio == 1) 308 { 309 pEquation->addr[0] = y5; 310 pEquation->xor1[0] = x3; 311 pEquation->addr[1] = y4; 312 pEquation->xor1[1] = y5; 313 pEquation->xor2[1] = x4; 314 pEquation->addr[2] = y3; 315 pEquation->xor1[2] = x5; 316 } 317 else if (pTileInfo->macroAspectRatio == 2) 318 { 319 pEquation->addr[0] = x3; 320 pEquation->xor1[0] = y5; 321 pEquation->addr[1] = y4; 322 pEquation->xor1[1] = y5; 323 pEquation->xor2[1] = x4; 324 pEquation->addr[2] = y3; 325 pEquation->xor1[2] = x5; 326 } 327 else if (pTileInfo->macroAspectRatio == 4) 328 { 329 pEquation->addr[0] = x3; 330 pEquation->xor1[0] = y5; 331 pEquation->addr[1] = x4; 332 pEquation->xor1[1] = y4; 333 pEquation->xor2[1] = y5; 334 pEquation->addr[2] = y3; 335 pEquation->xor1[2] = x5; 336 } 337 else 338 { 339 ADDR_ASSERT_ALWAYS(); 340 } 341 pEquation->numBits = 3; 342 break; 343 case 4: 344 if (pTileInfo->macroAspectRatio == 1) 345 { 346 pEquation->addr[0] = y4; 347 pEquation->xor1[0] = x3; 348 pEquation->addr[1] = y3; 349 pEquation->xor1[1] = x4; 350 } 351 else if (pTileInfo->macroAspectRatio == 2) 352 { 353 pEquation->addr[0] = x3; 354 pEquation->xor1[0] = y4; 355 pEquation->addr[1] = y3; 356 pEquation->xor1[1] = x4; 357 } 358 else 359 { 360 pEquation->addr[0] = x3; 361 pEquation->xor1[0] = y4; 362 pEquation->addr[1] = x4; 363 pEquation->xor1[1] = y3; 364 } 365 pEquation->numBits = 2; 366 break; 367 case 2: 368 if (pTileInfo->macroAspectRatio == 1) 369 { 370 pEquation->addr[0] = y3; 371 pEquation->xor1[0] = x3; 372 } 373 else 374 { 375 pEquation->addr[0] = x3; 376 pEquation->xor1[0] = y3; 377 } 378 pEquation->numBits = 1; 379 break; 380 default: 381 pEquation->numBits = 0; 382 retCode = ADDR_NOTSUPPORTED; 383 ADDR_ASSERT_ALWAYS(); 384 break; 385 } 386 387 for (UINT_32 i = 0; i < pEquation->numBits; i++) 388 { 389 if (pEquation->addr[i].value == 0) 390 { 391 if (pEquation->xor1[i].value == 0) 392 { 393 // 00X -> X00 394 pEquation->addr[i].value = pEquation->xor2[i].value; 395 pEquation->xor2[i].value = 0; 396 } 397 else 398 { 399 pEquation->addr[i].value = pEquation->xor1[i].value; 400 401 if (pEquation->xor2[i].value != 0) 402 { 403 // 0XY -> XY0 404 pEquation->xor1[i].value = pEquation->xor2[i].value; 405 pEquation->xor2[i].value = 0; 406 } 407 else 408 { 409 // 0X0 -> X00 410 pEquation->xor1[i].value = 0; 411 } 412 } 413 } 414 else if (pEquation->xor1[i].value == 0) 415 { 416 if (pEquation->xor2[i].value != 0) 417 { 418 // X0Y -> XY0 419 pEquation->xor1[i].value = pEquation->xor2[i].value; 420 pEquation->xor2[i].value = 0; 421 } 422 } 423 } 424 425 if ((pTileInfo->bankWidth == 1) && 426 ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || 427 (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32))) 428 { 429 retCode = ADDR_NOTSUPPORTED; 430 } 431 432 return retCode; 433 } 434 435 /** 436 **************************************************************************************************** 437 * SiLib::ComputePipeEquation 438 * 439 * @brief 440 * Compute pipe equation 441 * 442 * @return 443 * If equation can be computed 444 **************************************************************************************************** 445 */ 446 ADDR_E_RETURNCODE SiLib::ComputePipeEquation( 447 UINT_32 log2BytesPP, ///< [in] Log2 of bytes per pixel 448 UINT_32 threshX, ///< [in] Threshold for X channel 449 UINT_32 threshY, ///< [in] Threshold for Y channel 450 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 451 ADDR_EQUATION* pEquation ///< [out] Pipe configure 452 ) const 453 { 454 ADDR_E_RETURNCODE retCode = ADDR_OK; 455 456 ADDR_CHANNEL_SETTING* pAddr = pEquation->addr; 457 ADDR_CHANNEL_SETTING* pXor1 = pEquation->xor1; 458 ADDR_CHANNEL_SETTING* pXor2 = pEquation->xor2; 459 460 ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, 3 + log2BytesPP); 461 ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, 4 + log2BytesPP); 462 ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, 5 + log2BytesPP); 463 ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, 6 + log2BytesPP); 464 ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, 3); 465 ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, 4); 466 ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, 5); 467 ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, 6); 468 469 x3.value = (threshX > 3) ? x3.value : 0; 470 x4.value = (threshX > 4) ? x4.value : 0; 471 x5.value = (threshX > 5) ? x5.value : 0; 472 x6.value = (threshX > 6) ? x6.value : 0; 473 y3.value = (threshY > 3) ? y3.value : 0; 474 y4.value = (threshY > 4) ? y4.value : 0; 475 y5.value = (threshY > 5) ? y5.value : 0; 476 y6.value = (threshY > 6) ? y6.value : 0; 477 478 switch (pTileInfo->pipeConfig) 479 { 480 case ADDR_PIPECFG_P2: 481 pAddr[0] = x3; 482 pXor1[0] = y3; 483 pEquation->numBits = 1; 484 break; 485 case ADDR_PIPECFG_P4_8x16: 486 pAddr[0] = x4; 487 pXor1[0] = y3; 488 pAddr[1] = x3; 489 pXor1[1] = y4; 490 pEquation->numBits = 2; 491 break; 492 case ADDR_PIPECFG_P4_16x16: 493 pAddr[0] = x3; 494 pXor1[0] = y3; 495 pXor2[0] = x4; 496 pAddr[1] = x4; 497 pXor1[1] = y4; 498 pEquation->numBits = 2; 499 break; 500 case ADDR_PIPECFG_P4_16x32: 501 pAddr[0] = x3; 502 pXor1[0] = y3; 503 pXor2[0] = x4; 504 pAddr[1] = x4; 505 pXor1[1] = y5; 506 pEquation->numBits = 2; 507 break; 508 case ADDR_PIPECFG_P4_32x32: 509 pAddr[0] = x3; 510 pXor1[0] = y3; 511 pXor2[0] = x5; 512 pAddr[1] = x5; 513 pXor1[1] = y5; 514 pEquation->numBits = 2; 515 break; 516 case ADDR_PIPECFG_P8_16x16_8x16: 517 pAddr[0] = x4; 518 pXor1[0] = y3; 519 pXor2[0] = x5; 520 pAddr[1] = x3; 521 pXor1[1] = y5; 522 pEquation->numBits = 3; 523 break; 524 case ADDR_PIPECFG_P8_16x32_8x16: 525 pAddr[0] = x4; 526 pXor1[0] = y3; 527 pXor2[0] = x5; 528 pAddr[1] = x3; 529 pXor1[1] = y4; 530 pAddr[2] = x4; 531 pXor1[2] = y5; 532 pEquation->numBits = 3; 533 break; 534 case ADDR_PIPECFG_P8_16x32_16x16: 535 pAddr[0] = x3; 536 pXor1[0] = y3; 537 pXor2[0] = x4; 538 pAddr[1] = x5; 539 pXor1[1] = y4; 540 pAddr[2] = x4; 541 pXor1[2] = y5; 542 pEquation->numBits = 3; 543 break; 544 case ADDR_PIPECFG_P8_32x32_8x16: 545 pAddr[0] = x4; 546 pXor1[0] = y3; 547 pXor2[0] = x5; 548 pAddr[1] = x3; 549 pXor1[1] = y4; 550 pAddr[2] = x5; 551 pXor1[2] = y5; 552 pEquation->numBits = 3; 553 break; 554 case ADDR_PIPECFG_P8_32x32_16x16: 555 pAddr[0] = x3; 556 pXor1[0] = y3; 557 pXor2[0] = x4; 558 pAddr[1] = x4; 559 pXor1[1] = y4; 560 pAddr[2] = x5; 561 pXor1[2] = y5; 562 pEquation->numBits = 3; 563 break; 564 case ADDR_PIPECFG_P8_32x32_16x32: 565 pAddr[0] = x3; 566 pXor1[0] = y3; 567 pXor2[0] = x4; 568 pAddr[1] = x4; 569 pXor1[1] = y6; 570 pAddr[2] = x5; 571 pXor1[2] = y5; 572 pEquation->numBits = 3; 573 break; 574 case ADDR_PIPECFG_P8_32x64_32x32: 575 pAddr[0] = x3; 576 pXor1[0] = y3; 577 pXor2[0] = x5; 578 pAddr[1] = x6; 579 pXor1[1] = y5; 580 pAddr[2] = x5; 581 pXor1[2] = y6; 582 pEquation->numBits = 3; 583 break; 584 case ADDR_PIPECFG_P16_32x32_8x16: 585 pAddr[0] = x4; 586 pXor1[0] = y3; 587 pAddr[1] = x3; 588 pXor1[1] = y4; 589 pAddr[2] = x5; 590 pXor1[2] = y6; 591 pAddr[3] = x6; 592 pXor1[3] = y5; 593 pEquation->numBits = 4; 594 break; 595 case ADDR_PIPECFG_P16_32x32_16x16: 596 pAddr[0] = x3; 597 pXor1[0] = y3; 598 pXor2[0] = x4; 599 pAddr[1] = x4; 600 pXor1[1] = y4; 601 pAddr[2] = x5; 602 pXor1[2] = y6; 603 pAddr[3] = x6; 604 pXor1[3] = y5; 605 pEquation->numBits = 4; 606 break; 607 default: 608 ADDR_UNHANDLED_CASE(); 609 pEquation->numBits = 0; 610 retCode = ADDR_NOTSUPPORTED; 611 break; 612 } 613 614 for (UINT_32 i = 0; i < pEquation->numBits; i++) 615 { 616 if (pAddr[i].value == 0) 617 { 618 if (pXor1[i].value == 0) 619 { 620 pAddr[i].value = pXor2[i].value; 621 } 622 else 623 { 624 pAddr[i].value = pXor1[i].value; 625 pXor1[i].value = 0; 626 } 627 } 628 } 629 630 return retCode; 631 } 632 633 /** 634 **************************************************************************************************** 635 * SiLib::ComputePipeFromCoord 636 * 637 * @brief 638 * Compute pipe number from coordinates 639 * @return 640 * Pipe number 641 **************************************************************************************************** 642 */ 643 UINT_32 SiLib::ComputePipeFromCoord( 644 UINT_32 x, ///< [in] x coordinate 645 UINT_32 y, ///< [in] y coordinate 646 UINT_32 slice, ///< [in] slice index 647 AddrTileMode tileMode, ///< [in] tile mode 648 UINT_32 pipeSwizzle, ///< [in] pipe swizzle 649 BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored 650 ADDR_TILEINFO* pTileInfo ///< [in] Tile info 651 ) const 652 { 653 UINT_32 pipe; 654 UINT_32 pipeBit0 = 0; 655 UINT_32 pipeBit1 = 0; 656 UINT_32 pipeBit2 = 0; 657 UINT_32 pipeBit3 = 0; 658 UINT_32 sliceRotation; 659 UINT_32 numPipes = 0; 660 661 UINT_32 tx = x / MicroTileWidth; 662 UINT_32 ty = y / MicroTileHeight; 663 UINT_32 x3 = _BIT(tx,0); 664 UINT_32 x4 = _BIT(tx,1); 665 UINT_32 x5 = _BIT(tx,2); 666 UINT_32 x6 = _BIT(tx,3); 667 UINT_32 y3 = _BIT(ty,0); 668 UINT_32 y4 = _BIT(ty,1); 669 UINT_32 y5 = _BIT(ty,2); 670 UINT_32 y6 = _BIT(ty,3); 671 672 switch (pTileInfo->pipeConfig) 673 { 674 case ADDR_PIPECFG_P2: 675 pipeBit0 = x3 ^ y3; 676 numPipes = 2; 677 break; 678 case ADDR_PIPECFG_P4_8x16: 679 pipeBit0 = x4 ^ y3; 680 pipeBit1 = x3 ^ y4; 681 numPipes = 4; 682 break; 683 case ADDR_PIPECFG_P4_16x16: 684 pipeBit0 = x3 ^ y3 ^ x4; 685 pipeBit1 = x4 ^ y4; 686 numPipes = 4; 687 break; 688 case ADDR_PIPECFG_P4_16x32: 689 pipeBit0 = x3 ^ y3 ^ x4; 690 pipeBit1 = x4 ^ y5; 691 numPipes = 4; 692 break; 693 case ADDR_PIPECFG_P4_32x32: 694 pipeBit0 = x3 ^ y3 ^ x5; 695 pipeBit1 = x5 ^ y5; 696 numPipes = 4; 697 break; 698 case ADDR_PIPECFG_P8_16x16_8x16: 699 pipeBit0 = x4 ^ y3 ^ x5; 700 pipeBit1 = x3 ^ y5; 701 numPipes = 8; 702 break; 703 case ADDR_PIPECFG_P8_16x32_8x16: 704 pipeBit0 = x4 ^ y3 ^ x5; 705 pipeBit1 = x3 ^ y4; 706 pipeBit2 = x4 ^ y5; 707 numPipes = 8; 708 break; 709 case ADDR_PIPECFG_P8_16x32_16x16: 710 pipeBit0 = x3 ^ y3 ^ x4; 711 pipeBit1 = x5 ^ y4; 712 pipeBit2 = x4 ^ y5; 713 numPipes = 8; 714 break; 715 case ADDR_PIPECFG_P8_32x32_8x16: 716 pipeBit0 = x4 ^ y3 ^ x5; 717 pipeBit1 = x3 ^ y4; 718 pipeBit2 = x5 ^ y5; 719 numPipes = 8; 720 break; 721 case ADDR_PIPECFG_P8_32x32_16x16: 722 pipeBit0 = x3 ^ y3 ^ x4; 723 pipeBit1 = x4 ^ y4; 724 pipeBit2 = x5 ^ y5; 725 numPipes = 8; 726 break; 727 case ADDR_PIPECFG_P8_32x32_16x32: 728 pipeBit0 = x3 ^ y3 ^ x4; 729 pipeBit1 = x4 ^ y6; 730 pipeBit2 = x5 ^ y5; 731 numPipes = 8; 732 break; 733 case ADDR_PIPECFG_P8_32x64_32x32: 734 pipeBit0 = x3 ^ y3 ^ x5; 735 pipeBit1 = x6 ^ y5; 736 pipeBit2 = x5 ^ y6; 737 numPipes = 8; 738 break; 739 case ADDR_PIPECFG_P16_32x32_8x16: 740 pipeBit0 = x4 ^ y3; 741 pipeBit1 = x3 ^ y4; 742 pipeBit2 = x5 ^ y6; 743 pipeBit3 = x6 ^ y5; 744 numPipes = 16; 745 break; 746 case ADDR_PIPECFG_P16_32x32_16x16: 747 pipeBit0 = x3 ^ y3 ^ x4; 748 pipeBit1 = x4 ^ y4; 749 pipeBit2 = x5 ^ y6; 750 pipeBit3 = x6 ^ y5; 751 numPipes = 16; 752 break; 753 default: 754 ADDR_UNHANDLED_CASE(); 755 break; 756 } 757 pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3); 758 759 UINT_32 microTileThickness = Thickness(tileMode); 760 761 // 762 // Apply pipe rotation for the slice. 763 // 764 switch (tileMode) 765 { 766 case ADDR_TM_3D_TILED_THIN1: //fall through thin 767 case ADDR_TM_3D_TILED_THICK: //fall through thick 768 case ADDR_TM_3D_TILED_XTHICK: 769 sliceRotation = 770 Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness); 771 break; 772 default: 773 sliceRotation = 0; 774 break; 775 } 776 pipeSwizzle += sliceRotation; 777 pipeSwizzle &= (numPipes - 1); 778 779 pipe = pipe ^ pipeSwizzle; 780 781 return pipe; 782 } 783 784 /** 785 **************************************************************************************************** 786 * SiLib::ComputeTileCoordFromPipeAndElemIdx 787 * 788 * @brief 789 * Compute (x,y) of a tile within a macro tile from address 790 * @return 791 * Pipe number 792 **************************************************************************************************** 793 */ 794 VOID SiLib::ComputeTileCoordFromPipeAndElemIdx( 795 UINT_32 elemIdx, ///< [in] per pipe element index within a macro tile 796 UINT_32 pipe, ///< [in] pipe index 797 AddrPipeCfg pipeCfg, ///< [in] pipe config 798 UINT_32 pitchInMacroTile, ///< [in] surface pitch in macro tile 799 UINT_32 x, ///< [in] x coordinate of the (0,0) tile in a macro tile 800 UINT_32 y, ///< [in] y coordinate of the (0,0) tile in a macro tile 801 UINT_32* pX, ///< [out] x coordinate 802 UINT_32* pY ///< [out] y coordinate 803 ) const 804 { 805 UINT_32 pipebit0 = _BIT(pipe,0); 806 UINT_32 pipebit1 = _BIT(pipe,1); 807 UINT_32 pipebit2 = _BIT(pipe,2); 808 UINT_32 pipebit3 = _BIT(pipe,3); 809 UINT_32 elemIdx0 = _BIT(elemIdx,0); 810 UINT_32 elemIdx1 = _BIT(elemIdx,1); 811 UINT_32 elemIdx2 = _BIT(elemIdx,2); 812 UINT_32 x3 = 0; 813 UINT_32 x4 = 0; 814 UINT_32 x5 = 0; 815 UINT_32 x6 = 0; 816 UINT_32 y3 = 0; 817 UINT_32 y4 = 0; 818 UINT_32 y5 = 0; 819 UINT_32 y6 = 0; 820 821 switch(pipeCfg) 822 { 823 case ADDR_PIPECFG_P2: 824 x4 = elemIdx2; 825 y4 = elemIdx1 ^ x4; 826 y3 = elemIdx0 ^ x4; 827 x3 = pipebit0 ^ y3; 828 *pY = Bits2Number(2, y4, y3); 829 *pX = Bits2Number(2, x4, x3); 830 break; 831 case ADDR_PIPECFG_P4_8x16: 832 x4 = elemIdx1; 833 y4 = elemIdx0 ^ x4; 834 x3 = pipebit1 ^ y4; 835 y3 = pipebit0 ^ x4; 836 *pY = Bits2Number(2, y4, y3); 837 *pX = Bits2Number(2, x4, x3); 838 break; 839 case ADDR_PIPECFG_P4_16x16: 840 x4 = elemIdx1; 841 y3 = elemIdx0 ^ x4; 842 y4 = pipebit1 ^ x4; 843 x3 = pipebit0 ^ y3 ^ x4; 844 *pY = Bits2Number(2, y4, y3); 845 *pX = Bits2Number(2, x4, x3); 846 break; 847 case ADDR_PIPECFG_P4_16x32: 848 x3 = elemIdx0 ^ pipebit0; 849 y5 = _BIT(y,5); 850 x4 = pipebit1 ^ y5; 851 y3 = pipebit0 ^ x3 ^ x4; 852 y4 = elemIdx1 ^ x4; 853 *pY = Bits2Number(2, y4, y3); 854 *pX = Bits2Number(2, x4, x3); 855 break; 856 case ADDR_PIPECFG_P4_32x32: 857 x4 = elemIdx2; 858 y3 = elemIdx0 ^ x4; 859 y4 = elemIdx1 ^ x4; 860 if((pitchInMacroTile % 2) == 0) 861 { //even 862 y5 = _BIT(y,5); 863 x5 = pipebit1 ^ y5; 864 x3 = pipebit0 ^ y3 ^ x5; 865 *pY = Bits2Number(2, y4, y3); 866 *pX = Bits2Number(3, x5, x4, x3); 867 } 868 else 869 { //odd 870 x5 = _BIT(x,5); 871 x3 = pipebit0 ^ y3 ^ x5; 872 *pY = Bits2Number(2, y4, y3); 873 *pX = Bits2Number(2, x4, x3); 874 } 875 break; 876 case ADDR_PIPECFG_P8_16x16_8x16: 877 x4 = elemIdx0; 878 y5 = _BIT(y,5); 879 x5 = _BIT(x,5); 880 x3 = pipebit1 ^ y5; 881 y4 = pipebit2 ^ x4; 882 y3 = pipebit0 ^ x5 ^ x4; 883 *pY = Bits2Number(2, y4, y3); 884 *pX = Bits2Number(2, x4, x3); 885 break; 886 case ADDR_PIPECFG_P8_16x32_8x16: 887 x3 = elemIdx0; 888 y4 = pipebit1 ^ x3; 889 y5 = _BIT(y,5); 890 x5 = _BIT(x,5); 891 x4 = pipebit2 ^ y5; 892 y3 = pipebit0 ^ x4 ^ x5; 893 *pY = Bits2Number(2, y4, y3); 894 *pX = Bits2Number(2, x4, x3); 895 break; 896 case ADDR_PIPECFG_P8_32x32_8x16: 897 x4 = elemIdx1; 898 y4 = elemIdx0 ^ x4; 899 x3 = pipebit1 ^ y4; 900 if((pitchInMacroTile % 2) == 0) 901 { //even 902 y5 = _BIT(y,5); 903 x5 = _BIT(x,5); 904 x5 = pipebit2 ^ y5; 905 y3 = pipebit0 ^ x4 ^ x5; 906 *pY = Bits2Number(2, y4, y3); 907 *pX = Bits2Number(3, x5, x4, x3); 908 } 909 else 910 { //odd 911 x5 = _BIT(x,5); 912 y3 = pipebit0 ^ x4 ^ x5; 913 *pY = Bits2Number(2, y4, y3); 914 *pX = Bits2Number(2, x4, x3); 915 } 916 break; 917 case ADDR_PIPECFG_P8_16x32_16x16: 918 x3 = elemIdx0; 919 x5 = _BIT(x,5); 920 y5 = _BIT(y,5); 921 x4 = pipebit2 ^ y5; 922 y4 = pipebit1 ^ x5; 923 y3 = pipebit0 ^ x3 ^ x4; 924 *pY = Bits2Number(2, y4, y3); 925 *pX = Bits2Number(2, x4, x3); 926 break; 927 case ADDR_PIPECFG_P8_32x32_16x16: 928 x4 = elemIdx1; 929 y3 = elemIdx0 ^ x4; 930 x3 = y3^x4^pipebit0; 931 y4 = pipebit1 ^ x4; 932 if((pitchInMacroTile % 2) == 0) 933 { //even 934 y5 = _BIT(y,5); 935 x5 = pipebit2 ^ y5; 936 *pY = Bits2Number(2, y4, y3); 937 *pX = Bits2Number(3, x5, x4, x3); 938 } 939 else 940 { //odd 941 *pY = Bits2Number(2, y4, y3); 942 *pX = Bits2Number(2, x4, x3); 943 } 944 break; 945 case ADDR_PIPECFG_P8_32x32_16x32: 946 if((pitchInMacroTile % 2) == 0) 947 { //even 948 y5 = _BIT(y,5); 949 y6 = _BIT(y,6); 950 x4 = pipebit1 ^ y6; 951 y3 = elemIdx0 ^ x4; 952 y4 = elemIdx1 ^ x4; 953 x3 = pipebit0 ^ y3 ^ x4; 954 x5 = pipebit2 ^ y5; 955 *pY = Bits2Number(2, y4, y3); 956 *pX = Bits2Number(3, x5, x4, x3); 957 } 958 else 959 { //odd 960 y6 = _BIT(y,6); 961 x4 = pipebit1 ^ y6; 962 y3 = elemIdx0 ^ x4; 963 y4 = elemIdx1 ^ x4; 964 x3 = pipebit0 ^ y3 ^ x4; 965 *pY = Bits2Number(2, y4, y3); 966 *pX = Bits2Number(2, x4, x3); 967 } 968 break; 969 case ADDR_PIPECFG_P8_32x64_32x32: 970 x4 = elemIdx2; 971 y3 = elemIdx0 ^ x4; 972 y4 = elemIdx1 ^ x4; 973 if((pitchInMacroTile % 4) == 0) 974 { //multiple of 4 975 y5 = _BIT(y,5); 976 y6 = _BIT(y,6); 977 x5 = pipebit2 ^ y6; 978 x6 = pipebit1 ^ y5; 979 x3 = pipebit0 ^ y3 ^ x5; 980 *pY = Bits2Number(2, y4, y3); 981 *pX = Bits2Number(4, x6, x5, x4, x3); 982 } 983 else 984 { 985 y6 = _BIT(y,6); 986 x5 = pipebit2 ^ y6; 987 x3 = pipebit0 ^ y3 ^ x5; 988 *pY = Bits2Number(2, y4, y3); 989 *pX = Bits2Number(3, x5, x4, x3); 990 } 991 break; 992 case ADDR_PIPECFG_P16_32x32_8x16: 993 x4 = elemIdx1; 994 y4 = elemIdx0 ^ x4; 995 y3 = pipebit0 ^ x4; 996 x3 = pipebit1 ^ y4; 997 if((pitchInMacroTile % 4) == 0) 998 { //multiple of 4 999 y5 = _BIT(y,5); 1000 y6 = _BIT(y,6); 1001 x5 = pipebit2 ^ y6; 1002 x6 = pipebit3 ^ y5; 1003 *pY = Bits2Number(2, y4, y3); 1004 *pX = Bits2Number(4, x6, x5,x4, x3); 1005 } 1006 else 1007 { 1008 y6 = _BIT(y,6); 1009 x5 = pipebit2 ^ y6; 1010 *pY = Bits2Number(2, y4, y3); 1011 *pX = Bits2Number(3, x5, x4, x3); 1012 } 1013 break; 1014 case ADDR_PIPECFG_P16_32x32_16x16: 1015 x4 = elemIdx1; 1016 y3 = elemIdx0 ^ x4; 1017 y4 = pipebit1 ^ x4; 1018 x3 = pipebit0 ^ y3 ^ x4; 1019 if((pitchInMacroTile % 4) == 0) 1020 { //multiple of 4 1021 y5 = _BIT(y,5); 1022 y6 = _BIT(y,6); 1023 x5 = pipebit2 ^ y6; 1024 x6 = pipebit3 ^ y5; 1025 *pY = Bits2Number(2, y4, y3); 1026 *pX = Bits2Number(4, x6, x5, x4, x3); 1027 } 1028 else 1029 { 1030 y6 = _BIT(y,6); 1031 x5 = pipebit2 ^ y6; 1032 *pY = Bits2Number(2, y4, y3); 1033 *pX = Bits2Number(3, x5, x4, x3); 1034 } 1035 break; 1036 default: 1037 ADDR_UNHANDLED_CASE(); 1038 } 1039 } 1040 1041 /** 1042 **************************************************************************************************** 1043 * SiLib::TileCoordToMaskElementIndex 1044 * 1045 * @brief 1046 * Compute element index from coordinates in tiles 1047 * @return 1048 * Element index 1049 **************************************************************************************************** 1050 */ 1051 UINT_32 SiLib::TileCoordToMaskElementIndex( 1052 UINT_32 tx, ///< [in] x coord, in Tiles 1053 UINT_32 ty, ///< [in] y coord, in Tiles 1054 AddrPipeCfg pipeConfig, ///< [in] pipe config 1055 UINT_32* macroShift, ///< [out] macro shift 1056 UINT_32* elemIdxBits ///< [out] tile offset bits 1057 ) const 1058 { 1059 UINT_32 elemIdx = 0; 1060 UINT_32 elemIdx0, elemIdx1, elemIdx2; 1061 UINT_32 tx0, tx1; 1062 UINT_32 ty0, ty1; 1063 1064 tx0 = _BIT(tx,0); 1065 tx1 = _BIT(tx,1); 1066 ty0 = _BIT(ty,0); 1067 ty1 = _BIT(ty,1); 1068 1069 switch(pipeConfig) 1070 { 1071 case ADDR_PIPECFG_P2: 1072 *macroShift = 3; 1073 *elemIdxBits =3; 1074 elemIdx2 = tx1; 1075 elemIdx1 = tx1 ^ ty1; 1076 elemIdx0 = tx1 ^ ty0; 1077 elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0); 1078 break; 1079 case ADDR_PIPECFG_P4_8x16: 1080 *macroShift = 2; 1081 *elemIdxBits =2; 1082 elemIdx1 = tx1; 1083 elemIdx0 = tx1 ^ ty1; 1084 elemIdx = Bits2Number(2,elemIdx1,elemIdx0); 1085 break; 1086 case ADDR_PIPECFG_P4_16x16: 1087 *macroShift = 2; 1088 *elemIdxBits =2; 1089 elemIdx0 = tx1^ty0; 1090 elemIdx1 = tx1; 1091 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1092 break; 1093 case ADDR_PIPECFG_P4_16x32: 1094 *macroShift = 2; 1095 *elemIdxBits =2; 1096 elemIdx0 = tx1^ty0; 1097 elemIdx1 = tx1^ty1; 1098 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1099 break; 1100 case ADDR_PIPECFG_P4_32x32: 1101 *macroShift = 2; 1102 *elemIdxBits =3; 1103 elemIdx0 = tx1^ty0; 1104 elemIdx1 = tx1^ty1; 1105 elemIdx2 = tx1; 1106 elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); 1107 break; 1108 case ADDR_PIPECFG_P8_16x16_8x16: 1109 *macroShift = 1; 1110 *elemIdxBits =1; 1111 elemIdx0 = tx1; 1112 elemIdx = elemIdx0; 1113 break; 1114 case ADDR_PIPECFG_P8_16x32_8x16: 1115 *macroShift = 1; 1116 *elemIdxBits =1; 1117 elemIdx0 = tx0; 1118 elemIdx = elemIdx0; 1119 break; 1120 case ADDR_PIPECFG_P8_32x32_8x16: 1121 *macroShift = 1; 1122 *elemIdxBits =2; 1123 elemIdx1 = tx1; 1124 elemIdx0 = tx1^ty1; 1125 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1126 break; 1127 case ADDR_PIPECFG_P8_16x32_16x16: 1128 *macroShift = 1; 1129 *elemIdxBits =1; 1130 elemIdx0 = tx0; 1131 elemIdx = elemIdx0; 1132 break; 1133 case ADDR_PIPECFG_P8_32x32_16x16: 1134 *macroShift = 1; 1135 *elemIdxBits =2; 1136 elemIdx0 = tx1^ty0; 1137 elemIdx1 = tx1; 1138 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1139 break; 1140 case ADDR_PIPECFG_P8_32x32_16x32: 1141 *macroShift = 1; 1142 *elemIdxBits =2; 1143 elemIdx0 = tx1^ty0; 1144 elemIdx1 = tx1^ty1; 1145 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1146 break; 1147 case ADDR_PIPECFG_P8_32x64_32x32: 1148 *macroShift = 1; 1149 *elemIdxBits =3; 1150 elemIdx0 = tx1^ty0; 1151 elemIdx1 = tx1^ty1; 1152 elemIdx2 = tx1; 1153 elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); 1154 break; 1155 case ADDR_PIPECFG_P16_32x32_8x16: 1156 *macroShift = 0; 1157 *elemIdxBits =2; 1158 elemIdx0 = tx1^ty1; 1159 elemIdx1 = tx1; 1160 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1161 break; 1162 case ADDR_PIPECFG_P16_32x32_16x16: 1163 *macroShift = 0; 1164 *elemIdxBits =2; 1165 elemIdx0 = tx1^ty0; 1166 elemIdx1 = tx1; 1167 elemIdx = Bits2Number(2, elemIdx1, elemIdx0); 1168 break; 1169 default: 1170 ADDR_UNHANDLED_CASE(); 1171 break; 1172 } 1173 1174 return elemIdx; 1175 } 1176 1177 /** 1178 **************************************************************************************************** 1179 * SiLib::HwlComputeTileDataWidthAndHeightLinear 1180 * 1181 * @brief 1182 * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout 1183 * 1184 * @return 1185 * N/A 1186 * 1187 * @note 1188 * MacroWidth and macroHeight are measured in pixels 1189 **************************************************************************************************** 1190 */ 1191 VOID SiLib::HwlComputeTileDataWidthAndHeightLinear( 1192 UINT_32* pMacroWidth, ///< [out] macro tile width 1193 UINT_32* pMacroHeight, ///< [out] macro tile height 1194 UINT_32 bpp, ///< [in] bits per pixel 1195 ADDR_TILEINFO* pTileInfo ///< [in] tile info 1196 ) const 1197 { 1198 ADDR_ASSERT(pTileInfo != NULL); 1199 UINT_32 macroWidth; 1200 UINT_32 macroHeight; 1201 1202 /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles 1203 /// but for P8_32x64_32x32, it must be padded out to 8 tiles 1204 /// Actually there are more pipe configs which need 8-tile padding but SI family 1205 /// has a bug which is fixed in CI family 1206 if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) || 1207 (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || 1208 (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16)) 1209 { 1210 macroWidth = 8*MicroTileWidth; 1211 macroHeight = 8*MicroTileHeight; 1212 } 1213 else 1214 { 1215 macroWidth = 4*MicroTileWidth; 1216 macroHeight = 4*MicroTileHeight; 1217 } 1218 1219 *pMacroWidth = macroWidth; 1220 *pMacroHeight = macroHeight; 1221 } 1222 1223 /** 1224 **************************************************************************************************** 1225 * SiLib::HwlComputeHtileBytes 1226 * 1227 * @brief 1228 * Compute htile size in bytes 1229 * 1230 * @return 1231 * Htile size in bytes 1232 **************************************************************************************************** 1233 */ 1234 UINT_64 SiLib::HwlComputeHtileBytes( 1235 UINT_32 pitch, ///< [in] pitch 1236 UINT_32 height, ///< [in] height 1237 UINT_32 bpp, ///< [in] bits per pixel 1238 BOOL_32 isLinear, ///< [in] if it is linear mode 1239 UINT_32 numSlices, ///< [in] number of slices 1240 UINT_64* pSliceBytes, ///< [out] bytes per slice 1241 UINT_32 baseAlign ///< [in] base alignments 1242 ) const 1243 { 1244 return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign); 1245 } 1246 1247 /** 1248 **************************************************************************************************** 1249 * SiLib::HwlComputeXmaskAddrFromCoord 1250 * 1251 * @brief 1252 * Compute address from coordinates for htile/cmask 1253 * @return 1254 * Byte address 1255 **************************************************************************************************** 1256 */ 1257 UINT_64 SiLib::HwlComputeXmaskAddrFromCoord( 1258 UINT_32 pitch, ///< [in] pitch 1259 UINT_32 height, ///< [in] height 1260 UINT_32 x, ///< [in] x coord 1261 UINT_32 y, ///< [in] y coord 1262 UINT_32 slice, ///< [in] slice/depth index 1263 UINT_32 numSlices, ///< [in] number of slices 1264 UINT_32 factor, ///< [in] factor that indicates cmask(2) or htile(1) 1265 BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout 1266 BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 1267 BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 1268 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 1269 UINT_32* pBitPosition ///< [out] bit position inside a byte 1270 ) const 1271 { 1272 UINT_32 tx = x / MicroTileWidth; 1273 UINT_32 ty = y / MicroTileHeight; 1274 UINT_32 newPitch; 1275 UINT_32 newHeight; 1276 UINT_64 totalBytes; 1277 UINT_32 macroWidth; 1278 UINT_32 macroHeight; 1279 UINT_64 pSliceBytes; 1280 UINT_32 pBaseAlign; 1281 UINT_32 tileNumPerPipe; 1282 UINT_32 elemBits; 1283 1284 if (factor == 2) //CMASK 1285 { 1286 ADDR_CMASK_FLAGS flags = {{0}}; 1287 1288 tileNumPerPipe = 256; 1289 1290 ComputeCmaskInfo(flags, 1291 pitch, 1292 height, 1293 numSlices, 1294 isLinear, 1295 pTileInfo, 1296 &newPitch, 1297 &newHeight, 1298 &totalBytes, 1299 ¯oWidth, 1300 ¯oHeight); 1301 elemBits = CmaskElemBits; 1302 } 1303 else //HTile 1304 { 1305 ADDR_HTILE_FLAGS flags = {{0}}; 1306 1307 tileNumPerPipe = 512; 1308 1309 ComputeHtileInfo(flags, 1310 pitch, 1311 height, 1312 numSlices, 1313 isLinear, 1314 TRUE, 1315 TRUE, 1316 pTileInfo, 1317 &newPitch, 1318 &newHeight, 1319 &totalBytes, 1320 ¯oWidth, 1321 ¯oHeight, 1322 &pSliceBytes, 1323 &pBaseAlign); 1324 elemBits = 32; 1325 } 1326 1327 const UINT_32 pitchInTile = newPitch / MicroTileWidth; 1328 const UINT_32 heightInTile = newHeight / MicroTileWidth; 1329 UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies. 1330 UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies. 1331 UINT_32 microX; 1332 UINT_32 microY; 1333 UINT_64 microOffset; 1334 UINT_32 microShift; 1335 UINT_64 totalOffset; 1336 UINT_32 elemIdxBits; 1337 UINT_32 elemIdx = 1338 TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, µShift, &elemIdxBits); 1339 1340 UINT_32 numPipes = HwlGetPipes(pTileInfo); 1341 1342 if (isLinear) 1343 { //linear addressing 1344 // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full 1345 // slice memory foot print instead of divided by numPipes. 1346 microX = tx / 4; // Macro Tile is 4x4 1347 microY = ty / 4 ; 1348 microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift; 1349 1350 UINT_32 sliceBits = pitchInTile * heightInTile; 1351 1352 // do htile single slice alignment if the flag is true 1353 if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile 1354 { 1355 sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits); 1356 } 1357 macroOffset = slice * (sliceBits / numPipes) * elemBits ; 1358 } 1359 else 1360 { //tiled addressing 1361 const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles 1362 const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight; 1363 const UINT_32 pitchInCL = pitchInTile / macroWidthInTile; 1364 const UINT_32 heightInCL = heightInTile / macroHeightInTile; 1365 1366 const UINT_32 macroX = x / macroWidth; 1367 const UINT_32 macroY = y / macroHeight; 1368 const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL; 1369 1370 // Per pipe starting offset of the cache line in which this tile lies. 1371 microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4 1372 microY = (y % macroHeight) / MicroTileHeight / 4 ; 1373 microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift; 1374 1375 macroOffset = macroNumber * tileNumPerPipe * elemBits; 1376 } 1377 1378 if(elemIdxBits == microShift) 1379 { 1380 microNumber += elemIdx; 1381 } 1382 else 1383 { 1384 microNumber >>= elemIdxBits; 1385 microNumber <<= elemIdxBits; 1386 microNumber += elemIdx; 1387 } 1388 1389 microOffset = elemBits * microNumber; 1390 totalOffset = microOffset + macroOffset; 1391 1392 UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo); 1393 UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) + 1394 pipe * (m_pipeInterleaveBytes * 8) + 1395 totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes; 1396 *pBitPosition = static_cast<UINT_32>(addrInBits) % 8; 1397 UINT_64 addr = addrInBits / 8; 1398 1399 return addr; 1400 } 1401 1402 /** 1403 **************************************************************************************************** 1404 * SiLib::HwlComputeXmaskCoordFromAddr 1405 * 1406 * @brief 1407 * Compute the coord from an address of a cmask/htile 1408 * 1409 * @return 1410 * N/A 1411 * 1412 * @note 1413 * This method is reused by htile, so rename to Xmask 1414 **************************************************************************************************** 1415 */ 1416 VOID SiLib::HwlComputeXmaskCoordFromAddr( 1417 UINT_64 addr, ///< [in] address 1418 UINT_32 bitPosition, ///< [in] bitPosition in a byte 1419 UINT_32 pitch, ///< [in] pitch 1420 UINT_32 height, ///< [in] height 1421 UINT_32 numSlices, ///< [in] number of slices 1422 UINT_32 factor, ///< [in] factor that indicates cmask or htile 1423 BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout 1424 BOOL_32 isWidth8, ///< [in] Not used by SI 1425 BOOL_32 isHeight8, ///< [in] Not used by SI 1426 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 1427 UINT_32* pX, ///< [out] x coord 1428 UINT_32* pY, ///< [out] y coord 1429 UINT_32* pSlice ///< [out] slice index 1430 ) const 1431 { 1432 UINT_32 newPitch; 1433 UINT_32 newHeight; 1434 UINT_64 totalBytes; 1435 UINT_32 clWidth; 1436 UINT_32 clHeight; 1437 UINT_32 tileNumPerPipe; 1438 UINT_64 sliceBytes; 1439 1440 *pX = 0; 1441 *pY = 0; 1442 *pSlice = 0; 1443 1444 if (factor == 2) //CMASK 1445 { 1446 ADDR_CMASK_FLAGS flags = {{0}}; 1447 1448 tileNumPerPipe = 256; 1449 1450 ComputeCmaskInfo(flags, 1451 pitch, 1452 height, 1453 numSlices, 1454 isLinear, 1455 pTileInfo, 1456 &newPitch, 1457 &newHeight, 1458 &totalBytes, 1459 &clWidth, 1460 &clHeight); 1461 } 1462 else //HTile 1463 { 1464 ADDR_HTILE_FLAGS flags = {{0}}; 1465 1466 tileNumPerPipe = 512; 1467 1468 ComputeHtileInfo(flags, 1469 pitch, 1470 height, 1471 numSlices, 1472 isLinear, 1473 TRUE, 1474 TRUE, 1475 pTileInfo, 1476 &newPitch, 1477 &newHeight, 1478 &totalBytes, 1479 &clWidth, 1480 &clHeight, 1481 &sliceBytes); 1482 } 1483 1484 const UINT_32 pitchInTile = newPitch / MicroTileWidth; 1485 const UINT_32 heightInTile = newHeight / MicroTileWidth; 1486 const UINT_32 pitchInMacroTile = pitchInTile / 4; 1487 UINT_32 macroShift; 1488 UINT_32 elemIdxBits; 1489 // get macroShift and elemIdxBits 1490 TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, ¯oShift, &elemIdxBits); 1491 1492 const UINT_32 numPipes = HwlGetPipes(pTileInfo); 1493 const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes); 1494 // per pipe 1495 UINT_64 localOffset = (addr % m_pipeInterleaveBytes) + 1496 (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes; 1497 1498 UINT_32 tileIndex; 1499 if (factor == 2) //CMASK 1500 { 1501 tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0)); 1502 } 1503 else 1504 { 1505 tileIndex = (UINT_32)(localOffset / 4); 1506 } 1507 1508 UINT_32 macroOffset; 1509 if (isLinear) 1510 { 1511 UINT_32 sliceSizeInTile = pitchInTile * heightInTile; 1512 1513 // do htile single slice alignment if the flag is true 1514 if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile 1515 { 1516 sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64); 1517 } 1518 *pSlice = tileIndex / (sliceSizeInTile / numPipes); 1519 macroOffset = tileIndex % (sliceSizeInTile / numPipes); 1520 } 1521 else 1522 { 1523 const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles 1524 const UINT_32 clHeightInTile = clHeight / MicroTileHeight; 1525 const UINT_32 pitchInCL = pitchInTile / clWidthInTile; 1526 const UINT_32 heightInCL = heightInTile / clHeightInTile; 1527 const UINT_32 clIndex = tileIndex / tileNumPerPipe; 1528 1529 UINT_32 clX = clIndex % pitchInCL; 1530 UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL; 1531 1532 *pX = clX * clWidthInTile * MicroTileWidth; 1533 *pY = clY * clHeightInTile * MicroTileHeight; 1534 *pSlice = clIndex / (heightInCL * pitchInCL); 1535 1536 macroOffset = tileIndex % tileNumPerPipe; 1537 } 1538 1539 UINT_32 elemIdx = macroOffset & 7; 1540 macroOffset >>= elemIdxBits; 1541 1542 if (elemIdxBits != macroShift) 1543 { 1544 macroOffset <<= (elemIdxBits - macroShift); 1545 1546 UINT_32 pipebit1 = _BIT(pipe,1); 1547 UINT_32 pipebit2 = _BIT(pipe,2); 1548 UINT_32 pipebit3 = _BIT(pipe,3); 1549 if (pitchInMacroTile % 2) 1550 { //odd 1551 switch (pTileInfo->pipeConfig) 1552 { 1553 case ADDR_PIPECFG_P4_32x32: 1554 macroOffset |= pipebit1; 1555 break; 1556 case ADDR_PIPECFG_P8_32x32_8x16: 1557 case ADDR_PIPECFG_P8_32x32_16x16: 1558 case ADDR_PIPECFG_P8_32x32_16x32: 1559 macroOffset |= pipebit2; 1560 break; 1561 default: 1562 break; 1563 } 1564 1565 } 1566 1567 if (pitchInMacroTile % 4) 1568 { 1569 if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) 1570 { 1571 macroOffset |= (pipebit1<<1); 1572 } 1573 if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || 1574 (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16)) 1575 { 1576 macroOffset |= (pipebit3<<1); 1577 } 1578 } 1579 } 1580 1581 UINT_32 macroX; 1582 UINT_32 macroY; 1583 1584 if (isLinear) 1585 { 1586 macroX = macroOffset % pitchInMacroTile; 1587 macroY = macroOffset / pitchInMacroTile; 1588 } 1589 else 1590 { 1591 const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4); 1592 macroX = macroOffset % clWidthInMacroTile; 1593 macroY = macroOffset / clWidthInMacroTile; 1594 } 1595 1596 *pX += macroX * 4 * MicroTileWidth; 1597 *pY += macroY * 4 * MicroTileHeight; 1598 1599 UINT_32 microX; 1600 UINT_32 microY; 1601 ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile, 1602 *pX, *pY, µX, µY); 1603 1604 *pX += microX * MicroTileWidth; 1605 *pY += microY * MicroTileWidth; 1606 } 1607 1608 /** 1609 **************************************************************************************************** 1610 * SiLib::HwlGetPitchAlignmentLinear 1611 * @brief 1612 * Get pitch alignment 1613 * @return 1614 * pitch alignment 1615 **************************************************************************************************** 1616 */ 1617 UINT_32 SiLib::HwlGetPitchAlignmentLinear( 1618 UINT_32 bpp, ///< [in] bits per pixel 1619 ADDR_SURFACE_FLAGS flags ///< [in] surface flags 1620 ) const 1621 { 1622 UINT_32 pitchAlign; 1623 1624 // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment 1625 if (flags.interleaved) 1626 { 1627 pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp)); 1628 1629 } 1630 else 1631 { 1632 pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp)); 1633 } 1634 1635 return pitchAlign; 1636 } 1637 1638 /** 1639 **************************************************************************************************** 1640 * SiLib::HwlGetSizeAdjustmentLinear 1641 * 1642 * @brief 1643 * Adjust linear surface pitch and slice size 1644 * 1645 * @return 1646 * Logical slice size in bytes 1647 **************************************************************************************************** 1648 */ 1649 UINT_64 SiLib::HwlGetSizeAdjustmentLinear( 1650 AddrTileMode tileMode, ///< [in] tile mode 1651 UINT_32 bpp, ///< [in] bits per pixel 1652 UINT_32 numSamples, ///< [in] number of samples 1653 UINT_32 baseAlign, ///< [in] base alignment 1654 UINT_32 pitchAlign, ///< [in] pitch alignment 1655 UINT_32* pPitch, ///< [in,out] pointer to pitch 1656 UINT_32* pHeight, ///< [in,out] pointer to height 1657 UINT_32* pHeightAlign ///< [in,out] pointer to height align 1658 ) const 1659 { 1660 UINT_64 sliceSize; 1661 if (tileMode == ADDR_TM_LINEAR_GENERAL) 1662 { 1663 sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples); 1664 } 1665 else 1666 { 1667 UINT_32 pitch = *pPitch; 1668 UINT_32 height = *pHeight; 1669 1670 UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp); 1671 UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave; 1672 1673 // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value) 1674 UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; 1675 1676 while (pixelPerSlice % sliceAlignInPixel) 1677 { 1678 pitch += pitchAlign; 1679 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; 1680 } 1681 1682 *pPitch = pitch; 1683 1684 UINT_32 heightAlign = 1; 1685 1686 while ((pitch * heightAlign) % sliceAlignInPixel) 1687 { 1688 heightAlign++; 1689 } 1690 1691 *pHeightAlign = heightAlign; 1692 1693 sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp); 1694 } 1695 1696 return sliceSize; 1697 } 1698 1699 /** 1700 **************************************************************************************************** 1701 * SiLib::HwlPreHandleBaseLvl3xPitch 1702 * 1703 * @brief 1704 * Pre-handler of 3x pitch (96 bit) adjustment 1705 * 1706 * @return 1707 * Expected pitch 1708 **************************************************************************************************** 1709 */ 1710 UINT_32 SiLib::HwlPreHandleBaseLvl3xPitch( 1711 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input 1712 UINT_32 expPitch ///< [in] pitch 1713 ) const 1714 { 1715 ADDR_ASSERT(pIn->width == expPitch); 1716 1717 // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to 1718 // do here 1719 if (pIn->flags.pow2Pad == FALSE) 1720 { 1721 Addr::V1::Lib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch); 1722 } 1723 else 1724 { 1725 ADDR_ASSERT(IsPow2(expPitch)); 1726 } 1727 1728 return expPitch; 1729 } 1730 1731 /** 1732 **************************************************************************************************** 1733 * SiLib::HwlPostHandleBaseLvl3xPitch 1734 * 1735 * @brief 1736 * Post-handler of 3x pitch adjustment 1737 * 1738 * @return 1739 * Expected pitch 1740 **************************************************************************************************** 1741 */ 1742 UINT_32 SiLib::HwlPostHandleBaseLvl3xPitch( 1743 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input 1744 UINT_32 expPitch ///< [in] pitch 1745 ) const 1746 { 1747 /** 1748 * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should 1749 * be able to compute a correct pitch from it as h/w address library is doing the job. 1750 */ 1751 // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here 1752 if (pIn->flags.pow2Pad == FALSE) 1753 { 1754 Addr::V1::Lib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch); 1755 } 1756 1757 return expPitch; 1758 } 1759 1760 /** 1761 **************************************************************************************************** 1762 * SiLib::HwlGetPitchAlignmentMicroTiled 1763 * 1764 * @brief 1765 * Compute 1D tiled surface pitch alignment 1766 * 1767 * @return 1768 * pitch alignment 1769 **************************************************************************************************** 1770 */ 1771 UINT_32 SiLib::HwlGetPitchAlignmentMicroTiled( 1772 AddrTileMode tileMode, ///< [in] tile mode 1773 UINT_32 bpp, ///< [in] bits per pixel 1774 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags 1775 UINT_32 numSamples ///< [in] number of samples 1776 ) const 1777 { 1778 UINT_32 pitchAlign; 1779 1780 if (flags.qbStereo) 1781 { 1782 pitchAlign = EgBasedLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples); 1783 } 1784 else 1785 { 1786 pitchAlign = 8; 1787 } 1788 1789 return pitchAlign; 1790 } 1791 1792 /** 1793 **************************************************************************************************** 1794 * SiLib::HwlGetSizeAdjustmentMicroTiled 1795 * 1796 * @brief 1797 * Adjust 1D tiled surface pitch and slice size 1798 * 1799 * @return 1800 * Logical slice size in bytes 1801 **************************************************************************************************** 1802 */ 1803 UINT_64 SiLib::HwlGetSizeAdjustmentMicroTiled( 1804 UINT_32 thickness, ///< [in] thickness 1805 UINT_32 bpp, ///< [in] bits per pixel 1806 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags 1807 UINT_32 numSamples, ///< [in] number of samples 1808 UINT_32 baseAlign, ///< [in] base alignment 1809 UINT_32 pitchAlign, ///< [in] pitch alignment 1810 UINT_32* pPitch, ///< [in,out] pointer to pitch 1811 UINT_32* pHeight ///< [in,out] pointer to height 1812 ) const 1813 { 1814 UINT_64 logicalSliceSize; 1815 UINT_64 physicalSliceSize; 1816 1817 UINT_32 pitch = *pPitch; 1818 UINT_32 height = *pHeight; 1819 1820 // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1) 1821 logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); 1822 1823 // Physical slice: multiplied by thickness 1824 physicalSliceSize = logicalSliceSize * thickness; 1825 1826 // Pitch alignment is always 8, so if slice size is not padded to base alignment 1827 // (pipe_interleave_size), we need to increase pitch 1828 while ((physicalSliceSize % baseAlign) != 0) 1829 { 1830 pitch += pitchAlign; 1831 1832 logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); 1833 1834 physicalSliceSize = logicalSliceSize * thickness; 1835 } 1836 1837 #if !ALT_TEST 1838 // 1839 // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since 1840 // the stencil plane may have larger pitch if the slice size is smaller than base alignment. 1841 // 1842 // Note: this actually does not work for mipmap but mipmap depth texture is not really 1843 // sampled with mipmap. 1844 // 1845 if (flags.depth && (flags.noStencil == FALSE)) 1846 { 1847 ADDR_ASSERT(numSamples == 1); 1848 1849 UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil 1850 1851 while ((logicalSiceSizeStencil % baseAlign) != 0) 1852 { 1853 pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's 1854 1855 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; 1856 } 1857 1858 if (pitch != *pPitch) 1859 { 1860 // If this is a mipmap, this padded one cannot be sampled as a whole mipmap! 1861 logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp); 1862 } 1863 } 1864 #endif 1865 *pPitch = pitch; 1866 1867 // No adjust for pHeight 1868 1869 return logicalSliceSize; 1870 } 1871 1872 /** 1873 **************************************************************************************************** 1874 * SiLib::HwlConvertChipFamily 1875 * 1876 * @brief 1877 * Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision 1878 * @return 1879 * ChipFamily 1880 **************************************************************************************************** 1881 */ 1882 ChipFamily SiLib::HwlConvertChipFamily( 1883 UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h 1884 UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h 1885 { 1886 ChipFamily family = ADDR_CHIP_FAMILY_SI; 1887 1888 switch (uChipFamily) 1889 { 1890 case FAMILY_SI: 1891 m_settings.isSouthernIsland = 1; 1892 m_settings.isTahiti = ASICREV_IS_TAHITI_P(uChipRevision); 1893 m_settings.isPitCairn = ASICREV_IS_PITCAIRN_PM(uChipRevision); 1894 m_settings.isCapeVerde = ASICREV_IS_CAPEVERDE_M(uChipRevision); 1895 m_settings.isOland = ASICREV_IS_OLAND_M(uChipRevision); 1896 m_settings.isHainan = ASICREV_IS_HAINAN_V(uChipRevision); 1897 break; 1898 default: 1899 ADDR_ASSERT(!"This should be a Fusion"); 1900 break; 1901 } 1902 1903 return family; 1904 } 1905 1906 /** 1907 **************************************************************************************************** 1908 * SiLib::HwlSetupTileInfo 1909 * 1910 * @brief 1911 * Setup default value of tile info for SI 1912 **************************************************************************************************** 1913 */ 1914 VOID SiLib::HwlSetupTileInfo( 1915 AddrTileMode tileMode, ///< [in] Tile mode 1916 ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags 1917 UINT_32 bpp, ///< [in] Bits per pixel 1918 UINT_32 pitch, ///< [in] Pitch in pixels 1919 UINT_32 height, ///< [in] Height in pixels 1920 UINT_32 numSamples, ///< [in] Number of samples 1921 ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default 1922 ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output 1923 AddrTileType inTileType, ///< [in] Tile type 1924 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output 1925 ) const 1926 { 1927 UINT_32 thickness = Thickness(tileMode); 1928 ADDR_TILEINFO* pTileInfo = pTileInfoOut; 1929 INT index = TileIndexInvalid; 1930 1931 // Fail-safe code 1932 if (IsLinear(tileMode) == FALSE) 1933 { 1934 // 128 bpp/thick tiling must be non-displayable. 1935 // Fmask reuse color buffer's entry but bank-height field can be from another entry 1936 // To simplify the logic, fmask entry should be picked from non-displayable ones 1937 if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt) 1938 { 1939 inTileType = ADDR_NON_DISPLAYABLE; 1940 } 1941 1942 if (flags.depth || flags.stencil) 1943 { 1944 inTileType = ADDR_DEPTH_SAMPLE_ORDER; 1945 } 1946 } 1947 1948 // Partial valid fields are not allowed for SI. 1949 if (IsTileInfoAllZero(pTileInfo)) 1950 { 1951 if (IsMacroTiled(tileMode)) 1952 { 1953 if (flags.prt) 1954 { 1955 if (numSamples == 1) 1956 { 1957 if (flags.depth) 1958 { 1959 switch (bpp) 1960 { 1961 case 16: 1962 index = 3; 1963 break; 1964 case 32: 1965 index = 6; 1966 break; 1967 default: 1968 ADDR_ASSERT_ALWAYS(); 1969 break; 1970 } 1971 } 1972 else 1973 { 1974 switch (bpp) 1975 { 1976 case 8: 1977 index = 21; 1978 break; 1979 case 16: 1980 index = 22; 1981 break; 1982 case 32: 1983 index = 23; 1984 break; 1985 case 64: 1986 index = 24; 1987 break; 1988 case 128: 1989 index = 25; 1990 break; 1991 default: 1992 break; 1993 } 1994 1995 if (thickness > 1) 1996 { 1997 ADDR_ASSERT(bpp != 128); 1998 index += 5; 1999 } 2000 } 2001 } 2002 else 2003 { 2004 ADDR_ASSERT(numSamples == 4); 2005 2006 if (flags.depth) 2007 { 2008 switch (bpp) 2009 { 2010 case 16: 2011 index = 5; 2012 break; 2013 case 32: 2014 index = 7; 2015 break; 2016 default: 2017 ADDR_ASSERT_ALWAYS(); 2018 break; 2019 } 2020 } 2021 else 2022 { 2023 switch (bpp) 2024 { 2025 case 8: 2026 index = 23; 2027 break; 2028 case 16: 2029 index = 24; 2030 break; 2031 case 32: 2032 index = 25; 2033 break; 2034 case 64: 2035 index = 30; 2036 break; 2037 default: 2038 ADDR_ASSERT_ALWAYS(); 2039 break; 2040 } 2041 } 2042 } 2043 }//end of PRT part 2044 // See table entries 0-7 2045 else if (flags.depth || flags.stencil) 2046 { 2047 if (flags.compressZ) 2048 { 2049 if (flags.stencil) 2050 { 2051 index = 0; 2052 } 2053 else 2054 { 2055 // optimal tile index for compressed depth/stencil. 2056 switch (numSamples) 2057 { 2058 case 1: 2059 index = 0; 2060 break; 2061 case 2: 2062 case 4: 2063 index = 1; 2064 break; 2065 case 8: 2066 index = 2; 2067 break; 2068 default: 2069 break; 2070 } 2071 } 2072 } 2073 else // unCompressZ 2074 { 2075 index = 3; 2076 } 2077 } 2078 else //non PRT & non Depth & non Stencil 2079 { 2080 // See table entries 9-12 2081 if (inTileType == ADDR_DISPLAYABLE) 2082 { 2083 switch (bpp) 2084 { 2085 case 8: 2086 index = 10; 2087 break; 2088 case 16: 2089 index = 11; 2090 break; 2091 case 32: 2092 index = 12; 2093 break; 2094 case 64: 2095 index = 12; 2096 break; 2097 default: 2098 break; 2099 } 2100 } 2101 else 2102 { 2103 // See table entries 13-17 2104 if (thickness == 1) 2105 { 2106 if (flags.fmask) 2107 { 2108 UINT_32 fmaskPixelSize = bpp * numSamples; 2109 2110 switch (fmaskPixelSize) 2111 { 2112 case 8: 2113 index = 14; 2114 break; 2115 case 16: 2116 index = 15; 2117 break; 2118 case 32: 2119 index = 16; 2120 break; 2121 case 64: 2122 index = 17; 2123 break; 2124 default: 2125 ADDR_ASSERT_ALWAYS(); 2126 } 2127 } 2128 else 2129 { 2130 switch (bpp) 2131 { 2132 case 8: 2133 index = 14; 2134 break; 2135 case 16: 2136 index = 15; 2137 break; 2138 case 32: 2139 index = 16; 2140 break; 2141 case 64: 2142 index = 17; 2143 break; 2144 case 128: 2145 index = 17; 2146 break; 2147 default: 2148 break; 2149 } 2150 } 2151 } 2152 else // thick tiling - entries 18-20 2153 { 2154 switch (thickness) 2155 { 2156 case 4: 2157 index = 20; 2158 break; 2159 case 8: 2160 index = 19; 2161 break; 2162 default: 2163 break; 2164 } 2165 } 2166 } 2167 } 2168 } 2169 else 2170 { 2171 if (tileMode == ADDR_TM_LINEAR_ALIGNED) 2172 { 2173 index = 8; 2174 } 2175 else if (tileMode == ADDR_TM_LINEAR_GENERAL) 2176 { 2177 index = TileIndexLinearGeneral; 2178 } 2179 else 2180 { 2181 if (flags.depth || flags.stencil) 2182 { 2183 index = 4; 2184 } 2185 else if (inTileType == ADDR_DISPLAYABLE) 2186 { 2187 index = 9; 2188 } 2189 else if (thickness == 1) 2190 { 2191 index = 13; 2192 } 2193 else 2194 { 2195 index = 18; 2196 } 2197 } 2198 } 2199 2200 if (index >= 0 && index <= 31) 2201 { 2202 *pTileInfo = m_tileTable[index].info; 2203 pOut->tileType = m_tileTable[index].type; 2204 } 2205 2206 if (index == TileIndexLinearGeneral) 2207 { 2208 *pTileInfo = m_tileTable[8].info; 2209 pOut->tileType = m_tileTable[8].type; 2210 } 2211 } 2212 else 2213 { 2214 if (pTileInfoIn) 2215 { 2216 if (flags.stencil && pTileInfoIn->tileSplitBytes == 0) 2217 { 2218 // Stencil always uses index 0 2219 *pTileInfo = m_tileTable[0].info; 2220 } 2221 } 2222 // Pass through tile type 2223 pOut->tileType = inTileType; 2224 } 2225 2226 pOut->tileIndex = index; 2227 pOut->prtTileIndex = flags.prt; 2228 } 2229 2230 /** 2231 **************************************************************************************************** 2232 * SiLib::DecodeGbRegs 2233 * 2234 * @brief 2235 * Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks 2236 * 2237 * @return 2238 * TRUE if all settings are valid 2239 * 2240 **************************************************************************************************** 2241 */ 2242 BOOL_32 SiLib::DecodeGbRegs( 2243 const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input 2244 { 2245 GB_ADDR_CONFIG reg; 2246 BOOL_32 valid = TRUE; 2247 2248 reg.val = pRegValue->gbAddrConfig; 2249 2250 switch (reg.f.pipe_interleave_size) 2251 { 2252 case ADDR_CONFIG_PIPE_INTERLEAVE_256B: 2253 m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B; 2254 break; 2255 case ADDR_CONFIG_PIPE_INTERLEAVE_512B: 2256 m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B; 2257 break; 2258 default: 2259 valid = FALSE; 2260 ADDR_UNHANDLED_CASE(); 2261 break; 2262 } 2263 2264 switch (reg.f.row_size) 2265 { 2266 case ADDR_CONFIG_1KB_ROW: 2267 m_rowSize = ADDR_ROWSIZE_1KB; 2268 break; 2269 case ADDR_CONFIG_2KB_ROW: 2270 m_rowSize = ADDR_ROWSIZE_2KB; 2271 break; 2272 case ADDR_CONFIG_4KB_ROW: 2273 m_rowSize = ADDR_ROWSIZE_4KB; 2274 break; 2275 default: 2276 valid = FALSE; 2277 ADDR_UNHANDLED_CASE(); 2278 break; 2279 } 2280 2281 switch (pRegValue->noOfBanks) 2282 { 2283 case 0: 2284 m_banks = 4; 2285 break; 2286 case 1: 2287 m_banks = 8; 2288 break; 2289 case 2: 2290 m_banks = 16; 2291 break; 2292 default: 2293 valid = FALSE; 2294 ADDR_UNHANDLED_CASE(); 2295 break; 2296 } 2297 2298 switch (pRegValue->noOfRanks) 2299 { 2300 case 0: 2301 m_ranks = 1; 2302 break; 2303 case 1: 2304 m_ranks = 2; 2305 break; 2306 default: 2307 valid = FALSE; 2308 ADDR_UNHANDLED_CASE(); 2309 break; 2310 } 2311 2312 m_logicalBanks = m_banks * m_ranks; 2313 2314 ADDR_ASSERT(m_logicalBanks <= 16); 2315 2316 return valid; 2317 } 2318 2319 /** 2320 **************************************************************************************************** 2321 * SiLib::HwlInitGlobalParams 2322 * 2323 * @brief 2324 * Initializes global parameters 2325 * 2326 * @return 2327 * TRUE if all settings are valid 2328 * 2329 **************************************************************************************************** 2330 */ 2331 BOOL_32 SiLib::HwlInitGlobalParams( 2332 const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input 2333 { 2334 BOOL_32 valid = TRUE; 2335 const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue; 2336 2337 valid = DecodeGbRegs(pRegValue); 2338 2339 if (valid) 2340 { 2341 if (m_settings.isTahiti || m_settings.isPitCairn) 2342 { 2343 m_pipes = 8; 2344 } 2345 else if (m_settings.isCapeVerde || m_settings.isOland) 2346 { 2347 m_pipes = 4; 2348 } 2349 else 2350 { 2351 // Hainan is 2-pipe (m_settings.isHainan == 1) 2352 m_pipes = 2; 2353 } 2354 2355 valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries); 2356 2357 if (valid) 2358 { 2359 InitEquationTable(); 2360 } 2361 2362 m_maxSamples = 16; 2363 } 2364 2365 return valid; 2366 } 2367 2368 /** 2369 **************************************************************************************************** 2370 * SiLib::HwlConvertTileInfoToHW 2371 * @brief 2372 * Entry of si's ConvertTileInfoToHW 2373 * @return 2374 * ADDR_E_RETURNCODE 2375 **************************************************************************************************** 2376 */ 2377 ADDR_E_RETURNCODE SiLib::HwlConvertTileInfoToHW( 2378 const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure 2379 ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure 2380 ) const 2381 { 2382 ADDR_E_RETURNCODE retCode = ADDR_OK; 2383 2384 retCode = EgBasedLib::HwlConvertTileInfoToHW(pIn, pOut); 2385 2386 if (retCode == ADDR_OK) 2387 { 2388 if (pIn->reverse == FALSE) 2389 { 2390 if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID) 2391 { 2392 retCode = ADDR_INVALIDPARAMS; 2393 } 2394 else 2395 { 2396 pOut->pTileInfo->pipeConfig = 2397 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1); 2398 } 2399 } 2400 else 2401 { 2402 pOut->pTileInfo->pipeConfig = 2403 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1); 2404 } 2405 } 2406 2407 return retCode; 2408 } 2409 2410 /** 2411 **************************************************************************************************** 2412 * SiLib::HwlComputeXmaskCoordYFrom8Pipe 2413 * 2414 * @brief 2415 * Compute the Y coord which will be added to Xmask Y 2416 * coord. 2417 * @return 2418 * Y coord 2419 **************************************************************************************************** 2420 */ 2421 UINT_32 SiLib::HwlComputeXmaskCoordYFrom8Pipe( 2422 UINT_32 pipe, ///< [in] pipe id 2423 UINT_32 x ///< [in] tile coord x, which is original x coord / 8 2424 ) const 2425 { 2426 // This function should never be called since it is 6xx/8xx specfic. 2427 // Keep this empty implementation to avoid any mis-use. 2428 ADDR_ASSERT_ALWAYS(); 2429 2430 return 0; 2431 } 2432 2433 /** 2434 **************************************************************************************************** 2435 * SiLib::HwlComputeSurfaceCoord2DFromBankPipe 2436 * 2437 * @brief 2438 * Compute surface x,y coordinates from bank/pipe info 2439 * @return 2440 * N/A 2441 **************************************************************************************************** 2442 */ 2443 VOID SiLib::HwlComputeSurfaceCoord2DFromBankPipe( 2444 AddrTileMode tileMode, ///< [in] tile mode 2445 UINT_32* pX, ///< [in,out] x coordinate 2446 UINT_32* pY, ///< [in,out] y coordinate 2447 UINT_32 slice, ///< [in] slice index 2448 UINT_32 bank, ///< [in] bank number 2449 UINT_32 pipe, ///< [in] pipe number 2450 UINT_32 bankSwizzle,///< [in] bank swizzle 2451 UINT_32 pipeSwizzle,///< [in] pipe swizzle 2452 UINT_32 tileSlices, ///< [in] slices in a micro tile 2453 BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored 2454 ADDR_TILEINFO* pTileInfo ///< [in] bank structure. **All fields to be valid on entry** 2455 ) const 2456 { 2457 UINT_32 xBit; 2458 UINT_32 yBit; 2459 UINT_32 yBit3 = 0; 2460 UINT_32 yBit4 = 0; 2461 UINT_32 yBit5 = 0; 2462 UINT_32 yBit6 = 0; 2463 2464 UINT_32 xBit3 = 0; 2465 UINT_32 xBit4 = 0; 2466 UINT_32 xBit5 = 0; 2467 2468 UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig); 2469 2470 CoordFromBankPipe xyBits = {0}; 2471 ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe, 2472 bankSwizzle, pipeSwizzle, tileSlices, pTileInfo, 2473 &xyBits); 2474 yBit3 = xyBits.yBit3; 2475 yBit4 = xyBits.yBit4; 2476 yBit5 = xyBits.yBit5; 2477 yBit6 = xyBits.yBit6; 2478 2479 xBit3 = xyBits.xBit3; 2480 xBit4 = xyBits.xBit4; 2481 xBit5 = xyBits.xBit5; 2482 2483 yBit = xyBits.yBits; 2484 2485 UINT_32 yBitTemp = 0; 2486 2487 if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || 2488 (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) 2489 { 2490 ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1); 2491 UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1; 2492 2493 ADDR_ASSERT(yBitToCheck <= 3); 2494 2495 yBitTemp = _BIT(yBit, yBitToCheck); 2496 2497 xBit3 = 0; 2498 } 2499 2500 yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3); 2501 xBit = Bits2Number(3, xBit5, xBit4, xBit3); 2502 2503 *pY += yBit * pTileInfo->bankHeight * MicroTileHeight; 2504 *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth; 2505 2506 //calculate the bank and pipe bits in x, y 2507 UINT_32 xTile; //x in micro tile 2508 UINT_32 x3 = 0; 2509 UINT_32 x4 = 0; 2510 UINT_32 x5 = 0; 2511 UINT_32 x6 = 0; 2512 UINT_32 y = *pY; 2513 2514 UINT_32 pipeBit0 = _BIT(pipe,0); 2515 UINT_32 pipeBit1 = _BIT(pipe,1); 2516 UINT_32 pipeBit2 = _BIT(pipe,2); 2517 2518 UINT_32 y3 = _BIT(y, 3); 2519 UINT_32 y4 = _BIT(y, 4); 2520 UINT_32 y5 = _BIT(y, 5); 2521 UINT_32 y6 = _BIT(y, 6); 2522 2523 // bankbit0 after ^x4^x5 2524 UINT_32 bankBit00 = _BIT(bank,0); 2525 UINT_32 bankBit0 = 0; 2526 2527 switch (pTileInfo->pipeConfig) 2528 { 2529 case ADDR_PIPECFG_P2: 2530 x3 = pipeBit0 ^ y3; 2531 break; 2532 case ADDR_PIPECFG_P4_8x16: 2533 x4 = pipeBit0 ^ y3; 2534 x3 = pipeBit0 ^ y4; 2535 break; 2536 case ADDR_PIPECFG_P4_16x16: 2537 x4 = pipeBit1 ^ y4; 2538 x3 = pipeBit0 ^ y3 ^ x4; 2539 break; 2540 case ADDR_PIPECFG_P4_16x32: 2541 x4 = pipeBit1 ^ y4; 2542 x3 = pipeBit0 ^ y3 ^ x4; 2543 break; 2544 case ADDR_PIPECFG_P4_32x32: 2545 x5 = pipeBit1 ^ y5; 2546 x3 = pipeBit0 ^ y3 ^ x5; 2547 bankBit0 = yBitTemp ^ x5; 2548 x4 = bankBit00 ^ x5 ^ bankBit0; 2549 *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8; 2550 break; 2551 case ADDR_PIPECFG_P8_16x16_8x16: 2552 x3 = pipeBit1 ^ y5; 2553 x4 = pipeBit2 ^ y4; 2554 x5 = pipeBit0 ^ y3 ^ x4; 2555 break; 2556 case ADDR_PIPECFG_P8_16x32_8x16: 2557 x3 = pipeBit1 ^ y4; 2558 x4 = pipeBit2 ^ y5; 2559 x5 = pipeBit0 ^ y3 ^ x4; 2560 break; 2561 case ADDR_PIPECFG_P8_32x32_8x16: 2562 x3 = pipeBit1 ^ y4; 2563 x5 = pipeBit2 ^ y5; 2564 x4 = pipeBit0 ^ y3 ^ x5; 2565 break; 2566 case ADDR_PIPECFG_P8_16x32_16x16: 2567 x4 = pipeBit2 ^ y5; 2568 x5 = pipeBit1 ^ y4; 2569 x3 = pipeBit0 ^ y3 ^ x4; 2570 break; 2571 case ADDR_PIPECFG_P8_32x32_16x16: 2572 x5 = pipeBit2 ^ y5; 2573 x4 = pipeBit1 ^ y4; 2574 x3 = pipeBit0 ^ y3 ^ x4; 2575 break; 2576 case ADDR_PIPECFG_P8_32x32_16x32: 2577 x5 = pipeBit2 ^ y5; 2578 x4 = pipeBit1 ^ y6; 2579 x3 = pipeBit0 ^ y3 ^ x4; 2580 break; 2581 case ADDR_PIPECFG_P8_32x64_32x32: 2582 x6 = pipeBit1 ^ y5; 2583 x5 = pipeBit2 ^ y6; 2584 x3 = pipeBit0 ^ y3 ^ x5; 2585 bankBit0 = yBitTemp ^ x6; 2586 x4 = bankBit00 ^ x5 ^ bankBit0; 2587 *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8; 2588 break; 2589 default: 2590 ADDR_ASSERT_ALWAYS(); 2591 } 2592 2593 xTile = Bits2Number(3, x5, x4, x3); 2594 2595 *pX += xTile << 3; 2596 } 2597 2598 /** 2599 **************************************************************************************************** 2600 * SiLib::HwlPreAdjustBank 2601 * 2602 * @brief 2603 * Adjust bank before calculating address acoording to bank/pipe 2604 * @return 2605 * Adjusted bank 2606 **************************************************************************************************** 2607 */ 2608 UINT_32 SiLib::HwlPreAdjustBank( 2609 UINT_32 tileX, ///< [in] x coordinate in unit of tile 2610 UINT_32 bank, ///< [in] bank 2611 ADDR_TILEINFO* pTileInfo ///< [in] tile info 2612 ) const 2613 { 2614 if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || 2615 (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1)) 2616 { 2617 UINT_32 bankBit0 = _BIT(bank, 0); 2618 UINT_32 x4 = _BIT(tileX, 1); 2619 UINT_32 x5 = _BIT(tileX, 2); 2620 2621 bankBit0 = bankBit0 ^ x4 ^ x5; 2622 bank |= bankBit0; 2623 2624 ADDR_ASSERT(pTileInfo->macroAspectRatio > 1); 2625 } 2626 2627 return bank; 2628 } 2629 2630 /** 2631 **************************************************************************************************** 2632 * SiLib::HwlComputeSurfaceInfo 2633 * 2634 * @brief 2635 * Entry of si's ComputeSurfaceInfo 2636 * @return 2637 * ADDR_E_RETURNCODE 2638 **************************************************************************************************** 2639 */ 2640 ADDR_E_RETURNCODE SiLib::HwlComputeSurfaceInfo( 2641 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure 2642 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure 2643 ) const 2644 { 2645 pOut->tileIndex = pIn->tileIndex; 2646 2647 ADDR_E_RETURNCODE retCode = EgBasedLib::HwlComputeSurfaceInfo(pIn, pOut); 2648 2649 UINT_32 tileIndex = static_cast<UINT_32>(pOut->tileIndex); 2650 2651 if (((pIn->flags.needEquation == TRUE) || 2652 (pIn->flags.preferEquation == TRUE)) && 2653 (pIn->numSamples <= 1) && 2654 (tileIndex < TileTableSize)) 2655 { 2656 static const UINT_32 SiUncompressDepthTileIndex = 3; 2657 2658 if ((pIn->numSlices > 1) && 2659 (IsMacroTiled(pOut->tileMode) == TRUE) && 2660 ((m_chipFamily == ADDR_CHIP_FAMILY_SI) || 2661 (IsPrtTileMode(pOut->tileMode) == FALSE))) 2662 { 2663 pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX; 2664 } 2665 else if ((pIn->flags.prt == FALSE) && 2666 (m_uncompressDepthEqIndex != 0) && 2667 (tileIndex == SiUncompressDepthTileIndex)) 2668 { 2669 pOut->equationIndex = m_uncompressDepthEqIndex + Log2(pIn->bpp >> 3); 2670 } 2671 else 2672 { 2673 2674 pOut->equationIndex = m_equationLookupTable[Log2(pIn->bpp >> 3)][tileIndex]; 2675 } 2676 2677 if (pOut->equationIndex != ADDR_INVALID_EQUATION_INDEX) 2678 { 2679 pOut->blockWidth = m_blockWidth[pOut->equationIndex]; 2680 2681 pOut->blockHeight = m_blockHeight[pOut->equationIndex]; 2682 2683 pOut->blockSlices = m_blockSlices[pOut->equationIndex]; 2684 } 2685 } 2686 else 2687 { 2688 pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX; 2689 } 2690 2691 return retCode; 2692 } 2693 2694 /** 2695 **************************************************************************************************** 2696 * SiLib::HwlComputeMipLevel 2697 * @brief 2698 * Compute MipLevel info (including level 0) 2699 * @return 2700 * TRUE if HWL's handled 2701 **************************************************************************************************** 2702 */ 2703 BOOL_32 SiLib::HwlComputeMipLevel( 2704 ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure 2705 ) const 2706 { 2707 // basePitch is calculated from level 0 so we only check this for mipLevel > 0 2708 if (pIn->mipLevel > 0) 2709 { 2710 // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if 2711 // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being 2712 // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2. 2713 if (ElemLib::IsExpand3x(pIn->format) == FALSE) 2714 { 2715 // Sublevel pitches are generated from base level pitch instead of width on SI 2716 // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain 2717 ADDR_ASSERT((pIn->flags.pow2Pad == FALSE) || 2718 ((pIn->basePitch != 0) && IsPow2(pIn->basePitch))); 2719 } 2720 2721 if (pIn->basePitch != 0) 2722 { 2723 pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel); 2724 } 2725 } 2726 2727 // pow2Pad is done in PostComputeMipLevel 2728 2729 return TRUE; 2730 } 2731 2732 /** 2733 **************************************************************************************************** 2734 * SiLib::HwlCheckLastMacroTiledLvl 2735 * 2736 * @brief 2737 * Sets pOut->last2DLevel to TRUE if it is 2738 * @note 2739 * 2740 **************************************************************************************************** 2741 */ 2742 VOID SiLib::HwlCheckLastMacroTiledLvl( 2743 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure 2744 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] Output structure (used as input, too) 2745 ) const 2746 { 2747 // pow2Pad covers all mipmap cases 2748 if (pIn->flags.pow2Pad) 2749 { 2750 ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); 2751 2752 UINT_32 nextPitch; 2753 UINT_32 nextHeight; 2754 UINT_32 nextSlices; 2755 2756 AddrTileMode nextTileMode; 2757 2758 if (pIn->mipLevel == 0 || pIn->basePitch == 0) 2759 { 2760 // Base level or fail-safe case (basePitch == 0) 2761 nextPitch = pOut->pitch >> 1; 2762 } 2763 else 2764 { 2765 // Sub levels 2766 nextPitch = pIn->basePitch >> (pIn->mipLevel + 1); 2767 } 2768 2769 // nextHeight must be shifted from this level's original height rather than a pow2 padded 2770 // one but this requires original height stored somewhere (pOut->height) 2771 ADDR_ASSERT(pOut->height != 0); 2772 2773 // next level's height is just current level's >> 1 in pixels 2774 nextHeight = pOut->height >> 1; 2775 // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block 2776 // compressed foramts 2777 if (ElemLib::IsBlockCompressed(pIn->format)) 2778 { 2779 nextHeight = (nextHeight + 3) / 4; 2780 } 2781 nextHeight = NextPow2(nextHeight); 2782 2783 // nextSlices may be 0 if this level's is 1 2784 if (pIn->flags.volume) 2785 { 2786 nextSlices = Max(1u, pIn->numSlices >> 1); 2787 } 2788 else 2789 { 2790 nextSlices = pIn->numSlices; 2791 } 2792 2793 nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode, 2794 pIn->bpp, 2795 nextPitch, 2796 nextHeight, 2797 nextSlices, 2798 pIn->numSamples, 2799 pOut->blockWidth, 2800 pOut->blockHeight, 2801 pOut->pTileInfo); 2802 2803 pOut->last2DLevel = IsMicroTiled(nextTileMode); 2804 } 2805 } 2806 2807 /** 2808 **************************************************************************************************** 2809 * SiLib::HwlDegradeThickTileMode 2810 * 2811 * @brief 2812 * Degrades valid tile mode for thick modes if needed 2813 * 2814 * @return 2815 * Suitable tile mode 2816 **************************************************************************************************** 2817 */ 2818 AddrTileMode SiLib::HwlDegradeThickTileMode( 2819 AddrTileMode baseTileMode, ///< base tile mode 2820 UINT_32 numSlices, ///< current number of slices 2821 UINT_32* pBytesPerTile ///< [in,out] pointer to bytes per slice 2822 ) const 2823 { 2824 return EgBasedLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile); 2825 } 2826 2827 /** 2828 **************************************************************************************************** 2829 * SiLib::HwlTileInfoEqual 2830 * 2831 * @brief 2832 * Return TRUE if all field are equal 2833 * @note 2834 * Only takes care of current HWL's data 2835 **************************************************************************************************** 2836 */ 2837 BOOL_32 SiLib::HwlTileInfoEqual( 2838 const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand 2839 const ADDR_TILEINFO* pRight ///<[in] Right compare operand 2840 ) const 2841 { 2842 BOOL_32 equal = FALSE; 2843 2844 if (pLeft->pipeConfig == pRight->pipeConfig) 2845 { 2846 equal = EgBasedLib::HwlTileInfoEqual(pLeft, pRight); 2847 } 2848 2849 return equal; 2850 } 2851 2852 /** 2853 **************************************************************************************************** 2854 * SiLib::GetTileSettings 2855 * 2856 * @brief 2857 * Get tile setting infos by index. 2858 * @return 2859 * Tile setting info. 2860 **************************************************************************************************** 2861 */ 2862 const TileConfig* SiLib::GetTileSetting( 2863 UINT_32 index ///< [in] Tile index 2864 ) const 2865 { 2866 ADDR_ASSERT(index < m_noOfEntries); 2867 return &m_tileTable[index]; 2868 } 2869 2870 /** 2871 **************************************************************************************************** 2872 * SiLib::HwlPostCheckTileIndex 2873 * 2874 * @brief 2875 * Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches 2876 * tile mode/type/info and change the index if needed 2877 * @return 2878 * Tile index. 2879 **************************************************************************************************** 2880 */ 2881 INT_32 SiLib::HwlPostCheckTileIndex( 2882 const ADDR_TILEINFO* pInfo, ///< [in] Tile Info 2883 AddrTileMode mode, ///< [in] Tile mode 2884 AddrTileType type, ///< [in] Tile type 2885 INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo 2886 ) const 2887 { 2888 INT_32 index = curIndex; 2889 2890 if (mode == ADDR_TM_LINEAR_GENERAL) 2891 { 2892 index = TileIndexLinearGeneral; 2893 } 2894 else 2895 { 2896 BOOL_32 macroTiled = IsMacroTiled(mode); 2897 2898 // We need to find a new index if either of them is true 2899 // 1. curIndex is invalid 2900 // 2. tile mode is changed 2901 // 3. tile info does not match for macro tiled 2902 if ((index == TileIndexInvalid || 2903 (mode != m_tileTable[index].mode) || 2904 (macroTiled && (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) == FALSE)))) 2905 { 2906 for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++) 2907 { 2908 if (macroTiled) 2909 { 2910 // macro tile modes need all to match 2911 if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) && 2912 (mode == m_tileTable[index].mode) && 2913 (type == m_tileTable[index].type)) 2914 { 2915 break; 2916 } 2917 } 2918 else if (mode == ADDR_TM_LINEAR_ALIGNED) 2919 { 2920 // linear mode only needs tile mode to match 2921 if (mode == m_tileTable[index].mode) 2922 { 2923 break; 2924 } 2925 } 2926 else 2927 { 2928 // micro tile modes only need tile mode and tile type to match 2929 if (mode == m_tileTable[index].mode && 2930 type == m_tileTable[index].type) 2931 { 2932 break; 2933 } 2934 } 2935 } 2936 } 2937 } 2938 2939 ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries)); 2940 2941 if (index >= static_cast<INT_32>(m_noOfEntries)) 2942 { 2943 index = TileIndexInvalid; 2944 } 2945 2946 return index; 2947 } 2948 2949 /** 2950 **************************************************************************************************** 2951 * SiLib::HwlSetupTileCfg 2952 * 2953 * @brief 2954 * Map tile index to tile setting. 2955 * @return 2956 * ADDR_E_RETURNCODE 2957 **************************************************************************************************** 2958 */ 2959 ADDR_E_RETURNCODE SiLib::HwlSetupTileCfg( 2960 UINT_32 bpp, ///< Bits per pixel 2961 INT_32 index, ///< Tile index 2962 INT_32 macroModeIndex, ///< Index in macro tile mode table(CI) 2963 ADDR_TILEINFO* pInfo, ///< [out] Tile Info 2964 AddrTileMode* pMode, ///< [out] Tile mode 2965 AddrTileType* pType ///< [out] Tile type 2966 ) const 2967 { 2968 ADDR_E_RETURNCODE returnCode = ADDR_OK; 2969 2970 // Global flag to control usage of tileIndex 2971 if (UseTileIndex(index)) 2972 { 2973 if (index == TileIndexLinearGeneral) 2974 { 2975 if (pMode) 2976 { 2977 *pMode = ADDR_TM_LINEAR_GENERAL; 2978 } 2979 2980 if (pType) 2981 { 2982 *pType = ADDR_DISPLAYABLE; 2983 } 2984 2985 if (pInfo) 2986 { 2987 pInfo->banks = 2; 2988 pInfo->bankWidth = 1; 2989 pInfo->bankHeight = 1; 2990 pInfo->macroAspectRatio = 1; 2991 pInfo->tileSplitBytes = 64; 2992 pInfo->pipeConfig = ADDR_PIPECFG_P2; 2993 } 2994 } 2995 else if (static_cast<UINT_32>(index) >= m_noOfEntries) 2996 { 2997 returnCode = ADDR_INVALIDPARAMS; 2998 } 2999 else 3000 { 3001 const TileConfig* pCfgTable = GetTileSetting(index); 3002 3003 if (pInfo) 3004 { 3005 *pInfo = pCfgTable->info; 3006 } 3007 else 3008 { 3009 if (IsMacroTiled(pCfgTable->mode)) 3010 { 3011 returnCode = ADDR_INVALIDPARAMS; 3012 } 3013 } 3014 3015 if (pMode) 3016 { 3017 *pMode = pCfgTable->mode; 3018 } 3019 3020 if (pType) 3021 { 3022 *pType = pCfgTable->type; 3023 } 3024 } 3025 } 3026 3027 return returnCode; 3028 } 3029 3030 /** 3031 **************************************************************************************************** 3032 * SiLib::ReadGbTileMode 3033 * 3034 * @brief 3035 * Convert GB_TILE_MODE HW value to TileConfig. 3036 * @return 3037 * NA. 3038 **************************************************************************************************** 3039 */ 3040 VOID SiLib::ReadGbTileMode( 3041 UINT_32 regValue, ///< [in] GB_TILE_MODE register 3042 TileConfig* pCfg ///< [out] output structure 3043 ) const 3044 { 3045 GB_TILE_MODE gbTileMode; 3046 gbTileMode.val = regValue; 3047 3048 pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode); 3049 pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height; 3050 pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width; 3051 pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1); 3052 pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect; 3053 pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split; 3054 pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1); 3055 3056 UINT_32 regArrayMode = gbTileMode.f.array_mode; 3057 3058 pCfg->mode = static_cast<AddrTileMode>(regArrayMode); 3059 3060 if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK 3061 { 3062 pCfg->mode = ADDR_TM_2D_TILED_XTHICK; 3063 } 3064 else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK 3065 { 3066 pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3); 3067 } 3068 } 3069 3070 /** 3071 **************************************************************************************************** 3072 * SiLib::InitTileSettingTable 3073 * 3074 * @brief 3075 * Initialize the ADDR_TILE_CONFIG table. 3076 * @return 3077 * TRUE if tile table is correctly initialized 3078 **************************************************************************************************** 3079 */ 3080 BOOL_32 SiLib::InitTileSettingTable( 3081 const UINT_32* pCfg, ///< [in] Pointer to table of tile configs 3082 UINT_32 noOfEntries ///< [in] Numbe of entries in the table above 3083 ) 3084 { 3085 BOOL_32 initOk = TRUE; 3086 3087 ADDR_ASSERT(noOfEntries <= TileTableSize); 3088 3089 memset(m_tileTable, 0, sizeof(m_tileTable)); 3090 3091 if (noOfEntries != 0) 3092 { 3093 m_noOfEntries = noOfEntries; 3094 } 3095 else 3096 { 3097 m_noOfEntries = TileTableSize; 3098 } 3099 3100 if (pCfg) // From Client 3101 { 3102 for (UINT_32 i = 0; i < m_noOfEntries; i++) 3103 { 3104 ReadGbTileMode(*(pCfg + i), &m_tileTable[i]); 3105 } 3106 } 3107 else 3108 { 3109 ADDR_ASSERT_ALWAYS(); 3110 initOk = FALSE; 3111 } 3112 3113 if (initOk) 3114 { 3115 ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED); 3116 } 3117 3118 return initOk; 3119 } 3120 3121 /** 3122 **************************************************************************************************** 3123 * SiLib::HwlGetTileIndex 3124 * 3125 * @brief 3126 * Return the virtual/real index for given mode/type/info 3127 * @return 3128 * ADDR_OK if successful. 3129 **************************************************************************************************** 3130 */ 3131 ADDR_E_RETURNCODE SiLib::HwlGetTileIndex( 3132 const ADDR_GET_TILEINDEX_INPUT* pIn, 3133 ADDR_GET_TILEINDEX_OUTPUT* pOut) const 3134 { 3135 ADDR_E_RETURNCODE returnCode = ADDR_OK; 3136 3137 pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType); 3138 3139 return returnCode; 3140 } 3141 3142 /** 3143 **************************************************************************************************** 3144 * SiLib::HwlFmaskPreThunkSurfInfo 3145 * 3146 * @brief 3147 * Some preparation before thunking a ComputeSurfaceInfo call for Fmask 3148 * @return 3149 * ADDR_E_RETURNCODE 3150 **************************************************************************************************** 3151 */ 3152 VOID SiLib::HwlFmaskPreThunkSurfInfo( 3153 const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info 3154 const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info 3155 ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info 3156 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info 3157 ) const 3158 { 3159 pSurfIn->tileIndex = pFmaskIn->tileIndex; 3160 } 3161 3162 /** 3163 **************************************************************************************************** 3164 * SiLib::HwlFmaskPostThunkSurfInfo 3165 * 3166 * @brief 3167 * Copy hwl extra field after calling thunked ComputeSurfaceInfo 3168 * @return 3169 * ADDR_E_RETURNCODE 3170 **************************************************************************************************** 3171 */ 3172 VOID SiLib::HwlFmaskPostThunkSurfInfo( 3173 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info 3174 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info 3175 ) const 3176 { 3177 pFmaskOut->macroModeIndex = TileIndexInvalid; 3178 pFmaskOut->tileIndex = pSurfOut->tileIndex; 3179 } 3180 3181 /** 3182 **************************************************************************************************** 3183 * SiLib::HwlComputeFmaskBits 3184 * @brief 3185 * Computes fmask bits 3186 * @return 3187 * Fmask bits 3188 **************************************************************************************************** 3189 */ 3190 UINT_32 SiLib::HwlComputeFmaskBits( 3191 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, 3192 UINT_32* pNumSamples 3193 ) const 3194 { 3195 UINT_32 numSamples = pIn->numSamples; 3196 UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags); 3197 UINT_32 bpp; 3198 3199 if (numFrags != numSamples) // EQAA 3200 { 3201 ADDR_ASSERT(numFrags <= 8); 3202 3203 if (pIn->resolved == FALSE) 3204 { 3205 if (numFrags == 1) 3206 { 3207 bpp = 1; 3208 numSamples = numSamples == 16 ? 16 : 8; 3209 } 3210 else if (numFrags == 2) 3211 { 3212 ADDR_ASSERT(numSamples >= 4); 3213 3214 bpp = 2; 3215 numSamples = numSamples; 3216 } 3217 else if (numFrags == 4) 3218 { 3219 ADDR_ASSERT(numSamples >= 4); 3220 3221 bpp = 4; 3222 numSamples = numSamples; 3223 } 3224 else // numFrags == 8 3225 { 3226 ADDR_ASSERT(numSamples == 16); 3227 3228 bpp = 4; 3229 numSamples = numSamples; 3230 } 3231 } 3232 else 3233 { 3234 if (numFrags == 1) 3235 { 3236 bpp = (numSamples == 16) ? 16 : 8; 3237 numSamples = 1; 3238 } 3239 else if (numFrags == 2) 3240 { 3241 ADDR_ASSERT(numSamples >= 4); 3242 3243 bpp = numSamples*2; 3244 numSamples = 1; 3245 } 3246 else if (numFrags == 4) 3247 { 3248 ADDR_ASSERT(numSamples >= 4); 3249 3250 bpp = numSamples*4; 3251 numSamples = 1; 3252 } 3253 else // numFrags == 8 3254 { 3255 ADDR_ASSERT(numSamples >= 16); 3256 3257 bpp = 16*4; 3258 numSamples = 1; 3259 } 3260 } 3261 } 3262 else // Normal AA 3263 { 3264 if (pIn->resolved == FALSE) 3265 { 3266 bpp = ComputeFmaskNumPlanesFromNumSamples(numSamples); 3267 numSamples = numSamples == 2 ? 8 : numSamples; 3268 } 3269 else 3270 { 3271 // The same as 8XX 3272 bpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); 3273 numSamples = 1; // 1x sample 3274 } 3275 } 3276 3277 SafeAssign(pNumSamples, numSamples); 3278 3279 return bpp; 3280 } 3281 3282 /** 3283 **************************************************************************************************** 3284 * SiLib::HwlOptimizeTileMode 3285 * 3286 * @brief 3287 * Optimize tile mode on SI 3288 * 3289 * @return 3290 * N/A 3291 * 3292 **************************************************************************************************** 3293 */ 3294 VOID SiLib::HwlOptimizeTileMode( 3295 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure 3296 ) const 3297 { 3298 AddrTileMode tileMode = pInOut->tileMode; 3299 3300 if ((pInOut->flags.needEquation == TRUE) && 3301 (IsMacroTiled(tileMode) == TRUE) && 3302 (pInOut->numSamples <= 1)) 3303 { 3304 UINT_32 thickness = Thickness(tileMode); 3305 3306 if (thickness > 1) 3307 { 3308 tileMode = ADDR_TM_1D_TILED_THICK; 3309 } 3310 else if (pInOut->numSlices > 1) 3311 { 3312 tileMode = ADDR_TM_1D_TILED_THIN1; 3313 } 3314 else 3315 { 3316 tileMode = ADDR_TM_2D_TILED_THIN1; 3317 } 3318 } 3319 3320 if (tileMode != pInOut->tileMode) 3321 { 3322 pInOut->tileMode = tileMode; 3323 } 3324 } 3325 3326 /** 3327 **************************************************************************************************** 3328 * SiLib::HwlOverrideTileMode 3329 * 3330 * @brief 3331 * Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI. 3332 * 3333 * @return 3334 * N/A 3335 * 3336 **************************************************************************************************** 3337 */ 3338 VOID SiLib::HwlOverrideTileMode( 3339 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure 3340 ) const 3341 { 3342 AddrTileMode tileMode = pInOut->tileMode; 3343 3344 switch (tileMode) 3345 { 3346 case ADDR_TM_PRT_TILED_THIN1: 3347 tileMode = ADDR_TM_2D_TILED_THIN1; 3348 break; 3349 3350 case ADDR_TM_PRT_TILED_THICK: 3351 tileMode = ADDR_TM_2D_TILED_THICK; 3352 break; 3353 3354 case ADDR_TM_PRT_2D_TILED_THICK: 3355 tileMode = ADDR_TM_2D_TILED_THICK; 3356 break; 3357 3358 case ADDR_TM_PRT_3D_TILED_THICK: 3359 tileMode = ADDR_TM_3D_TILED_THICK; 3360 break; 3361 3362 default: 3363 break; 3364 } 3365 3366 if (tileMode != pInOut->tileMode) 3367 { 3368 pInOut->tileMode = tileMode; 3369 // Only PRT tile modes are overridden for now. Revisit this once new modes are added above. 3370 pInOut->flags.prt = TRUE; 3371 } 3372 } 3373 3374 /** 3375 **************************************************************************************************** 3376 * SiLib::HwlSetPrtTileMode 3377 * 3378 * @brief 3379 * Set prt tile modes. 3380 * 3381 * @return 3382 * N/A 3383 * 3384 **************************************************************************************************** 3385 */ 3386 VOID SiLib::HwlSetPrtTileMode( 3387 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure 3388 ) const 3389 { 3390 pInOut->tileMode = ADDR_TM_2D_TILED_THIN1; 3391 pInOut->tileType = (pInOut->tileType == ADDR_DEPTH_SAMPLE_ORDER) ? 3392 ADDR_DEPTH_SAMPLE_ORDER : ADDR_NON_DISPLAYABLE; 3393 pInOut->flags.prt = TRUE; 3394 } 3395 3396 /** 3397 **************************************************************************************************** 3398 * SiLib::HwlSelectTileMode 3399 * 3400 * @brief 3401 * Select tile modes. 3402 * 3403 * @return 3404 * N/A 3405 * 3406 **************************************************************************************************** 3407 */ 3408 VOID SiLib::HwlSelectTileMode( 3409 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure 3410 ) const 3411 { 3412 AddrTileMode tileMode; 3413 AddrTileType tileType; 3414 3415 if (pInOut->flags.volume) 3416 { 3417 if (pInOut->numSlices >= 8) 3418 { 3419 tileMode = ADDR_TM_2D_TILED_XTHICK; 3420 } 3421 else if (pInOut->numSlices >= 4) 3422 { 3423 tileMode = ADDR_TM_2D_TILED_THICK; 3424 } 3425 else 3426 { 3427 tileMode = ADDR_TM_2D_TILED_THIN1; 3428 } 3429 tileType = ADDR_NON_DISPLAYABLE; 3430 } 3431 else 3432 { 3433 tileMode = ADDR_TM_2D_TILED_THIN1; 3434 3435 if (pInOut->flags.depth || pInOut->flags.stencil) 3436 { 3437 tileType = ADDR_DEPTH_SAMPLE_ORDER; 3438 } 3439 else if ((pInOut->bpp <= 32) || 3440 (pInOut->flags.display == TRUE) || 3441 (pInOut->flags.overlay == TRUE)) 3442 { 3443 tileType = ADDR_DISPLAYABLE; 3444 } 3445 else 3446 { 3447 tileType = ADDR_NON_DISPLAYABLE; 3448 } 3449 } 3450 3451 if (pInOut->flags.prt) 3452 { 3453 tileMode = ADDR_TM_2D_TILED_THIN1; 3454 tileType = (tileType == ADDR_DISPLAYABLE) ? ADDR_NON_DISPLAYABLE : tileType; 3455 } 3456 3457 pInOut->tileMode = tileMode; 3458 pInOut->tileType = tileType; 3459 3460 // Optimize tile mode if possible 3461 pInOut->flags.opt4Space = TRUE; 3462 3463 // Optimize tile mode if possible 3464 OptimizeTileMode(pInOut); 3465 3466 HwlOverrideTileMode(pInOut); 3467 } 3468 3469 /** 3470 **************************************************************************************************** 3471 * SiLib::HwlGetMaxAlignments 3472 * 3473 * @brief 3474 * Gets maximum alignments 3475 * @return 3476 * ADDR_E_RETURNCODE 3477 **************************************************************************************************** 3478 */ 3479 ADDR_E_RETURNCODE SiLib::HwlGetMaxAlignments( 3480 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure 3481 ) const 3482 { 3483 const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info); 3484 3485 // Initial size is 64 KiB for PRT. 3486 UINT_64 maxBaseAlign = 64 * 1024; 3487 3488 for (UINT_32 i = 0; i < m_noOfEntries; i++) 3489 { 3490 if ((IsMacroTiled(m_tileTable[i].mode) == TRUE) && 3491 (IsPrtTileMode(m_tileTable[i].mode) == FALSE)) 3492 { 3493 // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice. 3494 UINT_32 tileSize = Min(m_tileTable[i].info.tileSplitBytes, 3495 MicroTilePixels * 8 * 16); 3496 3497 UINT_64 baseAlign = tileSize * pipes * m_tileTable[i].info.banks * 3498 m_tileTable[i].info.bankWidth * m_tileTable[i].info.bankHeight; 3499 3500 if (baseAlign > maxBaseAlign) 3501 { 3502 maxBaseAlign = baseAlign; 3503 } 3504 } 3505 } 3506 3507 if (pOut != NULL) 3508 { 3509 pOut->baseAlign = maxBaseAlign; 3510 } 3511 3512 return ADDR_OK; 3513 } 3514 3515 /** 3516 **************************************************************************************************** 3517 * SiLib::HwlComputeSurfaceAlignmentsMacroTiled 3518 * 3519 * @brief 3520 * Hardware layer function to compute alignment request for macro tile mode 3521 * 3522 * @return 3523 * N/A 3524 * 3525 **************************************************************************************************** 3526 */ 3527 VOID SiLib::HwlComputeSurfaceAlignmentsMacroTiled( 3528 AddrTileMode tileMode, ///< [in] tile mode 3529 UINT_32 bpp, ///< [in] bits per pixel 3530 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags 3531 UINT_32 mipLevel, ///< [in] mip level 3532 UINT_32 numSamples, ///< [in] number of samples 3533 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] Surface output 3534 ) const 3535 { 3536 if ((mipLevel == 0) && (flags.prt)) 3537 { 3538 UINT_32 macroTileSize = pOut->blockWidth * pOut->blockHeight * numSamples * bpp / 8; 3539 3540 if (macroTileSize < PrtTileSize) 3541 { 3542 UINT_32 numMacroTiles = PrtTileSize / macroTileSize; 3543 3544 ADDR_ASSERT((PrtTileSize % macroTileSize) == 0); 3545 3546 pOut->pitchAlign *= numMacroTiles; 3547 pOut->baseAlign *= numMacroTiles; 3548 } 3549 } 3550 } 3551 3552 /** 3553 **************************************************************************************************** 3554 * SiLib::InitEquationTable 3555 * 3556 * @brief 3557 * Initialize Equation table. 3558 * 3559 * @return 3560 * N/A 3561 **************************************************************************************************** 3562 */ 3563 VOID SiLib::InitEquationTable() 3564 { 3565 ADDR_EQUATION_KEY equationKeyTable[EquationTableSize]; 3566 memset(equationKeyTable, 0, sizeof(equationKeyTable)); 3567 3568 memset(m_equationTable, 0, sizeof(m_equationTable)); 3569 3570 memset(m_blockWidth, 0, sizeof(m_blockWidth)); 3571 3572 memset(m_blockHeight, 0, sizeof(m_blockHeight)); 3573 3574 memset(m_blockSlices, 0, sizeof(m_blockSlices)); 3575 3576 // Loop all possible bpp 3577 for (UINT_32 log2ElementBytes = 0; log2ElementBytes < MaxNumElementBytes; log2ElementBytes++) 3578 { 3579 // Get bits per pixel 3580 UINT_32 bpp = 1 << (log2ElementBytes + 3); 3581 3582 // Loop all possible tile index 3583 for (INT_32 tileIndex = 0; tileIndex < static_cast<INT_32>(m_noOfEntries); tileIndex++) 3584 { 3585 UINT_32 equationIndex = ADDR_INVALID_EQUATION_INDEX; 3586 3587 TileConfig tileConfig = m_tileTable[tileIndex]; 3588 3589 ADDR_SURFACE_FLAGS flags = {{0}}; 3590 3591 // Compute tile info, hardcode numSamples to 1 because MSAA is not supported 3592 // in swizzle pattern equation 3593 HwlComputeMacroModeIndex(tileIndex, flags, bpp, 1, &tileConfig.info, NULL, NULL); 3594 3595 // Check if the input is supported 3596 if (IsEquationSupported(bpp, tileConfig, tileIndex, log2ElementBytes) == TRUE) 3597 { 3598 ADDR_EQUATION_KEY key = {{0}}; 3599 3600 // Generate swizzle equation key from bpp and tile config 3601 key.fields.log2ElementBytes = log2ElementBytes; 3602 key.fields.tileMode = tileConfig.mode; 3603 // Treat depth micro tile type and non-display micro tile type as the same key 3604 // because they have the same equation actually 3605 key.fields.microTileType = (tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) ? 3606 ADDR_NON_DISPLAYABLE : tileConfig.type; 3607 key.fields.pipeConfig = tileConfig.info.pipeConfig; 3608 key.fields.numBanksLog2 = Log2(tileConfig.info.banks); 3609 key.fields.bankWidth = tileConfig.info.bankWidth; 3610 key.fields.bankHeight = tileConfig.info.bankHeight; 3611 key.fields.macroAspectRatio = tileConfig.info.macroAspectRatio; 3612 key.fields.prt = ((m_chipFamily == ADDR_CHIP_FAMILY_SI) && 3613 ((1 << tileIndex) & SiPrtTileIndexMask)) ? 1 : 0; 3614 3615 // Find in the table if the equation has been built based on the key 3616 for (UINT_32 i = 0; i < m_numEquations; i++) 3617 { 3618 if (key.value == equationKeyTable[i].value) 3619 { 3620 equationIndex = i; 3621 break; 3622 } 3623 } 3624 3625 // If found, just fill the index into the lookup table and no need 3626 // to generate the equation again. Otherwise, generate the equation. 3627 if (equationIndex == ADDR_INVALID_EQUATION_INDEX) 3628 { 3629 ADDR_EQUATION equation; 3630 ADDR_E_RETURNCODE retCode; 3631 3632 memset(&equation, 0, sizeof(ADDR_EQUATION)); 3633 3634 // Generate the equation 3635 if (IsMicroTiled(tileConfig.mode)) 3636 { 3637 retCode = ComputeMicroTileEquation(log2ElementBytes, 3638 tileConfig.mode, 3639 tileConfig.type, 3640 &equation); 3641 } 3642 else 3643 { 3644 retCode = ComputeMacroTileEquation(log2ElementBytes, 3645 tileConfig.mode, 3646 tileConfig.type, 3647 &tileConfig.info, 3648 &equation); 3649 } 3650 // Only fill the equation into the table if the return code is ADDR_OK, 3651 // otherwise if the return code is not ADDR_OK, it indicates this is not 3652 // a valid input, we do nothing but just fill invalid equation index 3653 // into the lookup table. 3654 if (retCode == ADDR_OK) 3655 { 3656 equationIndex = m_numEquations; 3657 ADDR_ASSERT(equationIndex < EquationTableSize); 3658 3659 m_blockSlices[equationIndex] = Thickness(tileConfig.mode); 3660 3661 if (IsMicroTiled(tileConfig.mode)) 3662 { 3663 m_blockWidth[equationIndex] = MicroTileWidth; 3664 m_blockHeight[equationIndex] = MicroTileHeight; 3665 } 3666 else 3667 { 3668 const ADDR_TILEINFO* pTileInfo = &tileConfig.info; 3669 3670 m_blockWidth[equationIndex] = 3671 HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth * 3672 pTileInfo->macroAspectRatio; 3673 m_blockHeight[equationIndex] = 3674 MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks / 3675 pTileInfo->macroAspectRatio; 3676 3677 if (key.fields.prt) 3678 { 3679 UINT_32 macroTileSize = 3680 m_blockWidth[equationIndex] * m_blockHeight[equationIndex] * 3681 bpp / 8; 3682 3683 if (macroTileSize < PrtTileSize) 3684 { 3685 UINT_32 numMacroTiles = PrtTileSize / macroTileSize; 3686 3687 ADDR_ASSERT(macroTileSize == (1u << equation.numBits)); 3688 ADDR_ASSERT((PrtTileSize % macroTileSize) == 0); 3689 3690 UINT_32 numBits = Log2(numMacroTiles); 3691 3692 UINT_32 xStart = Log2(m_blockWidth[equationIndex]) + 3693 log2ElementBytes; 3694 3695 m_blockWidth[equationIndex] *= numMacroTiles; 3696 3697 for (UINT_32 i = 0; i < numBits; i++) 3698 { 3699 equation.addr[equation.numBits + i].valid = 1; 3700 equation.addr[equation.numBits + i].index = xStart + i; 3701 } 3702 3703 equation.numBits += numBits; 3704 } 3705 } 3706 } 3707 3708 equationKeyTable[equationIndex] = key; 3709 m_equationTable[equationIndex] = equation; 3710 3711 m_numEquations++; 3712 } 3713 } 3714 } 3715 3716 // Fill the index into the lookup table, if the combination is not supported 3717 // fill the invalid equation index 3718 m_equationLookupTable[log2ElementBytes][tileIndex] = equationIndex; 3719 } 3720 3721 if (m_chipFamily == ADDR_CHIP_FAMILY_SI) 3722 { 3723 // For tile index 3 which is shared between PRT depth and uncompressed depth 3724 m_uncompressDepthEqIndex = m_numEquations; 3725 3726 for (UINT_32 log2ElemBytes = 0; log2ElemBytes < MaxNumElementBytes; log2ElemBytes++) 3727 { 3728 TileConfig tileConfig = m_tileTable[3]; 3729 ADDR_EQUATION equation; 3730 ADDR_E_RETURNCODE retCode; 3731 3732 memset(&equation, 0, sizeof(ADDR_EQUATION)); 3733 3734 retCode = ComputeMacroTileEquation(log2ElemBytes, 3735 tileConfig.mode, 3736 tileConfig.type, 3737 &tileConfig.info, 3738 &equation); 3739 3740 if (retCode == ADDR_OK) 3741 { 3742 UINT_32 equationIndex = m_numEquations; 3743 ADDR_ASSERT(equationIndex < EquationTableSize); 3744 3745 m_blockSlices[equationIndex] = 1; 3746 3747 const ADDR_TILEINFO* pTileInfo = &tileConfig.info; 3748 3749 m_blockWidth[equationIndex] = 3750 HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth * 3751 pTileInfo->macroAspectRatio; 3752 m_blockHeight[equationIndex] = 3753 MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks / 3754 pTileInfo->macroAspectRatio; 3755 3756 m_equationTable[equationIndex] = equation; 3757 3758 m_numEquations++; 3759 } 3760 } 3761 } 3762 } 3763 } 3764 3765 /** 3766 **************************************************************************************************** 3767 * SiLib::IsEquationSupported 3768 * 3769 * @brief 3770 * Check if it is supported for given bpp and tile config to generate a equation. 3771 * 3772 * @return 3773 * TRUE if supported 3774 **************************************************************************************************** 3775 */ 3776 BOOL_32 SiLib::IsEquationSupported( 3777 UINT_32 bpp, ///< Bits per pixel 3778 TileConfig tileConfig, ///< Tile config 3779 INT_32 tileIndex, ///< Tile index 3780 UINT_32 elementBytesLog2 ///< Log2 of element bytes 3781 ) const 3782 { 3783 BOOL_32 supported = TRUE; 3784 3785 // Linear tile mode is not supported in swizzle pattern equation 3786 if (IsLinear(tileConfig.mode)) 3787 { 3788 supported = FALSE; 3789 } 3790 // These tile modes are for Tex2DArray and Tex3D which has depth (num_slice > 1) use, 3791 // which is not supported in swizzle pattern equation due to slice rotation 3792 else if ((tileConfig.mode == ADDR_TM_2D_TILED_THICK) || 3793 (tileConfig.mode == ADDR_TM_2D_TILED_XTHICK) || 3794 (tileConfig.mode == ADDR_TM_3D_TILED_THIN1) || 3795 (tileConfig.mode == ADDR_TM_3D_TILED_THICK) || 3796 (tileConfig.mode == ADDR_TM_3D_TILED_XTHICK)) 3797 { 3798 supported = FALSE; 3799 } 3800 // Only 8bpp(stencil), 16bpp and 32bpp is supported for depth 3801 else if ((tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) && (bpp > 32)) 3802 { 3803 supported = FALSE; 3804 } 3805 // Tile split is not supported in swizzle pattern equation 3806 else if (IsMacroTiled(tileConfig.mode)) 3807 { 3808 UINT_32 thickness = Thickness(tileConfig.mode); 3809 if (((bpp >> 3) * MicroTilePixels * thickness) > tileConfig.info.tileSplitBytes) 3810 { 3811 supported = FALSE; 3812 } 3813 3814 if ((supported == TRUE) && (m_chipFamily == ADDR_CHIP_FAMILY_SI)) 3815 { 3816 supported = m_EquationSupport[tileIndex][elementBytesLog2]; 3817 } 3818 } 3819 3820 return supported; 3821 } 3822 3823 } // V1 3824 } // Addr 3825