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