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