2 * Copyright © 2014 Advanced Micro Devices, Inc.
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:
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.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
28 ***************************************************************************************************
30 * @brief Contains the implementation for the SiAddrLib class.
31 ***************************************************************************************************
34 #include "siaddrlib.h"
36 #include "si_gb_reg.h"
38 #include "si_ci_vi_merged_enum.h"
41 #include "amdgpu_id.h"
46 ///////////////////////////////////////////////////////////////////////////////////////////////////
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
50 ***************************************************************************************************
54 * Creates an SiAddrLib object.
57 * Returns an SiAddrLib object pointer.
58 ***************************************************************************************************
60 AddrLib
* AddrSIHwlInit(const AddrClient
* pClient
)
62 return SiAddrLib::CreateObj(pClient
);
66 ***************************************************************************************************
67 * SiAddrLib::SiAddrLib
72 ***************************************************************************************************
74 SiAddrLib::SiAddrLib(const AddrClient
* pClient
) :
75 EgBasedAddrLib(pClient
),
80 memset(&m_settings
, 0, sizeof(m_settings
));
84 ***************************************************************************************************
85 * SiAddrLib::~SiAddrLib
89 ***************************************************************************************************
91 SiAddrLib::~SiAddrLib()
96 ***************************************************************************************************
97 * SiAddrLib::HwlGetPipes
103 ***************************************************************************************************
105 UINT_32
SiAddrLib::HwlGetPipes(
106 const ADDR_TILEINFO
* pTileInfo
///< [in] Tile info
113 numPipes
= GetPipePerSurf(pTileInfo
->pipeConfig
);
117 ADDR_ASSERT_ALWAYS();
118 numPipes
= m_pipes
; // Suppose we should still have a global pipes
125 ***************************************************************************************************
126 * SiAddrLib::GetPipePerSurf
128 * get pipe num base on inputing tileinfo->pipeconfig
131 ***************************************************************************************************
133 UINT_32
SiAddrLib::GetPipePerSurf(
134 AddrPipeCfg pipeConfig
///< [in] pipe config
137 UINT_32 numPipes
= 0;
141 case ADDR_PIPECFG_P2
:
144 case ADDR_PIPECFG_P4_8x16
:
145 case ADDR_PIPECFG_P4_16x16
:
146 case ADDR_PIPECFG_P4_16x32
:
147 case ADDR_PIPECFG_P4_32x32
:
150 case ADDR_PIPECFG_P8_16x16_8x16
:
151 case ADDR_PIPECFG_P8_16x32_8x16
:
152 case ADDR_PIPECFG_P8_32x32_8x16
:
153 case ADDR_PIPECFG_P8_16x32_16x16
:
154 case ADDR_PIPECFG_P8_32x32_16x16
:
155 case ADDR_PIPECFG_P8_32x32_16x32
:
156 case ADDR_PIPECFG_P8_32x64_32x32
:
159 case ADDR_PIPECFG_P16_32x32_8x16
:
160 case ADDR_PIPECFG_P16_32x32_16x16
:
164 ADDR_ASSERT(!"Invalid pipe config");
171 ***************************************************************************************************
172 * SiAddrLib::ComputeBankEquation
175 * Compute bank equation
178 * If equation can be computed
179 ***************************************************************************************************
181 ADDR_E_RETURNCODE
SiAddrLib::ComputeBankEquation(
182 UINT_32 log2BytesPP
, ///< [in] log2 of bytes per pixel
183 UINT_32 threshX
, ///< [in] threshold for x channel
184 UINT_32 threshY
, ///< [in] threshold for y channel
185 ADDR_TILEINFO
* pTileInfo
, ///< [in] tile info
186 ADDR_EQUATION
* pEquation
///< [out] bank equation
189 ADDR_E_RETURNCODE retCode
= ADDR_OK
;
191 UINT_32 pipes
= HwlGetPipes(pTileInfo
);
192 UINT_32 bankXStart
= 3 + Log2(pipes
) + Log2(pTileInfo
->bankWidth
);
193 UINT_32 bankYStart
= 3 + Log2(pTileInfo
->bankHeight
);
195 ADDR_CHANNEL_SETTING x3
= InitChannel(1, 0, log2BytesPP
+ bankXStart
);
196 ADDR_CHANNEL_SETTING x4
= InitChannel(1, 0, log2BytesPP
+ bankXStart
+ 1);
197 ADDR_CHANNEL_SETTING x5
= InitChannel(1, 0, log2BytesPP
+ bankXStart
+ 2);
198 ADDR_CHANNEL_SETTING x6
= InitChannel(1, 0, log2BytesPP
+ bankXStart
+ 3);
199 ADDR_CHANNEL_SETTING y3
= InitChannel(1, 1, bankYStart
);
200 ADDR_CHANNEL_SETTING y4
= InitChannel(1, 1, bankYStart
+ 1);
201 ADDR_CHANNEL_SETTING y5
= InitChannel(1, 1, bankYStart
+ 2);
202 ADDR_CHANNEL_SETTING y6
= InitChannel(1, 1, bankYStart
+ 3);
204 x3
.value
= (threshX
> bankXStart
) ? x3
.value
: 0;
205 x4
.value
= (threshX
> bankXStart
+ 1) ? x4
.value
: 0;
206 x5
.value
= (threshX
> bankXStart
+ 2) ? x5
.value
: 0;
207 x6
.value
= (threshX
> bankXStart
+ 3) ? x6
.value
: 0;
208 y3
.value
= (threshY
> bankYStart
) ? y3
.value
: 0;
209 y4
.value
= (threshY
> bankYStart
+ 1) ? y4
.value
: 0;
210 y5
.value
= (threshY
> bankYStart
+ 2) ? y5
.value
: 0;
211 y6
.value
= (threshY
> bankYStart
+ 3) ? y6
.value
: 0;
213 switch (pTileInfo
->banks
)
216 pEquation
->addr
[0] = y6
;
217 pEquation
->xor1
[0] = x3
;
218 pEquation
->addr
[1] = y5
;
219 pEquation
->xor1
[1] = y6
;
220 pEquation
->xor2
[1] = x4
;
221 pEquation
->addr
[2] = y4
;
222 pEquation
->xor1
[2] = x5
;
223 pEquation
->addr
[3] = y3
;
224 pEquation
->xor1
[3] = x6
;
225 pEquation
->numBits
= 4;
228 pEquation
->addr
[0] = y5
;
229 pEquation
->xor1
[0] = x3
;
230 pEquation
->addr
[1] = y4
;
231 pEquation
->xor1
[1] = y5
;
232 pEquation
->xor2
[1] = x4
;
233 pEquation
->addr
[2] = y3
;
234 pEquation
->xor1
[2] = x5
;
235 pEquation
->numBits
= 3;
238 pEquation
->addr
[0] = y4
;
239 pEquation
->xor1
[0] = x3
;
240 pEquation
->addr
[1] = y3
;
241 pEquation
->xor1
[1] = x4
;
242 pEquation
->numBits
= 2;
245 pEquation
->addr
[0] = y3
;
246 pEquation
->xor1
[0] = x3
;
247 pEquation
->numBits
= 1;
250 pEquation
->numBits
= 0;
251 retCode
= ADDR_NOTSUPPORTED
;
252 ADDR_ASSERT_ALWAYS();
256 for (UINT_32 i
= 0; i
< pEquation
->numBits
; i
++)
258 if (pEquation
->addr
[i
].value
== 0)
260 if (pEquation
->xor1
[i
].value
== 0)
263 pEquation
->addr
[i
].value
= pEquation
->xor2
[i
].value
;
264 pEquation
->xor2
[i
].value
= 0;
268 pEquation
->addr
[i
].value
= pEquation
->xor1
[i
].value
;
270 if (pEquation
->xor2
[i
].value
!= 0)
273 pEquation
->xor1
[i
].value
= pEquation
->xor2
[i
].value
;
274 pEquation
->xor2
[i
].value
= 0;
279 pEquation
->xor1
[i
].value
= 0;
283 else if (pEquation
->xor1
[i
].value
== 0)
285 if (pEquation
->xor2
[i
].value
!= 0)
288 pEquation
->xor1
[i
].value
= pEquation
->xor2
[i
].value
;
289 pEquation
->xor2
[i
].value
= 0;
294 if ((pTileInfo
->bankWidth
== 1) &&
295 ((pTileInfo
->pipeConfig
== ADDR_PIPECFG_P4_32x32
) ||
296 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x64_32x32
)))
298 retCode
= ADDR_NOTSUPPORTED
;
305 ***************************************************************************************************
306 * SiAddrLib::ComputePipeEquation
309 * Compute pipe equation
312 * If equation can be computed
313 ***************************************************************************************************
315 ADDR_E_RETURNCODE
SiAddrLib::ComputePipeEquation(
316 UINT_32 log2BytesPP
, ///< [in] Log2 of bytes per pixel
317 UINT_32 threshX
, ///< [in] Threshold for X channel
318 UINT_32 threshY
, ///< [in] Threshold for Y channel
319 ADDR_TILEINFO
* pTileInfo
, ///< [in] Tile info
320 ADDR_EQUATION
* pEquation
///< [out] Pipe configure
323 ADDR_E_RETURNCODE retCode
= ADDR_OK
;
325 ADDR_CHANNEL_SETTING
* pAddr
= pEquation
->addr
;
326 ADDR_CHANNEL_SETTING
* pXor1
= pEquation
->xor1
;
327 ADDR_CHANNEL_SETTING
* pXor2
= pEquation
->xor2
;
329 ADDR_CHANNEL_SETTING x3
= InitChannel(1, 0, 3 + log2BytesPP
);
330 ADDR_CHANNEL_SETTING x4
= InitChannel(1, 0, 4 + log2BytesPP
);
331 ADDR_CHANNEL_SETTING x5
= InitChannel(1, 0, 5 + log2BytesPP
);
332 ADDR_CHANNEL_SETTING x6
= InitChannel(1, 0, 6 + log2BytesPP
);
333 ADDR_CHANNEL_SETTING y3
= InitChannel(1, 1, 3);
334 ADDR_CHANNEL_SETTING y4
= InitChannel(1, 1, 4);
335 ADDR_CHANNEL_SETTING y5
= InitChannel(1, 1, 5);
336 ADDR_CHANNEL_SETTING y6
= InitChannel(1, 1, 6);
338 x3
.value
= (threshX
> 3) ? x3
.value
: 0;
339 x4
.value
= (threshX
> 4) ? x4
.value
: 0;
340 x5
.value
= (threshX
> 5) ? x5
.value
: 0;
341 x6
.value
= (threshX
> 6) ? x6
.value
: 0;
342 y3
.value
= (threshY
> 3) ? y3
.value
: 0;
343 y4
.value
= (threshY
> 4) ? y4
.value
: 0;
344 y5
.value
= (threshY
> 5) ? y5
.value
: 0;
345 y6
.value
= (threshY
> 6) ? y6
.value
: 0;
347 switch (pTileInfo
->pipeConfig
)
349 case ADDR_PIPECFG_P2
:
352 pEquation
->numBits
= 1;
354 case ADDR_PIPECFG_P4_8x16
:
359 pEquation
->numBits
= 2;
361 case ADDR_PIPECFG_P4_16x16
:
367 pEquation
->numBits
= 2;
369 case ADDR_PIPECFG_P4_16x32
:
375 pEquation
->numBits
= 2;
377 case ADDR_PIPECFG_P4_32x32
:
383 pEquation
->numBits
= 2;
385 case ADDR_PIPECFG_P8_16x16_8x16
:
391 pEquation
->numBits
= 3;
393 case ADDR_PIPECFG_P8_16x32_8x16
:
401 pEquation
->numBits
= 3;
403 case ADDR_PIPECFG_P8_16x32_16x16
:
411 pEquation
->numBits
= 3;
413 case ADDR_PIPECFG_P8_32x32_8x16
:
421 pEquation
->numBits
= 3;
423 case ADDR_PIPECFG_P8_32x32_16x16
:
431 pEquation
->numBits
= 3;
433 case ADDR_PIPECFG_P8_32x32_16x32
:
441 pEquation
->numBits
= 3;
443 case ADDR_PIPECFG_P8_32x64_32x32
:
451 pEquation
->numBits
= 3;
453 case ADDR_PIPECFG_P16_32x32_8x16
:
462 pEquation
->numBits
= 4;
464 case ADDR_PIPECFG_P16_32x32_16x16
:
474 pEquation
->numBits
= 4;
477 ADDR_UNHANDLED_CASE();
478 pEquation
->numBits
= 0;
479 retCode
= ADDR_NOTSUPPORTED
;
483 for (UINT_32 i
= 0; i
< pEquation
->numBits
; i
++)
485 if (pAddr
[i
].value
== 0)
487 if (pXor1
[i
].value
== 0)
489 pAddr
[i
].value
= pXor2
[i
].value
;
493 pAddr
[i
].value
= pXor1
[i
].value
;
503 ***************************************************************************************************
504 * SiAddrLib::ComputePipeFromCoord
507 * Compute pipe number from coordinates
510 ***************************************************************************************************
512 UINT_32
SiAddrLib::ComputePipeFromCoord(
513 UINT_32 x
, ///< [in] x coordinate
514 UINT_32 y
, ///< [in] y coordinate
515 UINT_32 slice
, ///< [in] slice index
516 AddrTileMode tileMode
, ///< [in] tile mode
517 UINT_32 pipeSwizzle
, ///< [in] pipe swizzle
518 BOOL_32 ignoreSE
, ///< [in] TRUE if shader engines are ignored
519 ADDR_TILEINFO
* pTileInfo
///< [in] Tile info
523 UINT_32 pipeBit0
= 0;
524 UINT_32 pipeBit1
= 0;
525 UINT_32 pipeBit2
= 0;
526 UINT_32 pipeBit3
= 0;
527 UINT_32 sliceRotation
;
528 UINT_32 numPipes
= 0;
530 UINT_32 tx
= x
/ MicroTileWidth
;
531 UINT_32 ty
= y
/ MicroTileHeight
;
532 UINT_32 x3
= _BIT(tx
,0);
533 UINT_32 x4
= _BIT(tx
,1);
534 UINT_32 x5
= _BIT(tx
,2);
535 UINT_32 x6
= _BIT(tx
,3);
536 UINT_32 y3
= _BIT(ty
,0);
537 UINT_32 y4
= _BIT(ty
,1);
538 UINT_32 y5
= _BIT(ty
,2);
539 UINT_32 y6
= _BIT(ty
,3);
541 switch (pTileInfo
->pipeConfig
)
543 case ADDR_PIPECFG_P2
:
547 case ADDR_PIPECFG_P4_8x16
:
552 case ADDR_PIPECFG_P4_16x16
:
553 pipeBit0
= x3
^ y3
^ x4
;
557 case ADDR_PIPECFG_P4_16x32
:
558 pipeBit0
= x3
^ y3
^ x4
;
562 case ADDR_PIPECFG_P4_32x32
:
563 pipeBit0
= x3
^ y3
^ x5
;
567 case ADDR_PIPECFG_P8_16x16_8x16
:
568 pipeBit0
= x4
^ y3
^ x5
;
572 case ADDR_PIPECFG_P8_16x32_8x16
:
573 pipeBit0
= x4
^ y3
^ x5
;
578 case ADDR_PIPECFG_P8_16x32_16x16
:
579 pipeBit0
= x3
^ y3
^ x4
;
584 case ADDR_PIPECFG_P8_32x32_8x16
:
585 pipeBit0
= x4
^ y3
^ x5
;
590 case ADDR_PIPECFG_P8_32x32_16x16
:
591 pipeBit0
= x3
^ y3
^ x4
;
596 case ADDR_PIPECFG_P8_32x32_16x32
:
597 pipeBit0
= x3
^ y3
^ x4
;
602 case ADDR_PIPECFG_P8_32x64_32x32
:
603 pipeBit0
= x3
^ y3
^ x5
;
608 case ADDR_PIPECFG_P16_32x32_8x16
:
615 case ADDR_PIPECFG_P16_32x32_16x16
:
616 pipeBit0
= x3
^ y3
^ x4
;
623 ADDR_UNHANDLED_CASE();
626 pipe
= pipeBit0
| (pipeBit1
<< 1) | (pipeBit2
<< 2) | (pipeBit3
<< 3);
628 UINT_32 microTileThickness
= Thickness(tileMode
);
631 // Apply pipe rotation for the slice.
635 case ADDR_TM_3D_TILED_THIN1
: //fall through thin
636 case ADDR_TM_3D_TILED_THICK
: //fall through thick
637 case ADDR_TM_3D_TILED_XTHICK
:
639 Max(1, static_cast<INT_32
>(numPipes
/ 2) - 1) * (slice
/ microTileThickness
);
645 pipeSwizzle
+= sliceRotation
;
646 pipeSwizzle
&= (numPipes
- 1);
648 pipe
= pipe
^ pipeSwizzle
;
654 ***************************************************************************************************
655 * SiAddrLib::ComputeTileCoordFromPipeAndElemIdx
658 * Compute (x,y) of a tile within a macro tile from address
661 ***************************************************************************************************
663 VOID
SiAddrLib::ComputeTileCoordFromPipeAndElemIdx(
664 UINT_32 elemIdx
, ///< [in] per pipe element index within a macro tile
665 UINT_32 pipe
, ///< [in] pipe index
666 AddrPipeCfg pipeCfg
, ///< [in] pipe config
667 UINT_32 pitchInMacroTile
, ///< [in] surface pitch in macro tile
668 UINT_32 x
, ///< [in] x coordinate of the (0,0) tile in a macro tile
669 UINT_32 y
, ///< [in] y coordinate of the (0,0) tile in a macro tile
670 UINT_32
* pX
, ///< [out] x coordinate
671 UINT_32
* pY
///< [out] y coordinate
674 UINT_32 pipebit0
= _BIT(pipe
,0);
675 UINT_32 pipebit1
= _BIT(pipe
,1);
676 UINT_32 pipebit2
= _BIT(pipe
,2);
677 UINT_32 pipebit3
= _BIT(pipe
,3);
678 UINT_32 elemIdx0
= _BIT(elemIdx
,0);
679 UINT_32 elemIdx1
= _BIT(elemIdx
,1);
680 UINT_32 elemIdx2
= _BIT(elemIdx
,2);
692 case ADDR_PIPECFG_P2
:
697 *pY
= Bits2Number(2, y4
, y3
);
698 *pX
= Bits2Number(2, x4
, x3
);
700 case ADDR_PIPECFG_P4_8x16
:
705 *pY
= Bits2Number(2, y4
, y3
);
706 *pX
= Bits2Number(2, x4
, x3
);
708 case ADDR_PIPECFG_P4_16x16
:
712 x3
= pipebit0
^ y3
^ x4
;
713 *pY
= Bits2Number(2, y4
, y3
);
714 *pX
= Bits2Number(2, x4
, x3
);
716 case ADDR_PIPECFG_P4_16x32
:
717 x3
= elemIdx0
^ pipebit0
;
720 y3
= pipebit0
^ x3
^ x4
;
722 *pY
= Bits2Number(2, y4
, y3
);
723 *pX
= Bits2Number(2, x4
, x3
);
725 case ADDR_PIPECFG_P4_32x32
:
729 if((pitchInMacroTile
% 2) == 0)
733 x3
= pipebit0
^ y3
^ x5
;
734 *pY
= Bits2Number(2, y4
, y3
);
735 *pX
= Bits2Number(3, x5
, x4
, x3
);
740 x3
= pipebit0
^ y3
^ x5
;
741 *pY
= Bits2Number(2, y4
, y3
);
742 *pX
= Bits2Number(2, x4
, x3
);
745 case ADDR_PIPECFG_P8_16x16_8x16
:
751 y3
= pipebit0
^ x5
^ x4
;
752 *pY
= Bits2Number(2, y4
, y3
);
753 *pX
= Bits2Number(2, x4
, x3
);
755 case ADDR_PIPECFG_P8_16x32_8x16
:
761 y3
= pipebit0
^ x4
^ x5
;
762 *pY
= Bits2Number(2, y4
, y3
);
763 *pX
= Bits2Number(2, x4
, x3
);
765 case ADDR_PIPECFG_P8_32x32_8x16
:
769 if((pitchInMacroTile
% 2) == 0)
774 y3
= pipebit0
^ x4
^ x5
;
775 *pY
= Bits2Number(2, y4
, y3
);
776 *pX
= Bits2Number(3, x5
, x4
, x3
);
781 y3
= pipebit0
^ x4
^ x5
;
782 *pY
= Bits2Number(2, y4
, y3
);
783 *pX
= Bits2Number(2, x4
, x3
);
786 case ADDR_PIPECFG_P8_16x32_16x16
:
792 y3
= pipebit0
^ x3
^ x4
;
793 *pY
= Bits2Number(2, y4
, y3
);
794 *pX
= Bits2Number(2, x4
, x3
);
796 case ADDR_PIPECFG_P8_32x32_16x16
:
801 if((pitchInMacroTile
% 2) == 0)
805 *pY
= Bits2Number(2, y4
, y3
);
806 *pX
= Bits2Number(3, x5
, x4
, x3
);
810 *pY
= Bits2Number(2, y4
, y3
);
811 *pX
= Bits2Number(2, x4
, x3
);
814 case ADDR_PIPECFG_P8_32x32_16x32
:
815 if((pitchInMacroTile
% 2) == 0)
822 x3
= pipebit0
^ y3
^ x4
;
824 *pY
= Bits2Number(2, y4
, y3
);
825 *pX
= Bits2Number(3, x5
, x4
, x3
);
833 x3
= pipebit0
^ y3
^ x4
;
834 *pY
= Bits2Number(2, y4
, y3
);
835 *pX
= Bits2Number(2, x4
, x3
);
838 case ADDR_PIPECFG_P8_32x64_32x32
:
842 if((pitchInMacroTile
% 4) == 0)
848 x3
= pipebit0
^ y3
^ x5
;
849 *pY
= Bits2Number(2, y4
, y3
);
850 *pX
= Bits2Number(4, x6
, x5
, x4
, x3
);
856 x3
= pipebit0
^ y3
^ x5
;
857 *pY
= Bits2Number(2, y4
, y3
);
858 *pX
= Bits2Number(3, x5
, x4
, x3
);
861 case ADDR_PIPECFG_P16_32x32_8x16
:
866 if((pitchInMacroTile
% 4) == 0)
872 *pY
= Bits2Number(2, y4
, y3
);
873 *pX
= Bits2Number(4, x6
, x5
,x4
, x3
);
879 *pY
= Bits2Number(2, y4
, y3
);
880 *pX
= Bits2Number(3, x5
, x4
, x3
);
883 case ADDR_PIPECFG_P16_32x32_16x16
:
887 x3
= pipebit0
^ y3
^ x4
;
888 if((pitchInMacroTile
% 4) == 0)
894 *pY
= Bits2Number(2, y4
, y3
);
895 *pX
= Bits2Number(4, x6
, x5
, x4
, x3
);
901 *pY
= Bits2Number(2, y4
, y3
);
902 *pX
= Bits2Number(3, x5
, x4
, x3
);
906 ADDR_UNHANDLED_CASE();
911 ***************************************************************************************************
912 * SiAddrLib::TileCoordToMaskElementIndex
915 * Compute element index from coordinates in tiles
918 ***************************************************************************************************
920 UINT_32
SiAddrLib::TileCoordToMaskElementIndex(
921 UINT_32 tx
, ///< [in] x coord, in Tiles
922 UINT_32 ty
, ///< [in] y coord, in Tiles
923 AddrPipeCfg pipeConfig
, ///< [in] pipe config
924 UINT_32
* macroShift
, ///< [out] macro shift
925 UINT_32
* elemIdxBits
///< [out] tile offset bits
929 UINT_32 elemIdx0
, elemIdx1
, elemIdx2
;
940 case ADDR_PIPECFG_P2
:
944 elemIdx1
= tx1
^ ty1
;
945 elemIdx0
= tx1
^ ty0
;
946 elemIdx
= Bits2Number(3,elemIdx2
,elemIdx1
,elemIdx0
);
948 case ADDR_PIPECFG_P4_8x16
:
952 elemIdx0
= tx1
^ ty1
;
953 elemIdx
= Bits2Number(2,elemIdx1
,elemIdx0
);
955 case ADDR_PIPECFG_P4_16x16
:
960 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
962 case ADDR_PIPECFG_P4_16x32
:
967 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
969 case ADDR_PIPECFG_P4_32x32
:
975 elemIdx
= Bits2Number(3, elemIdx2
, elemIdx1
, elemIdx0
);
977 case ADDR_PIPECFG_P8_16x16_8x16
:
983 case ADDR_PIPECFG_P8_16x32_8x16
:
989 case ADDR_PIPECFG_P8_32x32_8x16
:
994 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
996 case ADDR_PIPECFG_P8_16x32_16x16
:
1002 case ADDR_PIPECFG_P8_32x32_16x16
:
1007 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
1009 case ADDR_PIPECFG_P8_32x32_16x32
:
1014 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
1016 case ADDR_PIPECFG_P8_32x64_32x32
:
1022 elemIdx
= Bits2Number(3, elemIdx2
, elemIdx1
, elemIdx0
);
1024 case ADDR_PIPECFG_P16_32x32_8x16
:
1029 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
1031 case ADDR_PIPECFG_P16_32x32_16x16
:
1036 elemIdx
= Bits2Number(2, elemIdx1
, elemIdx0
);
1039 ADDR_UNHANDLED_CASE();
1047 ***************************************************************************************************
1048 * SiAddrLib::HwlComputeTileDataWidthAndHeightLinear
1051 * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1057 * MacroWidth and macroHeight are measured in pixels
1058 ***************************************************************************************************
1060 VOID
SiAddrLib::HwlComputeTileDataWidthAndHeightLinear(
1061 UINT_32
* pMacroWidth
, ///< [out] macro tile width
1062 UINT_32
* pMacroHeight
, ///< [out] macro tile height
1063 UINT_32 bpp
, ///< [in] bits per pixel
1064 ADDR_TILEINFO
* pTileInfo
///< [in] tile info
1067 ADDR_ASSERT(pTileInfo
!= NULL
);
1069 UINT_32 macroHeight
;
1071 /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles
1072 /// but for P8_32x64_32x32, it must be padded out to 8 tiles
1073 /// Actually there are more pipe configs which need 8-tile padding but SI family
1074 /// has a bug which is fixed in CI family
1075 if ((pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x64_32x32
) ||
1076 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P16_32x32_8x16
) ||
1077 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x32_16x16
))
1079 macroWidth
= 8*MicroTileWidth
;
1080 macroHeight
= 8*MicroTileHeight
;
1084 macroWidth
= 4*MicroTileWidth
;
1085 macroHeight
= 4*MicroTileHeight
;
1088 *pMacroWidth
= macroWidth
;
1089 *pMacroHeight
= macroHeight
;
1093 ***************************************************************************************************
1094 * SiAddrLib::HwlComputeHtileBytes
1097 * Compute htile size in bytes
1100 * Htile size in bytes
1101 ***************************************************************************************************
1103 UINT_64
SiAddrLib::HwlComputeHtileBytes(
1104 UINT_32 pitch
, ///< [in] pitch
1105 UINT_32 height
, ///< [in] height
1106 UINT_32 bpp
, ///< [in] bits per pixel
1107 BOOL_32 isLinear
, ///< [in] if it is linear mode
1108 UINT_32 numSlices
, ///< [in] number of slices
1109 UINT_64
* pSliceBytes
, ///< [out] bytes per slice
1110 UINT_32 baseAlign
///< [in] base alignments
1113 return ComputeHtileBytes(pitch
, height
, bpp
, isLinear
, numSlices
, pSliceBytes
, baseAlign
);
1117 ***************************************************************************************************
1118 * SiAddrLib::HwlComputeXmaskAddrFromCoord
1121 * Compute address from coordinates for htile/cmask
1124 ***************************************************************************************************
1126 UINT_64
SiAddrLib::HwlComputeXmaskAddrFromCoord(
1127 UINT_32 pitch
, ///< [in] pitch
1128 UINT_32 height
, ///< [in] height
1129 UINT_32 x
, ///< [in] x coord
1130 UINT_32 y
, ///< [in] y coord
1131 UINT_32 slice
, ///< [in] slice/depth index
1132 UINT_32 numSlices
, ///< [in] number of slices
1133 UINT_32 factor
, ///< [in] factor that indicates cmask(2) or htile(1)
1134 BOOL_32 isLinear
, ///< [in] linear or tiled HTILE layout
1135 BOOL_32 isWidth8
, ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1136 BOOL_32 isHeight8
, ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1137 ADDR_TILEINFO
* pTileInfo
, ///< [in] Tile info
1138 UINT_32
* pBitPosition
///< [out] bit position inside a byte
1141 UINT_32 tx
= x
/ MicroTileWidth
;
1142 UINT_32 ty
= y
/ MicroTileHeight
;
1147 UINT_32 macroHeight
;
1148 UINT_64 pSliceBytes
;
1150 UINT_32 tileNumPerPipe
;
1153 if (factor
== 2) //CMASK
1155 ADDR_CMASK_FLAGS flags
= {{0}};
1157 tileNumPerPipe
= 256;
1159 ComputeCmaskInfo(flags
,
1170 elemBits
= CmaskElemBits
;
1174 ADDR_HTILE_FLAGS flags
= {{0}};
1176 tileNumPerPipe
= 512;
1178 ComputeHtileInfo(flags
,
1196 const UINT_32 pitchInTile
= newPitch
/ MicroTileWidth
;
1197 const UINT_32 heightInTile
= newHeight
/ MicroTileWidth
;
1198 UINT_64 macroOffset
; // Per pipe starting offset of the macro tile in which this tile lies.
1199 UINT_64 microNumber
; // Per pipe starting offset of the macro tile in which this tile lies.
1202 UINT_64 microOffset
;
1204 UINT_64 totalOffset
;
1205 UINT_32 elemIdxBits
;
1207 TileCoordToMaskElementIndex(tx
, ty
, pTileInfo
->pipeConfig
, µShift
, &elemIdxBits
);
1209 UINT_32 numPipes
= HwlGetPipes(pTileInfo
);
1212 { //linear addressing
1213 // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full
1214 // slice memory foot print instead of divided by numPipes.
1215 microX
= tx
/ 4; // Macro Tile is 4x4
1217 microNumber
= static_cast<UINT_64
>(microX
+ microY
* (pitchInTile
/ 4)) << microShift
;
1219 UINT_32 sliceBits
= pitchInTile
* heightInTile
;
1221 // do htile single slice alignment if the flag is true
1222 if (m_configFlags
.useHtileSliceAlign
&& (factor
== 1)) //Htile
1224 sliceBits
= PowTwoAlign(sliceBits
, BITS_TO_BYTES(HtileCacheBits
) * numPipes
/ elemBits
);
1226 macroOffset
= slice
* (sliceBits
/ numPipes
) * elemBits
;
1229 { //tiled addressing
1230 const UINT_32 macroWidthInTile
= macroWidth
/ MicroTileWidth
; // Now in unit of Tiles
1231 const UINT_32 macroHeightInTile
= macroHeight
/ MicroTileHeight
;
1232 const UINT_32 pitchInCL
= pitchInTile
/ macroWidthInTile
;
1233 const UINT_32 heightInCL
= heightInTile
/ macroHeightInTile
;
1235 const UINT_32 macroX
= x
/ macroWidth
;
1236 const UINT_32 macroY
= y
/ macroHeight
;
1237 const UINT_32 macroNumber
= macroX
+ macroY
* pitchInCL
+ slice
* pitchInCL
* heightInCL
;
1239 // Per pipe starting offset of the cache line in which this tile lies.
1240 microX
= (x
% macroWidth
) / MicroTileWidth
/ 4; // Macro Tile is 4x4
1241 microY
= (y
% macroHeight
) / MicroTileHeight
/ 4 ;
1242 microNumber
= static_cast<UINT_64
>(microX
+ microY
* (macroWidth
/ MicroTileWidth
/ 4)) << microShift
;
1244 macroOffset
= macroNumber
* tileNumPerPipe
* elemBits
;
1247 if(elemIdxBits
== microShift
)
1249 microNumber
+= elemIdx
;
1253 microNumber
>>= elemIdxBits
;
1254 microNumber
<<= elemIdxBits
;
1255 microNumber
+= elemIdx
;
1258 microOffset
= elemBits
* microNumber
;
1259 totalOffset
= microOffset
+ macroOffset
;
1261 UINT_32 pipe
= ComputePipeFromCoord(x
, y
, 0, ADDR_TM_2D_TILED_THIN1
, 0, FALSE
, pTileInfo
);
1262 UINT_64 addrInBits
= totalOffset
% (m_pipeInterleaveBytes
* 8) +
1263 pipe
* (m_pipeInterleaveBytes
* 8) +
1264 totalOffset
/ (m_pipeInterleaveBytes
* 8) * (m_pipeInterleaveBytes
* 8) * numPipes
;
1265 *pBitPosition
= static_cast<UINT_32
>(addrInBits
) % 8;
1266 UINT_64 addr
= addrInBits
/ 8;
1272 ***************************************************************************************************
1273 * SiAddrLib::HwlComputeXmaskCoordFromAddr
1276 * Compute the coord from an address of a cmask/htile
1282 * This method is reused by htile, so rename to Xmask
1283 ***************************************************************************************************
1285 VOID
SiAddrLib::HwlComputeXmaskCoordFromAddr(
1286 UINT_64 addr
, ///< [in] address
1287 UINT_32 bitPosition
, ///< [in] bitPosition in a byte
1288 UINT_32 pitch
, ///< [in] pitch
1289 UINT_32 height
, ///< [in] height
1290 UINT_32 numSlices
, ///< [in] number of slices
1291 UINT_32 factor
, ///< [in] factor that indicates cmask or htile
1292 BOOL_32 isLinear
, ///< [in] linear or tiled HTILE layout
1293 BOOL_32 isWidth8
, ///< [in] Not used by SI
1294 BOOL_32 isHeight8
, ///< [in] Not used by SI
1295 ADDR_TILEINFO
* pTileInfo
, ///< [in] Tile info
1296 UINT_32
* pX
, ///< [out] x coord
1297 UINT_32
* pY
, ///< [out] y coord
1298 UINT_32
* pSlice
///< [out] slice index
1306 UINT_32 tileNumPerPipe
;
1313 if (factor
== 2) //CMASK
1315 ADDR_CMASK_FLAGS flags
= {{0}};
1317 tileNumPerPipe
= 256;
1319 ComputeCmaskInfo(flags
,
1333 ADDR_HTILE_FLAGS flags
= {{0}};
1335 tileNumPerPipe
= 512;
1337 ComputeHtileInfo(flags
,
1353 const UINT_32 pitchInTile
= newPitch
/ MicroTileWidth
;
1354 const UINT_32 heightInTile
= newHeight
/ MicroTileWidth
;
1355 const UINT_32 pitchInMacroTile
= pitchInTile
/ 4;
1357 UINT_32 elemIdxBits
;
1358 // get macroShift and elemIdxBits
1359 TileCoordToMaskElementIndex(0, 0, pTileInfo
->pipeConfig
, ¯oShift
, &elemIdxBits
);
1361 const UINT_32 numPipes
= HwlGetPipes(pTileInfo
);
1362 const UINT_32 pipe
= (UINT_32
)((addr
/ m_pipeInterleaveBytes
) % numPipes
);
1364 UINT_64 localOffset
= (addr
% m_pipeInterleaveBytes
) +
1365 (addr
/ m_pipeInterleaveBytes
/ numPipes
)* m_pipeInterleaveBytes
;
1368 if (factor
== 2) //CMASK
1370 tileIndex
= (UINT_32
)(localOffset
* 2 + (bitPosition
!= 0));
1374 tileIndex
= (UINT_32
)(localOffset
/ 4);
1377 UINT_32 macroOffset
;
1380 UINT_32 sliceSizeInTile
= pitchInTile
* heightInTile
;
1382 // do htile single slice alignment if the flag is true
1383 if (m_configFlags
.useHtileSliceAlign
&& (factor
== 1)) //Htile
1385 sliceSizeInTile
= PowTwoAlign(sliceSizeInTile
, static_cast<UINT_32
>(sliceBytes
) / 64);
1387 *pSlice
= tileIndex
/ (sliceSizeInTile
/ numPipes
);
1388 macroOffset
= tileIndex
% (sliceSizeInTile
/ numPipes
);
1392 const UINT_32 clWidthInTile
= clWidth
/ MicroTileWidth
; // Now in unit of Tiles
1393 const UINT_32 clHeightInTile
= clHeight
/ MicroTileHeight
;
1394 const UINT_32 pitchInCL
= pitchInTile
/ clWidthInTile
;
1395 const UINT_32 heightInCL
= heightInTile
/ clHeightInTile
;
1396 const UINT_32 clIndex
= tileIndex
/ tileNumPerPipe
;
1398 UINT_32 clX
= clIndex
% pitchInCL
;
1399 UINT_32 clY
= (clIndex
% (heightInCL
* pitchInCL
)) / pitchInCL
;
1401 *pX
= clX
* clWidthInTile
* MicroTileWidth
;
1402 *pY
= clY
* clHeightInTile
* MicroTileHeight
;
1403 *pSlice
= clIndex
/ (heightInCL
* pitchInCL
);
1405 macroOffset
= tileIndex
% tileNumPerPipe
;
1408 UINT_32 elemIdx
= macroOffset
& 7;
1409 macroOffset
>>= elemIdxBits
;
1411 if (elemIdxBits
!= macroShift
)
1413 macroOffset
<<= (elemIdxBits
- macroShift
);
1415 UINT_32 pipebit1
= _BIT(pipe
,1);
1416 UINT_32 pipebit2
= _BIT(pipe
,2);
1417 UINT_32 pipebit3
= _BIT(pipe
,3);
1418 if (pitchInMacroTile
% 2)
1420 switch (pTileInfo
->pipeConfig
)
1422 case ADDR_PIPECFG_P4_32x32
:
1423 macroOffset
|= pipebit1
;
1425 case ADDR_PIPECFG_P8_32x32_8x16
:
1426 case ADDR_PIPECFG_P8_32x32_16x16
:
1427 case ADDR_PIPECFG_P8_32x32_16x32
:
1428 macroOffset
|= pipebit2
;
1436 if (pitchInMacroTile
% 4)
1438 if (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x64_32x32
)
1440 macroOffset
|= (pipebit1
<<1);
1442 if((pTileInfo
->pipeConfig
== ADDR_PIPECFG_P16_32x32_8x16
) ||
1443 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P16_32x32_16x16
))
1445 macroOffset
|= (pipebit3
<<1);
1455 macroX
= macroOffset
% pitchInMacroTile
;
1456 macroY
= macroOffset
/ pitchInMacroTile
;
1460 const UINT_32 clWidthInMacroTile
= clWidth
/ (MicroTileWidth
* 4);
1461 macroX
= macroOffset
% clWidthInMacroTile
;
1462 macroY
= macroOffset
/ clWidthInMacroTile
;
1465 *pX
+= macroX
* 4 * MicroTileWidth
;
1466 *pY
+= macroY
* 4 * MicroTileHeight
;
1470 ComputeTileCoordFromPipeAndElemIdx(elemIdx
, pipe
, pTileInfo
->pipeConfig
, pitchInMacroTile
,
1471 *pX
, *pY
, µX
, µY
);
1473 *pX
+= microX
* MicroTileWidth
;
1474 *pY
+= microY
* MicroTileWidth
;
1478 ***************************************************************************************************
1479 * SiAddrLib::HwlGetPitchAlignmentLinear
1481 * Get pitch alignment
1484 ***************************************************************************************************
1486 UINT_32
SiAddrLib::HwlGetPitchAlignmentLinear(
1487 UINT_32 bpp
, ///< [in] bits per pixel
1488 ADDR_SURFACE_FLAGS flags
///< [in] surface flags
1493 // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment
1494 if (flags
.interleaved
)
1496 pitchAlign
= Max(64u, m_pipeInterleaveBytes
/ BITS_TO_BYTES(bpp
));
1501 pitchAlign
= Max(8u, 64 / BITS_TO_BYTES(bpp
));
1508 ***************************************************************************************************
1509 * SiAddrLib::HwlGetSizeAdjustmentLinear
1512 * Adjust linear surface pitch and slice size
1515 * Logical slice size in bytes
1516 ***************************************************************************************************
1518 UINT_64
SiAddrLib::HwlGetSizeAdjustmentLinear(
1519 AddrTileMode tileMode
, ///< [in] tile mode
1520 UINT_32 bpp
, ///< [in] bits per pixel
1521 UINT_32 numSamples
, ///< [in] number of samples
1522 UINT_32 baseAlign
, ///< [in] base alignment
1523 UINT_32 pitchAlign
, ///< [in] pitch alignment
1524 UINT_32
* pPitch
, ///< [in/out] pointer to pitch
1525 UINT_32
* pHeight
, ///< [in/out] pointer to height
1526 UINT_32
* pHeightAlign
///< [in/out] pointer to height align
1530 if (tileMode
== ADDR_TM_LINEAR_GENERAL
)
1532 sliceSize
= BITS_TO_BYTES(static_cast<UINT_64
>(*pPitch
) * (*pHeight
) * bpp
* numSamples
);
1536 UINT_32 pitch
= *pPitch
;
1537 UINT_32 height
= *pHeight
;
1539 UINT_32 pixelsPerPipeInterleave
= m_pipeInterleaveBytes
/ BITS_TO_BYTES(bpp
);
1540 UINT_32 sliceAlignInPixel
= pixelsPerPipeInterleave
< 64 ? 64 : pixelsPerPipeInterleave
;
1542 // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value)
1543 UINT_64 pixelPerSlice
= static_cast<UINT_64
>(pitch
) * height
* numSamples
;
1545 while (pixelPerSlice
% sliceAlignInPixel
)
1547 pitch
+= pitchAlign
;
1548 pixelPerSlice
= static_cast<UINT_64
>(pitch
) * height
* numSamples
;
1553 UINT_32 heightAlign
= 1;
1555 while ((pitch
* heightAlign
) % sliceAlignInPixel
)
1560 *pHeightAlign
= heightAlign
;
1562 sliceSize
= BITS_TO_BYTES(pixelPerSlice
* bpp
);
1569 ***************************************************************************************************
1570 * SiAddrLib::HwlPreHandleBaseLvl3xPitch
1573 * Pre-handler of 3x pitch (96 bit) adjustment
1577 ***************************************************************************************************
1579 UINT_32
SiAddrLib::HwlPreHandleBaseLvl3xPitch(
1580 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] input
1581 UINT_32 expPitch
///< [in] pitch
1584 ADDR_ASSERT(pIn
->width
== expPitch
);
1586 // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to
1588 if (pIn
->flags
.pow2Pad
== FALSE
)
1590 AddrLib1::HwlPreHandleBaseLvl3xPitch(pIn
, expPitch
);
1594 ADDR_ASSERT(IsPow2(expPitch
));
1601 ***************************************************************************************************
1602 * SiAddrLib::HwlPostHandleBaseLvl3xPitch
1605 * Post-handler of 3x pitch adjustment
1609 ***************************************************************************************************
1611 UINT_32
SiAddrLib::HwlPostHandleBaseLvl3xPitch(
1612 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] input
1613 UINT_32 expPitch
///< [in] pitch
1617 * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should
1618 * be able to compute a correct pitch from it as h/w address library is doing the job.
1620 // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here
1621 if (pIn
->flags
.pow2Pad
== FALSE
)
1623 AddrLib1::HwlPostHandleBaseLvl3xPitch(pIn
, expPitch
);
1630 ***************************************************************************************************
1631 * SiAddrLib::HwlGetPitchAlignmentMicroTiled
1634 * Compute 1D tiled surface pitch alignment
1638 ***************************************************************************************************
1640 UINT_32
SiAddrLib::HwlGetPitchAlignmentMicroTiled(
1641 AddrTileMode tileMode
, ///< [in] tile mode
1642 UINT_32 bpp
, ///< [in] bits per pixel
1643 ADDR_SURFACE_FLAGS flags
, ///< [in] surface flags
1644 UINT_32 numSamples
///< [in] number of samples
1651 pitchAlign
= EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled(tileMode
,bpp
,flags
,numSamples
);
1662 ***************************************************************************************************
1663 * SiAddrLib::HwlGetSizeAdjustmentMicroTiled
1666 * Adjust 1D tiled surface pitch and slice size
1669 * Logical slice size in bytes
1670 ***************************************************************************************************
1672 UINT_64
SiAddrLib::HwlGetSizeAdjustmentMicroTiled(
1673 UINT_32 thickness
, ///< [in] thickness
1674 UINT_32 bpp
, ///< [in] bits per pixel
1675 ADDR_SURFACE_FLAGS flags
, ///< [in] surface flags
1676 UINT_32 numSamples
, ///< [in] number of samples
1677 UINT_32 baseAlign
, ///< [in] base alignment
1678 UINT_32 pitchAlign
, ///< [in] pitch alignment
1679 UINT_32
* pPitch
, ///< [in/out] pointer to pitch
1680 UINT_32
* pHeight
///< [in/out] pointer to height
1683 UINT_64 logicalSliceSize
;
1684 UINT_64 physicalSliceSize
;
1686 UINT_32 pitch
= *pPitch
;
1687 UINT_32 height
= *pHeight
;
1689 // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
1690 logicalSliceSize
= BITS_TO_BYTES(static_cast<UINT_64
>(pitch
) * height
* bpp
* numSamples
);
1692 // Physical slice: multiplied by thickness
1693 physicalSliceSize
= logicalSliceSize
* thickness
;
1695 // Pitch alignment is always 8, so if slice size is not padded to base alignment
1696 // (pipe_interleave_size), we need to increase pitch
1697 while ((physicalSliceSize
% baseAlign
) != 0)
1699 pitch
+= pitchAlign
;
1701 logicalSliceSize
= BITS_TO_BYTES(static_cast<UINT_64
>(pitch
) * height
* bpp
* numSamples
);
1703 physicalSliceSize
= logicalSliceSize
* thickness
;
1708 // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since
1709 // the stencil plane may have larger pitch if the slice size is smaller than base alignment.
1711 // Note: this actually does not work for mipmap but mipmap depth texture is not really
1712 // sampled with mipmap.
1714 if (flags
.depth
&& (flags
.noStencil
== FALSE
))
1716 ADDR_ASSERT(numSamples
== 1);
1718 UINT_64 logicalSiceSizeStencil
= static_cast<UINT_64
>(pitch
) * height
; // 1 byte stencil
1720 while ((logicalSiceSizeStencil
% baseAlign
) != 0)
1722 pitch
+= pitchAlign
; // Stencil plane's pitch alignment is the same as depth plane's
1724 logicalSiceSizeStencil
= static_cast<UINT_64
>(pitch
) * height
;
1727 if (pitch
!= *pPitch
)
1729 // If this is a mipmap, this padded one cannot be sampled as a whole mipmap!
1730 logicalSliceSize
= logicalSiceSizeStencil
* BITS_TO_BYTES(bpp
);
1736 // No adjust for pHeight
1738 return logicalSliceSize
;
1742 ***************************************************************************************************
1743 * SiAddrLib::HwlConvertChipFamily
1746 * Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision
1749 ***************************************************************************************************
1751 AddrChipFamily
SiAddrLib::HwlConvertChipFamily(
1752 UINT_32 uChipFamily
, ///< [in] chip family defined in atiih.h
1753 UINT_32 uChipRevision
) ///< [in] chip revision defined in "asic_family"_id.h
1755 AddrChipFamily family
= ADDR_CHIP_FAMILY_SI
;
1757 switch (uChipFamily
)
1760 m_settings
.isSouthernIsland
= 1;
1761 m_settings
.isTahiti
= ASICREV_IS_TAHITI_P(uChipRevision
);
1762 m_settings
.isPitCairn
= ASICREV_IS_PITCAIRN_PM(uChipRevision
);
1763 m_settings
.isCapeVerde
= ASICREV_IS_CAPEVERDE_M(uChipRevision
);
1764 m_settings
.isOland
= ASICREV_IS_OLAND_M(uChipRevision
);
1765 m_settings
.isHainan
= ASICREV_IS_HAINAN_V(uChipRevision
);
1768 ADDR_ASSERT(!"This should be a Fusion");
1776 ***************************************************************************************************
1777 * SiAddrLib::HwlSetupTileInfo
1780 * Setup default value of tile info for SI
1781 ***************************************************************************************************
1783 VOID
SiAddrLib::HwlSetupTileInfo(
1784 AddrTileMode tileMode
, ///< [in] Tile mode
1785 ADDR_SURFACE_FLAGS flags
, ///< [in] Surface type flags
1786 UINT_32 bpp
, ///< [in] Bits per pixel
1787 UINT_32 pitch
, ///< [in] Pitch in pixels
1788 UINT_32 height
, ///< [in] Height in pixels
1789 UINT_32 numSamples
, ///< [in] Number of samples
1790 ADDR_TILEINFO
* pTileInfoIn
, ///< [in] Tile info input: NULL for default
1791 ADDR_TILEINFO
* pTileInfoOut
, ///< [out] Tile info output
1792 AddrTileType inTileType
, ///< [in] Tile type
1793 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] Output
1796 UINT_32 thickness
= Thickness(tileMode
);
1797 ADDR_TILEINFO
* pTileInfo
= pTileInfoOut
;
1798 INT index
= TileIndexInvalid
;
1801 if (IsLinear(tileMode
) == FALSE
)
1803 // 128 bpp/thick tiling must be non-displayable.
1804 // Fmask reuse color buffer's entry but bank-height field can be from another entry
1805 // To simplify the logic, fmask entry should be picked from non-displayable ones
1806 if (bpp
== 128 || thickness
> 1 || flags
.fmask
|| flags
.prt
)
1808 inTileType
= ADDR_NON_DISPLAYABLE
;
1811 if (flags
.depth
|| flags
.stencil
)
1813 inTileType
= ADDR_DEPTH_SAMPLE_ORDER
;
1817 // Partial valid fields are not allowed for SI.
1818 if (IsTileInfoAllZero(pTileInfo
))
1820 if (IsMacroTiled(tileMode
))
1824 if (numSamples
== 1)
1837 ADDR_ASSERT_ALWAYS();
1866 ADDR_ASSERT(bpp
!= 128);
1873 ADDR_ASSERT(numSamples
== 4);
1886 ADDR_ASSERT_ALWAYS();
1907 ADDR_ASSERT_ALWAYS();
1913 // See table entries 0-7
1914 else if (flags
.depth
|| flags
.stencil
)
1916 if (flags
.compressZ
)
1924 // optimal tile index for compressed depth/stencil.
1947 else //non PRT & non Depth & non Stencil
1949 // See table entries 9-12
1950 if (inTileType
== ADDR_DISPLAYABLE
)
1972 // See table entries 13-17
1977 UINT_32 fmaskPixelSize
= bpp
* numSamples
;
1979 switch (fmaskPixelSize
)
1994 ADDR_ASSERT_ALWAYS();
2021 else // thick tiling - entries 18-20
2040 if (tileMode
== ADDR_TM_LINEAR_ALIGNED
)
2044 else if (tileMode
== ADDR_TM_LINEAR_GENERAL
)
2046 index
= TileIndexLinearGeneral
;
2050 if (flags
.depth
|| flags
.stencil
)
2054 else if (inTileType
== ADDR_DISPLAYABLE
)
2058 else if (thickness
== 1)
2069 if (index
>= 0 && index
<= 31)
2071 *pTileInfo
= m_tileTable
[index
].info
;
2072 pOut
->tileType
= m_tileTable
[index
].type
;
2075 if (index
== TileIndexLinearGeneral
)
2077 *pTileInfo
= m_tileTable
[8].info
;
2078 pOut
->tileType
= m_tileTable
[8].type
;
2085 if (flags
.stencil
&& pTileInfoIn
->tileSplitBytes
== 0)
2087 // Stencil always uses index 0
2088 *pTileInfo
= m_tileTable
[0].info
;
2091 // Pass through tile type
2092 pOut
->tileType
= inTileType
;
2095 pOut
->tileIndex
= index
;
2099 ***************************************************************************************************
2100 * SiAddrLib::DecodeGbRegs
2103 * Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks
2106 * TRUE if all settings are valid
2108 ***************************************************************************************************
2110 BOOL_32
SiAddrLib::DecodeGbRegs(
2111 const ADDR_REGISTER_VALUE
* pRegValue
) ///< [in] create input
2114 BOOL_32 valid
= TRUE
;
2116 reg
.val
= pRegValue
->gbAddrConfig
;
2118 switch (reg
.f
.pipe_interleave_size
)
2120 case ADDR_CONFIG_PIPE_INTERLEAVE_256B
:
2121 m_pipeInterleaveBytes
= ADDR_PIPEINTERLEAVE_256B
;
2123 case ADDR_CONFIG_PIPE_INTERLEAVE_512B
:
2124 m_pipeInterleaveBytes
= ADDR_PIPEINTERLEAVE_512B
;
2128 ADDR_UNHANDLED_CASE();
2132 switch (reg
.f
.row_size
)
2134 case ADDR_CONFIG_1KB_ROW
:
2135 m_rowSize
= ADDR_ROWSIZE_1KB
;
2137 case ADDR_CONFIG_2KB_ROW
:
2138 m_rowSize
= ADDR_ROWSIZE_2KB
;
2140 case ADDR_CONFIG_4KB_ROW
:
2141 m_rowSize
= ADDR_ROWSIZE_4KB
;
2145 ADDR_UNHANDLED_CASE();
2149 switch (pRegValue
->noOfBanks
)
2162 ADDR_UNHANDLED_CASE();
2166 switch (pRegValue
->noOfRanks
)
2176 ADDR_UNHANDLED_CASE();
2180 m_logicalBanks
= m_banks
* m_ranks
;
2182 ADDR_ASSERT(m_logicalBanks
<= 16);
2188 ***************************************************************************************************
2189 * SiAddrLib::HwlInitGlobalParams
2192 * Initializes global parameters
2195 * TRUE if all settings are valid
2197 ***************************************************************************************************
2199 BOOL_32
SiAddrLib::HwlInitGlobalParams(
2200 const ADDR_CREATE_INPUT
* pCreateIn
) ///< [in] create input
2202 BOOL_32 valid
= TRUE
;
2203 const ADDR_REGISTER_VALUE
* pRegValue
= &pCreateIn
->regValue
;
2205 valid
= DecodeGbRegs(pRegValue
);
2209 if (m_settings
.isTahiti
|| m_settings
.isPitCairn
)
2213 else if (m_settings
.isCapeVerde
|| m_settings
.isOland
)
2219 // Hainan is 2-pipe (m_settings.isHainan == 1)
2223 valid
= InitTileSettingTable(pRegValue
->pTileConfig
, pRegValue
->noOfEntries
);
2227 InitEquationTable();
2237 ***************************************************************************************************
2238 * SiAddrLib::HwlConvertTileInfoToHW
2240 * Entry of si's ConvertTileInfoToHW
2243 ***************************************************************************************************
2245 ADDR_E_RETURNCODE
SiAddrLib::HwlConvertTileInfoToHW(
2246 const ADDR_CONVERT_TILEINFOTOHW_INPUT
* pIn
, ///< [in] input structure
2247 ADDR_CONVERT_TILEINFOTOHW_OUTPUT
* pOut
///< [out] output structure
2250 ADDR_E_RETURNCODE retCode
= ADDR_OK
;
2252 retCode
= EgBasedAddrLib::HwlConvertTileInfoToHW(pIn
, pOut
);
2254 if (retCode
== ADDR_OK
)
2256 if (pIn
->reverse
== FALSE
)
2258 if (pIn
->pTileInfo
->pipeConfig
== ADDR_PIPECFG_INVALID
)
2260 retCode
= ADDR_INVALIDPARAMS
;
2264 pOut
->pTileInfo
->pipeConfig
=
2265 static_cast<AddrPipeCfg
>(pIn
->pTileInfo
->pipeConfig
- 1);
2270 pOut
->pTileInfo
->pipeConfig
=
2271 static_cast<AddrPipeCfg
>(pIn
->pTileInfo
->pipeConfig
+ 1);
2279 ***************************************************************************************************
2280 * SiAddrLib::HwlComputeXmaskCoordYFrom8Pipe
2283 * Compute the Y coord which will be added to Xmask Y
2287 ***************************************************************************************************
2289 UINT_32
SiAddrLib::HwlComputeXmaskCoordYFrom8Pipe(
2290 UINT_32 pipe
, ///< [in] pipe id
2291 UINT_32 x
///< [in] tile coord x, which is original x coord / 8
2294 // This function should never be called since it is 6xx/8xx specfic.
2295 // Keep this empty implementation to avoid any mis-use.
2296 ADDR_ASSERT_ALWAYS();
2302 ***************************************************************************************************
2303 * SiAddrLib::HwlComputeSurfaceCoord2DFromBankPipe
2306 * Compute surface x,y coordinates from bank/pipe info
2309 ***************************************************************************************************
2311 VOID
SiAddrLib::HwlComputeSurfaceCoord2DFromBankPipe(
2312 AddrTileMode tileMode
, ///< [in] tile mode
2313 UINT_32
* pX
, ///< [in/out] x coordinate
2314 UINT_32
* pY
, ///< [in/out] y coordinate
2315 UINT_32 slice
, ///< [in] slice index
2316 UINT_32 bank
, ///< [in] bank number
2317 UINT_32 pipe
, ///< [in] pipe number
2318 UINT_32 bankSwizzle
,///< [in] bank swizzle
2319 UINT_32 pipeSwizzle
,///< [in] pipe swizzle
2320 UINT_32 tileSlices
, ///< [in] slices in a micro tile
2321 BOOL_32 ignoreSE
, ///< [in] TRUE if shader engines are ignored
2322 ADDR_TILEINFO
* pTileInfo
///< [in] bank structure. **All fields to be valid on entry**
2336 UINT_32 numPipes
= GetPipePerSurf(pTileInfo
->pipeConfig
);
2338 CoordFromBankPipe xyBits
= {0};
2339 ComputeSurfaceCoord2DFromBankPipe(tileMode
, *pX
, *pY
, slice
, bank
, pipe
,
2340 bankSwizzle
, pipeSwizzle
, tileSlices
, pTileInfo
,
2342 yBit3
= xyBits
.yBit3
;
2343 yBit4
= xyBits
.yBit4
;
2344 yBit5
= xyBits
.yBit5
;
2345 yBit6
= xyBits
.yBit6
;
2347 xBit3
= xyBits
.xBit3
;
2348 xBit4
= xyBits
.xBit4
;
2349 xBit5
= xyBits
.xBit5
;
2351 yBit
= xyBits
.yBits
;
2353 UINT_32 yBitTemp
= 0;
2355 if ((pTileInfo
->pipeConfig
== ADDR_PIPECFG_P4_32x32
) ||
2356 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x64_32x32
))
2358 ADDR_ASSERT(pTileInfo
->bankWidth
== 1 && pTileInfo
->macroAspectRatio
> 1);
2359 UINT_32 yBitToCheck
= QLog2(pTileInfo
->banks
) - 1;
2361 ADDR_ASSERT(yBitToCheck
<= 3);
2363 yBitTemp
= _BIT(yBit
, yBitToCheck
);
2368 yBit
= Bits2Number(4, yBit6
, yBit5
, yBit4
, yBit3
);
2369 xBit
= Bits2Number(3, xBit5
, xBit4
, xBit3
);
2371 *pY
+= yBit
* pTileInfo
->bankHeight
* MicroTileHeight
;
2372 *pX
+= xBit
* numPipes
* pTileInfo
->bankWidth
* MicroTileWidth
;
2374 //calculate the bank and pipe bits in x, y
2375 UINT_32 xTile
; //x in micro tile
2382 UINT_32 pipeBit0
= _BIT(pipe
,0);
2383 UINT_32 pipeBit1
= _BIT(pipe
,1);
2384 UINT_32 pipeBit2
= _BIT(pipe
,2);
2386 UINT_32 y3
= _BIT(y
, 3);
2387 UINT_32 y4
= _BIT(y
, 4);
2388 UINT_32 y5
= _BIT(y
, 5);
2389 UINT_32 y6
= _BIT(y
, 6);
2391 // bankbit0 after ^x4^x5
2392 UINT_32 bankBit00
= _BIT(bank
,0);
2393 UINT_32 bankBit0
= 0;
2395 switch (pTileInfo
->pipeConfig
)
2397 case ADDR_PIPECFG_P2
:
2400 case ADDR_PIPECFG_P4_8x16
:
2404 case ADDR_PIPECFG_P4_16x16
:
2406 x3
= pipeBit0
^ y3
^ x4
;
2408 case ADDR_PIPECFG_P4_16x32
:
2410 x3
= pipeBit0
^ y3
^ x4
;
2412 case ADDR_PIPECFG_P4_32x32
:
2414 x3
= pipeBit0
^ y3
^ x5
;
2415 bankBit0
= yBitTemp
^ x5
;
2416 x4
= bankBit00
^ x5
^ bankBit0
;
2417 *pX
+= x5
* 4 * 1 * 8; // x5 * num_pipes * bank_width * 8;
2419 case ADDR_PIPECFG_P8_16x16_8x16
:
2422 x5
= pipeBit0
^ y3
^ x4
;
2424 case ADDR_PIPECFG_P8_16x32_8x16
:
2427 x5
= pipeBit0
^ y3
^ x4
;
2429 case ADDR_PIPECFG_P8_32x32_8x16
:
2432 x4
= pipeBit0
^ y3
^ x5
;
2434 case ADDR_PIPECFG_P8_16x32_16x16
:
2437 x3
= pipeBit0
^ y3
^ x4
;
2439 case ADDR_PIPECFG_P8_32x32_16x16
:
2442 x3
= pipeBit0
^ y3
^ x4
;
2444 case ADDR_PIPECFG_P8_32x32_16x32
:
2447 x3
= pipeBit0
^ y3
^ x4
;
2449 case ADDR_PIPECFG_P8_32x64_32x32
:
2452 x3
= pipeBit0
^ y3
^ x5
;
2453 bankBit0
= yBitTemp
^ x6
;
2454 x4
= bankBit00
^ x5
^ bankBit0
;
2455 *pX
+= x6
* 8 * 1 * 8; // x6 * num_pipes * bank_width * 8;
2458 ADDR_ASSERT_ALWAYS();
2461 xTile
= Bits2Number(3, x5
, x4
, x3
);
2467 ***************************************************************************************************
2468 * SiAddrLib::HwlPreAdjustBank
2471 * Adjust bank before calculating address acoording to bank/pipe
2474 ***************************************************************************************************
2476 UINT_32
SiAddrLib::HwlPreAdjustBank(
2477 UINT_32 tileX
, ///< [in] x coordinate in unit of tile
2478 UINT_32 bank
, ///< [in] bank
2479 ADDR_TILEINFO
* pTileInfo
///< [in] tile info
2482 if (((pTileInfo
->pipeConfig
== ADDR_PIPECFG_P4_32x32
) ||
2483 (pTileInfo
->pipeConfig
== ADDR_PIPECFG_P8_32x64_32x32
)) && (pTileInfo
->bankWidth
== 1))
2485 UINT_32 bankBit0
= _BIT(bank
, 0);
2486 UINT_32 x4
= _BIT(tileX
, 1);
2487 UINT_32 x5
= _BIT(tileX
, 2);
2489 bankBit0
= bankBit0
^ x4
^ x5
;
2492 ADDR_ASSERT(pTileInfo
->macroAspectRatio
> 1);
2499 ***************************************************************************************************
2500 * SiAddrLib::HwlComputeSurfaceInfo
2503 * Entry of si's ComputeSurfaceInfo
2506 ***************************************************************************************************
2508 ADDR_E_RETURNCODE
SiAddrLib::HwlComputeSurfaceInfo(
2509 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] input structure
2510 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] output structure
2513 pOut
->tileIndex
= pIn
->tileIndex
;
2515 ADDR_E_RETURNCODE retCode
= EgBasedAddrLib::HwlComputeSurfaceInfo(pIn
, pOut
);
2517 UINT_32 tileIndex
= static_cast<UINT_32
>(pOut
->tileIndex
);
2519 if ((pIn
->flags
.needEquation
== TRUE
) &&
2520 (pIn
->numSamples
<= 1) &&
2521 (tileIndex
< TileTableSize
))
2523 pOut
->equationIndex
= m_equationLookupTable
[Log2(pIn
->bpp
>> 3)][tileIndex
];
2525 if (pOut
->equationIndex
!= ADDR_INVALID_EQUATION_INDEX
)
2527 pOut
->blockWidth
= m_blockWidth
[pOut
->equationIndex
];
2529 pOut
->blockHeight
= m_blockHeight
[pOut
->equationIndex
];
2531 pOut
->blockSlices
= m_blockSlices
[pOut
->equationIndex
];
2536 pOut
->equationIndex
= ADDR_INVALID_EQUATION_INDEX
;
2543 ***************************************************************************************************
2544 * SiAddrLib::HwlComputeMipLevel
2546 * Compute MipLevel info (including level 0)
2548 * TRUE if HWL's handled
2549 ***************************************************************************************************
2551 BOOL_32
SiAddrLib::HwlComputeMipLevel(
2552 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
///< [in/out] Input structure
2555 // basePitch is calculated from level 0 so we only check this for mipLevel > 0
2556 if (pIn
->mipLevel
> 0)
2558 // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if
2559 // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being
2560 // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2.
2561 if (AddrElemLib::IsExpand3x(pIn
->format
) == FALSE
)
2563 // Sublevel pitches are generated from base level pitch instead of width on SI
2564 // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain
2565 ADDR_ASSERT((pIn
->flags
.pow2Pad
== FALSE
) ||
2566 ((pIn
->basePitch
!= 0) && IsPow2(pIn
->basePitch
)));
2569 if (pIn
->basePitch
!= 0)
2571 pIn
->width
= Max(1u, pIn
->basePitch
>> pIn
->mipLevel
);
2575 // pow2Pad is done in PostComputeMipLevel
2581 ***************************************************************************************************
2582 * SiAddrLib::HwlCheckLastMacroTiledLvl
2585 * Sets pOut->last2DLevel to TRUE if it is
2588 ***************************************************************************************************
2590 VOID
SiAddrLib::HwlCheckLastMacroTiledLvl(
2591 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] Input structure
2592 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [in/out] Output structure (used as input, too)
2595 // pow2Pad covers all mipmap cases
2596 if (pIn
->flags
.pow2Pad
)
2598 ADDR_ASSERT(IsMacroTiled(pIn
->tileMode
));
2604 AddrTileMode nextTileMode
;
2606 if (pIn
->mipLevel
== 0 || pIn
->basePitch
== 0)
2608 // Base level or fail-safe case (basePitch == 0)
2609 nextPitch
= pOut
->pitch
>> 1;
2614 nextPitch
= pIn
->basePitch
>> (pIn
->mipLevel
+ 1);
2617 // nextHeight must be shifted from this level's original height rather than a pow2 padded
2618 // one but this requires original height stored somewhere (pOut->height)
2619 ADDR_ASSERT(pOut
->height
!= 0);
2621 // next level's height is just current level's >> 1 in pixels
2622 nextHeight
= pOut
->height
>> 1;
2623 // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
2624 // compressed foramts
2625 if (AddrElemLib::IsBlockCompressed(pIn
->format
))
2627 nextHeight
= (nextHeight
+ 3) / 4;
2629 nextHeight
= NextPow2(nextHeight
);
2631 // nextSlices may be 0 if this level's is 1
2632 if (pIn
->flags
.volume
)
2634 nextSlices
= Max(1u, pIn
->numSlices
>> 1);
2638 nextSlices
= pIn
->numSlices
;
2641 nextTileMode
= ComputeSurfaceMipLevelTileMode(pIn
->tileMode
,
2651 pOut
->last2DLevel
= IsMicroTiled(nextTileMode
);
2656 ***************************************************************************************************
2657 * SiAddrLib::HwlDegradeThickTileMode
2660 * Degrades valid tile mode for thick modes if needed
2663 * Suitable tile mode
2664 ***************************************************************************************************
2666 AddrTileMode
SiAddrLib::HwlDegradeThickTileMode(
2667 AddrTileMode baseTileMode
, ///< [in] base tile mode
2668 UINT_32 numSlices
, ///< [in] current number of slices
2669 UINT_32
* pBytesPerTile
///< [in/out] pointer to bytes per slice
2672 return EgBasedAddrLib::HwlDegradeThickTileMode(baseTileMode
, numSlices
, pBytesPerTile
);
2676 ***************************************************************************************************
2677 * SiAddrLib::HwlTileInfoEqual
2680 * Return TRUE if all field are equal
2682 * Only takes care of current HWL's data
2683 ***************************************************************************************************
2685 BOOL_32
SiAddrLib::HwlTileInfoEqual(
2686 const ADDR_TILEINFO
* pLeft
, ///<[in] Left compare operand
2687 const ADDR_TILEINFO
* pRight
///<[in] Right compare operand
2690 BOOL_32 equal
= FALSE
;
2692 if (pLeft
->pipeConfig
== pRight
->pipeConfig
)
2694 equal
= EgBasedAddrLib::HwlTileInfoEqual(pLeft
, pRight
);
2701 ***************************************************************************************************
2702 * SiAddrLib::GetTileSettings
2705 * Get tile setting infos by index.
2707 * Tile setting info.
2708 ***************************************************************************************************
2710 const AddrTileConfig
* SiAddrLib::GetTileSetting(
2711 UINT_32 index
///< [in] Tile index
2714 ADDR_ASSERT(index
< m_noOfEntries
);
2715 return &m_tileTable
[index
];
2719 ***************************************************************************************************
2720 * SiAddrLib::HwlPostCheckTileIndex
2723 * Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
2724 * tile mode/type/info and change the index if needed
2727 ***************************************************************************************************
2729 INT_32
SiAddrLib::HwlPostCheckTileIndex(
2730 const ADDR_TILEINFO
* pInfo
, ///< [in] Tile Info
2731 AddrTileMode mode
, ///< [in] Tile mode
2732 AddrTileType type
, ///< [in] Tile type
2733 INT curIndex
///< [in] Current index assigned in HwlSetupTileInfo
2736 INT_32 index
= curIndex
;
2738 if (mode
== ADDR_TM_LINEAR_GENERAL
)
2740 index
= TileIndexLinearGeneral
;
2744 BOOL_32 macroTiled
= IsMacroTiled(mode
);
2746 // We need to find a new index if either of them is true
2747 // 1. curIndex is invalid
2748 // 2. tile mode is changed
2749 // 3. tile info does not match for macro tiled
2750 if ((index
== TileIndexInvalid
||
2751 (mode
!= m_tileTable
[index
].mode
) ||
2752 (macroTiled
&& (HwlTileInfoEqual(pInfo
, &m_tileTable
[index
].info
) == FALSE
))))
2754 for (index
= 0; index
< static_cast<INT_32
>(m_noOfEntries
); index
++)
2758 // macro tile modes need all to match
2759 if (HwlTileInfoEqual(pInfo
, &m_tileTable
[index
].info
) &&
2760 (mode
== m_tileTable
[index
].mode
) &&
2761 (type
== m_tileTable
[index
].type
))
2766 else if (mode
== ADDR_TM_LINEAR_ALIGNED
)
2768 // linear mode only needs tile mode to match
2769 if (mode
== m_tileTable
[index
].mode
)
2776 // micro tile modes only need tile mode and tile type to match
2777 if (mode
== m_tileTable
[index
].mode
&&
2778 type
== m_tileTable
[index
].type
)
2787 ADDR_ASSERT(index
< static_cast<INT_32
>(m_noOfEntries
));
2789 if (index
>= static_cast<INT_32
>(m_noOfEntries
))
2791 index
= TileIndexInvalid
;
2798 ***************************************************************************************************
2799 * SiAddrLib::HwlSetupTileCfg
2802 * Map tile index to tile setting.
2805 ***************************************************************************************************
2807 ADDR_E_RETURNCODE
SiAddrLib::HwlSetupTileCfg(
2808 UINT_32 bpp
, ///< [in] Bits per pixel
2809 INT_32 index
, ///< [in] Tile index
2810 INT_32 macroModeIndex
, ///< [in] Index in macro tile mode table(CI)
2811 ADDR_TILEINFO
* pInfo
, ///< [out] Tile Info
2812 AddrTileMode
* pMode
, ///< [out] Tile mode
2813 AddrTileType
* pType
///< [out] Tile type
2816 ADDR_E_RETURNCODE returnCode
= ADDR_OK
;
2818 // Global flag to control usage of tileIndex
2819 if (UseTileIndex(index
))
2821 if (index
== TileIndexLinearGeneral
)
2825 *pMode
= ADDR_TM_LINEAR_GENERAL
;
2830 *pType
= ADDR_DISPLAYABLE
;
2836 pInfo
->bankWidth
= 1;
2837 pInfo
->bankHeight
= 1;
2838 pInfo
->macroAspectRatio
= 1;
2839 pInfo
->tileSplitBytes
= 64;
2840 pInfo
->pipeConfig
= ADDR_PIPECFG_P2
;
2843 else if (static_cast<UINT_32
>(index
) >= m_noOfEntries
)
2845 returnCode
= ADDR_INVALIDPARAMS
;
2849 const AddrTileConfig
* pCfgTable
= GetTileSetting(index
);
2853 *pInfo
= pCfgTable
->info
;
2857 if (IsMacroTiled(pCfgTable
->mode
))
2859 returnCode
= ADDR_INVALIDPARAMS
;
2865 *pMode
= pCfgTable
->mode
;
2870 *pType
= pCfgTable
->type
;
2879 ***************************************************************************************************
2880 * SiAddrLib::ReadGbTileMode
2883 * Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
2886 ***************************************************************************************************
2888 VOID
SiAddrLib::ReadGbTileMode(
2889 UINT_32 regValue
, ///< [in] GB_TILE_MODE register
2890 AddrTileConfig
* pCfg
///< [out] output structure
2893 GB_TILE_MODE gbTileMode
;
2894 gbTileMode
.val
= regValue
;
2896 pCfg
->type
= static_cast<AddrTileType
>(gbTileMode
.f
.micro_tile_mode
);
2897 pCfg
->info
.bankHeight
= 1 << gbTileMode
.f
.bank_height
;
2898 pCfg
->info
.bankWidth
= 1 << gbTileMode
.f
.bank_width
;
2899 pCfg
->info
.banks
= 1 << (gbTileMode
.f
.num_banks
+ 1);
2900 pCfg
->info
.macroAspectRatio
= 1 << gbTileMode
.f
.macro_tile_aspect
;
2901 pCfg
->info
.tileSplitBytes
= 64 << gbTileMode
.f
.tile_split
;
2902 pCfg
->info
.pipeConfig
= static_cast<AddrPipeCfg
>(gbTileMode
.f
.pipe_config
+ 1);
2904 UINT_32 regArrayMode
= gbTileMode
.f
.array_mode
;
2906 pCfg
->mode
= static_cast<AddrTileMode
>(regArrayMode
);
2908 if (regArrayMode
== 8) //ARRAY_2D_TILED_XTHICK
2910 pCfg
->mode
= ADDR_TM_2D_TILED_XTHICK
;
2912 else if (regArrayMode
>= 14) //ARRAY_3D_TILED_XTHICK
2914 pCfg
->mode
= static_cast<AddrTileMode
>(pCfg
->mode
+ 3);
2919 ***************************************************************************************************
2920 * SiAddrLib::InitTileSettingTable
2923 * Initialize the ADDR_TILE_CONFIG table.
2925 * TRUE if tile table is correctly initialized
2926 ***************************************************************************************************
2928 BOOL_32
SiAddrLib::InitTileSettingTable(
2929 const UINT_32
* pCfg
, ///< [in] Pointer to table of tile configs
2930 UINT_32 noOfEntries
///< [in] Numbe of entries in the table above
2933 BOOL_32 initOk
= TRUE
;
2935 ADDR_ASSERT(noOfEntries
<= TileTableSize
);
2937 memset(m_tileTable
, 0, sizeof(m_tileTable
));
2939 if (noOfEntries
!= 0)
2941 m_noOfEntries
= noOfEntries
;
2945 m_noOfEntries
= TileTableSize
;
2948 if (pCfg
) // From Client
2950 for (UINT_32 i
= 0; i
< m_noOfEntries
; i
++)
2952 ReadGbTileMode(*(pCfg
+ i
), &m_tileTable
[i
]);
2957 ADDR_ASSERT_ALWAYS();
2963 ADDR_ASSERT(m_tileTable
[TILEINDEX_LINEAR_ALIGNED
].mode
== ADDR_TM_LINEAR_ALIGNED
);
2970 ***************************************************************************************************
2971 * SiAddrLib::HwlGetTileIndex
2974 * Return the virtual/real index for given mode/type/info
2976 * ADDR_OK if successful.
2977 ***************************************************************************************************
2979 ADDR_E_RETURNCODE
SiAddrLib::HwlGetTileIndex(
2980 const ADDR_GET_TILEINDEX_INPUT
* pIn
,
2981 ADDR_GET_TILEINDEX_OUTPUT
* pOut
) const
2983 ADDR_E_RETURNCODE returnCode
= ADDR_OK
;
2985 pOut
->index
= HwlPostCheckTileIndex(pIn
->pTileInfo
, pIn
->tileMode
, pIn
->tileType
);
2991 ***************************************************************************************************
2992 * SiAddrLib::HwlFmaskPreThunkSurfInfo
2995 * Some preparation before thunking a ComputeSurfaceInfo call for Fmask
2998 ***************************************************************************************************
3000 VOID
SiAddrLib::HwlFmaskPreThunkSurfInfo(
3001 const ADDR_COMPUTE_FMASK_INFO_INPUT
* pFmaskIn
, ///< [in] Input of fmask info
3002 const ADDR_COMPUTE_FMASK_INFO_OUTPUT
* pFmaskOut
, ///< [in] Output of fmask info
3003 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pSurfIn
, ///< [out] Input of thunked surface info
3004 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pSurfOut
///< [out] Output of thunked surface info
3007 pSurfIn
->tileIndex
= pFmaskIn
->tileIndex
;
3011 ***************************************************************************************************
3012 * SiAddrLib::HwlFmaskPostThunkSurfInfo
3015 * Copy hwl extra field after calling thunked ComputeSurfaceInfo
3018 ***************************************************************************************************
3020 VOID
SiAddrLib::HwlFmaskPostThunkSurfInfo(
3021 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pSurfOut
, ///< [in] Output of surface info
3022 ADDR_COMPUTE_FMASK_INFO_OUTPUT
* pFmaskOut
///< [out] Output of fmask info
3025 pFmaskOut
->macroModeIndex
= TileIndexInvalid
;
3026 pFmaskOut
->tileIndex
= pSurfOut
->tileIndex
;
3030 ***************************************************************************************************
3031 * SiAddrLib::HwlComputeFmaskBits
3033 * Computes fmask bits
3036 ***************************************************************************************************
3038 UINT_32
SiAddrLib::HwlComputeFmaskBits(
3039 const ADDR_COMPUTE_FMASK_INFO_INPUT
* pIn
,
3040 UINT_32
* pNumSamples
3043 UINT_32 numSamples
= pIn
->numSamples
;
3044 UINT_32 numFrags
= GetNumFragments(numSamples
, pIn
->numFrags
);
3047 if (numFrags
!= numSamples
) // EQAA
3049 ADDR_ASSERT(numFrags
<= 8);
3051 if (pIn
->resolved
== FALSE
)
3056 numSamples
= numSamples
== 16 ? 16 : 8;
3058 else if (numFrags
== 2)
3060 ADDR_ASSERT(numSamples
>= 4);
3063 numSamples
= numSamples
;
3065 else if (numFrags
== 4)
3067 ADDR_ASSERT(numSamples
>= 4);
3070 numSamples
= numSamples
;
3072 else // numFrags == 8
3074 ADDR_ASSERT(numSamples
== 16);
3077 numSamples
= numSamples
;
3084 bpp
= (numSamples
== 16) ? 16 : 8;
3087 else if (numFrags
== 2)
3089 ADDR_ASSERT(numSamples
>= 4);
3094 else if (numFrags
== 4)
3096 ADDR_ASSERT(numSamples
>= 4);
3101 else // numFrags == 8
3103 ADDR_ASSERT(numSamples
>= 16);
3112 if (pIn
->resolved
== FALSE
)
3114 bpp
= ComputeFmaskNumPlanesFromNumSamples(numSamples
);
3115 numSamples
= numSamples
== 2 ? 8 : numSamples
;
3120 bpp
= ComputeFmaskResolvedBppFromNumSamples(numSamples
);
3121 numSamples
= 1; // 1x sample
3125 SafeAssign(pNumSamples
, numSamples
);
3131 ***************************************************************************************************
3132 * SiAddrLib::HwlOverrideTileMode
3135 * Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
3140 ***************************************************************************************************
3142 void SiAddrLib::HwlOverrideTileMode(
3143 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pInOut
///< [in/out] input output structure
3146 AddrTileMode tileMode
= pInOut
->tileMode
;
3150 case ADDR_TM_PRT_TILED_THIN1
:
3151 tileMode
= ADDR_TM_2D_TILED_THIN1
;
3154 case ADDR_TM_PRT_TILED_THICK
:
3155 tileMode
= ADDR_TM_2D_TILED_THICK
;
3158 case ADDR_TM_PRT_2D_TILED_THICK
:
3159 tileMode
= ADDR_TM_2D_TILED_THICK
;
3162 case ADDR_TM_PRT_3D_TILED_THICK
:
3163 tileMode
= ADDR_TM_3D_TILED_THICK
;
3170 if ((pInOut
->flags
.needEquation
== TRUE
) &&
3171 (IsMacroTiled(tileMode
) == TRUE
) &&
3172 (pInOut
->numSamples
<= 1))
3174 UINT_32 thickness
= Thickness(tileMode
);
3176 pInOut
->flags
.prt
= TRUE
;
3180 tileMode
= ADDR_TM_1D_TILED_THICK
;
3182 else if (pInOut
->numSlices
> 1)
3184 tileMode
= ADDR_TM_1D_TILED_THIN1
;
3188 tileMode
= ADDR_TM_2D_TILED_THIN1
;
3192 if (tileMode
!= pInOut
->tileMode
)
3194 pInOut
->tileMode
= tileMode
;
3196 ADDR_ASSERT(pInOut
->flags
.prt
== TRUE
);
3201 ***************************************************************************************************
3202 * SiAddrLib::HwlGetMaxAlignments
3205 * Gets maximum alignments
3208 ***************************************************************************************************
3210 ADDR_E_RETURNCODE
SiAddrLib::HwlGetMaxAlignments(
3211 ADDR_GET_MAX_ALINGMENTS_OUTPUT
* pOut
///< [out] output structure
3214 const UINT_32 pipes
= HwlGetPipes(&m_tileTable
[0].info
);
3216 // Initial size is 64 KiB for PRT.
3217 UINT_64 maxBaseAlign
= 64 * 1024;
3219 for (UINT_32 i
= 0; i
< m_noOfEntries
; i
++)
3221 if ((IsMacroTiled(m_tileTable
[i
].mode
) == TRUE
) &&
3222 (IsPrtTileMode(m_tileTable
[i
].mode
) == FALSE
))
3224 // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
3225 UINT_32 tileSize
= Min(m_tileTable
[i
].info
.tileSplitBytes
,
3226 MicroTilePixels
* 8 * 16);
3228 UINT_64 baseAlign
= tileSize
* pipes
* m_tileTable
[i
].info
.banks
*
3229 m_tileTable
[i
].info
.bankWidth
* m_tileTable
[i
].info
.bankHeight
;
3231 if (baseAlign
> maxBaseAlign
)
3233 maxBaseAlign
= baseAlign
;
3240 pOut
->baseAlign
= maxBaseAlign
;
3247 ***************************************************************************************************
3248 * SiAddrLib::InitEquationTable
3251 * Initialize Equation table.
3255 ***************************************************************************************************
3257 VOID
SiAddrLib::InitEquationTable()
3259 ADDR_EQUATION_KEY equationKeyTable
[EquationTableSize
];
3260 memset(equationKeyTable
, 0, sizeof(equationKeyTable
));
3262 memset(m_equationTable
, 0, sizeof(m_equationTable
));
3264 memset(m_blockWidth
, 0, sizeof(m_blockWidth
));
3266 memset(m_blockHeight
, 0, sizeof(m_blockHeight
));
3268 memset(m_blockSlices
, 0, sizeof(m_blockSlices
));
3270 // Loop all possible bpp
3271 for (UINT_32 log2ElementBytes
= 0; log2ElementBytes
< MaxNumElementBytes
; log2ElementBytes
++)
3273 // Get bits per pixel
3274 UINT_32 bpp
= 1 << (log2ElementBytes
+ 3);
3276 // Loop all possible tile index
3277 for (INT_32 tileIndex
= 0; tileIndex
< static_cast<INT_32
>(m_noOfEntries
); tileIndex
++)
3279 UINT_32 equationIndex
= ADDR_INVALID_EQUATION_INDEX
;
3281 AddrTileConfig tileConfig
= m_tileTable
[tileIndex
];
3283 ADDR_SURFACE_FLAGS flags
= {{0}};
3285 // Compute tile info, hardcode numSamples to 1 because MSAA is not supported
3286 // in swizzle pattern equation
3287 HwlComputeMacroModeIndex(tileIndex
, flags
, bpp
, 1, &tileConfig
.info
, NULL
, NULL
);
3289 // Check if the input is supported
3290 if (IsEquationSupported(bpp
, tileConfig
, tileIndex
) == TRUE
)
3292 ADDR_EQUATION_KEY key
= {{0}};
3294 // Generate swizzle equation key from bpp and tile config
3295 key
.fields
.log2ElementBytes
= log2ElementBytes
;
3296 key
.fields
.tileMode
= tileConfig
.mode
;
3297 // Treat depth micro tile type and non-display micro tile type as the same key
3298 // because they have the same equation actually
3299 key
.fields
.microTileType
= (tileConfig
.type
== ADDR_DEPTH_SAMPLE_ORDER
) ?
3300 ADDR_NON_DISPLAYABLE
: tileConfig
.type
;
3301 key
.fields
.pipeConfig
= tileConfig
.info
.pipeConfig
;
3302 key
.fields
.numBanks
= tileConfig
.info
.banks
;
3303 key
.fields
.bankWidth
= tileConfig
.info
.bankWidth
;
3304 key
.fields
.bankHeight
= tileConfig
.info
.bankHeight
;
3305 key
.fields
.macroAspectRatio
= tileConfig
.info
.macroAspectRatio
;
3307 // Find in the table if the equation has been built based on the key
3308 for (UINT_32 i
= 0; i
< m_numEquations
; i
++)
3310 if (key
.value
== equationKeyTable
[i
].value
)
3317 // If found, just fill the index into the lookup table and no need
3318 // to generate the equation again. Otherwise, generate the equation.
3319 if (equationIndex
== ADDR_INVALID_EQUATION_INDEX
)
3321 ADDR_EQUATION equation
;
3322 ADDR_E_RETURNCODE retCode
;
3324 memset(&equation
, 0, sizeof(ADDR_EQUATION
));
3326 // Generate the equation
3327 if (IsMicroTiled(tileConfig
.mode
))
3329 retCode
= ComputeMicroTileEquation(log2ElementBytes
,
3336 retCode
= ComputeMacroTileEquation(log2ElementBytes
,
3342 // Only fill the equation into the table if the return code is ADDR_OK,
3343 // otherwise if the return code is not ADDR_OK, it indicates this is not
3344 // a valid input, we do nothing but just fill invalid equation index
3345 // into the lookup table.
3346 if (retCode
== ADDR_OK
)
3348 equationIndex
= m_numEquations
;
3349 ADDR_ASSERT(equationIndex
< EquationTableSize
);
3351 m_blockSlices
[equationIndex
] = Thickness(tileConfig
.mode
);
3353 if (IsMicroTiled(tileConfig
.mode
))
3355 m_blockWidth
[equationIndex
] = MicroTileWidth
;
3356 m_blockHeight
[equationIndex
] = MicroTileHeight
;
3360 const ADDR_TILEINFO
* pTileInfo
= &tileConfig
.info
;
3362 m_blockWidth
[equationIndex
] =
3363 HwlGetPipes(pTileInfo
) * MicroTileWidth
* pTileInfo
->bankWidth
*
3364 pTileInfo
->macroAspectRatio
;
3365 m_blockHeight
[equationIndex
] =
3366 MicroTileHeight
* pTileInfo
->bankHeight
* pTileInfo
->banks
/
3367 pTileInfo
->macroAspectRatio
;
3369 if (m_chipFamily
== ADDR_CHIP_FAMILY_SI
)
3371 static const UINT_32 PrtTileSize
= 0x10000;
3373 UINT_32 macroTileSize
=
3374 m_blockWidth
[equationIndex
] * m_blockHeight
[equationIndex
] *
3377 if (macroTileSize
< PrtTileSize
)
3379 UINT_32 numMacroTiles
= PrtTileSize
/ macroTileSize
;
3381 ADDR_ASSERT(macroTileSize
== (1u << equation
.numBits
));
3382 ADDR_ASSERT((PrtTileSize
% macroTileSize
) == 0);
3384 UINT_32 numBits
= Log2(numMacroTiles
);
3386 UINT_32 xStart
= Log2(m_blockWidth
[equationIndex
]) +
3389 m_blockWidth
[equationIndex
] *= numMacroTiles
;
3391 for (UINT_32 i
= 0; i
< numBits
; i
++)
3393 equation
.addr
[equation
.numBits
+ i
].valid
= 1;
3394 equation
.addr
[equation
.numBits
+ i
].index
= xStart
+ i
;
3397 equation
.numBits
+= numBits
;
3402 equationKeyTable
[equationIndex
] = key
;
3403 m_equationTable
[equationIndex
] = equation
;
3410 // Fill the index into the lookup table, if the combination is not supported
3411 // fill the invalid equation index
3412 m_equationLookupTable
[log2ElementBytes
][tileIndex
] = equationIndex
;
3418 ***************************************************************************************************
3419 * SiAddrLib::IsEquationSupported
3422 * Check if it is supported for given bpp and tile config to generate a equation.
3426 ***************************************************************************************************
3428 BOOL_32
SiAddrLib::IsEquationSupported(
3429 UINT_32 bpp
, ///< Bits per pixel
3430 AddrTileConfig tileConfig
, ///< Tile config
3431 INT_32 tileIndex
///< Tile index
3434 BOOL_32 supported
= TRUE
;
3436 // Linear tile mode is not supported in swizzle pattern equation
3437 if (IsLinear(tileConfig
.mode
))
3441 // These tile modes are for Tex2DArray and Tex3D which has depth (num_slice > 1) use,
3442 // which is not supported in swizzle pattern equation due to slice rotation
3443 else if ((tileConfig
.mode
== ADDR_TM_2D_TILED_THICK
) ||
3444 (tileConfig
.mode
== ADDR_TM_2D_TILED_XTHICK
) ||
3445 (tileConfig
.mode
== ADDR_TM_3D_TILED_THIN1
) ||
3446 (tileConfig
.mode
== ADDR_TM_3D_TILED_THICK
) ||
3447 (tileConfig
.mode
== ADDR_TM_3D_TILED_XTHICK
))
3451 // Only 8bpp(stencil), 16bpp and 32bpp is supported for depth
3452 else if ((tileConfig
.type
== ADDR_DEPTH_SAMPLE_ORDER
) && (bpp
> 32))
3456 // Tile split is not supported in swizzle pattern equation
3457 else if (IsMacroTiled(tileConfig
.mode
))
3459 UINT_32 thickness
= Thickness(tileConfig
.mode
);
3460 if (((bpp
>> 3) * MicroTilePixels
* thickness
) > tileConfig
.info
.tileSplitBytes
)
3465 if ((supported
== TRUE
) && (m_chipFamily
== ADDR_CHIP_FAMILY_SI
))
3467 // Please refer to SiAddrLib::HwlSetupTileInfo for PRT tile index selecting
3468 // Tile index 3, 6, 21-25 are for PRT single sample
3471 supported
= (bpp
== 16);
3473 else if (tileIndex
== 6)
3475 supported
= (bpp
== 32);
3477 else if ((tileIndex
>= 21) && (tileIndex
<= 25))
3479 supported
= (bpp
== 8u * (1u << (static_cast<UINT_32
>(tileIndex
) - 21u)));