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