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