2 * Copyright © 2007-2019 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 helper function and constants.
31 ****************************************************************************************************
34 #ifndef __ADDR_COMMON_H__
35 #define __ADDR_COMMON_H__
37 #include "addrinterface.h"
47 // ADDR_LNX_KERNEL_BUILD is for internal build
48 // Moved from addrinterface.h so __KERNEL__ is not needed any more
49 #if ADDR_LNX_KERNEL_BUILD // || (defined(__GNUC__) && defined(__KERNEL__))
51 #elif !defined(__APPLE__) || defined(HAVE_TSERVER)
57 #include "util/macros.h"
59 ////////////////////////////////////////////////////////////////////////////////////////////////////
60 // Platform specific debug break defines
61 ////////////////////////////////////////////////////////////////////////////////////////////////////
64 #define ADDR_DBG_BREAK() assert(false)
65 #elif defined(__APPLE__)
66 #define ADDR_DBG_BREAK() { IOPanic("");}
68 #define ADDR_DBG_BREAK() { __debugbreak(); }
71 #define ADDR_DBG_BREAK()
73 ////////////////////////////////////////////////////////////////////////////////////////////////////
75 ////////////////////////////////////////////////////////////////////////////////////////////////////
76 // Debug assertions used in AddrLib
77 ////////////////////////////////////////////////////////////////////////////////////////////////////
78 #if defined(_WIN32) && (_MSC_VER >= 1400)
79 #define ADDR_ANALYSIS_ASSUME(expr) __analysis_assume(expr)
81 #define ADDR_ANALYSIS_ASSUME(expr) do { (void)(expr); } while (0)
84 #define ADDR_ASSERT(__e) assert(__e)
85 #define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
86 #define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
87 #define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
88 ////////////////////////////////////////////////////////////////////////////////////////////////////
90 ////////////////////////////////////////////////////////////////////////////////////////////////////
91 // Debug print macro from legacy address library
92 ////////////////////////////////////////////////////////////////////////////////////////////////////
95 #define ADDR_PRNT(a) Object::DebugPrint a
97 /// @brief Macro for reporting informational messages
100 /// This macro optionally prints an informational message to stdout.
101 /// The first parameter is a condition -- if it is true, nothing is done.
102 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
103 /// starting with a string. This is passed to printf() or an equivalent
104 /// in order to format the informational message. For example,
105 /// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
107 #define ADDR_INFO(cond, a) \
108 { if (!(cond)) { ADDR_PRNT(a); } }
110 /// @brief Macro for reporting error warning messages
113 /// This macro optionally prints an error warning message to stdout,
114 /// followed by the file name and line number where the macro was called.
115 /// The first parameter is a condition -- if it is true, nothing is done.
116 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
117 /// starting with a string. This is passed to printf() or an equivalent
118 /// in order to format the informational message. For example,
119 /// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
120 /// a second line with the file name and line number.
122 #define ADDR_WARN(cond, a) \
125 ADDR_PRNT((" WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
128 /// @brief Macro for reporting fatal error conditions
131 /// This macro optionally stops execution of the current routine
132 /// after printing an error warning message to stdout,
133 /// followed by the file name and line number where the macro was called.
134 /// The first parameter is a condition -- if it is true, nothing is done.
135 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
136 /// starting with a string. This is passed to printf() or an equivalent
137 /// in order to format the informational message. For example,
138 /// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
139 /// a second line with the file name and line number, then stops execution.
141 #define ADDR_EXIT(cond, a) \
143 { ADDR_PRNT(a); ADDR_DBG_BREAK();\
148 #define ADDRDPF 1 ? (void)0 : (void)
152 #define ADDR_DBG_BREAK()
154 #define ADDR_INFO(cond, a)
156 #define ADDR_WARN(cond, a)
158 #define ADDR_EXIT(cond, a)
161 ////////////////////////////////////////////////////////////////////////////////////////////////////
163 #define ADDR_C_ASSERT(__e) STATIC_ASSERT(__e)
170 ////////////////////////////////////////////////////////////////////////////////////////////////////
172 ////////////////////////////////////////////////////////////////////////////////////////////////////
173 static const UINT_32 MicroTileWidth
= 8; ///< Micro tile width, for 1D and 2D tiling
174 static const UINT_32 MicroTileHeight
= 8; ///< Micro tile height, for 1D and 2D tiling
175 static const UINT_32 ThickTileThickness
= 4; ///< Micro tile thickness, for THICK modes
176 static const UINT_32 XThickTileThickness
= 8; ///< Extra thick tiling thickness
177 static const UINT_32 PowerSaveTileBytes
= 64; ///< Nuber of bytes per tile for power save 64
178 static const UINT_32 CmaskCacheBits
= 1024; ///< Number of bits for CMASK cache
179 static const UINT_32 CmaskElemBits
= 4; ///< Number of bits for CMASK element
180 static const UINT_32 HtileCacheBits
= 16384; ///< Number of bits for HTILE cache 512*32
182 static const UINT_32 MicroTilePixels
= MicroTileWidth
* MicroTileHeight
;
184 static const INT_32 TileIndexInvalid
= TILEINDEX_INVALID
;
185 static const INT_32 TileIndexLinearGeneral
= TILEINDEX_LINEAR_GENERAL
;
186 static const INT_32 TileIndexNoMacroIndex
= -3;
192 ////////////////////////////////////////////////////////////////////////////////////////////////////
194 ////////////////////////////////////////////////////////////////////////////////////////////////////
195 static const UINT_32 MaxSurfaceHeight
= 16384;
199 ////////////////////////////////////////////////////////////////////////////////////////////////////
201 ////////////////////////////////////////////////////////////////////////////////////////////////////
202 #define BITS_PER_BYTE 8
203 #define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
204 #define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )
206 /// Helper macros to select a single bit from an int (undefined later in section)
207 #define _BIT(v,b) (((v) >> (b) ) & 1)
210 ****************************************************************************************************
211 * @brief Enums to identify AddrLib type
212 ****************************************************************************************************
225 ****************************************************************************************************
229 * Neutral enums that specifies chip family.
231 ****************************************************************************************************
235 ADDR_CHIP_FAMILY_IVLD
, ///< Invalid family
236 ADDR_CHIP_FAMILY_R6XX
,
237 ADDR_CHIP_FAMILY_R7XX
,
238 ADDR_CHIP_FAMILY_R8XX
,
244 ADDR_CHIP_FAMILY_NAVI
,
248 ****************************************************************************************************
252 * This structure is used to set configuration flags.
253 ****************************************************************************************************
259 /// These flags are set up internally thru AddrLib::Create() based on ADDR_CREATE_FLAGS
260 UINT_32 optimalBankSwap
: 1; ///< New bank tiling for RV770 only
261 UINT_32 noCubeMipSlicesPad
: 1; ///< Disables faces padding for cubemap mipmaps
262 UINT_32 fillSizeFields
: 1; ///< If clients fill size fields in all input and
264 UINT_32 ignoreTileInfo
: 1; ///< Don't use tile info structure
265 UINT_32 useTileIndex
: 1; ///< Make tileIndex field in input valid
266 UINT_32 useCombinedSwizzle
: 1; ///< Use combined swizzle
267 UINT_32 checkLast2DLevel
: 1; ///< Check the last 2D mip sub level
268 UINT_32 useHtileSliceAlign
: 1; ///< Do htile single slice alignment
269 UINT_32 allowLargeThickTile
: 1; ///< Allow 64*thickness*bytesPerPixel > rowSize
270 UINT_32 disableLinearOpt
: 1; ///< Disallow tile modes to be optimized to linear
271 UINT_32 use32bppFor422Fmt
: 1; ///< View 422 formats as 32 bits per pixel element
272 UINT_32 forceDccAndTcCompat
: 1; ///< Force enable DCC and TC compatibility
273 UINT_32 nonPower2MemConfig
: 1; ///< Physical video memory size is not power of 2
274 UINT_32 reserved
: 19; ///< Reserved bits for future use
280 ////////////////////////////////////////////////////////////////////////////////////////////////////
281 // Misc helper functions
282 ////////////////////////////////////////////////////////////////////////////////////////////////////
285 ****************************************************************************************************
289 * Xor the right-side numberOfBits bits of x.
290 ****************************************************************************************************
292 static inline UINT_32
XorReduce(
294 UINT_32 numberOfBits
)
297 UINT_32 result
= x
& 1;
299 for (i
=1; i
<numberOfBits
; i
++)
301 result
^= ((x
>>i
) & 1);
308 ****************************************************************************************************
312 * Check if the size (UINT_32) is pow 2
313 ****************************************************************************************************
315 static inline UINT_32
IsPow2(
316 UINT_32 dim
) ///< [in] dimension of miplevel
318 ADDR_ASSERT(dim
> 0);
319 return !(dim
& (dim
- 1));
323 ****************************************************************************************************
327 * Check if the size (UINT_64) is pow 2
328 ****************************************************************************************************
330 static inline UINT_64
IsPow2(
331 UINT_64 dim
) ///< [in] dimension of miplevel
333 ADDR_ASSERT(dim
> 0);
334 return !(dim
& (dim
- 1));
338 ****************************************************************************************************
342 * Align UINT_32 "x" to "align" alignment, "align" should be power of 2
343 ****************************************************************************************************
345 static inline UINT_32
PowTwoAlign(
350 // Assert that x is a power of two.
352 ADDR_ASSERT(IsPow2(align
));
353 return (x
+ (align
- 1)) & (~(align
- 1));
357 ****************************************************************************************************
361 * Align UINT_64 "x" to "align" alignment, "align" should be power of 2
362 ****************************************************************************************************
364 static inline UINT_64
PowTwoAlign(
369 // Assert that x is a power of two.
371 ADDR_ASSERT(IsPow2(align
));
372 return (x
+ (align
- 1)) & (~(align
- 1));
376 ****************************************************************************************************
380 * Get the min value between two unsigned values
381 ****************************************************************************************************
383 static inline UINT_32
Min(
387 return ((value1
< (value2
)) ? (value1
) : value2
);
391 ****************************************************************************************************
395 * Get the min value between two signed values
396 ****************************************************************************************************
398 static inline INT_32
Min(
402 return ((value1
< (value2
)) ? (value1
) : value2
);
406 ****************************************************************************************************
410 * Get the max value between two unsigned values
411 ****************************************************************************************************
413 static inline UINT_32
Max(
417 return ((value1
> (value2
)) ? (value1
) : value2
);
421 ****************************************************************************************************
425 * Get the max value between two signed values
426 ****************************************************************************************************
428 static inline INT_32
Max(
432 return ((value1
> (value2
)) ? (value1
) : value2
);
436 ****************************************************************************************************
440 * Compute the mipmap's next level dim size
441 ****************************************************************************************************
443 static inline UINT_32
NextPow2(
444 UINT_32 dim
) ///< [in] dimension of miplevel
448 if (dim
> 0x7fffffff)
450 ADDR_ASSERT_ALWAYS();
465 ****************************************************************************************************
469 * Compute log of base 2 no matter the target is power of 2 or not
470 ****************************************************************************************************
472 static inline UINT_32
Log2NonPow2(
473 UINT_32 x
) ///< [in] the value should calculate log based 2
488 ****************************************************************************************************
492 * Compute log of base 2
493 ****************************************************************************************************
495 static inline UINT_32
Log2(
496 UINT_32 x
) ///< [in] the value should calculate log based 2
498 // Assert that x is a power of two.
499 ADDR_ASSERT(IsPow2(x
));
501 return Log2NonPow2(x
);
505 ****************************************************************************************************
509 * Compute log of base 2 quickly (<= 16)
510 ****************************************************************************************************
512 static inline UINT_32
QLog2(
513 UINT_32 x
) ///< [in] the value should calculate log based 2
515 ADDR_ASSERT(x
<= 16);
537 ADDR_ASSERT_ALWAYS();
544 ****************************************************************************************************
548 * NULL pointer safe assignment
549 ****************************************************************************************************
551 static inline VOID
SafeAssign(
552 UINT_32
* pLVal
, ///< [in] Pointer to left val
553 UINT_32 rVal
) ///< [in] Right value
562 ****************************************************************************************************
566 * NULL pointer safe assignment for 64bit values
567 ****************************************************************************************************
569 static inline VOID
SafeAssign(
570 UINT_64
* pLVal
, ///< [in] Pointer to left val
571 UINT_64 rVal
) ///< [in] Right value
580 ****************************************************************************************************
584 * NULL pointer safe assignment for AddrTileMode
585 ****************************************************************************************************
587 static inline VOID
SafeAssign(
588 AddrTileMode
* pLVal
, ///< [in] Pointer to left val
589 AddrTileMode rVal
) ///< [in] Right value
598 ****************************************************************************************************
603 ****************************************************************************************************
605 static inline UINT_32
RoundHalf(
606 UINT_32 x
) ///< [in] input value
611 return (x
>> 1) + (x
& 1);
618 ****************************************************************************************************
622 * Calculate sum of a geometric progression whose ratio is 1/2
623 ****************************************************************************************************
625 static inline UINT_32
SumGeo(
626 UINT_32 base
, ///< [in] First term in the geometric progression
627 UINT_32 num
) ///< [in] Number of terms to be added into sum
629 ADDR_ASSERT(base
> 0);
633 for (; (i
< num
) && (base
> 1); i
++)
636 base
= RoundHalf(base
);
644 ****************************************************************************************************
648 * Extract bit N value (0 or 1) of a UINT32 value.
649 ****************************************************************************************************
651 static inline UINT_32
GetBit(
652 UINT_32 u32
, ///< [in] UINT32 value
653 UINT_32 pos
) ///< [in] bit position from LSB, valid range is [0..31]
655 ADDR_ASSERT(pos
<= 31);
657 return (u32
>> pos
) & 0x1;
661 ****************************************************************************************************
665 * Copy 'bitsNum' bits from src start from srcStartPos into destination from dstStartPos
666 * srcStartPos: 0~31 for UINT_32
667 * bitsNum : 1~32 for UINT_32
668 * srcStartPos: 0~31 for UINT_32
671 * src : b[31] b[30] b[29] ... ... ... ... ... ... ... ... b[end]..b[beg] ... b[1] b[0]
672 * || Bits num || copy length || Bits num ||
673 * dst : b[31] b[30] b[29] ... b[end]..b[beg] ... ... ... ... ... ... ... ... b[1] b[0]
676 ****************************************************************************************************
678 static inline UINT_32
GetBits(
684 ADDR_ASSERT((srcStartPos
< 32) && (dstStartPos
< 32) && (bitsNum
> 0));
685 ADDR_ASSERT((bitsNum
+ dstStartPos
<= 32) && (bitsNum
+ srcStartPos
<= 32));
687 return ((src
>> srcStartPos
) << (32 - bitsNum
)) >> (32 - bitsNum
- dstStartPos
);
691 ****************************************************************************************************
695 * Generate 2D Morton interleave code with num lowest bits in each channel
696 ****************************************************************************************************
698 static inline UINT_32
MortonGen2d(
699 UINT_32 x
, ///< [in] First channel
700 UINT_32 y
, ///< [in] Second channel
701 UINT_32 num
) ///< [in] Number of bits extracted from each channel
705 for (UINT_32 i
= 0; i
< num
; i
++)
707 mort
|= (GetBit(y
, i
) << (2 * i
));
708 mort
|= (GetBit(x
, i
) << (2 * i
+ 1));
715 ****************************************************************************************************
719 * Generate 3D Morton interleave code with num lowest bits in each channel
720 ****************************************************************************************************
722 static inline UINT_32
MortonGen3d(
723 UINT_32 x
, ///< [in] First channel
724 UINT_32 y
, ///< [in] Second channel
725 UINT_32 z
, ///< [in] Third channel
726 UINT_32 num
) ///< [in] Number of bits extracted from each channel
730 for (UINT_32 i
= 0; i
< num
; i
++)
732 mort
|= (GetBit(z
, i
) << (3 * i
));
733 mort
|= (GetBit(y
, i
) << (3 * i
+ 1));
734 mort
|= (GetBit(x
, i
) << (3 * i
+ 2));
741 ****************************************************************************************************
745 * Return reversed lowest num bits of v: v[0]v[1]...v[num-2]v[num-1]
746 ****************************************************************************************************
748 static inline UINT_32
ReverseBitVector(
749 UINT_32 v
, ///< [in] Reverse operation base value
750 UINT_32 num
) ///< [in] Number of bits used in reverse operation
754 for (UINT_32 i
= 0; i
< num
; i
++)
756 reverse
|= (GetBit(v
, num
- 1 - i
) << i
);
763 ****************************************************************************************************
767 * Xor bit vector v[num-1]v[num-2]...v[1]v[0] with v[num]v[num+1]...v[2*num-2]v[2*num-1]
768 ****************************************************************************************************
770 static inline UINT_32
FoldXor2d(
771 UINT_32 v
, ///< [in] Xor operation base value
772 UINT_32 num
) ///< [in] Number of bits used in fold xor operation
774 return (v
& ((1 << num
) - 1)) ^ ReverseBitVector(v
>> num
, num
);
778 ****************************************************************************************************
782 * Return v[0] | v[2] | v[4] | v[6]... | v[2*num - 2]
783 ****************************************************************************************************
785 static inline UINT_32
DeMort(
786 UINT_32 v
, ///< [in] DeMort operation base value
787 UINT_32 num
) ///< [in] Number of bits used in fold DeMort operation
791 for (UINT_32 i
= 0; i
< num
; i
++)
793 d
|= ((v
& (1 << (i
<< 1))) >> i
);
800 ****************************************************************************************************
804 * v[0]...v[num-1] ^ v[3*num-1]v[3*num-3]...v[num+2]v[num] ^ v[3*num-2]...v[num+1]v[num-1]
805 ****************************************************************************************************
807 static inline UINT_32
FoldXor3d(
808 UINT_32 v
, ///< [in] Xor operation base value
809 UINT_32 num
) ///< [in] Number of bits used in fold xor operation
811 UINT_32 t
= v
& ((1 << num
) - 1);
812 t
^= ReverseBitVector(DeMort(v
>> num
, num
), num
);
813 t
^= ReverseBitVector(DeMort(v
>> (num
+ 1), num
), num
);
819 ****************************************************************************************************
823 * Set channel initialization value via a return value
824 ****************************************************************************************************
826 static inline ADDR_CHANNEL_SETTING
InitChannel(
827 UINT_32 valid
, ///< [in] valid setting
828 UINT_32 channel
, ///< [in] channel setting
829 UINT_32 index
) ///< [in] index setting
831 ADDR_CHANNEL_SETTING t
;
840 ****************************************************************************************************
844 * Set channel initialization value via channel pointer
845 ****************************************************************************************************
847 static inline VOID
InitChannel(
848 UINT_32 valid
, ///< [in] valid setting
849 UINT_32 channel
, ///< [in] channel setting
850 UINT_32 index
, ///< [in] index setting
851 ADDR_CHANNEL_SETTING
*pChanSet
) ///< [out] channel setting to be initialized
853 pChanSet
->valid
= valid
;
854 pChanSet
->channel
= channel
;
855 pChanSet
->index
= index
;
859 ****************************************************************************************************
863 * Set channel initialization value via another channel
864 ****************************************************************************************************
866 static inline VOID
InitChannel(
867 ADDR_CHANNEL_SETTING
*pChanDst
, ///< [in] channel setting to be copied from
868 ADDR_CHANNEL_SETTING
*pChanSrc
) ///< [out] channel setting to be initialized
870 pChanDst
->valid
= pChanSrc
->valid
;
871 pChanDst
->channel
= pChanSrc
->channel
;
872 pChanDst
->index
= pChanSrc
->index
;
876 ****************************************************************************************************
877 * GetMaxValidChannelIndex
880 * Get max valid index for a specific channel
881 ****************************************************************************************************
883 static inline UINT_32
GetMaxValidChannelIndex(
884 const ADDR_CHANNEL_SETTING
*pChanSet
, ///< [in] channel setting to be initialized
885 UINT_32 searchCount
,///< [in] number of channel setting to be searched
886 UINT_32 channel
) ///< [in] channel to be searched
890 for (UINT_32 i
= 0; i
< searchCount
; i
++)
892 if (pChanSet
[i
].valid
&& (pChanSet
[i
].channel
== channel
))
894 index
= Max(index
, static_cast<UINT_32
>(pChanSet
[i
].index
));
902 ****************************************************************************************************
906 * Get bit mask which indicates which positions in the equation match the target coord
907 ****************************************************************************************************
909 static inline UINT_32
GetCoordActiveMask(
910 const ADDR_CHANNEL_SETTING
*pChanSet
, ///< [in] channel setting to be initialized
911 UINT_32 searchCount
,///< [in] number of channel setting to be searched
912 UINT_32 channel
, ///< [in] channel to be searched
913 UINT_32 index
) ///< [in] index to be searched
917 for (UINT_32 i
= 0; i
< searchCount
; i
++)
919 if ((pChanSet
[i
].valid
== TRUE
) &&
920 (pChanSet
[i
].channel
== channel
) &&
921 (pChanSet
[i
].index
== index
))
931 ****************************************************************************************************
935 * Apply righ-shift with ceiling
936 ****************************************************************************************************
938 static inline UINT_32
ShiftCeil(
939 UINT_32 a
, ///< [in] value to be right-shifted
940 UINT_32 b
) ///< [in] number of bits to shift
942 return (a
>> b
) + (((a
& ((1 << b
) - 1)) != 0) ? 1 : 0);
947 #endif // __ADDR_COMMON_H__