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