amdgpu/addrlib: add ADDR_ANALYSIS_ASSUME
[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 == FALSE)
1256 {
1257 AddrLib1::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 == FALSE)
1289 {
1290 AddrLib1::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 == FALSE))
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) == FALSE)
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) == FALSE)
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 == FALSE) ||
2204 ((pIn->basePitch != 0) && IsPow2(pIn->basePitch)));
2205 }
2206
2207 if (pIn->basePitch != 0)
2208 {
2209 pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel);
2210 }
2211 }
2212
2213 // pow2Pad is done in PostComputeMipLevel
2214
2215 return TRUE;
2216 }
2217
2218 /**
2219 ***************************************************************************************************
2220 * SiAddrLib::HwlCheckLastMacroTiledLvl
2221 *
2222 * @brief
2223 * Sets pOut->last2DLevel to TRUE if it is
2224 * @note
2225 *
2226 ***************************************************************************************************
2227 */
2228 VOID SiAddrLib::HwlCheckLastMacroTiledLvl(
2229 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
2230 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] Output structure (used as input, too)
2231 ) const
2232 {
2233 // pow2Pad covers all mipmap cases
2234 if (pIn->flags.pow2Pad)
2235 {
2236 ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
2237
2238 UINT_32 nextPitch;
2239 UINT_32 nextHeight;
2240 UINT_32 nextSlices;
2241
2242 AddrTileMode nextTileMode;
2243
2244 if (pIn->mipLevel == 0 || pIn->basePitch == 0)
2245 {
2246 // Base level or fail-safe case (basePitch == 0)
2247 nextPitch = pOut->pitch >> 1;
2248 }
2249 else
2250 {
2251 // Sub levels
2252 nextPitch = pIn->basePitch >> (pIn->mipLevel + 1);
2253 }
2254
2255 // nextHeight must be shifted from this level's original height rather than a pow2 padded
2256 // one but this requires original height stored somewhere (pOut->height)
2257 ADDR_ASSERT(pOut->height != 0);
2258
2259 // next level's height is just current level's >> 1 in pixels
2260 nextHeight = pOut->height >> 1;
2261 // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
2262 // compressed foramts
2263 if (AddrElemLib::IsBlockCompressed(pIn->format))
2264 {
2265 nextHeight = (nextHeight + 3) / 4;
2266 }
2267 nextHeight = NextPow2(nextHeight);
2268
2269 // nextSlices may be 0 if this level's is 1
2270 if (pIn->flags.volume)
2271 {
2272 nextSlices = Max(1u, pIn->numSlices >> 1);
2273 }
2274 else
2275 {
2276 nextSlices = pIn->numSlices;
2277 }
2278
2279 nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode,
2280 pIn->bpp,
2281 nextPitch,
2282 nextHeight,
2283 nextSlices,
2284 pIn->numSamples,
2285 pOut->pitchAlign,
2286 pOut->heightAlign,
2287 pOut->pTileInfo);
2288
2289 pOut->last2DLevel = IsMicroTiled(nextTileMode);
2290 }
2291 }
2292
2293 /**
2294 ***************************************************************************************************
2295 * SiAddrLib::HwlDegradeThickTileMode
2296 *
2297 * @brief
2298 * Degrades valid tile mode for thick modes if needed
2299 *
2300 * @return
2301 * Suitable tile mode
2302 ***************************************************************************************************
2303 */
2304 AddrTileMode SiAddrLib::HwlDegradeThickTileMode(
2305 AddrTileMode baseTileMode, ///< [in] base tile mode
2306 UINT_32 numSlices, ///< [in] current number of slices
2307 UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice
2308 ) const
2309 {
2310 return EgBasedAddrLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile);
2311 }
2312
2313 /**
2314 ***************************************************************************************************
2315 * SiAddrLib::HwlTileInfoEqual
2316 *
2317 * @brief
2318 * Return TRUE if all field are equal
2319 * @note
2320 * Only takes care of current HWL's data
2321 ***************************************************************************************************
2322 */
2323 BOOL_32 SiAddrLib::HwlTileInfoEqual(
2324 const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
2325 const ADDR_TILEINFO* pRight ///<[in] Right compare operand
2326 ) const
2327 {
2328 BOOL_32 equal = FALSE;
2329
2330 if (pLeft->pipeConfig == pRight->pipeConfig)
2331 {
2332 equal = EgBasedAddrLib::HwlTileInfoEqual(pLeft, pRight);
2333 }
2334
2335 return equal;
2336 }
2337
2338 /**
2339 ***************************************************************************************************
2340 * SiAddrLib::GetTileSettings
2341 *
2342 * @brief
2343 * Get tile setting infos by index.
2344 * @return
2345 * Tile setting info.
2346 ***************************************************************************************************
2347 */
2348 const ADDR_TILECONFIG* SiAddrLib::GetTileSetting(
2349 UINT_32 index ///< [in] Tile index
2350 ) const
2351 {
2352 ADDR_ASSERT(index < m_noOfEntries);
2353 return &m_tileTable[index];
2354 }
2355
2356 /**
2357 ***************************************************************************************************
2358 * SiAddrLib::HwlPostCheckTileIndex
2359 *
2360 * @brief
2361 * Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
2362 * tile mode/type/info and change the index if needed
2363 * @return
2364 * Tile index.
2365 ***************************************************************************************************
2366 */
2367 INT_32 SiAddrLib::HwlPostCheckTileIndex(
2368 const ADDR_TILEINFO* pInfo, ///< [in] Tile Info
2369 AddrTileMode mode, ///< [in] Tile mode
2370 AddrTileType type, ///< [in] Tile type
2371 INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo
2372 ) const
2373 {
2374 INT_32 index = curIndex;
2375
2376 if (mode == ADDR_TM_LINEAR_GENERAL)
2377 {
2378 index = TileIndexLinearGeneral;
2379 }
2380 else
2381 {
2382 BOOL_32 macroTiled = IsMacroTiled(mode);
2383
2384 // We need to find a new index if either of them is true
2385 // 1. curIndex is invalid
2386 // 2. tile mode is changed
2387 // 3. tile info does not match for macro tiled
2388 if ((index == TileIndexInvalid ||
2389 (mode != m_tileTable[index].mode) ||
2390 (macroTiled && (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) == FALSE))))
2391 {
2392 for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
2393 {
2394 if (macroTiled)
2395 {
2396 // macro tile modes need all to match
2397 if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) &&
2398 (mode == m_tileTable[index].mode) &&
2399 (type == m_tileTable[index].type))
2400 {
2401 break;
2402 }
2403 }
2404 else if (mode == ADDR_TM_LINEAR_ALIGNED)
2405 {
2406 // linear mode only needs tile mode to match
2407 if (mode == m_tileTable[index].mode)
2408 {
2409 break;
2410 }
2411 }
2412 else
2413 {
2414 // micro tile modes only need tile mode and tile type to match
2415 if (mode == m_tileTable[index].mode &&
2416 type == m_tileTable[index].type)
2417 {
2418 break;
2419 }
2420 }
2421 }
2422 }
2423 }
2424
2425 ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
2426
2427 if (index >= static_cast<INT_32>(m_noOfEntries))
2428 {
2429 index = TileIndexInvalid;
2430 }
2431
2432 return index;
2433 }
2434
2435 /**
2436 ***************************************************************************************************
2437 * SiAddrLib::HwlSetupTileCfg
2438 *
2439 * @brief
2440 * Map tile index to tile setting.
2441 * @return
2442 * ADDR_E_RETURNCODE
2443 ***************************************************************************************************
2444 */
2445 ADDR_E_RETURNCODE SiAddrLib::HwlSetupTileCfg(
2446 UINT_32 bpp, ///< [in] Bits per pixel
2447 INT_32 index, ///< [in] Tile index
2448 INT_32 macroModeIndex, ///< [in] Index in macro tile mode table(CI)
2449 ADDR_TILEINFO* pInfo, ///< [out] Tile Info
2450 AddrTileMode* pMode, ///< [out] Tile mode
2451 AddrTileType* pType ///< [out] Tile type
2452 ) const
2453 {
2454 ADDR_E_RETURNCODE returnCode = ADDR_OK;
2455
2456 // Global flag to control usage of tileIndex
2457 if (UseTileIndex(index))
2458 {
2459 if (index == TileIndexLinearGeneral)
2460 {
2461 if (pMode)
2462 {
2463 *pMode = ADDR_TM_LINEAR_GENERAL;
2464 }
2465
2466 if (pType)
2467 {
2468 *pType = ADDR_DISPLAYABLE;
2469 }
2470
2471 if (pInfo)
2472 {
2473 pInfo->banks = 2;
2474 pInfo->bankWidth = 1;
2475 pInfo->bankHeight = 1;
2476 pInfo->macroAspectRatio = 1;
2477 pInfo->tileSplitBytes = 64;
2478 pInfo->pipeConfig = ADDR_PIPECFG_P2;
2479 }
2480 }
2481 else if (static_cast<UINT_32>(index) >= m_noOfEntries)
2482 {
2483 returnCode = ADDR_INVALIDPARAMS;
2484 }
2485 else
2486 {
2487 const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index);
2488
2489 if (pInfo)
2490 {
2491 *pInfo = pCfgTable->info;
2492 }
2493 else
2494 {
2495 if (IsMacroTiled(pCfgTable->mode))
2496 {
2497 returnCode = ADDR_INVALIDPARAMS;
2498 }
2499 }
2500
2501 if (pMode)
2502 {
2503 *pMode = pCfgTable->mode;
2504 }
2505
2506 if (pType)
2507 {
2508 *pType = pCfgTable->type;
2509 }
2510 }
2511 }
2512
2513 return returnCode;
2514 }
2515
2516 /**
2517 ***************************************************************************************************
2518 * SiAddrLib::ReadGbTileMode
2519 *
2520 * @brief
2521 * Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
2522 * @return
2523 * NA.
2524 ***************************************************************************************************
2525 */
2526 VOID SiAddrLib::ReadGbTileMode(
2527 UINT_32 regValue, ///< [in] GB_TILE_MODE register
2528 ADDR_TILECONFIG* pCfg ///< [out] output structure
2529 ) const
2530 {
2531 GB_TILE_MODE gbTileMode;
2532 gbTileMode.val = regValue;
2533
2534 pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode);
2535 pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height;
2536 pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width;
2537 pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1);
2538 pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
2539 pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
2540 pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
2541
2542 UINT_32 regArrayMode = gbTileMode.f.array_mode;
2543
2544 pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
2545
2546 if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK
2547 {
2548 pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
2549 }
2550 else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK
2551 {
2552 pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3);
2553 }
2554 }
2555
2556 /**
2557 ***************************************************************************************************
2558 * SiAddrLib::InitTileSettingTable
2559 *
2560 * @brief
2561 * Initialize the ADDR_TILE_CONFIG table.
2562 * @return
2563 * TRUE if tile table is correctly initialized
2564 ***************************************************************************************************
2565 */
2566 BOOL_32 SiAddrLib::InitTileSettingTable(
2567 const UINT_32* pCfg, ///< [in] Pointer to table of tile configs
2568 UINT_32 noOfEntries ///< [in] Numbe of entries in the table above
2569 )
2570 {
2571 BOOL_32 initOk = TRUE;
2572
2573 ADDR_ASSERT(noOfEntries <= TileTableSize);
2574
2575 memset(m_tileTable, 0, sizeof(m_tileTable));
2576
2577 if (noOfEntries != 0)
2578 {
2579 m_noOfEntries = noOfEntries;
2580 }
2581 else
2582 {
2583 m_noOfEntries = TileTableSize;
2584 }
2585
2586 if (pCfg) // From Client
2587 {
2588 for (UINT_32 i = 0; i < m_noOfEntries; i++)
2589 {
2590 ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
2591 }
2592 }
2593 else
2594 {
2595 ADDR_ASSERT_ALWAYS();
2596 initOk = FALSE;
2597 }
2598
2599 if (initOk)
2600 {
2601 ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
2602 }
2603
2604 return initOk;
2605 }
2606
2607 /**
2608 ***************************************************************************************************
2609 * SiAddrLib::HwlGetTileIndex
2610 *
2611 * @brief
2612 * Return the virtual/real index for given mode/type/info
2613 * @return
2614 * ADDR_OK if successful.
2615 ***************************************************************************************************
2616 */
2617 ADDR_E_RETURNCODE SiAddrLib::HwlGetTileIndex(
2618 const ADDR_GET_TILEINDEX_INPUT* pIn,
2619 ADDR_GET_TILEINDEX_OUTPUT* pOut) const
2620 {
2621 ADDR_E_RETURNCODE returnCode = ADDR_OK;
2622
2623 pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType);
2624
2625 return returnCode;
2626 }
2627
2628 /**
2629 ***************************************************************************************************
2630 * SiAddrLib::HwlFmaskPreThunkSurfInfo
2631 *
2632 * @brief
2633 * Some preparation before thunking a ComputeSurfaceInfo call for Fmask
2634 * @return
2635 * ADDR_E_RETURNCODE
2636 ***************************************************************************************************
2637 */
2638 VOID SiAddrLib::HwlFmaskPreThunkSurfInfo(
2639 const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info
2640 const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info
2641 ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info
2642 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info
2643 ) const
2644 {
2645 pSurfIn->tileIndex = pFmaskIn->tileIndex;
2646 }
2647
2648 /**
2649 ***************************************************************************************************
2650 * SiAddrLib::HwlFmaskPostThunkSurfInfo
2651 *
2652 * @brief
2653 * Copy hwl extra field after calling thunked ComputeSurfaceInfo
2654 * @return
2655 * ADDR_E_RETURNCODE
2656 ***************************************************************************************************
2657 */
2658 VOID SiAddrLib::HwlFmaskPostThunkSurfInfo(
2659 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info
2660 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info
2661 ) const
2662 {
2663 pFmaskOut->macroModeIndex = TileIndexInvalid;
2664 pFmaskOut->tileIndex = pSurfOut->tileIndex;
2665 }
2666
2667 /**
2668 ***************************************************************************************************
2669 * SiAddrLib::HwlComputeFmaskBits
2670 * @brief
2671 * Computes fmask bits
2672 * @return
2673 * Fmask bits
2674 ***************************************************************************************************
2675 */
2676 UINT_32 SiAddrLib::HwlComputeFmaskBits(
2677 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn,
2678 UINT_32* pNumSamples
2679 ) const
2680 {
2681 UINT_32 numSamples = pIn->numSamples;
2682 UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags);
2683 UINT_32 bpp;
2684
2685 if (numFrags != numSamples) // EQAA
2686 {
2687 ADDR_ASSERT(numFrags <= 8);
2688
2689 if (pIn->resolved == FALSE)
2690 {
2691 if (numFrags == 1)
2692 {
2693 bpp = 1;
2694 numSamples = numSamples == 16 ? 16 : 8;
2695 }
2696 else if (numFrags == 2)
2697 {
2698 ADDR_ASSERT(numSamples >= 4);
2699
2700 bpp = 2;
2701 numSamples = numSamples;
2702 }
2703 else if (numFrags == 4)
2704 {
2705 ADDR_ASSERT(numSamples >= 4);
2706
2707 bpp = 4;
2708 numSamples = numSamples;
2709 }
2710 else // numFrags == 8
2711 {
2712 ADDR_ASSERT(numSamples == 16);
2713
2714 bpp = 4;
2715 numSamples = numSamples;
2716 }
2717 }
2718 else
2719 {
2720 if (numFrags == 1)
2721 {
2722 bpp = (numSamples == 16) ? 16 : 8;
2723 numSamples = 1;
2724 }
2725 else if (numFrags == 2)
2726 {
2727 ADDR_ASSERT(numSamples >= 4);
2728
2729 bpp = numSamples*2;
2730 numSamples = 1;
2731 }
2732 else if (numFrags == 4)
2733 {
2734 ADDR_ASSERT(numSamples >= 4);
2735
2736 bpp = numSamples*4;
2737 numSamples = 1;
2738 }
2739 else // numFrags == 8
2740 {
2741 ADDR_ASSERT(numSamples >= 16);
2742
2743 bpp = 16*4;
2744 numSamples = 1;
2745 }
2746 }
2747 }
2748 else // Normal AA
2749 {
2750 if (pIn->resolved == FALSE)
2751 {
2752 bpp = ComputeFmaskNumPlanesFromNumSamples(numSamples);
2753 numSamples = numSamples == 2 ? 8 : numSamples;
2754 }
2755 else
2756 {
2757 // The same as 8XX
2758 bpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
2759 numSamples = 1; // 1x sample
2760 }
2761 }
2762
2763 SafeAssign(pNumSamples, numSamples);
2764
2765 return bpp;
2766 }
2767
2768 /**
2769 ***************************************************************************************************
2770 * SiAddrLib::HwlOverrideTileMode
2771 *
2772 * @brief
2773 * Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
2774 *
2775 * @return
2776 * Suitable tile mode
2777 *
2778 ***************************************************************************************************
2779 */
2780 BOOL_32 SiAddrLib::HwlOverrideTileMode(
2781 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
2782 AddrTileMode* pTileMode, ///< [in/out] pointer to the tile mode
2783 AddrTileType* pTileType ///< [in/out] pointer to the tile type
2784 ) const
2785 {
2786 BOOL_32 bOverrided = FALSE;
2787 AddrTileMode tileMode = *pTileMode;
2788
2789 switch (tileMode)
2790 {
2791 case ADDR_TM_PRT_TILED_THIN1:
2792 tileMode = ADDR_TM_2D_TILED_THIN1;
2793 break;
2794
2795 case ADDR_TM_PRT_TILED_THICK:
2796 tileMode = ADDR_TM_2D_TILED_THICK;
2797 break;
2798
2799 case ADDR_TM_PRT_2D_TILED_THICK:
2800 tileMode = ADDR_TM_2D_TILED_THICK;
2801 break;
2802
2803 case ADDR_TM_PRT_3D_TILED_THICK:
2804 tileMode = ADDR_TM_3D_TILED_THICK;
2805 break;
2806
2807 default:
2808 break;
2809 }
2810
2811 if (tileMode != *pTileMode)
2812 {
2813 *pTileMode = tileMode;
2814 bOverrided = TRUE;
2815 ADDR_ASSERT(pIn->flags.prt == TRUE);
2816 }
2817
2818 return bOverrided;
2819 }
2820
2821 /**
2822 ***************************************************************************************************
2823 * SiAddrLib::HwlGetMaxAlignments
2824 *
2825 * @brief
2826 * Gets maximum alignments
2827 * @return
2828 * ADDR_E_RETURNCODE
2829 ***************************************************************************************************
2830 */
2831 ADDR_E_RETURNCODE SiAddrLib::HwlGetMaxAlignments(
2832 ADDR_GET_MAX_ALINGMENTS_OUTPUT* pOut ///< [out] output structure
2833 ) const
2834 {
2835 const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
2836
2837 // Initial size is 64 KiB for PRT.
2838 UINT_64 maxBaseAlign = 64 * 1024;
2839
2840 for (UINT_32 i = 0; i < m_noOfEntries; i++)
2841 {
2842 if ((IsMacroTiled(m_tileTable[i].mode) == TRUE) &&
2843 (IsPrtTileMode(m_tileTable[i].mode) == FALSE))
2844 {
2845 // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
2846 UINT_32 tileSize = Min(m_tileTable[i].info.tileSplitBytes,
2847 MicroTilePixels * 8 * 16);
2848
2849 UINT_64 baseAlign = tileSize * pipes * m_tileTable[i].info.banks *
2850 m_tileTable[i].info.bankWidth * m_tileTable[i].info.bankHeight;
2851
2852 if (baseAlign > maxBaseAlign)
2853 {
2854 maxBaseAlign = baseAlign;
2855 }
2856 }
2857 }
2858
2859 if (pOut != NULL)
2860 {
2861 pOut->baseAlign = maxBaseAlign;
2862 }
2863
2864 return ADDR_OK;
2865 }
2866