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