From ff47395757001f8bb299948ce4822958b72dc6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 19 Mar 2023 18:02:05 -0400 Subject: [PATCH] amd: import gfx12 addrlib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Samuel Pitoiset Acked-by: Timur Kristóf Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/amd/addrlib/inc/addrinterface.h | 458 ++++- src/amd/addrlib/inc/addrtypes.h | 20 + src/amd/addrlib/meson.build | 8 +- src/amd/addrlib/src/addrinterface.cpp | 201 ++ src/amd/addrlib/src/amdgpu_asic_addr.h | 7 + src/amd/addrlib/src/chip/gfx12/gfx12_gb_reg.h | 57 + src/amd/addrlib/src/core/addrcommon.h | 1 + src/amd/addrlib/src/core/addrlib.cpp | 3 + src/amd/addrlib/src/core/addrlib.h | 1 + src/amd/addrlib/src/core/addrlib3.cpp | 965 ++++++++++ src/amd/addrlib/src/core/addrlib3.h | 442 +++++ .../addrlib/src/gfx12/gfx12SwizzlePattern.h | 279 +++ src/amd/addrlib/src/gfx12/gfx12addrlib.cpp | 1611 +++++++++++++++++ src/amd/addrlib/src/gfx12/gfx12addrlib.h | 209 +++ 14 files changed, 4260 insertions(+), 2 deletions(-) create mode 100644 src/amd/addrlib/src/chip/gfx12/gfx12_gb_reg.h create mode 100644 src/amd/addrlib/src/core/addrlib3.cpp create mode 100644 src/amd/addrlib/src/core/addrlib3.h create mode 100644 src/amd/addrlib/src/gfx12/gfx12SwizzlePattern.h create mode 100644 src/amd/addrlib/src/gfx12/gfx12addrlib.cpp create mode 100644 src/amd/addrlib/src/gfx12/gfx12addrlib.h diff --git a/src/amd/addrlib/inc/addrinterface.h b/src/amd/addrlib/inc/addrinterface.h index 769d91b344b..8eb19fd9c53 100644 --- a/src/amd/addrlib/inc/addrinterface.h +++ b/src/amd/addrlib/inc/addrinterface.h @@ -24,7 +24,7 @@ extern "C" #endif #define ADDRLIB_VERSION_MAJOR 9 -#define ADDRLIB_VERSION_MINOR 0 +#define ADDRLIB_VERSION_MINOR 1 #define ADDRLIB_VERSION ((ADDRLIB_VERSION_MAJOR << 16) | ADDRLIB_VERSION_MINOR) /// Virtually all interface functions need ADDR_HANDLE as first parameter @@ -4042,6 +4042,462 @@ BOOL_32 Addr2BlockTypeWithinMemoryBudget( BOOL_32 newBlockTypeBigger); #endif +/** +**************************************************************************************************** +* ADDR3_SURFACE_FLAGS +* +* @brief +* Surface flags +**************************************************************************************************** +*/ +typedef union _ADDR3_SURFACE_FLAGS +{ + struct + { + UINT_32 color : 1; ///< This resource is a color buffer, can be used with RTV + UINT_32 depth : 1; ///< This resource is a depth buffer, can be used with DSV + UINT_32 stencil : 1; ///< This resource is a stencil buffer, can be used with DSV + UINT_32 texture : 1; ///< This resource can be used with SRV + UINT_32 unordered : 1; ///< This resource can be used with UAV + UINT_32 hiZHiS : 1; + UINT_32 blockCompressed : 1; + UINT_32 nv12 : 1; + UINT_32 p010 : 1; + UINT_32 view3dAs2dArray : 1; + UINT_32 isVrsImage : 1; ///< This resource is a VRS source image + UINT_32 reserved : 21; ///< Reserved bits + }; + + UINT_32 value; +} ADDR3_SURFACE_FLAGS; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SURFACE_INFO_INPUT +* +* @brief +* Input structure for Addr3ComputeSurfaceInfo +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SURFACE_INFO_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + + ADDR3_SURFACE_FLAGS flags; ///< Surface flags + Addr3SwizzleMode swizzleMode; ///< Swizzle Mode for Gfx12 + AddrResourceType resourceType; ///< Surface type + AddrFormat format; ///< Surface format + UINT_32 bpp; ///< bits per pixel + UINT_32 width; ///< Width (of mip0), in pixels + UINT_32 height; ///< Height (of mip0), in pixels + UINT_32 numSlices; ///< Number surface slice/depth (of mip0), + UINT_32 numMipLevels; ///< Total mipmap levels. + UINT_32 numSamples; ///< Number of samples + UINT_32 pitchInElement; ///< Pitch in elements (blocks for compressed formats) + UINT_32 sliceAlign; ///< Required slice size in bytes +} ADDR3_COMPUTE_SURFACE_INFO_INPUT; + +/** +**************************************************************************************************** +* ADDR3_MIP_INFO +* +* @brief +* Structure that contains information for mip level +* +**************************************************************************************************** +*/ +typedef struct _ADDR3_MIP_INFO +{ + UINT_32 pitch; ///< Pitch in elements + UINT_32 height; ///< Padded height in elements + UINT_32 depth; ///< Padded depth + UINT_32 pixelPitch; ///< Pitch in pixels + UINT_32 pixelHeight; ///< Padded height in pixels + UINT_32 equationIndex; ///< Equation index in the equation table + UINT_64 offset; ///< Offset in bytes from mip base, should only be used + ///< to setup vam surface descriptor, can't be used + ///< to setup swizzle pattern + UINT_64 macroBlockOffset; ///< macro block offset in bytes from mip base + UINT_32 mipTailOffset; ///< mip tail offset in bytes + UINT_32 mipTailCoordX; ///< mip tail coord x + UINT_32 mipTailCoordY; ///< mip tail coord y + UINT_32 mipTailCoordZ; ///< mip tail coord z +} ADDR3_MIP_INFO; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SURFACE_INFO_OUTPUT +* +* @brief +* Output structure for Addr3ComputeSurfaceInfo +* @note + Element: AddrLib unit for computing. e.g. BCn: 4x4 blocks; R32B32B32: 32bit with 3x pitch + Pixel: Original pixel +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SURFACE_INFO_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_32 pitch; ///< Pitch in elements (blocks for compressed formats) + UINT_32 pixelPitch; ///< Pitch in original pixels + UINT_32 pixelHeight; ///< Height in original pixels + UINT_32 pixelBits; ///< Original bits per pixel, passed from input + UINT_32 bpp; ///< Bits per elements + /// (e.g. blocks for BCn, 1/3 for 96bit) + UINT_32 numSlices; ///< Padded depth for 3d resource + /// or padded number of slices for 2d array resource + UINT_32 height; ///< Padded height (of mip0) in elements + UINT_64 sliceSize; ///< Slice (total mip chain) size in bytes + UINT_64 surfSize; ///< Surface (total mip chain) size in bytes + UINT_32 baseAlign; ///< Base address alignment + ADDR_EXTENT3D blockExtent; ///< Dimensions in element inside one block + UINT_32 pixelMipChainPitch; ///< Mip chain pitch in original pixels + UINT_32 pixelMipChainHeight; ///< Mip chain height in original pixels + ADDR3_MIP_INFO* pMipInfo; ///< Info regarding the start, sizes of the mip levels + BOOL_32 mipChainInTail; ///< If whole mipchain falls into mip tail block + UINT_32 firstMipIdInTail; ///< The id of first mip in tail, if there is no mip + /// in tail, it will be set to number of mip levels +} ADDR3_COMPUTE_SURFACE_INFO_OUTPUT; + +/** +**************************************************************************************************** +* ADDR3_SWMODE_SET +* +* @brief +* Bit field that defines swizzle type +**************************************************************************************************** +*/ +// The bit order MUST be the same as Addr3SwizzleMode enumerations, otherwise using bitset to enable +// or disable swizzle modes will be problematic. +typedef union _ADDR3_SWMODE_SET +{ + struct + { + UINT_32 swLinear : 1; + UINT_32 sw2d256B : 1; + UINT_32 sw2d4kB : 1; + UINT_32 sw2d64kB : 1; + UINT_32 sw2d256kB : 1; + UINT_32 sw3d4kB : 1; + UINT_32 sw3d64kB : 1; + UINT_32 sw3d256kB : 1; + UINT_32 reserved : 24; + }; + + UINT_32 value; +} ADDR3_SWMODE_SET; + +/** +**************************************************************************************************** +* ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT +* +* @brief +* Input structure of Addr3GetPossibleSwizzleModes +**************************************************************************************************** +*/ +typedef struct _ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + + ADDR3_SURFACE_FLAGS flags; ///< Surface flags + AddrResourceType resourceType; ///< Surface type + UINT_32 bpp; ///< bits per pixel + UINT_32 width; ///< Width (of mip0), in pixels + UINT_32 height; ///< Height (of mip0), in pixels + UINT_32 numSlices; ///< Number surface slice/depth (of mip0), + UINT_32 numMipLevels; ///< Total mipmap levels. + UINT_32 numSamples; ///< Number of samples + UINT_32 maxAlign; ///< maximum base/size alignment requested by client +} ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT; + +/** +**************************************************************************************************** +* ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT +* +* @brief +* Output structure of Addr3GetPossibleSwizzleModes +**************************************************************************************************** +*/ +typedef struct _ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + ADDR3_SWMODE_SET validModes; ///< List of valid swizzle modes for this function. +} ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputeSurfaceInfo +* +* @brief +* Compute surface width/height/slices/alignments and suitable tiling mode +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSurfaceInfo( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut); + +/** +**************************************************************************************************** +* Addr3GetPossibleSwizzleModes +* +* @brief +* Returns a list of swizzle modes that are valid from the hardware's perspective for the +* client to choose from +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3GetPossibleSwizzleModes( + ADDR_HANDLE hLib, + const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn, + ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut); + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT +* +* @brief +* Input structure for Addr3ComputeSurfaceAddrFromCoord +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + + UINT_32 x; ///< X coordinate + UINT_32 y; ///< Y coordinate + UINT_32 slice; ///< Slice index + UINT_32 sample; ///< Sample index, use fragment index for EQAA + UINT_32 mipId; ///< the mip ID in mip chain + + Addr3SwizzleMode swizzleMode; ///< Swizzle mode for Gfx12 + ADDR3_SURFACE_FLAGS flags; ///< Surface flags + AddrResourceType resourceType; ///< Surface type + UINT_32 bpp; ///< Bits per pixel + ADDR_EXTENT3D unAlignedDims; ///< Surface original dimensions (of mip0) + UINT_32 numMipLevels; ///< Total mipmap levels + UINT_32 numSamples; ///< Number of samples + UINT_32 pitchInElement; ///< Pitch in elements (blocks for compressed formats) +} ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT +* +* @brief +* Output structure for Addr3ComputeSurfaceAddrFromCoord +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + + UINT_64 addr; ///< Byte offset from the image starting address + UINT_32 bitPosition; ///< Bit position within surfaceAddr, 0-7. + /// For surface bpp < 8, e.g. FMT_1. + UINT_32 prtBlockIndex; ///< Index of a PRT tile (64K block) +} ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputeSurfaceAddrFromCoord +* +* @brief +* Compute surface address from a given coordinate. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSurfaceAddrFromCoord( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut); + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_PIPEBANKXOR_INPUT +* +* @brief +* Input structure of Addr3ComputePipebankXor +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_PIPEBANKXOR_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_32 surfIndex; ///< Input surface index + Addr3SwizzleMode swizzleMode; ///< Surface swizzle mode +} ADDR3_COMPUTE_PIPEBANKXOR_INPUT; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT +* +* @brief +* Output structure of Addr3ComputePipebankXor +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_32 pipeBankXor; ///< Pipe bank xor +} ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputePipeBankXor +* +* @brief +* Calculate a valid bank pipe xor value for client to use. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputePipeBankXor( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut); + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT +* +* @brief +* Input structure of Addr3ComputeNonBlockCompressedView +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + ADDR3_SURFACE_FLAGS flags; ///< Surface flags + Addr3SwizzleMode swizzleMode; ///< Swizzle Mode for Gfx12 + AddrResourceType resourceType; ///< Surface type + AddrFormat format; ///< Surface format + ADDR_EXTENT3D unAlignedDims; ///< Surface original dimensions (of mip0) + UINT_32 numMipLevels; ///< Total mipmap levels. + UINT_32 pipeBankXor; ///< Combined swizzle used to do bank/pipe rotation + UINT_32 slice; ///< Index of slice to view + UINT_32 mipId; ///< Id of mip to view +} ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT +* +* @brief +* Output structure of Addr3ComputeNonBlockCompressedView +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_64 offset; ///< Offset from resource base for the view + UINT_32 pipeBankXor; ///< Pipe bank xor for the view + ADDR_EXTENT3D unAlignedDims; ///< Mip0 dimens (in element) for the view + UINT_32 numMipLevels; ///< Total mipmap levels for the view + UINT_32 mipId; ///< Mip ID for the view +} ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputeNonBlockCompressedView +* +* @brief +* Compute non-block-compressed view for a given mipmap level/slice +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeNonBlockCompressedView( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut); + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT +* +* @brief +* Input structure of Addr3ComputeSubResourceOffsetForSwizzlePattern +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + Addr3SwizzleMode swizzleMode; ///< Surface swizzle mode + AddrResourceType resourceType; ///< Surface resource type + UINT_32 pipeBankXor; ///< Per resource xor + UINT_32 slice; ///< Slice id + UINT_64 sliceSize; ///< Slice size of a mip chain + UINT_64 macroBlockOffset; ///< Macro block offset, returned in ADDR3_MIP_INFO + UINT_32 mipTailOffset; ///< Mip tail offset, returned in ADDR3_MIP_INFO +} ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT +* +* @brief +* Output structure of Addr3ComputeSubResourceOffsetForSwizzlePattern +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_64 offset; ///< offset +} ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputeSubResourceOffsetForSwizzlePattern +* +* @brief +* Calculate sub resource offset to support swizzle pattern. +**************************************************************************************************** +*/ +VOID ADDR_API Addr3ComputeSubResourceOffsetForSwizzlePattern( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut); + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT +* +* @brief +* Input structure of Addr2ComputeSlicePipeBankXor +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT +{ + UINT_32 size; ///< Size of this structure in bytes + Addr3SwizzleMode swizzleMode; ///< Surface swizzle mode + AddrResourceType resourceType; ///< Surface resource type + UINT_32 bpe; ///< bits per element (e.g. block size for BCn format) + UINT_32 basePipeBankXor; ///< Base pipe bank xor + UINT_32 slice; ///< Slice id + UINT_32 numSamples; ///< Number of samples +} ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT; + +/** +**************************************************************************************************** +* ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT +* +* @brief +* Output structure of Addr3ComputeSlicePipeBankXor +**************************************************************************************************** +*/ +typedef struct _ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT +{ + UINT_32 size; ///< Size of this structure in bytes + UINT_32 pipeBankXor; ///< Pipe bank xor +} ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT; + +/** +**************************************************************************************************** +* Addr3ComputeSlicePipeBankXor +* +* @brief +* Calculate slice pipe bank xor value based on base pipe bank xor and slice id. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSlicePipeBankXor( + ADDR_HANDLE hLib, + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut); + #if defined(__cplusplus) } #endif diff --git a/src/amd/addrlib/inc/addrtypes.h b/src/amd/addrlib/inc/addrtypes.h index 74b20d20415..aa1b48873eb 100644 --- a/src/amd/addrlib/inc/addrtypes.h +++ b/src/amd/addrlib/inc/addrtypes.h @@ -275,6 +275,26 @@ typedef enum _AddrSwizzleMode ADDR_SW_256KB_R_X = ADDR_SW_MISCDEF31, } AddrSwizzleMode; +/** +**************************************************************************************************** +* @brief +* Neutral enums that define swizzle modes for Gfx12+ ASIC +* +**************************************************************************************************** +*/ +typedef enum _Addr3SwizzleMode +{ + ADDR3_LINEAR = 0, + ADDR3_256B_2D = 1, + ADDR3_4KB_2D = 2, + ADDR3_64KB_2D = 3, + ADDR3_256KB_2D = 4, + ADDR3_4KB_3D = 5, + ADDR3_64KB_3D = 6, + ADDR3_256KB_3D = 7, + ADDR3_MAX_TYPE = 8, +} Addr3SwizzleMode; + /** **************************************************************************************************** * @brief diff --git a/src/amd/addrlib/meson.build b/src/amd/addrlib/meson.build index 60d00a4f098..c836f7d2f01 100644 --- a/src/amd/addrlib/meson.build +++ b/src/amd/addrlib/meson.build @@ -31,6 +31,8 @@ files_addrlib = files( 'src/core/addrlib1.h', 'src/core/addrlib2.cpp', 'src/core/addrlib2.h', + 'src/core/addrlib3.cpp', + 'src/core/addrlib3.h', 'src/core/addrobject.cpp', 'src/core/addrobject.h', 'src/core/coord.cpp', @@ -43,9 +45,13 @@ files_addrlib = files( 'src/gfx11/gfx11addrlib.cpp', 'src/gfx11/gfx11addrlib.h', 'src/gfx11/gfx11SwizzlePattern.h', + 'src/gfx12/gfx12addrlib.cpp', + 'src/gfx12/gfx12addrlib.h', + 'src/gfx12/gfx12SwizzlePattern.h', 'src/amdgpu_asic_addr.h', 'src/chip/gfx10/gfx10_gb_reg.h', 'src/chip/gfx11/gfx11_gb_reg.h', + 'src/chip/gfx12/gfx12_gb_reg.h', 'src/chip/gfx9/gfx9_gb_reg.h', 'src/chip/r800/si_gb_reg.h', 'src/r800/ciaddrlib.cpp', @@ -77,7 +83,7 @@ libamdgpu_addrlib = static_library( include_directories : [ include_directories( 'inc', 'src', 'src/core', 'src/chip/gfx9', 'src/chip/r800', - 'src/chip/gfx10', 'src/chip/gfx11', + 'src/chip/gfx10', 'src/chip/gfx11', 'src/chip/gfx12', ), inc_amd_common, inc_include, inc_src ], diff --git a/src/amd/addrlib/src/addrinterface.cpp b/src/amd/addrlib/src/addrinterface.cpp index 504ce515a1d..6ab2ba041da 100644 --- a/src/amd/addrlib/src/addrinterface.cpp +++ b/src/amd/addrlib/src/addrinterface.cpp @@ -15,6 +15,7 @@ #include "addrinterface.h" #include "addrlib1.h" #include "addrlib2.h" +#include "addrlib3.h" #include "addrcommon.h" @@ -1949,3 +1950,203 @@ BOOL_32 Addr2BlockTypeWithinMemoryBudget( return accept; } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Surface functions for Addr3 +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +**************************************************************************************************** +* Addr3ComputeSurfaceInfo +* +* @brief +* Calculate surface width/height/depth/alignments and suitable tiling mode +* +* @return +* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSurfaceInfo( + ADDR_HANDLE hLib, ///< address lib handle + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] surface information + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) ///< [out] surface parameters and alignments +{ + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (pLib != NULL) + { + returnCode = pLib->ComputeSurfaceInfo(pIn, pOut); + } + + return returnCode; +} + +/** +**************************************************************************************************** +* Addr3GetPossibleSwizzleModes +* +* @brief +* Get valid swizzle mode options given image input for further optimal selection +* +* @return +* ADDR_OK if successful, otherwise an error code of ADDR_PARAMSIZEMISMATCH +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3GetPossibleSwizzleModes( + ADDR_HANDLE hLib, ///< address lib handle + const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn, ///< [in] surface information + ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut) ///< [out] allowable swizzle mdoes +{ + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (pLib != NULL) + { + returnCode = pLib->GetPossibleSwizzleModes(pIn, pOut); + } + + return returnCode; +} + +/** +**************************************************************************************************** +* Addr3ComputeSurfaceAddrFromCoord +* +* @brief +* Compute surface address according to coordinates +* +* @return +* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSurfaceAddrFromCoord( + ADDR_HANDLE hLib, ///< address lib handle + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] surface info and coordinates + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] surface address +{ + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (pLib != NULL) + { + returnCode = pLib->ComputeSurfaceAddrFromCoord(pIn, pOut); + } + else + { + returnCode = ADDR_ERROR; + } + + return returnCode; +} + +/** +**************************************************************************************************** +* Addr3ComputePipeBankXor +* +* @brief +* Calculate a valid bank pipe xor value for client to use. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputePipeBankXor( + ADDR_HANDLE hLib, ///< handle of addrlib + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, ///< [in] input + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut) ///< [out] output +{ + ADDR_E_RETURNCODE returnCode; + + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + if (pLib != NULL) + { + returnCode = pLib->ComputePipeBankXor(pIn, pOut); + } + else + { + returnCode = ADDR_ERROR; + } + + return returnCode; +} + +/** +**************************************************************************************************** +* Addr3ComputeNonBlockCompressedView +* +* @brief +* Compute non-block-compressed view for a given mipmap level/slice. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeNonBlockCompressedView( + ADDR_HANDLE hLib, ///< handle of addrlib + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, ///< [in] input + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut) ///< [out] output +{ + ADDR_E_RETURNCODE returnCode; + + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + if (pLib != NULL) + { + returnCode = pLib->ComputeNonBlockCompressedView(pIn, pOut); + } + else + { + returnCode = ADDR_ERROR; + } + + return returnCode; +} + +/** +**************************************************************************************************** +* Addr3ComputeSubResourceOffsetForSwizzlePattern +* +* @brief +* Calculate sub resource offset for swizzle pattern. +**************************************************************************************************** +*/ +VOID ADDR_API Addr3ComputeSubResourceOffsetForSwizzlePattern( + ADDR_HANDLE hLib, ///< handle of addrlib + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, ///< [in] input + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut) ///< [out] output +{ + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + if (pLib != NULL) + { + pLib->ComputeSubResourceOffsetForSwizzlePattern(pIn, pOut); + } +} + +/** +**************************************************************************************************** +* Addr3ComputeSlicePipeBankXor +* +* @brief +* Calculate slice pipe bank xor value based on base pipe bank xor and slice id. +**************************************************************************************************** +*/ +ADDR_E_RETURNCODE ADDR_API Addr3ComputeSlicePipeBankXor( + ADDR_HANDLE hLib, ///< handle of addrlib + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, ///< [in] input + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut) ///< [out] output +{ + ADDR_E_RETURNCODE returnCode; + + V3::Lib* pLib = V3::Lib::GetLib(hLib); + + if (pLib != NULL) + { + returnCode = pLib->ComputeSlicePipeBankXor(pIn, pOut); + } + else + { + returnCode = ADDR_ERROR; + } + + return returnCode; +} diff --git a/src/amd/addrlib/src/amdgpu_asic_addr.h b/src/amd/addrlib/src/amdgpu_asic_addr.h index 86834de62b4..3b71bea0459 100644 --- a/src/amd/addrlib/src/amdgpu_asic_addr.h +++ b/src/amd/addrlib/src/amdgpu_asic_addr.h @@ -32,6 +32,7 @@ #define FAMILY_RMB 0x92 //# 146 / Rembrandt #define FAMILY_RPL 0x95 //# 149 / Raphael #define FAMILY_MDN 0x97 //# 151 / Mendocino +#define FAMILY_GFX12 0x98 // AMDGPU_FAMILY_IS(familyId, familyName) #define FAMILY_IS(f, fn) (f == FAMILY_##fn) @@ -47,6 +48,7 @@ #define FAMILY_IS_NV(f) FAMILY_IS(f, NV) #define FAMILY_IS_RMB(f) FAMILY_IS(f, RMB) #define FAMILY_IS_NV3(f) FAMILY_IS(f, NV3) +#define FAMILY_IS_GFX12(f) FAMILY_IS(f, GFX12) #define AMDGPU_UNKNOWN 0xFF @@ -107,6 +109,9 @@ #define AMDGPU_RAPHAEL_RANGE 0x01, 0xFF //# 1 <= x < max #define AMDGPU_MENDOCINO_RANGE 0x01, 0xFF //# 1 <= x < max +#define AMDGPU_GFX1200_RANGE 0x40, 0x50 +#define AMDGPU_GFX1201_RANGE 0x50, 0xFF + #define AMDGPU_EXPAND_FIX(x) x #define AMDGPU_RANGE_HELPER(val, min, max) ((val >= min) && (val < max)) #define AMDGPU_IN_RANGE(val, ...) AMDGPU_EXPAND_FIX(AMDGPU_RANGE_HELPER(val, __VA_ARGS__)) @@ -179,4 +184,6 @@ #define ASICREV_IS_RAPHAEL(r) ASICREV_IS(r, RAPHAEL) #define ASICREV_IS_MENDOCINO(r) ASICREV_IS(r, MENDOCINO) +#define ASICREV_IS_GFX1200(r) ASICREV_IS(r, GFX1200) + #endif // _AMDGPU_ASIC_ADDR_H diff --git a/src/amd/addrlib/src/chip/gfx12/gfx12_gb_reg.h b/src/amd/addrlib/src/chip/gfx12/gfx12_gb_reg.h new file mode 100644 index 00000000000..389b3871d95 --- /dev/null +++ b/src/amd/addrlib/src/chip/gfx12/gfx12_gb_reg.h @@ -0,0 +1,57 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2007-2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + +#if !defined (__GFX12_GB_REG_H__) +#define __GFX12_GB_REG_H__ + +/* +* gfx12_gb_reg.h +* +* Register Spec Release: 1.0 +* +*/ + +// +// Make sure the necessary endian defines are there. +// +#if defined(LITTLEENDIAN_CPU) +#elif defined(BIGENDIAN_CPU) +#else +#error "BIGENDIAN_CPU or LITTLEENDIAN_CPU must be defined" +#endif + +union GB_ADDR_CONFIG_GFX12 { + struct { +#if defined(LITTLEENDIAN_CPU) + unsigned int NUM_PIPES : 3; + unsigned int PIPE_INTERLEAVE_SIZE : 3; + unsigned int MAX_COMPRESSED_FRAGS : 2; + unsigned int NUM_PKRS : 3; + unsigned int : 8; + unsigned int NUM_SHADER_ENGINES : 4; + unsigned int : 3; + unsigned int NUM_RB_PER_SE : 2; + unsigned int : 4; +#elif defined(BIGENDIAN_CPU) + unsigned int : 4; + unsigned int NUM_RB_PER_SE : 2; + unsigned int : 3; + unsigned int NUM_SHADER_ENGINES : 4; + unsigned int : 8; + unsigned int NUM_PKRS : 3; + unsigned int MAX_COMPRESSED_FRAGS : 2; + unsigned int PIPE_INTERLEAVE_SIZE : 3; + unsigned int NUM_PIPES : 3; +#endif + } bitfields, bits; + unsigned int u32All; + int i32All; + float f32All; +}; + +#endif \ No newline at end of file diff --git a/src/amd/addrlib/src/core/addrcommon.h b/src/amd/addrlib/src/core/addrcommon.h index 71231e0a87c..ff22b0400dc 100644 --- a/src/amd/addrlib/src/core/addrcommon.h +++ b/src/amd/addrlib/src/core/addrcommon.h @@ -249,6 +249,7 @@ enum ChipFamily ADDR_CHIP_FAMILY_VI, ADDR_CHIP_FAMILY_AI, ADDR_CHIP_FAMILY_NAVI, + ADDR_CHIP_FAMILY_UNKNOWN, }; /** diff --git a/src/amd/addrlib/src/core/addrlib.cpp b/src/amd/addrlib/src/core/addrlib.cpp index 1cb1f9243b9..fe85c04a3e8 100644 --- a/src/amd/addrlib/src/core/addrlib.cpp +++ b/src/amd/addrlib/src/core/addrlib.cpp @@ -220,6 +220,9 @@ ADDR_E_RETURNCODE Lib::Create( case FAMILY_GFX1103: pLib = Gfx11HwlInit(&client); break; + case FAMILY_GFX12: + pLib = Gfx12HwlInit(&client); + break; default: ADDR_ASSERT_ALWAYS(); break; diff --git a/src/amd/addrlib/src/core/addrlib.h b/src/amd/addrlib/src/core/addrlib.h index 853b635445c..7a1f59dc1c5 100644 --- a/src/amd/addrlib/src/core/addrlib.h +++ b/src/amd/addrlib/src/core/addrlib.h @@ -407,6 +407,7 @@ Lib* CiHwlInit (const Client* pClient); Lib* Gfx9HwlInit (const Client* pClient); Lib* Gfx10HwlInit(const Client* pClient); Lib* Gfx11HwlInit(const Client* pClient); +Lib* Gfx12HwlInit(const Client* pClient); } // Addr #endif diff --git a/src/amd/addrlib/src/core/addrlib3.cpp b/src/amd/addrlib/src/core/addrlib3.cpp new file mode 100644 index 00000000000..6013b20be25 --- /dev/null +++ b/src/amd/addrlib/src/core/addrlib3.cpp @@ -0,0 +1,965 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2007-2022 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + + +/** +************************************************************************************************************************ +* @file addrlib3.cpp +* @brief Contains the implementation for the AddrLib3 base class. +************************************************************************************************************************ +*/ + +#include "addrinterface.h" +#include "addrlib3.h" +#include "addrcommon.h" + +namespace Addr +{ +namespace V3 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Constructor/Destructor +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +************************************************************************************************************************ +* Lib::Lib +* +* @brief +* Constructor for the Addr::V3::Lib class +* +************************************************************************************************************************ +*/ +Lib::Lib() + : + Addr::Lib(), + m_pipesLog2(0), + m_pipeInterleaveLog2(0), + m_numEquations(0) +{ + Init(); +} + +/** +************************************************************************************************************************ +* Lib::Lib +* +* @brief +* Constructor for the AddrLib3 class with hClient as parameter +* +************************************************************************************************************************ +*/ +Lib::Lib( + const Client* pClient) + : + Addr::Lib(pClient), + m_pipesLog2(0), + m_pipeInterleaveLog2(0), + m_numEquations(0) +{ + Init(); +} + +/** +************************************************************************************************************************ +* Lib::Init +* +* @brief +* Initialization of class +* +************************************************************************************************************************ +*/ +void Lib::Init() +{ + memset(m_equationTable, 0, sizeof(m_equationTable)); + memset(m_blockDimensionTable, 0, sizeof(m_blockDimensionTable)); + + // There is no equation table entry for linear, so start at the "next" swizzle mode entry. + for (UINT_32 swizzleModeIdx = ADDR3_LINEAR + 1; swizzleModeIdx < ADDR3_MAX_TYPE; swizzleModeIdx++) + { + for (UINT_32 msaaRateIdx = 0; msaaRateIdx < MaxMsaaRateLog2; msaaRateIdx++) + { + for (UINT_32 log2BytesIdx = 0; log2BytesIdx < MaxElementBytesLog2; log2BytesIdx++) + { + SetEquationTableEntry(static_cast(swizzleModeIdx), + msaaRateIdx, + log2BytesIdx, + ADDR_INVALID_EQUATION_INDEX); + } + } + } +} + +/** +************************************************************************************************************************ +* Lib::~Lib +* +* @brief +* Destructor for the AddrLib2 class +* +************************************************************************************************************************ +*/ +Lib::~Lib() +{ +} + +/** +************************************************************************************************************************ +* Lib::GetLib +* +* @brief +* Get Addr::V3::Lib pointer +* +* @return +* An Addr::V2::Lib class pointer +************************************************************************************************************************ +*/ +Lib* Lib::GetLib( + ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE +{ + Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib); + + return static_cast(hLib); +} + +/** +************************************************************************************************************************ +* Lib::GetBlockSize +* +* @brief +* Returns the byte size of a block for the swizzle mode. +* +* @return +* Byte size of the block, zero if swizzle mode is invalid. +************************************************************************************************************************ +*/ +UINT_32 Lib::GetBlockSize( + Addr3SwizzleMode swizzleMode, + BOOL_32 forPitch + ) const +{ + return (1 << GetBlockSizeLog2(swizzleMode, forPitch)); +} + +/** +************************************************************************************************************************ +* Lib::GetBlockSizeLog2 +* +* @brief +* Returns the log2 of the byte size of a block for the swizzle mode. +* +* @return +* Byte size of the block, zero if swizzle mode is invalid. +************************************************************************************************************************ +*/ +UINT_32 Lib::GetBlockSizeLog2( + Addr3SwizzleMode swizzleMode, + BOOL_32 forPitch + ) const +{ + UINT_32 blockSize = 0; + + switch (swizzleMode) + { + case ADDR3_256B_2D: + blockSize = 8; + break; + case ADDR3_4KB_2D: + case ADDR3_4KB_3D: + blockSize = 12; + break; + case ADDR3_64KB_2D: + case ADDR3_64KB_3D: + blockSize = 16; + break; + case ADDR3_256KB_2D: + case ADDR3_256KB_3D: + blockSize = 18; + break; + case ADDR3_LINEAR: + blockSize = (forPitch ? 7 : 8); + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + + return blockSize; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSurfaceInfo +* +* @brief +* Interface function stub of ComputeSurfaceInfo. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (GetFillSizeFieldsFlags() == TRUE) + { + if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_INPUT)) || + (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT))) + { + returnCode = ADDR_PARAMSIZEMISMATCH; + } + } + + // Adjust incoming parameters. + ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn; + localIn.width = Max(pIn->width, 1u); + localIn.height = Max(pIn->height, 1u); + localIn.numMipLevels = Max(pIn->numMipLevels, 1u); + localIn.numSlices = Max(pIn->numSlices, 1u); + localIn.numSamples = Max(pIn->numSamples, 1u); + + UINT_32 expandX = 1; + UINT_32 expandY = 1; + ElemMode elemMode = ADDR_UNCOMPRESSED; + + if (returnCode == ADDR_OK) + { + // Set format to INVALID will skip this conversion + if (localIn.format != ADDR_FMT_INVALID) + { + // Get compression/expansion factors and element mode which indicates compression/expansion + localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format, + &elemMode, + &expandX, + &expandY); + + // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is + // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear- + // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw + // restrictions are different. + // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround + // but we use this flag to skip RestoreSurfaceInfo below + if ((elemMode == ADDR_EXPANDED) && (expandX > 1)) + { + ADDR_ASSERT(IsLinear(localIn.swizzleMode)); + } + + UINT_32 basePitch = 0; + GetElemLib()->AdjustSurfaceInfo(elemMode, + expandX, + expandY, + &localIn.bpp, + &basePitch, + &localIn.width, + &localIn.height); + + // Overwrite these parameters if we have a valid format + } + + if (localIn.bpp != 0) + { + localIn.width = Max(localIn.width, 1u); + localIn.height = Max(localIn.height, 1u); + } + else // Rule out some invalid parameters + { + returnCode = ADDR_INVALIDPARAMS; + } + } + + if (returnCode == ADDR_OK) + { + returnCode = HwlComputeSurfaceInfo(&localIn, pOut); + + if (returnCode == ADDR_OK) + { + pOut->bpp = localIn.bpp; + pOut->pixelPitch = pOut->pitch; + pOut->pixelHeight = pOut->height; + + if (localIn.format != ADDR_FMT_INVALID) + { + UINT_32 pixelBits = pOut->pixelBits; + + GetElemLib()->RestoreSurfaceInfo(elemMode, + expandX, + expandY, + &pOut->pixelBits, + &pOut->pixelPitch, + &pOut->pixelHeight); + + GetElemLib()->RestoreSurfaceInfo(elemMode, + expandX, + expandY, + &pixelBits, + &pOut->pixelMipChainPitch, + &pOut->pixelMipChainHeight); + + if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL)) + { + for (UINT_32 i = 0; i < localIn.numMipLevels; i++) + { + pOut->pMipInfo[i].pixelPitch = pOut->pMipInfo[i].pitch; + pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height; + + GetElemLib()->RestoreSurfaceInfo(elemMode, + expandX, + expandY, + &pixelBits, + &pOut->pMipInfo[i].pixelPitch, + &pOut->pMipInfo[i].pixelHeight); + } + } + } + } + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::GetPossibleSwizzleModes +* +* @brief +* Interface function stub of AddrComputeSurfaceInfo. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes( + const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn, ///< [in] input structure + ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (GetFillSizeFieldsFlags() == TRUE) + { + if ((pIn->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT)) || + (pOut->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT))) + { + returnCode = ADDR_PARAMSIZEMISMATCH; + } + } + + if (returnCode == ADDR_OK) + { + const ADDR3_SURFACE_FLAGS flags = pIn->flags; + + // VRS images can only be 2D from the client API rules. + ADDR_ASSERT((flags.isVrsImage == 0) || IsTex2d(pIn->resourceType)); + + if (pIn->bpp == 96) + { + pOut->validModes.swLinear = 1; + } + // Depth/Stencil images can't be linear and must be 2D swizzle modes. + // These three are related to DB block that supports only SW_64KB_2D and SW_256KB_2D for DSV. + else if (flags.depth || flags.stencil) + { + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + // The organization of elements in the hierarchical surface is the same as any other surface, and it can support + // any 2D swizzle mode (SW_256_2D, SW_4KB_2D, SW_64KB_2D, or SW_256KB_2D). The swizzle mode can be selected + // orthogonally to the underlying z or stencil surface. + else if (pIn->flags.hiZHiS) + { + pOut->validModes.sw2d256B = 1; + pOut->validModes.sw2d4kB = 1; + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + // MSAA can't be linear and must be 2D swizzle modes. + else if (pIn->numSamples > 1) + { + // NOTE: SW_256B_2D still supports MSAA. The removal of 256B for MSAA is reverted in HW Doc. + pOut->validModes.sw2d256B = 1; + pOut->validModes.sw2d4kB = 1; + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + // Block-compressed images need to be either using 2D or linear swizzle modes. + else if (flags.blockCompressed) + { + pOut->validModes.swLinear = 1; + + // We find cases where Tex3d BlockCompressed image adopts 2D_256B should be prohibited. + if (IsTex3d(pIn->resourceType) == FALSE) + { + pOut->validModes.sw2d256B = 1; + } + pOut->validModes.sw2d4kB = 1; + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + else if (IsTex1d(pIn->resourceType)) + { + pOut->validModes.swLinear = 1; + pOut->validModes.sw2d256B = 1; + pOut->validModes.sw2d4kB = 1; + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + else if (flags.nv12 || flags.p010 || IsTex2d(pIn->resourceType) || flags.view3dAs2dArray) + { + // NV12 and P010 support + // SW_LINEAR, SW_256B_2D, SW_4KB_2D, SW_64KB_2D, SW_256KB_2D + // There could be more multimedia formats that require more hw specific tiling modes... + + // The exception is VRS images. + // Linear is not allowed and the VRS surface needs to be 8BPP format. + if (flags.isVrsImage) + { + ADDR_ASSERT(pIn->bpp == 8); + } + else + { + pOut->validModes.swLinear = 1; + } + if (flags.view3dAs2dArray == 0) + { + // ADDR3_256B_2D can't support 3D images. + pOut->validModes.sw2d256B = 1; + } + pOut->validModes.sw2d4kB = 1; + pOut->validModes.sw2d64kB = 1; + pOut->validModes.sw2d256kB = 1; + } + else if (IsTex3d(pIn->resourceType)) + { + // An eventual determination would be based on pal setting of height_watermark and depth_watermark. + // However, we just adopt the simpler logic currently. + // For 3D images w/ view3dAs2dArray = 0, SW_3D is preferred. + // For 3D images w/ view3dAs2dArray = 1, it should go to 2D path above. + // Enable linear since client may force linear tiling for 3D texture that does not set view3dAs2dArray. + pOut->validModes.swLinear = 1; + pOut->validModes.sw3d4kB = 1; + pOut->validModes.sw3d64kB = 1; + pOut->validModes.sw3d256kB = 1; + } + } + + constexpr UINT_32 Size256 = 256u; + constexpr UINT_32 Size4K = 4 * 1024; + constexpr UINT_32 Size64K = 64 * 1024; + constexpr UINT_32 Size256K = 256 * 1024; + + // If client specifies a max alignment, remove swizzles that require alignment beyond it. + if (pIn->maxAlign != 0) + { + if (pIn->maxAlign < Size256K) + { + pOut->validModes.value &= ~Gfx12Blk256KBSwModeMask; + } + + if (pIn->maxAlign < Size64K) + { + pOut->validModes.value &= ~Gfx12Blk64KBSwModeMask; + } + + if (pIn->maxAlign < Size4K) + { + pOut->validModes.value &= ~Gfx12Blk4KBSwModeMask; + } + + if (pIn->maxAlign < Size256) + { + pOut->validModes.value &= ~Gfx12Blk256BSwModeMask; + } + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeBlockDimensionForSurf +* +* @brief +* Internal function to get block width/height/depth in elements from surface input params. +* +* @return +* VOID +************************************************************************************************************************ +*/ +VOID Lib::ComputeBlockDimensionForSurf( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR_EXTENT3D* pExtent + ) const +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + const UINT_32 log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode); + + HwlCalcBlockSize(pIn, pExtent); +} + +/** +************************************************************************************************************************ +* Lib::GetMipTailDim +* +* @brief +* Internal function to get out max dimension of first level in mip tail +* +* @return +* Max Width/Height/Depth value of the first mip fitted in mip tail +************************************************************************************************************************ +*/ +ADDR_EXTENT3D Lib::GetMipTailDim( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& blockDims + ) const +{ + return HwlGetMipInTailMaxSize(pIn, blockDims); +} + +/** +************************************************************************************************************************ +* Lib::ComputeSurfaceAddrFromCoord +* +* @brief +* Interface function stub of ComputeSurfaceAddrFromCoord. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (GetFillSizeFieldsFlags() == TRUE) + { + if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) || + (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT))) + { + returnCode = ADDR_PARAMSIZEMISMATCH; + } + } + + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn; + localIn.unAlignedDims.width = Max(pIn->unAlignedDims.width, 1u); + localIn.unAlignedDims.height = Max(pIn->unAlignedDims.height, 1u); + localIn.unAlignedDims.depth = Max(pIn->unAlignedDims.depth, 1u); + localIn.numMipLevels = Max(pIn->numMipLevels, 1u); + localIn.numSamples = Max(pIn->numSamples, 1u); + + if ((localIn.bpp < 8) || + (localIn.bpp > 128) || + ((localIn.bpp % 8) != 0) || + (localIn.sample >= localIn.numSamples) || + (localIn.slice >= localIn.unAlignedDims.depth) || + (localIn.mipId >= localIn.numMipLevels) || + (IsTex3d(localIn.resourceType) && + (Valid3DMipSliceIdConstraint(localIn.unAlignedDims.depth, localIn.mipId, localIn.slice) == FALSE))) + { + returnCode = ADDR_INVALIDPARAMS; + } + + if (returnCode == ADDR_OK) + { + if (IsLinear(localIn.swizzleMode)) + { + returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut); + } + else + { + returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut); + } + + if (returnCode == ADDR_OK) + { + pOut->prtBlockIndex = static_cast(pOut->addr / (64 * 1024)); + } + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSurfaceAddrFromCoord +* +* @brief +* Interface function stub of Addr3ComputePipeBankXor. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputePipeBankXor( + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut) +{ + ADDR_E_RETURNCODE returnCode; + + if ((GetFillSizeFieldsFlags() == TRUE) && + ((pIn->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_INPUT)) || + (pOut->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT)))) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + returnCode = HwlComputePipeBankXor(pIn, pOut); + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSurfaceAddrFromCoordLinear +* +* @brief +* Internal function to calculate address from coord for linear swizzle surface +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + BOOL_32 valid = (pIn->numSamples <= 1); + + if (valid) + { + if (IsTex1d(pIn->resourceType)) + { + valid = (pIn->y == 0); + } + } + + if (valid) + { + ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = {0}; + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0}; + ADDR3_MIP_INFO mipInfo[MaxMipLevels]; + ADDR_ASSERT(pIn->numMipLevels <= MaxMipLevels); + + localIn.size = sizeof(localIn); + localIn.flags = pIn->flags; + localIn.swizzleMode = ADDR3_LINEAR; + localIn.resourceType = pIn->resourceType; + localIn.format = ADDR_FMT_INVALID; + localIn.bpp = pIn->bpp; + localIn.width = Max(pIn->unAlignedDims.width, 1u); + localIn.height = Max(pIn->unAlignedDims.height, 1u); + localIn.numSlices = Max(pIn->unAlignedDims.depth, 1u); + localIn.numMipLevels = Max(pIn->numMipLevels, 1u); + localIn.numSamples = Max(pIn->numSamples, 1u); + + if (localIn.numMipLevels <= 1) + { + localIn.pitchInElement = pIn->pitchInElement; + } + + localOut.size = sizeof(localOut); + localOut.pMipInfo = mipInfo; + + returnCode = ComputeSurfaceInfo(&localIn, &localOut); + + if (returnCode == ADDR_OK) + { + pOut->addr = (localOut.sliceSize * pIn->slice) + + mipInfo[pIn->mipId].offset + + (pIn->y * mipInfo[pIn->mipId].pitch + pIn->x) * (pIn->bpp >> 3); + pOut->bitPosition = 0; + } + else + { + valid = FALSE; + } + } + + if (valid == FALSE) + { + returnCode = ADDR_INVALIDPARAMS; + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSurfaceAddrFromCoordTiled +* +* @brief +* Internal function to calculate address from coord for tiled swizzle surface +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut); +} + +/** +************************************************************************************************************************ +* Lib::ComputeNonBlockCompressedView +* +* @brief +* Interface function stub of Addr3ComputeNonBlockCompressedView. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView( + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut) +{ + ADDR_E_RETURNCODE returnCode; + + if ((GetFillSizeFieldsFlags() == TRUE) && + ((pIn->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) || + (pOut->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT)))) + { + returnCode = ADDR_INVALIDPARAMS; + } + else if (Is3dSwizzle(pIn->swizzleMode)) + { + // 3D volume images using ADDR3_XX_3D is currently not supported. + returnCode = ADDR_NOTSUPPORTED; + } + else + { + returnCode = HwlComputeNonBlockCompressedView(pIn, pOut); + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSubResourceOffsetForSwizzlePattern +* +* @brief +* Interface function stub of Addr3ComputeSubResourceOffsetForSwizzlePattern. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern( + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut) +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if ((GetFillSizeFieldsFlags() == TRUE) && + ((pIn->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) || + (pOut->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT)))) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut); + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::ComputeSlicePipeBankXor +* +* @brief +* Interface function stub of Addr3ComputeSlicePipeBankXor. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor( + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut) +{ + ADDR_E_RETURNCODE returnCode; + + if ((GetFillSizeFieldsFlags() == TRUE) && + ((pIn->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) || + (pOut->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT)))) + { + returnCode = ADDR_INVALIDPARAMS; + } + if ((pIn->bpe != 0) && + (pIn->bpe != 8) && + (pIn->bpe != 16) && + (pIn->bpe != 32) && + (pIn->bpe != 64) && + (pIn->bpe != 128)) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + returnCode = HwlComputeSlicePipeBankXor(pIn, pOut); + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Lib::UseCustomHeight +* +* @brief +* Determines if the calculations for this surface should use minimal HW values or user-specified values. +* +* @return +* Returns TRUE if the user-specified alignment should be used +************************************************************************************************************************ +*/ +BOOL_32 Lib::UseCustomHeight( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn + ) const +{ + return ((pIn->numMipLevels <= 1) && + IsLinear(pIn->swizzleMode) && + (pIn->sliceAlign > 0)); +} + +/** +************************************************************************************************************************ +* Lib::UseCustomPitch +* +* @brief +* Determines if the calculations for this surface should use minimal HW values or user-specified values. +* +* @return +* Returns TRUE if the user-specified pitch should be used +************************************************************************************************************************ +*/ +BOOL_32 Lib::UseCustomPitch( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn + ) const +{ + return ((pIn->numMipLevels <= 1) && + IsLinear(pIn->swizzleMode) && + (pIn->pitchInElement > 0)); +} + +/** +************************************************************************************************************************ +* Lib::CanTrimLinearPadding +* +* @brief +* Determines if the calculations for this surface can omit extra trailing padding for linear surfaces. +* +* @return +* Returns TRUE if the trailing padding can be omitted. +************************************************************************************************************************ +*/ +BOOL_32 Lib::CanTrimLinearPadding( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn + ) const +{ + return ((IsTex3d(pIn->resourceType) == FALSE) && + (pIn->numSlices <= 1) && + IsLinear(pIn->swizzleMode)); +} + +/** +************************************************************************************************************************ +* Lib::ApplyCustomizedPitchHeight +* +* @brief +* Helper function to override hw required row pitch/slice pitch by customrized one +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + const UINT_32 elementBytes = pIn->bpp >> 3; + + // We may use 128B pitch alignment for linear addressing mip0 image under some restriction. + if ((pIn->numMipLevels == 1) && CanTrimLinearPadding(pIn)) + { + pOut->pitch = PowTwoAlign(pIn->width, 128u / elementBytes); + } + else + { + // Calculate the default pitch/height without any user inputs + pOut->pitch = PowTwoAlign(pIn->width, pOut->blockExtent.width); + } + pOut->height = PowTwoAlign(pIn->height, pOut->blockExtent.height); + + // Custom pitches / alignments are only possible with single mip level / linear images; otherwise, + // ignore those parameters. + if (UseCustomPitch(pIn)) + { + const UINT_32 pitchAlignmentBytes = 1 << GetBlockSizeLog2(pIn->swizzleMode, TRUE); + const UINT_32 pitchAlignmentElements = pitchAlignmentBytes / elementBytes; + + // Their requested pitch has to meet the pitch alignment constraints applied by the HW. + if ((pIn->pitchInElement % pitchAlignmentElements) != 0) + { + returnCode = ADDR_INVALIDPARAMS; + } + // And their pitch can't be less than the minimum + else if (pIn->pitchInElement < pOut->pitch) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + pOut->pitch = pIn->pitchInElement; + } + } + + if ((returnCode == ADDR_OK) && UseCustomHeight(pIn)) + { + UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / pOut->pitch; + + if (customizedHeight * elementBytes * pOut->pitch != pIn->sliceAlign) + { + returnCode = ADDR_INVALIDPARAMS; + } + else if ((pIn->numSlices > 1) && (pOut->height != customizedHeight)) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + pOut->height = customizedHeight; + } + } + + return returnCode; +} + +} // V3 +} // Addr diff --git a/src/amd/addrlib/src/core/addrlib3.h b/src/amd/addrlib/src/core/addrlib3.h new file mode 100644 index 00000000000..ecd8b1b3abb --- /dev/null +++ b/src/amd/addrlib/src/core/addrlib3.h @@ -0,0 +1,442 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + + +/** +************************************************************************************************************************ +* @file addrlib3.h +* @brief Contains the Addr::V3::Lib class definition. +************************************************************************************************************************ +*/ + +#ifndef __ADDR3_LIB3_H__ +#define __ADDR3_LIB3_H__ + +#include "addrlib.h" + +namespace Addr +{ +namespace V3 +{ + +struct ADDR3_COORD +{ + INT_32 x; + INT_32 y; + INT_32 z; +}; + +// The HW address library utilizes an "addr_params" structure that is GPU-specific; therefore, we use a "void" pointer +// here to allow the HWL's to interpret this pointer with the appropriate structure. +// To reduce the frequency of conversion between the "ADDR3_COMPUTE_SURFACE_INFO_INPUT" structure and the "addr_params" +// structure, we create this super-structure to tie the two structures together. +struct ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo; + void* pvAddrParams; +}; + +/** +************************************************************************************************************************ +* @brief Bitmasks for swizzle mode determination on GFX12 +************************************************************************************************************************ +*/ +const UINT_32 Gfx12Blk256KBSwModeMask = (1u << ADDR3_256KB_2D) | + (1u << ADDR3_256KB_3D); + +const UINT_32 Gfx12Blk64KBSwModeMask = (1u << ADDR3_64KB_2D) | + (1u << ADDR3_64KB_3D); + +const UINT_32 Gfx12Blk4KBSwModeMask = (1u << ADDR3_4KB_2D) | + (1u << ADDR3_4KB_3D); + +const UINT_32 Gfx12Blk256BSwModeMask = (1u << ADDR3_256B_2D); + +/** +************************************************************************************************************************ +* @brief Bit setting for swizzle pattern +************************************************************************************************************************ +*/ +union ADDR_BIT_SETTING +{ + struct + { + UINT_16 x; + UINT_16 y; + UINT_16 z; + UINT_16 s; + }; + UINT_64 value; +}; + +/** +************************************************************************************************************************ +* @brief Flags for SwizzleModeTable +************************************************************************************************************************ +*/ +union SwizzleModeFlags +{ + struct + { + // Swizzle mode + UINT_32 isLinear : 1; // Linear + UINT_32 is2d : 1; // 2d mode + UINT_32 is3d : 1; // 3d mode + + // Block size + UINT_32 is256b : 1; // Block size is 256B + UINT_32 is4kb : 1; // Block size is 4KB + UINT_32 is64kb : 1; // Block size is 64KB + UINT_32 is256kb : 1; // Block size is 256KB + + UINT_32 reserved : 25; // Reserved bits + }; + + UINT_32 u32All; +}; + +const UINT_32 Log2Size256 = 8u; + +const UINT_32 Log2Size256K = 18u; + +/** +************************************************************************************************************************ +* @brief Swizzle pattern information +************************************************************************************************************************ +*/ +// Accessed by index representing the logbase2 of (8bpp/16bpp/32bpp/64bpp/128bpp) +// contains the indices which map to 2D arrays SW_PATTERN_NIBBLE[1-4] which contain sections of an index equation. +struct ADDR_SW_PATINFO +{ + UINT_8 nibble1Idx; + UINT_8 nibble2Idx; + UINT_8 nibble3Idx; + UINT_8 nibble4Idx; +}; + +/** +************************************************************************************************************************ +* InitBit +* +* @brief +* Initialize bit setting value via a return value +************************************************************************************************************************ +*/ +#define InitBit(c, index) (1ull << ((c << 4) + index)) + +const UINT_64 X0 = InitBit(0, 0); +const UINT_64 X1 = InitBit(0, 1); +const UINT_64 X2 = InitBit(0, 2); +const UINT_64 X3 = InitBit(0, 3); +const UINT_64 X4 = InitBit(0, 4); +const UINT_64 X5 = InitBit(0, 5); +const UINT_64 X6 = InitBit(0, 6); +const UINT_64 X7 = InitBit(0, 7); +const UINT_64 X8 = InitBit(0, 8); + +const UINT_64 Y0 = InitBit(1, 0); +const UINT_64 Y1 = InitBit(1, 1); +const UINT_64 Y2 = InitBit(1, 2); +const UINT_64 Y3 = InitBit(1, 3); +const UINT_64 Y4 = InitBit(1, 4); +const UINT_64 Y5 = InitBit(1, 5); +const UINT_64 Y6 = InitBit(1, 6); +const UINT_64 Y7 = InitBit(1, 7); +const UINT_64 Y8 = InitBit(1, 8); + +const UINT_64 Z0 = InitBit(2, 0); +const UINT_64 Z1 = InitBit(2, 1); +const UINT_64 Z2 = InitBit(2, 2); +const UINT_64 Z3 = InitBit(2, 3); +const UINT_64 Z4 = InitBit(2, 4); +const UINT_64 Z5 = InitBit(2, 5); + +const UINT_64 S0 = InitBit(3, 0); +const UINT_64 S1 = InitBit(3, 1); +const UINT_64 S2 = InitBit(3, 2); + +/** +************************************************************************************************************************ +* @brief Bit setting for swizzle pattern +************************************************************************************************************************ +*/ + +/** +************************************************************************************************************************ +* @brief This class contains asic independent address lib functionalities +************************************************************************************************************************ +*/ +class Lib : public Addr::Lib +{ +public: + virtual ~Lib(); + + static Lib* GetLib( + ADDR_HANDLE hLib); + + // + // Interface stubs + // + + // For data surface + ADDR_E_RETURNCODE ComputeSurfaceInfo( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + ADDR_E_RETURNCODE GetPossibleSwizzleModes( + const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn, + ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut) const; + + ADDR_E_RETURNCODE ComputeSurfaceAddrFromCoord( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; + + // Misc + ADDR_E_RETURNCODE ComputePipeBankXor( + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut); + + ADDR_E_RETURNCODE ComputeNonBlockCompressedView( + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut); + + ADDR_E_RETURNCODE ComputeSubResourceOffsetForSwizzlePattern( + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut); + + ADDR_E_RETURNCODE ComputeSlicePipeBankXor( + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut); + +protected: + Lib(); // Constructor is protected + Lib(const Client* pClient); + + static const UINT_32 MaxImageDim = 65536; // Max image size is 64k + static const UINT_32 MaxMipLevels = 17; + UINT_32 m_pipesLog2; ///< Number of pipe per shader engine Log2 + UINT_32 m_pipeInterleaveLog2; ///< Log2 of pipe interleave bytes + + SwizzleModeFlags m_swizzleModeTable[ADDR3_MAX_TYPE]; ///< Swizzle mode table + + // Number of unique MSAA sample rates (1/2/4/8) + static const UINT_32 MaxMsaaRateLog2 = 4; + // Max number of bpp (8bpp/16bpp/32bpp/64bpp/128bpp) + static const UINT_32 MaxElementBytesLog2 = 5; + // Number of unique swizzle patterns (one entry per swizzle mode + MSAA + bpp configuration) + static const UINT_32 NumSwizzlePatterns = 19 * MaxElementBytesLog2; + + // Number of equation entries in the table + UINT_32 m_numEquations; + + // Swizzle equation lookup table according to swizzle mode, MSAA sample rate and bpp. This does not include linear. + UINT_32 m_equationLookupTable[ADDR3_MAX_TYPE - 1][MaxMsaaRateLog2][MaxElementBytesLog2]; + + // Equation table + ADDR_EQUATION m_equationTable[NumSwizzlePatterns]; + + // Block dimension lookup table according to swizzle mode, MSAA sample rate and bpp. This includes linear. + ADDR_EXTENT3D m_blockDimensionTable[ADDR3_MAX_TYPE][MaxMsaaRateLog2][MaxElementBytesLog2]; + + void SetEquationTableEntry( + Addr3SwizzleMode swMode, + UINT_32 msaaLog2, + UINT_32 elementBytesLog2, + UINT_32 value) + { + m_equationLookupTable[swMode - 1][msaaLog2][elementBytesLog2] = value; + } + + const UINT_32 GetEquationTableEntry( + Addr3SwizzleMode swMode, + UINT_32 msaaLog2, + UINT_32 elementBytesLog2) const + { + return m_equationLookupTable[swMode - 1][msaaLog2][elementBytesLog2]; + } + + const ADDR_EXTENT3D GetBlockDimensionTableEntry( + Addr3SwizzleMode swMode, + UINT_32 msaaLog2, + UINT_32 elementBytesLog2) const + { + return m_blockDimensionTable[swMode][msaaLog2][elementBytesLog2]; + } + + static BOOL_32 Valid3DMipSliceIdConstraint( + UINT_32 numSlices, + UINT_32 mipId, + UINT_32 slice) + { + return (Max((numSlices >> mipId), 1u) > slice); + } + + UINT_32 GetBlockSize( + Addr3SwizzleMode swizzleMode, + BOOL_32 forPitch = FALSE) const; + + UINT_32 GetBlockSizeLog2( + Addr3SwizzleMode swizzleMode, + BOOL_32 forPitch = FALSE) const; + + BOOL_32 IsValidSwMode(Addr3SwizzleMode swizzleMode) const + { + return (m_swizzleModeTable[swizzleMode].u32All != 0); + } + + UINT_32 IsLinear(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].isLinear; + } + + // Checking block size + BOOL_32 IsBlock256b(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is256b; + } + + // Checking block size + BOOL_32 IsBlock4kb(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is4kb; + } + + // Checking block size + BOOL_32 IsBlock64kb(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is64kb; + } + + // Checking block size + BOOL_32 IsBlock256kb(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is256kb; + } + + BOOL_32 Is2dSwizzle(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is2d; + } + + BOOL_32 Is3dSwizzle(Addr3SwizzleMode swizzleMode) const + { + return m_swizzleModeTable[swizzleMode].is3d; + } + + // miptail is applied to only larger block size (4kb, 64kb, 256kb), so there is no miptail in linear and + // 256b_2d addressing since they are both 256b block. + BOOL_32 SupportsMipTail(Addr3SwizzleMode swizzleMode) const + { + return GetBlockSize(swizzleMode) > 256u; + } + + virtual UINT_32 HwlComputeMaxBaseAlignments() const { return 256 * 1024; } + + virtual BOOL_32 HwlInitGlobalParams(const ADDR_CREATE_INPUT* pCreateIn) + { + ADDR_NOT_IMPLEMENTED(); + // Although GFX12 addressing should be consistent regardless of the configuration, we still need to + // call some initialization for member variables. + return TRUE; + } + + virtual UINT_32 HwlComputeMaxMetaBaseAlignments() const { return 0; } + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + return ADDR_NOTSUPPORTED; + } + + virtual ADDR_E_RETURNCODE HwlComputePipeBankXor( + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + return ADDR_NOTSUPPORTED; + } + + VOID ComputeBlockDimensionForSurf( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR_EXTENT3D* pExtent) const; + + ADDR_EXTENT3D GetMipTailDim( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& blockDims) const; + + ADDR_E_RETURNCODE ComputeSurfaceAddrFromCoordLinear( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; + + ADDR_E_RETURNCODE ComputeSurfaceAddrFromCoordTiled( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceAddrFromCoordTiled( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + return ADDR_NOTIMPLEMENTED; + } + + virtual ADDR_E_RETURNCODE HwlComputeNonBlockCompressedView( + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + return ADDR_NOTSUPPORTED; + } + + virtual VOID HwlComputeSubResourceOffsetForSwizzlePattern( + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + } + + virtual ADDR_E_RETURNCODE HwlComputeSlicePipeBankXor( + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut) const + { + ADDR_NOT_IMPLEMENTED(); + return ADDR_NOTSUPPORTED; + } + + ADDR_E_RETURNCODE ApplyCustomizedPitchHeight( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + BOOL_32 UseCustomHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + BOOL_32 UseCustomPitch(const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + BOOL_32 CanTrimLinearPadding(const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + + virtual VOID HwlCalcBlockSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR_EXTENT3D* pExtent) const = 0; + + virtual ADDR_EXTENT3D HwlGetMipInTailMaxSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& blockDims) const = 0; + +private: + // Disallow the copy constructor + Lib(const Lib& a); + + // Disallow the assignment operator + Lib& operator=(const Lib& a); + + void Init(); +}; + +} // V3 +} // Addr + +#endif \ No newline at end of file diff --git a/src/amd/addrlib/src/gfx12/gfx12SwizzlePattern.h b/src/amd/addrlib/src/gfx12/gfx12SwizzlePattern.h new file mode 100644 index 00000000000..b29fbb8ef47 --- /dev/null +++ b/src/amd/addrlib/src/gfx12/gfx12SwizzlePattern.h @@ -0,0 +1,279 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + +/** +************************************************************************************************************************ +* @file gfx12SwizzlePattern.h +* @brief swizzle pattern for gfx12. +************************************************************************************************************************ +*/ + +#ifndef __GFX12_SWIZZLE_PATTERN_H__ +#define __GFX12_SWIZZLE_PATTERN_H__ + +namespace Addr +{ +namespace V3 +{ + const ADDR_SW_PATINFO GFX12_SW_256B_2D_1xAA_PATINFO[] = + { + { 0, 0, 0, 0, } , // 1 BPE @ SW_256B_2D_1xAA + { 1, 0, 0, 0, } , // 2 BPE @ SW_256B_2D_1xAA + { 2, 0, 0, 0, } , // 4 BPE @ SW_256B_2D_1xAA + { 3, 0, 0, 0, } , // 8 BPE @ SW_256B_2D_1xAA + { 4, 0, 0, 0, } , // 16 BPE @ SW_256B_2D_1xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256B_2D_2xAA_PATINFO[] = + { + { 5, 0, 0, 0, } , // 1 BPE @ SW_256B_2D_2xAA + { 6, 0, 0, 0, } , // 2 BPE @ SW_256B_2D_2xAA + { 7, 0, 0, 0, } , // 4 BPE @ SW_256B_2D_2xAA + { 8, 0, 0, 0, } , // 8 BPE @ SW_256B_2D_2xAA + { 9, 0, 0, 0, } , // 16 BPE @ SW_256B_2D_2xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256B_2D_4xAA_PATINFO[] = + { + { 10, 0, 0, 0, } , // 1 BPE @ SW_256B_2D_4xAA + { 11, 0, 0, 0, } , // 2 BPE @ SW_256B_2D_4xAA + { 12, 0, 0, 0, } , // 4 BPE @ SW_256B_2D_4xAA + { 13, 0, 0, 0, } , // 8 BPE @ SW_256B_2D_4xAA + { 14, 0, 0, 0, } , // 16 BPE @ SW_256B_2D_4xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256B_2D_8xAA_PATINFO[] = + { + { 15, 0, 0, 0, } , // 1 BPE @ SW_256B_2D_8xAA + { 16, 0, 0, 0, } , // 2 BPE @ SW_256B_2D_8xAA + { 17, 0, 0, 0, } , // 4 BPE @ SW_256B_2D_8xAA + { 18, 0, 0, 0, } , // 8 BPE @ SW_256B_2D_8xAA + { 19, 0, 0, 0, } , // 16 BPE @ SW_256B_2D_8xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_4KB_2D_1xAA_PATINFO[] = + { + { 0, 1, 0, 0, } , // 1 BPE @ SW_4KB_2D_1xAA + { 1, 2, 0, 0, } , // 2 BPE @ SW_4KB_2D_1xAA + { 2, 3, 0, 0, } , // 4 BPE @ SW_4KB_2D_1xAA + { 3, 4, 0, 0, } , // 8 BPE @ SW_4KB_2D_1xAA + { 4, 5, 0, 0, } , // 16 BPE @ SW_4KB_2D_1xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_4KB_2D_2xAA_PATINFO[] = + { + { 5, 2, 0, 0, } , // 1 BPE @ SW_4KB_2D_2xAA + { 6, 3, 0, 0, } , // 2 BPE @ SW_4KB_2D_2xAA + { 7, 4, 0, 0, } , // 4 BPE @ SW_4KB_2D_2xAA + { 8, 5, 0, 0, } , // 8 BPE @ SW_4KB_2D_2xAA + { 9, 6, 0, 0, } , // 16 BPE @ SW_4KB_2D_2xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_4KB_2D_4xAA_PATINFO[] = + { + { 10, 3, 0, 0, } , // 1 BPE @ SW_4KB_2D_4xAA + { 11, 4, 0, 0, } , // 2 BPE @ SW_4KB_2D_4xAA + { 12, 5, 0, 0, } , // 4 BPE @ SW_4KB_2D_4xAA + { 13, 6, 0, 0, } , // 8 BPE @ SW_4KB_2D_4xAA + { 14, 7, 0, 0, } , // 16 BPE @ SW_4KB_2D_4xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_4KB_2D_8xAA_PATINFO[] = + { + { 15, 4, 0, 0, } , // 1 BPE @ SW_4KB_2D_8xAA + { 16, 5, 0, 0, } , // 2 BPE @ SW_4KB_2D_8xAA + { 17, 6, 0, 0, } , // 4 BPE @ SW_4KB_2D_8xAA + { 18, 7, 0, 0, } , // 8 BPE @ SW_4KB_2D_8xAA + { 19, 8, 0, 0, } , // 16 BPE @ SW_4KB_2D_8xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_64KB_2D_1xAA_PATINFO[] = + { + { 0, 1, 1, 0, } , // 1 BPE @ SW_64KB_2D_1xAA + { 1, 2, 2, 0, } , // 2 BPE @ SW_64KB_2D_1xAA + { 2, 3, 3, 0, } , // 4 BPE @ SW_64KB_2D_1xAA + { 3, 4, 4, 0, } , // 8 BPE @ SW_64KB_2D_1xAA + { 4, 5, 5, 0, } , // 16 BPE @ SW_64KB_2D_1xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_64KB_2D_2xAA_PATINFO[] = + { + { 5, 2, 2, 0, } , // 1 BPE @ SW_64KB_2D_2xAA + { 6, 3, 3, 0, } , // 2 BPE @ SW_64KB_2D_2xAA + { 7, 4, 4, 0, } , // 4 BPE @ SW_64KB_2D_2xAA + { 8, 5, 5, 0, } , // 8 BPE @ SW_64KB_2D_2xAA + { 9, 6, 6, 0, } , // 16 BPE @ SW_64KB_2D_2xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_64KB_2D_4xAA_PATINFO[] = + { + { 10, 3, 3, 0, } , // 1 BPE @ SW_64KB_2D_4xAA + { 11, 4, 4, 0, } , // 2 BPE @ SW_64KB_2D_4xAA + { 12, 5, 5, 0, } , // 4 BPE @ SW_64KB_2D_4xAA + { 13, 6, 6, 0, } , // 8 BPE @ SW_64KB_2D_4xAA + { 14, 7, 7, 0, } , // 16 BPE @ SW_64KB_2D_4xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_64KB_2D_8xAA_PATINFO[] = + { + { 15, 4, 4, 0, } , // 1 BPE @ SW_64KB_2D_8xAA + { 16, 5, 5, 0, } , // 2 BPE @ SW_64KB_2D_8xAA + { 17, 6, 6, 0, } , // 4 BPE @ SW_64KB_2D_8xAA + { 18, 7, 7, 0, } , // 8 BPE @ SW_64KB_2D_8xAA + { 19, 8, 8, 0, } , // 16 BPE @ SW_64KB_2D_8xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256KB_2D_1xAA_PATINFO[] = + { + { 0, 1, 1, 1, } , // 1 BPE @ SW_256KB_2D_1xAA + { 1, 2, 2, 2, } , // 2 BPE @ SW_256KB_2D_1xAA + { 2, 3, 3, 3, } , // 4 BPE @ SW_256KB_2D_1xAA + { 3, 4, 4, 4, } , // 8 BPE @ SW_256KB_2D_1xAA + { 4, 5, 5, 5, } , // 16 BPE @ SW_256KB_2D_1xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256KB_2D_2xAA_PATINFO[] = + { + { 5, 2, 2, 2, } , // 1 BPE @ SW_256KB_2D_2xAA + { 6, 3, 3, 3, } , // 2 BPE @ SW_256KB_2D_2xAA + { 7, 4, 4, 4, } , // 4 BPE @ SW_256KB_2D_2xAA + { 8, 5, 5, 5, } , // 8 BPE @ SW_256KB_2D_2xAA + { 9, 6, 6, 6, } , // 16 BPE @ SW_256KB_2D_2xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256KB_2D_4xAA_PATINFO[] = + { + { 10, 3, 3, 3, } , // 1 BPE @ SW_256KB_2D_4xAA + { 11, 4, 4, 4, } , // 2 BPE @ SW_256KB_2D_4xAA + { 12, 5, 5, 5, } , // 4 BPE @ SW_256KB_2D_4xAA + { 13, 6, 6, 6, } , // 8 BPE @ SW_256KB_2D_4xAA + { 14, 7, 7, 7, } , // 16 BPE @ SW_256KB_2D_4xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_256KB_2D_8xAA_PATINFO[] = + { + { 15, 4, 4, 4, } , // 1 BPE @ SW_256KB_2D_8xAA + { 16, 5, 5, 5, } , // 2 BPE @ SW_256KB_2D_8xAA + { 17, 6, 6, 6, } , // 4 BPE @ SW_256KB_2D_8xAA + { 18, 7, 7, 7, } , // 8 BPE @ SW_256KB_2D_8xAA + { 19, 8, 8, 8, } , // 16 BPE @ SW_256KB_2D_8xAA + }; + + const ADDR_SW_PATINFO GFX12_SW_4KB_3D_PATINFO[] = + { + { 20, 9, 0, 0, } , // 1 BPE @ SW_4KB_3D + { 21, 10, 0, 0, } , // 2 BPE @ SW_4KB_3D + { 22, 11, 0, 0, } , // 4 BPE @ SW_4KB_3D + { 23, 12, 0, 0, } , // 8 BPE @ SW_4KB_3D + { 24, 13, 0, 0, } , // 16 BPE @ SW_4KB_3D + }; + + const ADDR_SW_PATINFO GFX12_SW_64KB_3D_PATINFO[] = + { + { 20, 9, 9, 0, } , // 1 BPE @ SW_64KB_3D + { 21, 10, 10, 0, } , // 2 BPE @ SW_64KB_3D + { 22, 11, 11, 0, } , // 4 BPE @ SW_64KB_3D + { 23, 12, 12, 0, } , // 8 BPE @ SW_64KB_3D + { 24, 13, 13, 0, } , // 16 BPE @ SW_64KB_3D + }; + + const ADDR_SW_PATINFO GFX12_SW_256KB_3D_PATINFO[] = + { + { 20, 9, 9, 9, } , // 1 BPE @ SW_256KB_3D + { 21, 10, 10, 9, } , // 2 BPE @ SW_256KB_3D + { 22, 11, 11, 10, } , // 4 BPE @ SW_256KB_3D + { 23, 12, 12, 11, } , // 8 BPE @ SW_256KB_3D + { 24, 13, 13, 11, } , // 16 BPE @ SW_256KB_3D + }; + + + const UINT_64 GFX12_SW_PATTERN_NIBBLE1[][8] = + { + {X0, X1, Y0, X2, Y1, Y2, X3, Y3, }, // 0 + {0, X0, Y0, X1, Y1, X2, Y2, X3, }, // 1 + {0, 0, X0, Y0, X1, Y1, X2, Y2, }, // 2 + {0, 0, 0, X0, Y0, X1, X2, Y1, }, // 3 + {0, 0, 0, 0, X0, Y0, X1, Y1, }, // 4 + {S0, X0, Y0, X1, Y1, X2, Y2, X3, }, // 5 + {0, S0, X0, Y0, X1, Y1, X2, Y2, }, // 6 + {0, 0, S0, X0, Y0, X1, Y1, X2, }, // 7 + {0, 0, 0, S0, X0, Y0, X1, Y1, }, // 8 + {0, 0, 0, 0, S0, X0, Y0, X1, }, // 9 + {S0, S1, X0, Y0, X1, Y1, X2, Y2, }, // 10 + {0, S0, S1, X0, Y0, X1, Y1, X2, }, // 11 + {0, 0, S0, S1, X0, Y0, X1, Y1, }, // 12 + {0, 0, 0, S0, S1, X0, Y0, X1, }, // 13 + {0, 0, 0, 0, S0, S1, X0, Y0, }, // 14 + {S0, S1, S2, X0, Y0, X1, Y1, X2, }, // 15 + {0, S0, S1, S2, X0, Y0, X1, Y1, }, // 16 + {0, 0, S0, S1, S2, X0, Y0, X1, }, // 17 + {0, 0, 0, S0, S1, S2, X0, Y0, }, // 18 + {0, 0, 0, 0, S0, S1, S2, X0, }, // 19 + {X0, X1, Z0, Y0, Y1, Z1, X2, Z2, }, // 20 + {0, X0, Z0, Y0, X1, Z1, Y1, Z2, }, // 21 + {0, 0, X0, Y0, X1, Z0, Y1, Z1, }, // 22 + {0, 0, 0, X0, Y0, Z0, X1, Z1, }, // 23 + {0, 0, 0, 0, X0, Z0, Y0, Z1, }, // 24 + }; + + const UINT_64 GFX12_SW_PATTERN_NIBBLE2[][4] = + { + {0, 0, 0, 0, }, // 0 + {Y4, X4, Y5, X5, }, // 1 + {Y3, X4, Y4, X5, }, // 2 + {Y3, X3, Y4, X4, }, // 3 + {Y2, X3, Y3, X4, }, // 4 + {Y2, X2, Y3, X3, }, // 5 + {Y1, X2, Y2, X3, }, // 6 + {Y1, X1, Y2, X2, }, // 7 + {Y0, X1, Y1, X2, }, // 8 + {Y2, X3, Z3, Y3, }, // 9 + {Y2, X2, Z3, Y3, }, // 10 + {Y2, X2, Z2, Y3, }, // 11 + {Y1, X2, Z2, Y2, }, // 12 + {Y1, X1, Z2, Y2, }, // 13 + }; + + const UINT_64 GFX12_SW_PATTERN_NIBBLE3[][4] = + { + {0, 0, 0, 0, }, // 0 + {Y6, X6, Y7, X7, }, // 1 + {Y5, X6, Y6, X7, }, // 2 + {Y5, X5, Y6, X6, }, // 3 + {Y4, X5, Y5, X6, }, // 4 + {Y4, X4, Y5, X5, }, // 5 + {Y3, X4, Y4, X5, }, // 6 + {Y3, X3, Y4, X4, }, // 7 + {Y2, X3, Y3, X4, }, // 8 + {X4, Z4, Y4, X5, }, // 9 + {X3, Z4, Y4, X4, }, // 10 + {X3, Z3, Y4, X4, }, // 11 + {X3, Z3, Y3, X4, }, // 12 + {X2, Z3, Y3, X3, }, // 13 + }; + + const UINT_64 GFX12_SW_PATTERN_NIBBLE4[][2] = + { + {0, 0, }, // 0 + {Y8, X8, }, // 1 + {Y7, X8, }, // 2 + {Y7, X7, }, // 3 + {Y6, X7, }, // 4 + {Y6, X6, }, // 5 + {Y5, X6, }, // 6 + {Y5, X5, }, // 7 + {Y4, X5, }, // 8 + {Z5, Y5, }, // 9 + {Z4, Y5, }, // 10 + {Z4, Y4, }, // 11 + }; + +} // V3 +} // Addr + +#endif diff --git a/src/amd/addrlib/src/gfx12/gfx12addrlib.cpp b/src/amd/addrlib/src/gfx12/gfx12addrlib.cpp new file mode 100644 index 00000000000..e9a024cc847 --- /dev/null +++ b/src/amd/addrlib/src/gfx12/gfx12addrlib.cpp @@ -0,0 +1,1611 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + +/** +************************************************************************************************************************ +* @file gfx12addrlib.cpp +* @brief Contain the implementation for the Gfx12Lib class. +************************************************************************************************************************ +*/ + +#include "gfx12addrlib.h" +#include "gfx12_gb_reg.h" + +#include "amdgpu_asic_addr.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace Addr +{ +/** +************************************************************************************************************************ +* Gfx12HwlInit +* +* @brief +* Creates an Gfx12Lib object. +* +* @return +* Returns an Gfx12Lib object pointer. +************************************************************************************************************************ +*/ +Addr::Lib* Gfx12HwlInit( + const Client* pClient) +{ + return V3::Gfx12Lib::CreateObj(pClient); +} + +namespace V3 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Static Const Member +//////////////////////////////////////////////////////////////////////////////////////////////////// +const SwizzleModeFlags Gfx12Lib::SwizzleModeTable[ADDR3_MAX_TYPE] = +{//Linear 2d 3d 256B 4KB 64KB 256KB Reserved + {{1, 0, 0, 0, 0, 0, 0, 0}}, // ADDR3_LINEAR + {{0, 1, 0, 1, 0, 0, 0, 0}}, // ADDR3_256B_2D + {{0, 1, 0, 0, 1, 0, 0, 0}}, // ADDR3_4KB_2D + {{0, 1, 0, 0, 0, 1, 0, 0}}, // ADDR3_64KB_2D + {{0, 1, 0, 0, 0, 0, 1, 0}}, // ADDR3_256KB_2D + {{0, 0, 1, 0, 1, 0, 0, 0}}, // ADDR3_4KB_3D + {{0, 0, 1, 0, 0, 1, 0, 0}}, // ADDR3_64KB_3D + {{0, 0, 1, 0, 0, 0, 1, 0}}, // ADDR3_256KB_3D +}; + +/** +************************************************************************************************************************ +* Gfx12Lib::Gfx12Lib +* +* @brief +* Constructor +* +************************************************************************************************************************ +*/ +Gfx12Lib::Gfx12Lib( + const Client* pClient) + : + Lib(pClient), + m_numSwizzleBits(0) +{ + memcpy(m_swizzleModeTable, SwizzleModeTable, sizeof(SwizzleModeTable)); +} + +/** +************************************************************************************************************************ +* Gfx12Lib::~Gfx12Lib +* +* @brief +* Destructor +************************************************************************************************************************ +*/ +Gfx12Lib::~Gfx12Lib() +{ +} + +/** +************************************************************************************************************************ +* Gfx12Lib::ConvertSwizzlePatternToEquation +* +* @brief +* Convert swizzle pattern to equation. +* +* @return +* N/A +************************************************************************************************************************ +*/ +VOID Gfx12Lib::ConvertSwizzlePatternToEquation( + UINT_32 elemLog2, ///< [in] element bytes log2 + Addr3SwizzleMode swMode, ///< [in] swizzle mode + const ADDR_SW_PATINFO* pPatInfo, ///< [in] swizzle pattern info + ADDR_EQUATION* pEquation) ///< [out] equation converted from swizzle pattern + const +{ + ADDR_BIT_SETTING fullSwizzlePattern[Log2Size256K]; + GetSwizzlePatternFromPatternInfo(pPatInfo, fullSwizzlePattern); + + const ADDR_BIT_SETTING* pSwizzle = fullSwizzlePattern; + const UINT_32 blockSizeLog2 = GetBlockSizeLog2(swMode, TRUE); + + pEquation->numBits = blockSizeLog2; + pEquation->stackedDepthSlices = FALSE; + + for (UINT_32 i = 0; i < elemLog2; i++) + { + pEquation->addr[i].channel = 0; + pEquation->addr[i].valid = 1; + pEquation->addr[i].index = i; + } + + for (UINT_32 i = elemLog2; i < blockSizeLog2; i++) + { + ADDR_ASSERT(IsPow2(pSwizzle[i].value)); + + if (pSwizzle[i].x != 0) + { + ADDR_ASSERT(IsPow2(static_cast(pSwizzle[i].x))); + + pEquation->addr[i].channel = 0; + pEquation->addr[i].valid = 1; + pEquation->addr[i].index = Log2(pSwizzle[i].x) + elemLog2; + } + else if (pSwizzle[i].y != 0) + { + ADDR_ASSERT(IsPow2(static_cast(pSwizzle[i].y))); + + pEquation->addr[i].channel = 1; + pEquation->addr[i].valid = 1; + pEquation->addr[i].index = Log2(pSwizzle[i].y); + } + else if (pSwizzle[i].z != 0) + { + ADDR_ASSERT(IsPow2(static_cast(pSwizzle[i].z))); + + pEquation->addr[i].channel = 2; + pEquation->addr[i].valid = 1; + pEquation->addr[i].index = Log2(pSwizzle[i].z); + } + else if (pSwizzle[i].s != 0) + { + ADDR_ASSERT(IsPow2(static_cast(pSwizzle[i].s))); + + pEquation->addr[i].channel = 3; + pEquation->addr[i].valid = 1; + pEquation->addr[i].index = Log2(pSwizzle[i].s); + } + else + { + ADDR_ASSERT_ALWAYS(); + } + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::InitEquationTable +* +* @brief +* Initialize Equation table. +* +* @return +* N/A +************************************************************************************************************************ +*/ +VOID Gfx12Lib::InitEquationTable() +{ + memset(m_equationTable, 0, sizeof(m_equationTable)); + + for (UINT_32 swModeIdx = 0; swModeIdx < ADDR3_MAX_TYPE; swModeIdx++) + { + const Addr3SwizzleMode swMode = static_cast(swModeIdx); + + ADDR_ASSERT(IsValidSwMode(swMode)); + + if (IsLinear(swMode)) + { + // Skip linear equation (data table is not useful for 2D/3D images-- only contains x-coordinate bits) + continue; + } + + const UINT_32 maxMsaa = Is2dSwizzle(swMode) ? MaxMsaaRateLog2 : 1; + + for (UINT_32 msaaIdx = 0; msaaIdx < maxMsaa; msaaIdx++) + { + for (UINT_32 elemLog2 = 0; elemLog2 < MaxElementBytesLog2; elemLog2++) + { + UINT_32 equationIndex = ADDR_INVALID_EQUATION_INDEX; + const ADDR_SW_PATINFO* pPatInfo = GetSwizzlePatternInfo(swMode, elemLog2, 1 << msaaIdx); + + if (pPatInfo != NULL) + { + ADDR_EQUATION equation = {}; + + ConvertSwizzlePatternToEquation(elemLog2, swMode, pPatInfo, &equation); + + equationIndex = m_numEquations; + ADDR_ASSERT(equationIndex < NumSwizzlePatterns); + + m_equationTable[equationIndex] = equation; + m_numEquations++; + } + SetEquationTableEntry(swMode, msaaIdx, elemLog2, equationIndex); + } + } + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::InitBlockDimensionTable +* +* @brief +* Initialize block dimension table for all swizzle modes + msaa samples + bpp bundles. +* +* @return +* N/A +************************************************************************************************************************ +*/ +VOID Gfx12Lib::InitBlockDimensionTable() +{ + memset(m_blockDimensionTable, 0, sizeof(m_blockDimensionTable)); + + ADDR3_COMPUTE_SURFACE_INFO_INPUT surfaceInfo {}; + + + for (UINT_32 swModeIdx = 0; swModeIdx < ADDR3_MAX_TYPE; swModeIdx++) + { + const Addr3SwizzleMode swMode = static_cast(swModeIdx); + ADDR_ASSERT(IsValidSwMode(swMode)); + + surfaceInfo.swizzleMode = swMode; + const UINT_32 maxMsaa = Is2dSwizzle(swMode) ? MaxMsaaRateLog2 : 1; + + for (UINT_32 msaaIdx = 0; msaaIdx < maxMsaa; msaaIdx++) + { + surfaceInfo.numSamples = (1u << msaaIdx); + for (UINT_32 elementBytesLog2 = 0; elementBytesLog2 < MaxElementBytesLog2; elementBytesLog2++) + { + surfaceInfo.bpp = (1u << (elementBytesLog2 + 3)); + ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT input{ &surfaceInfo }; + ComputeBlockDimensionForSurf(&input, &m_blockDimensionTable[swModeIdx][msaaIdx][elementBytesLog2]); + } + } + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::GetMipOrigin +* +* @brief +* Internal function to calculate origins of the mip levels +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +VOID Gfx12Lib::GetMipOrigin( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, ///< [in] input structure + const ADDR_EXTENT3D& mipExtentFirstInTail, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + const BOOL_32 is3d = Is3dSwizzle(pSurfInfo->swizzleMode); + const UINT_32 bytesPerPixel = pSurfInfo->bpp >> 3; + const UINT_32 elementBytesLog2 = Log2(bytesPerPixel); + const UINT_32 samplesLog2 = Log2(pSurfInfo->numSamples); + + // Calculate the width/height/depth for ADDR3_4KB_3D swizzle mode. + // Note that only 2D swizzle mode supports MSAA, 1D and 3D all assume no MSAA, i.e., samplesLog2 == 0, so we must + // pass a 0 instead of samplesLog2 for the following ADDR3_4KB_3D. + // See implementation of Addrlib3::ComputeBlockDimensionForSurf(). + ADDR_EXTENT3D pixelDimOfAddr4kb3d = GetBlockDimensionTableEntry(ADDR3_4KB_3D, 0, elementBytesLog2); + const ADDR_EXTENT3D tailMaxDim = GetMipTailDim(pIn, pOut->blockExtent); + const UINT_32 blockSizeLog2 = GetBlockSizeLog2(pSurfInfo->swizzleMode); + + UINT_32 pitch = tailMaxDim.width; + UINT_32 height = tailMaxDim.height; + + UINT_32 depth = (is3d ? PowTwoAlign(mipExtentFirstInTail.depth, pixelDimOfAddr4kb3d.depth) : 1); + + const UINT_32 tailMaxDepth = (is3d ? (depth / pixelDimOfAddr4kb3d.depth) : 1); + + // Calculate the width/height/depth for ADDR3_256B_2D swizzle mode. + ADDR_EXTENT3D blockDimOfAddr256b2d = GetBlockDimensionTableEntry(ADDR3_256B_2D, samplesLog2, elementBytesLog2); + + for (UINT_32 i = pOut->firstMipIdInTail; i < pSurfInfo->numMipLevels; i++) + { + const INT_32 mipInTail = CalcMipInTail(pIn, pOut, i); + const UINT_32 mipOffset = CalcMipOffset(pIn, mipInTail); + + pOut->pMipInfo[i].offset = mipOffset * tailMaxDepth; + pOut->pMipInfo[i].mipTailOffset = mipOffset; + pOut->pMipInfo[i].macroBlockOffset = 0; + + pOut->pMipInfo[i].pitch = pitch; + pOut->pMipInfo[i].height = height; + pOut->pMipInfo[i].depth = depth; + if (IsLinear(pSurfInfo->swizzleMode)) + { + pOut->pMipInfo[i].mipTailCoordX = mipOffset >> 8; + pOut->pMipInfo[i].mipTailCoordY = 0; + pOut->pMipInfo[i].mipTailCoordZ = 0; + } + else + { + UINT_32 mipX = ((mipOffset >> 9) & 1) | + ((mipOffset >> 10) & 2) | + ((mipOffset >> 11) & 4) | + ((mipOffset >> 12) & 8) | + ((mipOffset >> 13) & 16) | + ((mipOffset >> 14) & 32); + UINT_32 mipY = ((mipOffset >> 8) & 1) | + ((mipOffset >> 9) & 2) | + ((mipOffset >> 10) & 4) | + ((mipOffset >> 11) & 8) | + ((mipOffset >> 12) & 16) | + ((mipOffset >> 13) & 32); + + if (is3d == FALSE) + { + pOut->pMipInfo[i].mipTailCoordX = mipX * blockDimOfAddr256b2d.width; + pOut->pMipInfo[i].mipTailCoordY = mipY * blockDimOfAddr256b2d.height; + pOut->pMipInfo[i].mipTailCoordZ = 0; + } + else + { + pOut->pMipInfo[i].mipTailCoordX = mipX * pixelDimOfAddr4kb3d.width; + pOut->pMipInfo[i].mipTailCoordY = mipY * pixelDimOfAddr4kb3d.height; + pOut->pMipInfo[i].mipTailCoordZ = 0; + } + } + if (IsLinear(pSurfInfo->swizzleMode)) + { + pitch = Max(pitch >> 1, 1u); + } + else if (is3d) + { + pitch = Max(pitch >> 1, blockDimOfAddr256b2d.width); + height = Max(height >> 1, blockDimOfAddr256b2d.height); + depth = 1; + } + else + { + pitch = Max(pitch >> 1, pixelDimOfAddr4kb3d.width); + height = Max(height >> 1, pixelDimOfAddr4kb3d.height); + depth = PowTwoAlign(Max(depth >> 1, 1u), pixelDimOfAddr4kb3d.depth); + } + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::GetMipOffset +* +* @brief +* Internal function to calculate alignment for a surface +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +VOID Gfx12Lib::GetMipOffset( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + const UINT_32 bytesPerPixel = pSurfInfo->bpp >> 3; + const UINT_32 elementBytesLog2 = Log2(bytesPerPixel); + const UINT_32 blockSizeLog2 = GetBlockSizeLog2(pSurfInfo->swizzleMode); + const UINT_32 blockSize = 1 << blockSizeLog2; + const ADDR_EXTENT3D tailMaxDim = GetMipTailDim(pIn, pOut->blockExtent);; + const ADDR_EXTENT3D mip0Dims = GetBaseMipExtents(pSurfInfo); + const UINT_32 maxMipsInTail = GetMaxNumMipsInTail(pIn); + + UINT_32 firstMipInTail = pSurfInfo->numMipLevels; + UINT_64 mipChainSliceSize = 0; + UINT_64 mipSize[MaxMipLevels]; + UINT_64 mipSliceSize[MaxMipLevels]; + + const BOOL_32 useCustomPitch = UseCustomPitch(pSurfInfo); + const BOOL_32 trimLinearPadding = CanTrimLinearPadding(pSurfInfo); + for (UINT_32 mipIdx = 0; mipIdx < pSurfInfo->numMipLevels; mipIdx++) + { + const ADDR_EXTENT3D mipExtents = GetMipExtent(mip0Dims, mipIdx); + + if (Lib::SupportsMipTail(pSurfInfo->swizzleMode) && + IsInMipTail(tailMaxDim, mipExtents, maxMipsInTail, pSurfInfo->numMipLevels - mipIdx)) + { + firstMipInTail = mipIdx; + mipChainSliceSize += blockSize / pOut->blockExtent.depth; + break; + } + else + { + const BOOL_32 trimLinearPaddingForMip0 = ((mipIdx == 0) && trimLinearPadding); + UINT_32 pitch = 0u; + if (useCustomPitch) + { + pitch = pOut->pitch; + } + // We may use 128B pitch alignment for linear addressing mip0 image under some restriction, which is + // followed by a post-processing to conform to base alignment requirement. + else if (trimLinearPaddingForMip0) + { + pitch = PowTwoAlign(mipExtents.width, 128u / bytesPerPixel); + } + else + { + pitch = PowTwoAlign(mipExtents.width, pOut->blockExtent.width); + } + + const UINT_32 height = UseCustomHeight(pSurfInfo) + ? pOut->height + : PowTwoAlign(mipExtents.height, pOut->blockExtent.height); + const UINT_32 depth = PowTwoAlign(mipExtents.depth, pOut->blockExtent.depth); + + // The original "blockExtent" calculation does subtraction of logs (i.e., division) to get the + // sizes. We aligned our pitch and height to those sizes, which means we need to multiply the various + // factors back together to get back to the slice size. + UINT_64 sliceSize = static_cast(pitch) * height * pSurfInfo->numSamples * (pSurfInfo->bpp >> 3); + + // When using 128B for linear mip0, sometimes the calculated sliceSize above might be not 256B aligned, + // e.g., sliceSize is odd times of 128B, it might cause next plane to be base misaligned. + // We must check if sliceSize is 256B aligned, otherwise the pitch has to be adjusted to be 256B aligned + // instead of 128B. + if ((useCustomPitch == FALSE) && trimLinearPaddingForMip0 && (sliceSize % 256 != 0)) + { + pitch = PowTwoAlign(mipExtents.width, pOut->blockExtent.width); + sliceSize = PowTwoAlign(sliceSize, 256ul); + } + + mipSize[mipIdx] = sliceSize * depth; + mipSliceSize[mipIdx] = sliceSize * pOut->blockExtent.depth; + mipChainSliceSize += sliceSize; + + if (pOut->pMipInfo != NULL) + { + pOut->pMipInfo[mipIdx].pitch = pitch; + pOut->pMipInfo[mipIdx].height = height; + pOut->pMipInfo[mipIdx].depth = depth; + + // The slice size of a linear image was calculated above as if the "pitch" is 256 byte aligned. + // However, the rendering pitch is aligned to 128 bytes, and that is what needs to be reported + // to our clients. + if (IsLinear(pSurfInfo->swizzleMode) && + // If UseCustomPitch is true, the pitch should be from pOut->pitch instead of 128B + (useCustomPitch == FALSE)) + { + pOut->pMipInfo[mipIdx].pitch = PowTwoAlign(mipExtents.width, 128u / bytesPerPixel); + } + } + } + } + + pOut->sliceSize = mipChainSliceSize; + pOut->surfSize = mipChainSliceSize * pOut->numSlices; + pOut->mipChainInTail = (firstMipInTail == 0) ? TRUE : FALSE; + pOut->firstMipIdInTail = firstMipInTail; + + if (pOut->pMipInfo != NULL) + { + if (IsLinear(pSurfInfo->swizzleMode)) + { + // 1. Linear swizzle mode doesn't have miptails. + // 2. The organization of linear 3D mipmap resource is same as GFX11, we should use mip slice size to + // caculate mip offset. + ADDR_ASSERT(firstMipInTail == pSurfInfo->numMipLevels); + + UINT_64 sliceSize = 0; + + for (INT_32 i = static_cast(pSurfInfo->numMipLevels) - 1; i >= 0; i--) + { + pOut->pMipInfo[i].offset = sliceSize; + pOut->pMipInfo[i].macroBlockOffset = sliceSize; + pOut->pMipInfo[i].mipTailOffset = 0; + + sliceSize += mipSliceSize[i]; + } + } + else + { + UINT_64 offset = 0; + UINT_64 macroBlkOffset = 0; + + // Even though "firstMipInTail" is zero-based while "numMipLevels" is one-based, from definition of + // _ADDR3_COMPUTE_SURFACE_INFO_OUTPUT struct, + // UINT_32 firstMipIdInTail; ///< The id of first mip in tail, if there is no mip + // /// in tail, it will be set to number of mip levels + // See initialization: + // UINT_32 firstMipInTail = pIn->numMipLevels + // It is possible that they are equal if + // 1. a single mip level image that's larger than the largest mip that would fit in the mip tail if + // the mip tail existed + // 2. 256B_2D and linear images which don't have miptails from HWAL functionality + // + // We can use firstMipInTail != pIn->numMipLevels to check it has mip in tails and do mipInfo assignment. + if (firstMipInTail != pSurfInfo->numMipLevels) + { + // Determine the application dimensions of the first mip level that resides in the tail. + // This is distinct from "tailMaxDim" which is the maximum size of a mip level that will fit in the + // tail. + ADDR_EXTENT3D mipExtentFirstInTail = GetMipExtent(mip0Dims, firstMipInTail); + + // For a 2D image, "alignedDepth" is always "1". + // For a 3D image, this is effectively the number of application slices associated with the first mip + // in the tail (up-aligned to HW requirements). + const UINT_32 alignedDepth = PowTwoAlign(mipExtentFirstInTail.depth, pOut->blockExtent.depth); + + // "hwSlices" is the number of HW blocks required to represent the first mip level in the tail. + const UINT_32 hwSlices = alignedDepth / pOut->blockExtent.depth; + + // Note that for 3D images that utilize a 2D swizzle mode, there really can be multiple + // HW slices that encompass the mip tail; i.e., hwSlices is not necessarily one. + // For example, you could have a single mip level 8x8x32 image with a 4KB_2D swizzle mode + // The 8x8 region fits into a 4KB block (so it's "in the tail"), but because we have a 2D + // swizzle mode (where each slice is its own block, so blockExtent.depth == 1), hwSlices + // will now be equivalent to the number of application slices, or 32. + + // Mip tails are stored in "reverse" order -- i.e., the mip-tail itself is stored first, so the + // first mip level outside the tail has an offset that's the dimension of the tail itself, or one + // swizzle block in size. + offset = blockSize * hwSlices; + macroBlkOffset = blockSize; + + // And determine the per-mip information for everything inside the mip tail. + GetMipOrigin(pIn, mipExtentFirstInTail, pOut); + } + + // Again, because mip-levels are stored backwards (smallest first), we start determining mip-level + // offsets from the smallest to the largest. + // Note that firstMipInTail == 0 immediately terminates the loop, so there is no need to check for this + // case. + for (INT_32 i = firstMipInTail - 1; i >= 0; i--) + { + pOut->pMipInfo[i].offset = offset; + pOut->pMipInfo[i].macroBlockOffset = macroBlkOffset; + pOut->pMipInfo[i].mipTailOffset = 0; + + offset += mipSize[i]; + macroBlkOffset += mipSliceSize[i]; + } + } + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputeSurfaceInfo +* +* @brief +* Internal function to calculate alignment for a surface +* +* @return +* VOID +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Gfx12Lib::HwlComputeSurfaceInfo( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT input{ pSurfInfo }; + + // Check that only 2D swizzle mode supports MSAA + const UINT_32 samplesLog2 = Is2dSwizzle(pSurfInfo->swizzleMode) ? Log2(pSurfInfo->numSamples) : 0; + + // The block dimension width/height/depth is determined only by swizzle mode, MSAA samples and bpp + pOut->blockExtent = GetBlockDimensionTableEntry(pSurfInfo->swizzleMode, samplesLog2, Log2(pSurfInfo->bpp >> 3)); + + ADDR_E_RETURNCODE returnCode = ApplyCustomizedPitchHeight(pSurfInfo, pOut); + + if (returnCode == ADDR_OK) + { + pOut->numSlices = PowTwoAlign(pSurfInfo->numSlices, pOut->blockExtent.depth); + pOut->baseAlign = 1 << GetBlockSizeLog2(pSurfInfo->swizzleMode); + + GetMipOffset(&input, pOut); + + SanityCheckSurfSize(&input, pOut); + + // Slices must be exact multiples of the block sizes. However: + // - with 3D images, one block will contain multiple slices, so that needs to be taken into account. + // + // Note that with linear images that have only one slice, we can always guarantee pOut->sliceSize is 256B + // alignment so there is no need to worry about it. + ADDR_ASSERT(((pOut->sliceSize * pOut->blockExtent.depth) % GetBlockSize(pSurfInfo->swizzleMode)) == 0); + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::GetBaseMipExtents +* +* @brief +* Return the size of the base mip level in a nice cozy little structure. +* +************************************************************************************************************************ +*/ +ADDR_EXTENT3D Gfx12Lib::GetBaseMipExtents( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn + ) const +{ + return { pIn->width, + pIn->height, + (IsTex3d(pIn->resourceType) ? pIn->numSlices : 1) }; // slices is depth for 3d +} + +/** +************************************************************************************************************************ +* Gfx12Lib::GetMaxNumMipsInTail +* +* @brief +* Return max number of mips in tails +* +* @return +* Max number of mips in tails +************************************************************************************************************************ +*/ +UINT_32 Gfx12Lib::GetMaxNumMipsInTail( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn + ) const +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + const UINT_32 blockSizeLog2 = GetBlockSizeLog2(pSurfInfo->swizzleMode); + + UINT_32 effectiveLog2 = blockSizeLog2; + UINT_32 mipsInTail = 1; + + if (Is3dSwizzle(pSurfInfo->swizzleMode)) + { + effectiveLog2 -= (blockSizeLog2 - 8) / 3; + } + + if (effectiveLog2 > 8) + { + mipsInTail = (effectiveLog2 <= 11) ? (1 + (1 << (effectiveLog2 - 9))) : (effectiveLog2 - 4); + } + + return mipsInTail; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlCalcMipInTail +* +* @brief +* Internal function to calculate the "mipInTail" parameter. +* +* @return +* The magic "mipInTail" parameter. +************************************************************************************************************************ +*/ +INT_32 Gfx12Lib::CalcMipInTail( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut, + UINT_32 mipLevel + ) const +{ + const INT_32 firstMipIdInTail = static_cast(pOut->firstMipIdInTail); + + INT_32 mipInTail = 0; + + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + mipInTail = static_cast(mipLevel) - firstMipIdInTail; + if ((mipInTail < 0) || (pSurfInfo->numMipLevels == 1) || (GetBlockSize(pSurfInfo->swizzleMode) <= 256)) + { + mipInTail = MaxMipLevels; + } + + return mipInTail; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::CalcMipOffset +* +* @brief +* +* @return +* The magic "mipInTail" parameter. +************************************************************************************************************************ +*/ +UINT_32 Gfx12Lib::CalcMipOffset( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + UINT_32 mipInTail + ) const +{ + const UINT_32 maxMipsInTail = GetMaxNumMipsInTail(pIn); + + const INT_32 signedM = static_cast(maxMipsInTail) - static_cast(1) - mipInTail; + const UINT_32 m = Max(0, signedM); + const UINT_32 mipOffset = (m > 6) ? (16 << m) : (m << 8); + + return mipOffset; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputeSurfaceAddrFromCoordTiled +* +* @brief +* Internal function to calculate address from coord for tiled swizzle surface +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Gfx12Lib::HwlComputeSurfaceAddrFromCoordTiled( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + // 256B block cannot support 3D image. + ADDR_ASSERT((IsTex3d(pIn->resourceType) && IsBlock256b(pIn->swizzleMode)) == FALSE); + + ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = {}; + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT localOut = {}; + ADDR3_MIP_INFO mipInfo[MaxMipLevels] = {}; + + localIn.size = sizeof(localIn); + localIn.flags = pIn->flags; + localIn.swizzleMode = pIn->swizzleMode; + localIn.resourceType = pIn->resourceType; + localIn.format = ADDR_FMT_INVALID; + localIn.bpp = pIn->bpp; + localIn.width = Max(pIn->unAlignedDims.width, 1u); + localIn.height = Max(pIn->unAlignedDims.height, 1u); + localIn.numSlices = Max(pIn->unAlignedDims.depth, 1u); + localIn.numMipLevels = Max(pIn->numMipLevels, 1u); + localIn.numSamples = Max(pIn->numSamples, 1u); + + localOut.size = sizeof(localOut); + localOut.pMipInfo = mipInfo; + ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT input{ &localIn }; + + ADDR_E_RETURNCODE ret = ComputeSurfaceInfo(&localIn, &localOut); + + if (ret == ADDR_OK) + { + const UINT_32 elemLog2 = Log2(pIn->bpp >> 3); + const UINT_32 blkSizeLog2 = GetBlockSizeLog2(pIn->swizzleMode); + const UINT_32 eqIndex = GetEquationTableEntry(pIn->swizzleMode, Log2(localIn.numSamples), elemLog2); + + if (eqIndex != ADDR_INVALID_EQUATION_INDEX) + { + ADDR3_COORD coords = {}; + + // For a 3D image, one swizzle block contains multiple application slices. + // For any given image, each HW slice is addressed identically to any other HW slice. + // hwSliceSizeBytes is the size of one HW slice; i.e., the number of bytes for the pattern to repeat. + // hwSliceId is the index (0, 1, 2...) of the HW slice that an application slice resides in. + const UINT_64 hwSliceSizeBytes = localOut.sliceSize * localOut.blockExtent.depth; + const UINT_32 hwSliceId = pIn->slice / localOut.blockExtent.depth; + + const UINT_32 pb = mipInfo[pIn->mipId].pitch / localOut.blockExtent.width; + const UINT_32 yb = pIn->y / localOut.blockExtent.height; + const UINT_32 xb = pIn->x / localOut.blockExtent.width; + const UINT_64 blkIdx = yb * pb + xb; + + // Technically, the addition of "mipTailCoordX" is only necessary if we're in the mip-tail. + // The "mipTailCoordXYZ" values should be zero if we're not in the mip-tail. + const BOOL_32 inTail = ((mipInfo[pIn->mipId].mipTailOffset != 0) && (blkSizeLog2 != Log2Size256)); + + ADDR_ASSERT((inTail == TRUE) || + // If we're not in the tail, then all of these must be zero. + ((mipInfo[pIn->mipId].mipTailCoordX == 0) && + (mipInfo[pIn->mipId].mipTailCoordY == 0) && + (mipInfo[pIn->mipId].mipTailCoordZ == 0))); + + coords.x = pIn->x + mipInfo[pIn->mipId].mipTailCoordX; + coords.y = pIn->y + mipInfo[pIn->mipId].mipTailCoordY; + coords.z = pIn->slice + mipInfo[pIn->mipId].mipTailCoordZ; + + // Note that in this path, blkIdx does not account for the HW slice ID, so we need to + // add it in here. + pOut->addr = hwSliceSizeBytes * hwSliceId; + + const UINT_32 blkOffset = ComputeOffsetFromEquation(&m_equationTable[eqIndex], + coords.x << elemLog2, + coords.y, + coords.z, + pIn->sample); + + pOut->addr += mipInfo[pIn->mipId].macroBlockOffset + + (blkIdx << blkSizeLog2) + + blkOffset; + + ADDR_ASSERT(pOut->addr < localOut.surfSize); + } + else + { + ret = ADDR_INVALIDPARAMS; + } + } + + return ret; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputePipeBankXor +* +* @brief +* Generate a PipeBankXor value to be ORed into bits above numSwizzleBits of address +* +* @return +* PipeBankXor value +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Gfx12Lib::HwlComputePipeBankXor( + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut ///< [out] output structure + ) const +{ + if ((m_numSwizzleBits != 0) && // does this configuration support swizzling + // base address XOR in GFX12 will be applied to all blk_size = 4KB, 64KB, or 256KB swizzle modes, + // Note that Linear and 256B are excluded. + (IsLinear(pIn->swizzleMode) == FALSE) && + (IsBlock256b(pIn->swizzleMode) == FALSE)) + { + pOut->pipeBankXor = pIn->surfIndex % (1 << m_numSwizzleBits); + } + else + { + pOut->pipeBankXor = 0; + } + + return ADDR_OK; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::ComputeOffsetFromEquation +* +* @brief +* Compute offset from equation +* +* @return +* Offset +************************************************************************************************************************ +*/ +UINT_32 Gfx12Lib::ComputeOffsetFromEquation( + const ADDR_EQUATION* pEq, ///< Equation + UINT_32 x, ///< x coord in bytes + UINT_32 y, ///< y coord in pixel + UINT_32 z, ///< z coord in slice + UINT_32 s ///< MSAA sample index + ) const +{ + UINT_32 offset = 0; + + for (UINT_32 i = 0; i < pEq->numBits; i++) + { + UINT_32 v = 0; + + if (pEq->addr[i].valid) + { + if (pEq->addr[i].channel == 0) + { + v ^= (x >> pEq->addr[i].index) & 1; + } + else if (pEq->addr[i].channel == 1) + { + v ^= (y >> pEq->addr[i].index) & 1; + } + else if (pEq->addr[i].channel == 2) + { + v ^= (z >> pEq->addr[i].index) & 1; + } + else if (pEq->addr[i].channel == 3) + { + v ^= (s >> pEq->addr[i].index) & 1; + } + else + { + ADDR_ASSERT_ALWAYS(); + } + } + + offset |= (v << i); + } + + return offset; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::GetSwizzlePatternInfo +* +* @brief +* Get swizzle pattern +* +* @return +* Swizzle pattern information +************************************************************************************************************************ +*/ +const ADDR_SW_PATINFO* Gfx12Lib::GetSwizzlePatternInfo( + Addr3SwizzleMode swizzleMode, ///< Swizzle mode + UINT_32 elemLog2, ///< Element size in bytes log2 + UINT_32 numFrag ///< Number of fragment + ) const +{ + const ADDR_SW_PATINFO* patInfo = NULL; + + if (Is2dSwizzle(swizzleMode) == FALSE) + { + ADDR_ASSERT(numFrag == 1); + } + + switch (swizzleMode) + { + case ADDR3_256KB_2D: + switch (numFrag) + { + case 1: + patInfo = GFX12_SW_256KB_2D_1xAA_PATINFO; + break; + case 2: + patInfo = GFX12_SW_256KB_2D_2xAA_PATINFO; + break; + case 4: + patInfo = GFX12_SW_256KB_2D_4xAA_PATINFO; + break; + case 8: + patInfo = GFX12_SW_256KB_2D_8xAA_PATINFO; + break; + default: + ADDR_ASSERT_ALWAYS(); + } + break; + case ADDR3_256KB_3D: + patInfo = GFX12_SW_256KB_3D_PATINFO; + break; + case ADDR3_64KB_2D: + switch (numFrag) + { + case 1: + patInfo = GFX12_SW_64KB_2D_1xAA_PATINFO; + break; + case 2: + patInfo = GFX12_SW_64KB_2D_2xAA_PATINFO; + break; + case 4: + patInfo = GFX12_SW_64KB_2D_4xAA_PATINFO; + break; + case 8: + patInfo = GFX12_SW_64KB_2D_8xAA_PATINFO; + break; + default: + ADDR_ASSERT_ALWAYS(); + } + break; + case ADDR3_64KB_3D: + patInfo = GFX12_SW_64KB_3D_PATINFO; + break; + case ADDR3_4KB_2D: + switch (numFrag) + { + case 1: + patInfo = GFX12_SW_4KB_2D_1xAA_PATINFO; + break; + case 2: + patInfo = GFX12_SW_4KB_2D_2xAA_PATINFO; + break; + case 4: + patInfo = GFX12_SW_4KB_2D_4xAA_PATINFO; + break; + case 8: + patInfo = GFX12_SW_4KB_2D_8xAA_PATINFO; + break; + default: + ADDR_ASSERT_ALWAYS(); + } + break; + case ADDR3_4KB_3D: + patInfo = GFX12_SW_4KB_3D_PATINFO; + break; + case ADDR3_256B_2D: + switch (numFrag) + { + case 1: + patInfo = GFX12_SW_256B_2D_1xAA_PATINFO; + break; + case 2: + patInfo = GFX12_SW_256B_2D_2xAA_PATINFO; + break; + case 4: + patInfo = GFX12_SW_256B_2D_4xAA_PATINFO; + break; + case 8: + patInfo = GFX12_SW_256B_2D_8xAA_PATINFO; + break; + default: + break; + } + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + + return (patInfo != NULL) ? &patInfo[elemLog2] : NULL; +} +/** +************************************************************************************************************************ +* Gfx12Lib::HwlInitGlobalParams +* +* @brief +* Initializes global parameters +* +* @return +* TRUE if all settings are valid +* +************************************************************************************************************************ +*/ +BOOL_32 Gfx12Lib::HwlInitGlobalParams( + const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input +{ + BOOL_32 valid = TRUE; + GB_ADDR_CONFIG_GFX12 gbAddrConfig; + + gbAddrConfig.u32All = pCreateIn->regValue.gbAddrConfig; + + switch (gbAddrConfig.bits.NUM_PIPES) + { + case ADDR_CONFIG_1_PIPE: + m_pipesLog2 = 0; + break; + case ADDR_CONFIG_2_PIPE: + m_pipesLog2 = 1; + break; + case ADDR_CONFIG_4_PIPE: + m_pipesLog2 = 2; + break; + case ADDR_CONFIG_8_PIPE: + m_pipesLog2 = 3; + break; + case ADDR_CONFIG_16_PIPE: + m_pipesLog2 = 4; + break; + case ADDR_CONFIG_32_PIPE: + m_pipesLog2 = 5; + break; + case ADDR_CONFIG_64_PIPE: + m_pipesLog2 = 6; + break; + default: + ADDR_ASSERT_ALWAYS(); + valid = FALSE; + break; + } + + switch (gbAddrConfig.bits.PIPE_INTERLEAVE_SIZE) + { + case ADDR_CONFIG_PIPE_INTERLEAVE_256B: + m_pipeInterleaveLog2 = 8; + break; + case ADDR_CONFIG_PIPE_INTERLEAVE_512B: + m_pipeInterleaveLog2 = 9; + break; + case ADDR_CONFIG_PIPE_INTERLEAVE_1KB: + m_pipeInterleaveLog2 = 10; + break; + case ADDR_CONFIG_PIPE_INTERLEAVE_2KB: + m_pipeInterleaveLog2 = 11; + break; + default: + ADDR_ASSERT_ALWAYS(); + valid = FALSE; + break; + } + + m_numSwizzleBits = ((m_pipesLog2 >= 3) ? m_pipesLog2 - 2 : 0); + + if (valid) + { + InitEquationTable(); + InitBlockDimensionTable(); + } + + return valid; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputeNonBlockCompressedView +* +* @brief +* Compute non-block-compressed view for a given mipmap level/slice. +* +* @return +* ADDR_E_RETURNCODE +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Gfx12Lib::HwlComputeNonBlockCompressedView( + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (((pIn->format < ADDR_FMT_ASTC_4x4) || (pIn->format > ADDR_FMT_ETC2_128BPP)) && + ((pIn->format < ADDR_FMT_BC1) || (pIn->format > ADDR_FMT_BC7))) + { + // Only support BC1~BC7, ASTC, or ETC2 for now... + returnCode = ADDR_NOTSUPPORTED; + } + else + { + UINT_32 bcWidth, bcHeight; + const UINT_32 bpp = GetElemLib()->GetBitsPerPixel(pIn->format, NULL, &bcWidth, &bcHeight); + + ADDR3_COMPUTE_SURFACE_INFO_INPUT infoIn = {}; + infoIn.size = sizeof(infoIn); + infoIn.flags = pIn->flags; + infoIn.swizzleMode = pIn->swizzleMode; + infoIn.resourceType = pIn->resourceType; + infoIn.format = pIn->format; + infoIn.bpp = bpp; + infoIn.width = RoundUpQuotient(pIn->unAlignedDims.width, bcWidth); + infoIn.height = RoundUpQuotient(pIn->unAlignedDims.height, bcHeight); + infoIn.numSlices = pIn->unAlignedDims.depth; + infoIn.numMipLevels = pIn->numMipLevels; + infoIn.numSamples = 1; + + ADDR3_MIP_INFO mipInfo[MaxMipLevels] = {}; + + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT infoOut = {}; + infoOut.size = sizeof(infoOut); + infoOut.pMipInfo = mipInfo; + + returnCode = HwlComputeSurfaceInfo(&infoIn, &infoOut); + + if (returnCode == ADDR_OK) + { + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT subOffIn = {}; + subOffIn.size = sizeof(subOffIn); + subOffIn.swizzleMode = infoIn.swizzleMode; + subOffIn.resourceType = infoIn.resourceType; + subOffIn.pipeBankXor = pIn->pipeBankXor; + subOffIn.slice = pIn->slice; + subOffIn.sliceSize = infoOut.sliceSize; + subOffIn.macroBlockOffset = mipInfo[pIn->mipId].macroBlockOffset; + subOffIn.mipTailOffset = mipInfo[pIn->mipId].mipTailOffset; + + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT subOffOut = {}; + subOffOut.size = sizeof(subOffOut); + + // For any mipmap level, move nonBc view base address by offset + HwlComputeSubResourceOffsetForSwizzlePattern(&subOffIn, &subOffOut); + pOut->offset = subOffOut.offset; + + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT slicePbXorIn = {}; + slicePbXorIn.size = sizeof(slicePbXorIn); + slicePbXorIn.swizzleMode = infoIn.swizzleMode; + slicePbXorIn.resourceType = infoIn.resourceType; + slicePbXorIn.bpe = infoIn.bpp; + slicePbXorIn.basePipeBankXor = pIn->pipeBankXor; + slicePbXorIn.slice = pIn->slice; + slicePbXorIn.numSamples = 1; + + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT slicePbXorOut = {}; + slicePbXorOut.size = sizeof(slicePbXorOut); + + // For any mipmap level, nonBc view should use computed pbXor + HwlComputeSlicePipeBankXor(&slicePbXorIn, &slicePbXorOut); + pOut->pipeBankXor = slicePbXorOut.pipeBankXor; + + const BOOL_32 tiled = (pIn->swizzleMode != ADDR3_LINEAR); + const BOOL_32 inTail = tiled && (pIn->mipId >= infoOut.firstMipIdInTail); + const UINT_32 requestMipWidth = + RoundUpQuotient(Max(pIn->unAlignedDims.width >> pIn->mipId, 1u), bcWidth); + const UINT_32 requestMipHeight = + RoundUpQuotient(Max(pIn->unAlignedDims.height >> pIn->mipId, 1u), bcHeight); + + if (inTail) + { + // For mipmap level that is in mip tail block, hack a lot of things... + // Basically all mipmap levels in tail block will be viewed as a small mipmap chain that all levels + // are fit in tail block: + + // - mipId = relative mip id (which is counted from first mip ID in tail in original mip chain) + pOut->mipId = pIn->mipId - infoOut.firstMipIdInTail; + + // - at least 2 mipmap levels (since only 1 mipmap level will not be viewed as mipmap!) + pOut->numMipLevels = Max(infoIn.numMipLevels - infoOut.firstMipIdInTail, 2u); + + // - (mip0) width = requestMipWidth << mipId, the value can't exceed mip tail dimension threshold + pOut->unAlignedDims.width = Min(requestMipWidth << pOut->mipId, infoOut.blockExtent.width / 2); + + // - (mip0) height = requestMipHeight << mipId, the value can't exceed mip tail dimension threshold + pOut->unAlignedDims.height = Min(requestMipHeight << pOut->mipId, infoOut.blockExtent.height); + } + // This check should cover at least mipId == 0 + else if ((requestMipWidth << pIn->mipId) == infoIn.width) + { + // For mipmap level [N] that is not in mip tail block and downgraded without losing element: + // - only one mipmap level and mipId = 0 + pOut->mipId = 0; + pOut->numMipLevels = 1; + + // (mip0) width = requestMipWidth + pOut->unAlignedDims.width = requestMipWidth; + + // (mip0) height = requestMipHeight + pOut->unAlignedDims.height = requestMipHeight; + } + else + { + // For mipmap level [N] that is not in mip tail block and downgraded with element losing, + // We have to make it a multiple mipmap view (2 levels view here), add one extra element if needed, + // because single mip view may have different pitch value than original (multiple) mip view... + // A simple case would be: + // - 64KB block swizzle mode, 8 Bytes-Per-Element. Block dim = [0x80, 0x40] + // - 2 mipmap levels with API mip0 width = 0x401/mip1 width = 0x200 and non-BC view + // mip0 width = 0x101/mip1 width = 0x80 + // By multiple mip view, the pitch for mip level 1 would be 0x100 bytes, due to rounding up logic in + // GetMipSize(), and by single mip level view the pitch will only be 0x80 bytes. + + // - 2 levels and mipId = 1 + pOut->mipId = 1; + pOut->numMipLevels = 2; + + const UINT_32 upperMipWidth = + RoundUpQuotient(Max(pIn->unAlignedDims.width >> (pIn->mipId - 1), 1u), bcWidth); + const UINT_32 upperMipHeight = + RoundUpQuotient(Max(pIn->unAlignedDims.height >> (pIn->mipId - 1), 1u), bcHeight); + + const BOOL_32 needToAvoidInTail = tiled && + (requestMipWidth <= infoOut.blockExtent.width / 2) && + (requestMipHeight <= infoOut.blockExtent.height); + + const UINT_32 hwMipWidth = + PowTwoAlign(ShiftCeil(infoIn.width, pIn->mipId), infoOut.blockExtent.width); + const UINT_32 hwMipHeight = + PowTwoAlign(ShiftCeil(infoIn.height, pIn->mipId), infoOut.blockExtent.height); + + const BOOL_32 needExtraWidth = + ((upperMipWidth < requestMipWidth * 2) || + ((upperMipWidth == requestMipWidth * 2) && + ((needToAvoidInTail == TRUE) || + (hwMipWidth > PowTwoAlign(requestMipWidth, infoOut.blockExtent.width))))); + + const BOOL_32 needExtraHeight = + ((upperMipHeight < requestMipHeight * 2) || + ((upperMipHeight == requestMipHeight * 2) && + ((needToAvoidInTail == TRUE) || + (hwMipHeight > PowTwoAlign(requestMipHeight, infoOut.blockExtent.height))))); + + // (mip0) width = requestLastMipLevelWidth + pOut->unAlignedDims.width = upperMipWidth + (needExtraWidth ? 1: 0); + + // (mip0) height = requestLastMipLevelHeight + pOut->unAlignedDims.height = upperMipHeight + (needExtraHeight ? 1: 0); + } + + // Assert the downgrading from this mip[0] width would still generate correct mip[N] width + ADDR_ASSERT(ShiftRight(pOut->unAlignedDims.width, pOut->mipId) == requestMipWidth); + // Assert the downgrading from this mip[0] height would still generate correct mip[N] height + ADDR_ASSERT(ShiftRight(pOut->unAlignedDims.height, pOut->mipId) == requestMipHeight); + } + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputeSubResourceOffsetForSwizzlePattern +* +* @brief +* Compute sub resource offset to support swizzle pattern +* +* @return +* VOID +************************************************************************************************************************ +*/ +VOID Gfx12Lib::HwlComputeSubResourceOffsetForSwizzlePattern( + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut ///< [out] output structure + ) const +{ + pOut->offset = pIn->slice * pIn->sliceSize + pIn->macroBlockOffset; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlComputeSlicePipeBankXor +* +* @brief +* Generate slice PipeBankXor value based on base PipeBankXor value and slice id +* +* @return +* PipeBankXor value +************************************************************************************************************************ +*/ +ADDR_E_RETURNCODE Gfx12Lib::HwlComputeSlicePipeBankXor( + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, ///< [in] input structure + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + // PipeBankXor is only applied to 4KB, 64KB and 256KB on GFX12. + if ((IsLinear(pIn->swizzleMode) == FALSE) && (IsBlock256b(pIn->swizzleMode) == FALSE)) + { + if (pIn->bpe == 0) + { + // Require a valid bytes-per-element value passed from client... + returnCode = ADDR_INVALIDPARAMS; + } + else + { + const ADDR_SW_PATINFO* pPatInfo = GetSwizzlePatternInfo(pIn->swizzleMode, + Log2(pIn->bpe >> 3), + 1); + + if (pPatInfo != NULL) + { + const UINT_32 elemLog2 = Log2(pIn->bpe >> 3); + const UINT_32 eqIndex = GetEquationTableEntry(pIn->swizzleMode, Log2(pIn->numSamples), elemLog2); + + const UINT_32 pipeBankXorOffset = ComputeOffsetFromEquation(&m_equationTable[eqIndex], + 0, + 0, + pIn->slice, + 0); + + const UINT_32 pipeBankXor = pipeBankXorOffset >> m_pipeInterleaveLog2; + + // Should have no bit set under pipe interleave + ADDR_ASSERT((pipeBankXor << m_pipeInterleaveLog2) == pipeBankXorOffset); + + pOut->pipeBankXor = pIn->basePipeBankXor ^ pipeBankXor; + } + else + { + // Should never come here... + ADDR_NOT_IMPLEMENTED(); + + returnCode = ADDR_NOTSUPPORTED; + } + } + } + else + { + pOut->pipeBankXor = 0; + } + + return returnCode; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlConvertChipFamily +* +* @brief +* Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision +* @return +* ChipFamily +************************************************************************************************************************ +*/ +ChipFamily Gfx12Lib::HwlConvertChipFamily( + UINT_32 chipFamily, ///< [in] chip family defined in atiih.h + UINT_32 chipRevision) ///< [in] chip revision defined in "asic_family"_id.h +{ + return ADDR_CHIP_FAMILY_NAVI; +} + +/** +************************************************************************************************************************ +* Gfx12Lib::SanityCheckSurfSize +* +* @brief +* Calculate the surface size via the exact hardware algorithm to see if it matches. +* +* @return +************************************************************************************************************************ +*/ +void Gfx12Lib::SanityCheckSurfSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut + ) const +{ +#if DEBUG + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + // Verify that the requested image size is valid for the below algorithm. The below code includes + // implicit assumptions about the surface dimensions being less than "MaxImageDim"; otherwise, it can't + // calculate "firstMipInTail" accurately and the below assertion will trip incorrectly. + // + // Surfaces destined for use only on the SDMA engine can exceed the gfx-engine-imposed limitations of + // the "maximum" image dimensions. + if ((pSurfInfo->width <= MaxImageDim) && + (pSurfInfo->height <= MaxImageDim) && + (pSurfInfo->numMipLevels <= MaxMipLevels) && + (UseCustomPitch(pSurfInfo) == FALSE) && + (UseCustomHeight(pSurfInfo) == FALSE) && + // HiZS surfaces have a reduced image size (i.e,. each pixel represents an 8x8 region of the parent + // image, at least for single samples) but they still have the same number of mip levels as the + // parent image. This disconnect produces false assertions below as the image size doesn't apparently + // support the specified number of mip levels. + ((pSurfInfo->flags.hiZHiS == 0) || (pSurfInfo->numMipLevels == 1))) + { + UINT_32 lastMipSize = 1; + UINT_64 dataChainSize = 0; + + const ADDR_EXTENT3D mip0Dims = GetBaseMipExtents(pSurfInfo); + const UINT_32 blockSizeLog2 = GetBlockSizeLog2(pSurfInfo->swizzleMode); + const ADDR_EXTENT3D tailMaxDim = GetMipTailDim(pIn, pOut->blockExtent); + const UINT_32 maxMipsInTail = GetMaxNumMipsInTail(pIn); + + UINT_32 firstMipInTail = 0; + for (INT_32 mipIdx = MaxMipLevels - 1; mipIdx >= 0; mipIdx--) + { + const ADDR_EXTENT3D mipExtents = GetMipExtent(mip0Dims, mipIdx); + + if (IsInMipTail(tailMaxDim, mipExtents, maxMipsInTail, pSurfInfo->numMipLevels - mipIdx)) + { + firstMipInTail = mipIdx; + } + } + + for (INT_32 mipIdx = firstMipInTail - 1; mipIdx >= -1; mipIdx--) + { + if (mipIdx < (static_cast(pSurfInfo->numMipLevels) - 1)) + { + dataChainSize += lastMipSize; + } + + if (mipIdx >= 0) + { + const ADDR_EXTENT3D mipExtents = GetMipExtent(mip0Dims, mipIdx); + const UINT_32 mipBlockWidth = ShiftCeil(mipExtents.width, Log2(pOut->blockExtent.width)); + const UINT_32 mipBlockHeight = ShiftCeil(mipExtents.height, Log2(pOut->blockExtent.height)); + + lastMipSize = 4 * lastMipSize + - ((mipBlockWidth & 1) ? mipBlockHeight : 0) + - ((mipBlockHeight & 1) ? mipBlockWidth : 0) + - ((mipBlockWidth & mipBlockHeight & 1) ? 1 : 0); + } + } + + if (CanTrimLinearPadding(pSurfInfo)) + { + ADDR_ASSERT((pOut->sliceSize * pOut->blockExtent.depth) <= (dataChainSize << blockSizeLog2)); + } + else + { + ADDR_ASSERT((pOut->sliceSize * pOut->blockExtent.depth) == (dataChainSize << blockSizeLog2)); + } + } +#endif +} + + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlCalcBlockSize +* +* @brief +* Determines the extent, in pixels of a swizzle block. +* +* @return +************************************************************************************************************************ +*/ +VOID Gfx12Lib::HwlCalcBlockSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR_EXTENT3D* pExtent + ) const +{ + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo; + const UINT_32 log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode); + const UINT_32 eleBytes = pSurfInfo->bpp >> 3; + const UINT_32 log2EleBytes = Log2(eleBytes); + + if (IsLinear(pSurfInfo->swizzleMode)) + { + // 1D swizzle mode doesn't support MSAA, so there is no need to consider log2(samples) + pExtent->width = 1 << (log2BlkSize - log2EleBytes); + pExtent->height = 1; + pExtent->depth = 1; + } + else if (Is3dSwizzle(pSurfInfo->swizzleMode)) + { + // 3D swizlze mode doesn't support MSAA, so there is no need to consider log2(samples) + const UINT_32 base = (log2BlkSize / 3) - (log2EleBytes / 3); + const UINT_32 log2BlkSizeMod3 = log2BlkSize % 3; + const UINT_32 log2EleBytesMod3 = log2EleBytes % 3; + + UINT_32 x = base; + UINT_32 y = base; + UINT_32 z = base; + + if (log2BlkSizeMod3 > 0) + { + x++; + } + + if (log2BlkSizeMod3 > 1) + { + z++; + } + + if (log2EleBytesMod3 > 0) + { + x--; + } + + if (log2EleBytesMod3 > 1) + { + z--; + } + + pExtent->width = 1u << x; + pExtent->height = 1u << y; + pExtent->depth = 1u << z; + } + else + { + // Only 2D swizzle mode supports MSAA... + // Since for gfx12 MSAA is unconditionally supported by all 2D swizzle modes, we don't need to restrict samples + // to be 1 for ADDR3_256B_2D and ADDR3_4KB_2D as gfx10/11 did. + const UINT_32 log2Samples = Log2(pSurfInfo->numSamples); + const UINT_32 log2Width = (log2BlkSize >> 1) - + (log2EleBytes >> 1) - + (log2Samples >> 1) - + (log2EleBytes & log2Samples & 1); + const UINT_32 log2Height = (log2BlkSize >> 1) - + (log2EleBytes >> 1) - + (log2Samples >> 1) - + ((log2EleBytes | log2Samples) & 1); + + // Return the extent in actual units, not log2 + pExtent->width = 1u << log2Width; + pExtent->height = 1u << log2Height; + pExtent->depth = 1; + } +} + +/** +************************************************************************************************************************ +* Gfx12Lib::HwlGetMipInTailMaxSize +* +* @brief +* Determines the max size of a mip level that fits in the mip-tail. +* +* @return +************************************************************************************************************************ +*/ +ADDR_EXTENT3D Gfx12Lib::HwlGetMipInTailMaxSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& blockDims) const +{ + ADDR_EXTENT3D mipTailDim = {}; + const Addr3SwizzleMode swizzleMode = pIn->pSurfInfo->swizzleMode; + const UINT_32 log2BlkSize = GetBlockSizeLog2(swizzleMode); + + mipTailDim = blockDims; + + if (Is3dSwizzle(swizzleMode)) + { + const UINT_32 dim = log2BlkSize % 3; + + if (dim == 0) + { + mipTailDim.height >>= 1; + } + else if (dim == 1) + { + mipTailDim.width >>= 1; + } + else + { + mipTailDim.depth >>= 1; + } + } + else + { + if ((log2BlkSize % 2) == 0) + { + mipTailDim.width >>= 1; + } + else + { + mipTailDim.height >>= 1; + } + } + return mipTailDim; +} + +} // V3 +} // Addr diff --git a/src/amd/addrlib/src/gfx12/gfx12addrlib.h b/src/amd/addrlib/src/gfx12/gfx12addrlib.h new file mode 100644 index 00000000000..259c3a77afd --- /dev/null +++ b/src/amd/addrlib/src/gfx12/gfx12addrlib.h @@ -0,0 +1,209 @@ +/* +************************************************************************************************************************ +* +* Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +* +***********************************************************************************************************************/ + +/** +************************************************************************************************************************ +* @file gfx12addrlib.h +* @brief Contains the Gfx12Lib class definition. +************************************************************************************************************************ +*/ + +#ifndef __GFX12_ADDR_LIB_H__ +#define __GFX12_ADDR_LIB_H__ + +#include "addrlib3.h" +#include "coord.h" +#include "gfx12SwizzlePattern.h" + + +namespace Addr +{ +namespace V3 +{ + +/** +************************************************************************************************************************ +* @brief This class is the GFX12 specific address library +* function set. +************************************************************************************************************************ +*/ +class Gfx12Lib : public Lib +{ +public: + /// Creates Gfx12Lib object + static Addr::Lib* CreateObj(const Client* pClient) + { + VOID* pMem = Object::ClientAlloc(sizeof(Gfx12Lib), pClient); + return (pMem != NULL) ? new (pMem) Gfx12Lib(pClient) : NULL; + } + +protected: + Gfx12Lib(const Client* pClient); + virtual ~Gfx12Lib(); + + // Meta surfaces such as Hi-S/Z are essentially images on GFX12, so just return the max + // image alignment. + virtual UINT_32 HwlComputeMaxMetaBaseAlignments() const override { return 256 * 1024; } + + UINT_32 GetMaxNumMipsInTail( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn) const; + + BOOL_32 IsInMipTail( + const ADDR_EXTENT3D& mipTailDim, ///< The output of GetMipTailDim() function which is dimensions of the + /// largest mip level in the tail (again, only 4kb/64kb/256kb block). + const ADDR_EXTENT3D& mipDims, ///< The dimensions of the mip level being queried now. + INT_32 maxNumMipsInTail, ///< The output of GetMaxNumMipsInTail() function which is the maximal + /// number of the mip levels that could fit in the tail of larger + /// block. + INT_32 numMipsToTheEnd ///< This is (numMipLevels - mipIdx) and it may be negative when called + /// in SanityCheckSurfSize() since mipIdx has to be in [0, 16]. + ) const + { + BOOL_32 inTail = ((mipDims.width <= mipTailDim.width) && + (mipDims.height <= mipTailDim.height) && + (numMipsToTheEnd <= maxNumMipsInTail)); + + return inTail; + } + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceAddrFromCoordTiled( + const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const override; + + virtual ADDR_E_RETURNCODE HwlComputeNonBlockCompressedView( + const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn, + ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut) const override; + + virtual VOID HwlComputeSubResourceOffsetForSwizzlePattern( + const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn, + ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut) const override; + + virtual ADDR_E_RETURNCODE HwlComputeSlicePipeBankXor( + const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut) const override; + + virtual UINT_32 HwlGetEquationTableInfo(const ADDR_EQUATION** ppEquationTable) const override + { + *ppEquationTable = m_equationTable; + + return m_numEquations; + } + + virtual ChipFamily HwlConvertChipFamily(UINT_32 uChipFamily, UINT_32 uChipRevision) override; + +protected: + virtual VOID HwlCalcBlockSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR_EXTENT3D* pExtent) const override final; + + virtual ADDR_EXTENT3D HwlGetMipInTailMaxSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& blockDims) const override final; + +private: + static const SwizzleModeFlags SwizzleModeTable[ADDR3_MAX_TYPE]; + + virtual ADDR_E_RETURNCODE HwlComputePipeBankXor( + const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn, + ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut) const override; + + virtual BOOL_32 HwlInitGlobalParams(const ADDR_CREATE_INPUT* pCreateIn) override; + + void SanityCheckSurfSize( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + UINT_32 m_numSwizzleBits; + + // Initialize equation table + VOID InitEquationTable(); + + // Initialize block dimension table + VOID InitBlockDimensionTable(); + + VOID GetSwizzlePatternFromPatternInfo( + const ADDR_SW_PATINFO* pPatInfo, + ADDR_BIT_SETTING (&pSwizzle)[Log2Size256K]) const + { + memcpy(pSwizzle, + GFX12_SW_PATTERN_NIBBLE1[pPatInfo->nibble1Idx], + sizeof(GFX12_SW_PATTERN_NIBBLE1[pPatInfo->nibble1Idx])); + + memcpy(&pSwizzle[8], + GFX12_SW_PATTERN_NIBBLE2[pPatInfo->nibble2Idx], + sizeof(GFX12_SW_PATTERN_NIBBLE2[pPatInfo->nibble2Idx])); + + memcpy(&pSwizzle[12], + GFX12_SW_PATTERN_NIBBLE3[pPatInfo->nibble3Idx], + sizeof(GFX12_SW_PATTERN_NIBBLE3[pPatInfo->nibble3Idx])); + + memcpy(&pSwizzle[16], + GFX12_SW_PATTERN_NIBBLE4[pPatInfo->nibble4Idx], + sizeof(GFX12_SW_PATTERN_NIBBLE4[pPatInfo->nibble4Idx])); + } + + VOID ConvertSwizzlePatternToEquation( + UINT_32 elemLog2, + Addr3SwizzleMode swMode, + const ADDR_SW_PATINFO* pPatInfo, + ADDR_EQUATION* pEquation) const; + + ADDR_EXTENT3D GetBaseMipExtents( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + + INT_32 CalcMipInTail( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut, + UINT_32 mipLevel) const; + + UINT_32 CalcMipOffset( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + UINT_32 mipInTail) const; + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( + const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const override; + + static ADDR_EXTENT3D GetMipExtent( + const ADDR_EXTENT3D& mip0, + UINT_32 mipId) + { + return { + ShiftCeil(Max(mip0.width, 1u), mipId), + ShiftCeil(Max(mip0.height, 1u), mipId), + ShiftCeil(Max(mip0.depth, 1u), mipId) + }; + } + + UINT_32 ComputeOffsetFromEquation( + const ADDR_EQUATION* pEq, + UINT_32 x, + UINT_32 y, + UINT_32 z, + UINT_32 s) const; + + const ADDR_SW_PATINFO* GetSwizzlePatternInfo( + Addr3SwizzleMode swizzleMode, + UINT_32 log2Elem, + UINT_32 numFrag) const; + + VOID GetMipOffset( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + VOID GetMipOrigin( + const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn, + const ADDR_EXTENT3D& mipExtentFirstInTail, + ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + +}; + +} // V3 +} // Addr + +#endif