mirror of https://github.com/intel/gmmlib.git
1353 lines
53 KiB
C++
1353 lines
53 KiB
C++
/*==============================================================================
|
|
Copyright(c) 2019 Intel Corporation
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files(the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and / or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
============================================================================*/
|
|
|
|
|
|
#include "Internal/Common/GmmLibInc.h"
|
|
#include "Internal/Common/Texture/GmmGen10TextureCalc.h"
|
|
#include "Internal/Common/Texture/GmmGen11TextureCalc.h"
|
|
#include "Internal/Common/Texture/GmmGen12TextureCalc.h"
|
|
|
|
GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset1DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_1D_SURFACE;
|
|
GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset2DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_2D_SURFACE;
|
|
GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset3DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_3D_SURFACE;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Calculates height of the 2D mip layout on Gen9
|
|
///
|
|
/// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
|
|
///
|
|
/// @return height of 2D mip layout
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
uint32_t GmmLib::GmmGen12TextureCalc::Get2DMipMapHeight(GMM_TEXTURE_INFO *pTexInfo)
|
|
{
|
|
uint32_t BlockHeight, MipHeight;
|
|
uint32_t HeightLinesLevel0, HeightLinesLevel1, HeightLinesLevel2;
|
|
uint32_t i, MipLevel, VAlign, CompressHeight, CompressWidth, CompressDepth;
|
|
uint8_t Compressed;
|
|
GMM_DPF_ENTER;
|
|
|
|
const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
|
|
|
|
Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
|
|
MipHeight = pTexInfo->BaseHeight;
|
|
MipLevel = pTexInfo->MaxLod;
|
|
VAlign = pTexInfo->Alignment.VAlign;
|
|
GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
|
|
|
|
HeightLinesLevel0 = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
|
|
|
|
if(Compressed)
|
|
{
|
|
HeightLinesLevel0 /= CompressHeight;
|
|
}
|
|
|
|
// Mip0 height...
|
|
BlockHeight = HeightLinesLevel0;
|
|
|
|
if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
|
|
((pTexInfo->Alignment.MipTailStartLod == 0) || (pTexInfo->MaxLod == 0)))
|
|
{
|
|
// Do nothing. Height is already aligned.
|
|
}
|
|
else
|
|
{
|
|
// Height of Mip1 and Mip2..n needed later...
|
|
HeightLinesLevel1 = HeightLinesLevel2 = 0;
|
|
for(i = 1; i <= MipLevel; i++)
|
|
{
|
|
uint32_t AlignedHeightLines;
|
|
|
|
if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
|
|
(i == pTexInfo->Alignment.MipTailStartLod))
|
|
{
|
|
AlignedHeightLines = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
|
|
|
|
if(i == 1)
|
|
{
|
|
HeightLinesLevel1 = AlignedHeightLines;
|
|
}
|
|
else
|
|
{
|
|
HeightLinesLevel2 += AlignedHeightLines;
|
|
}
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
MipHeight = GmmTexGetMipHeight(pTexInfo, i);
|
|
|
|
AlignedHeightLines = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
|
|
|
|
if(Compressed)
|
|
{
|
|
AlignedHeightLines /= CompressHeight;
|
|
}
|
|
|
|
if(i == 1)
|
|
{
|
|
HeightLinesLevel1 = AlignedHeightLines;
|
|
}
|
|
else
|
|
{
|
|
HeightLinesLevel2 += AlignedHeightLines;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If Mip1 height covers all others, then that is all we need...
|
|
if(!(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)))
|
|
{
|
|
if(HeightLinesLevel1 >= HeightLinesLevel2)
|
|
{
|
|
BlockHeight += GFX_ALIGN(HeightLinesLevel1, VAlign);
|
|
}
|
|
else
|
|
{
|
|
BlockHeight += GFX_ALIGN(HeightLinesLevel2, VAlign);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//TR mode- requires TileMode height alignment
|
|
BlockHeight += (HeightLinesLevel1 >= HeightLinesLevel2) ? HeightLinesLevel1 : HeightLinesLevel2;
|
|
BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
|
|
}
|
|
}
|
|
|
|
GMM_DPF_EXIT;
|
|
|
|
return (BlockHeight);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Calculates Linear CCS size from main surface size
|
|
///
|
|
/// @param[in] pSurf: ptr to ::GMM_TEXTURE_INFO of main surface
|
|
/// @param[in] pAuxTexInfo: ptr to ::GMM_TEXTURE_INFO of Aux surface
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
GMM_STATUS GmmLib::GmmGen12TextureCalc::FillTexCCS(GMM_TEXTURE_INFO *pSurf,
|
|
GMM_TEXTURE_INFO *pAuxTexInfo)
|
|
{
|
|
if(pGmmLibContext->GetSkuTable().FtrFlatPhysCCS && !pSurf->Flags.Gpu.ProceduralTexture)
|
|
{
|
|
//No CCS allocation for lossless compression (exclude AMFS CCS).
|
|
return GMM_SUCCESS;
|
|
}
|
|
else if(pAuxTexInfo->Flags.Gpu.__NonMsaaLinearCCS)
|
|
{
|
|
GMM_TEXTURE_INFO Surf = *pSurf;
|
|
uint32_t Depth;
|
|
const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pSurf, pGmmLibContext);
|
|
pAuxTexInfo->Flags.Info.TiledW = 0;
|
|
pAuxTexInfo->Flags.Info.TiledYf = 0;
|
|
pAuxTexInfo->Flags.Info.TiledX = 0;
|
|
pAuxTexInfo->Flags.Info.Linear = 1;
|
|
GMM_SET_64KB_TILE(pAuxTexInfo->Flags, 0, pGmmLibContext);
|
|
GMM_SET_4KB_TILE(pAuxTexInfo->Flags, 0, pGmmLibContext);
|
|
|
|
pAuxTexInfo->ArraySize = Surf.ArraySize;
|
|
pAuxTexInfo->Alignment = {0};
|
|
pAuxTexInfo->BitsPerPixel = 8;
|
|
Depth = (Surf.Depth > 0) ? Surf.Depth : 1; // Depth = 0 needs to be handled gracefully
|
|
uint32_t ExpandedArraySize =
|
|
GFX_MAX(Surf.ArraySize, 1) *
|
|
((Surf.Type == RESOURCE_CUBE) ? 6 : 1) * // Cubemaps simply 6-element, 2D arrays.
|
|
((Surf.Type == RESOURCE_3D) ? Depth : 1) * // 3D's simply 2D arrays for sizing.
|
|
((Surf.Flags.Gpu.Depth || Surf.Flags.Gpu.SeparateStencil ||
|
|
GMM_IS_64KB_TILE(Surf.Flags) || Surf.Flags.Info.TiledYf) ?
|
|
1 :
|
|
Surf.MSAA.NumSamples) * // MSAA (non-Depth/Stencil) RT samples stored as array planes.
|
|
((GMM_IS_64KB_TILE(Surf.Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && (Surf.MSAA.NumSamples == 16)) ? 4 : // MSAA x8/x16 stored as pseudo array planes each with 4x samples
|
|
(GMM_IS_64KB_TILE(Surf.Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && (Surf.MSAA.NumSamples == 8)) ? 2 : 1);
|
|
|
|
if(GMM_IS_64KB_TILE(Surf.Flags) || Surf.Flags.Info.TiledYf)
|
|
{
|
|
ExpandedArraySize = GFX_ALIGN(ExpandedArraySize, pPlatform->TileInfo[Surf.TileMode].LogicalTileDepth);
|
|
}
|
|
|
|
if(GmmIsUVPacked(Surf.Format))
|
|
{
|
|
uint64_t YCcsSize = GFX_ALIGN((Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch), GMM_KBYTE(16)) >> 8;
|
|
YCcsSize = GFX_ALIGN(YCcsSize, PAGE_SIZE);
|
|
|
|
uint64_t PlanarSize = (Surf.ArraySize > 1) ? (Surf.OffsetInfo.Plane.ArrayQPitch) : Surf.Size;
|
|
|
|
uint64_t UVCcsSize = GFX_ALIGN(PlanarSize - (Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch), GMM_KBYTE(16)) >> 8;
|
|
if(UVCcsSize == 0)
|
|
{
|
|
//GMM_ASSERTDPF(UVCcsSize != 0, "Incorrect Planar Surface Size"); //Redescription of Yf/Ys planar surface P010 hits it (debug required?)
|
|
UVCcsSize = 1;
|
|
}
|
|
UVCcsSize = GFX_ALIGN_NP2(UVCcsSize, PAGE_SIZE);
|
|
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U] = YCcsSize; //Being Linear CCS, fill X-offset - Test GetAuxOffset UV_CCS is proper
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V] = YCcsSize; //Being Linear CCS, fill X-offset
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] = 0;
|
|
|
|
pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch = YCcsSize + UVCcsSize;
|
|
pAuxTexInfo->Size = pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch * ((Surf.ArraySize > 1) ? (Surf.ArraySize) : 1);
|
|
pAuxTexInfo->Alignment.QPitch = GFX_ULONG_CAST(pAuxTexInfo->Size) / ExpandedArraySize;
|
|
}
|
|
else if(GmmIsPlanar(Surf.Format))
|
|
{
|
|
//Doesn't require separate Aux surfaces since not displayable. Page-alignment ensures
|
|
//each hybrid plane is 4k-aligned, hence gets unique AuxT.L1e
|
|
uint64_t PlanarSize = (Surf.ArraySize > 1) ? (Surf.OffsetInfo.Plane.ArrayQPitch) : Surf.Size;
|
|
uint64_t CcsSize = GFX_ALIGN(PlanarSize, GMM_KBYTE(16)) >> 8;
|
|
CcsSize = GFX_ALIGN(CcsSize, PAGE_SIZE);
|
|
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U] = GFX_ALIGN(Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch, GMM_KBYTE(16)) >> 8; //Being Linear CCS, fill X-offset - Test GetAuxOffset UV_CCS is proper
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] = 0;
|
|
pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V] = GFX_ALIGN(Surf.OffsetInfo.Plane.Y[GMM_PLANE_V] * Surf.Pitch, GMM_KBYTE(16)) >> 8; //Being Linear CCS, fill X-offset
|
|
pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] = 0;
|
|
|
|
pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch = CcsSize;
|
|
pAuxTexInfo->Size = pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch *
|
|
((Surf.ArraySize > 1) ? (Surf.ArraySize) : 1);
|
|
pAuxTexInfo->Alignment.QPitch = GFX_ULONG_CAST(pAuxTexInfo->Size) / ExpandedArraySize;
|
|
}
|
|
else
|
|
{
|
|
pAuxTexInfo->Size = (GFX_ALIGN(Surf.Size, GMM_KBYTE(16)) >> 8);
|
|
|
|
uint32_t qPitch;
|
|
if(ExpandedArraySize > 1)
|
|
{
|
|
uint64_t sliceSize = ((GFX_ALIGN(Surf.Pitch * Surf.Alignment.QPitch, GMM_KBYTE(16)) >> 8));
|
|
qPitch = GFX_ULONG_CAST(sliceSize); //HW doesn't use QPitch for Aux except MCS, how'd AMFS get sw-filled non-zero QPitch?
|
|
|
|
|
|
if(Surf.MSAA.NumSamples && !pGmmLibContext->GetSkuTable().FtrTileY)
|
|
{
|
|
//MSAA Qpitch is sample-distance, multiply NumSamples in a tile
|
|
qPitch *= GFX_MIN(Surf.MSAA.NumSamples, 4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qPitch = GFX_ULONG_CAST(pAuxTexInfo->Size);
|
|
}
|
|
|
|
pAuxTexInfo->Alignment.QPitch = qPitch;
|
|
}
|
|
__GMM_ASSERT(ExpandedArraySize || (pAuxTexInfo->Size == 0));
|
|
pAuxTexInfo->Pitch = 0;
|
|
pAuxTexInfo->Type = RESOURCE_BUFFER;
|
|
pAuxTexInfo->Alignment.BaseAlignment = GMM_KBYTE(4); //TODO: TiledResource?
|
|
pAuxTexInfo->Size = GFX_ALIGN(pAuxTexInfo->Size, PAGE_SIZE); //page-align final size
|
|
|
|
if(pAuxTexInfo->Flags.Gpu.TiledResource)
|
|
{
|
|
pAuxTexInfo->Alignment.BaseAlignment = GMM_KBYTE(64); //TODO: TiledResource?
|
|
pAuxTexInfo->Size = GFX_ALIGN(pAuxTexInfo->Size, GMM_KBYTE(64)); //page-align final size
|
|
}
|
|
|
|
//Clear compression request in CCS
|
|
pAuxTexInfo->Flags.Info.RenderCompressed = 0;
|
|
pAuxTexInfo->Flags.Info.MediaCompressed = 0;
|
|
pAuxTexInfo->Flags.Info.RedecribedPlanes = 0;
|
|
SetTileMode(pAuxTexInfo);
|
|
|
|
return GMM_SUCCESS;
|
|
}
|
|
return GMM_SUCCESS;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Allocates the 2D mip layout for surface state programming.
|
|
///
|
|
/// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
|
|
/// @param[in] pRestrictions: ptr to surface alignment and size restrictions
|
|
///
|
|
/// @return ::GMM_STATUS
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::FillTex2D(GMM_TEXTURE_INFO * pTexInfo,
|
|
__GMM_BUFFER_TYPE *pRestrictions)
|
|
{
|
|
uint32_t Width, Height, BitsPerPixel;
|
|
uint32_t HAlign, VAlign, DAlign, CompressHeight, CompressWidth, CompressDepth;
|
|
uint32_t AlignedWidth, BlockHeight, ExpandedArraySize, Pitch;
|
|
uint8_t Compress = 0;
|
|
GMM_STATUS Status;
|
|
|
|
GMM_DPF_ENTER;
|
|
|
|
__GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
|
|
__GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
|
|
|
|
const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
|
|
|
|
BitsPerPixel = pTexInfo->BitsPerPixel;
|
|
//TODO: Deprecate TileY usage
|
|
if((pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs))
|
|
{
|
|
// Aux Surfaces are 8bpp.
|
|
BitsPerPixel = 8;
|
|
}
|
|
|
|
Height = pTexInfo->BaseHeight;
|
|
Width = GFX_ULONG_CAST(pTexInfo->BaseWidth);
|
|
|
|
pTexInfo->MSAA.NumSamples = GFX_MAX(pTexInfo->MSAA.NumSamples, 1);
|
|
|
|
if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags))
|
|
{
|
|
FindMipTailStartLod(pTexInfo);
|
|
}
|
|
|
|
ExpandedArraySize =
|
|
GFX_MAX(pTexInfo->ArraySize, 1) *
|
|
((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1) * // Cubemaps simply 6-element, 2D arrays.
|
|
((pTexInfo->Type == RESOURCE_3D) ? pTexInfo->Depth : 1) * // 3D's simply 2D arrays for sizing.
|
|
((pTexInfo->Flags.Gpu.Depth || pTexInfo->Flags.Gpu.SeparateStencil ||
|
|
(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)) ? // MSAA Ys/Yf samples are ALSO stored as array planes, calculate size for single sample and expand it later.
|
|
1 :
|
|
pTexInfo->MSAA.NumSamples) * // MSAA (non-Depth/Stencil) RT samples stored as array planes.
|
|
((GMM_IS_64KB_TILE(pTexInfo->Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && (pTexInfo->MSAA.NumSamples == 16)) ? 4 : // MSAA x8/x16 stored as pseudo array planes each with 4x samples
|
|
(GMM_IS_64KB_TILE(pTexInfo->Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && (pTexInfo->MSAA.NumSamples == 8)) ? 2 : 1);
|
|
|
|
if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)
|
|
{
|
|
ExpandedArraySize = GFX_CEIL_DIV(ExpandedArraySize, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth);
|
|
}
|
|
|
|
//
|
|
// Check for color separation
|
|
//
|
|
if(pTexInfo->Flags.Gpu.ColorSeparation || pTexInfo->Flags.Gpu.ColorSeparationRGBX)
|
|
{
|
|
bool csRestrictionsMet = (((ExpandedArraySize <= 2) &&
|
|
(ExpandedArraySize == pTexInfo->ArraySize) &&
|
|
((pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM) ||
|
|
(pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM_SRGB) ||
|
|
(pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM) ||
|
|
(pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM_SRGB) ||
|
|
(pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM) ||
|
|
(pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM_SRGB)) &&
|
|
((pTexInfo->Flags.Gpu.ColorSeparation && (Width % 16) == 0) ||
|
|
(pTexInfo->Flags.Gpu.ColorSeparationRGBX && (Width % 12) == 0))));
|
|
|
|
if(csRestrictionsMet)
|
|
{
|
|
ExpandedArraySize = GMM_COLOR_SEPARATION_ARRAY_SIZE;
|
|
}
|
|
else
|
|
{
|
|
pTexInfo->Flags.Gpu.ColorSeparation = 0;
|
|
pTexInfo->Flags.Gpu.ColorSeparationRGBX = 0;
|
|
}
|
|
}
|
|
|
|
HAlign = pTexInfo->Alignment.HAlign;
|
|
VAlign = pTexInfo->Alignment.VAlign;
|
|
DAlign = pTexInfo->Alignment.DAlign;
|
|
|
|
GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
|
|
|
|
Compress = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
|
|
|
|
/////////////////////////////////
|
|
// Calculate Block Surface Height
|
|
/////////////////////////////////
|
|
|
|
if(ExpandedArraySize > 1)
|
|
{
|
|
uint32_t Alignment = VAlign;
|
|
if((pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear) ||
|
|
(pTexInfo->Flags.Gpu.S3dDx && pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d) ||
|
|
(pTexInfo->Flags.Wa.MediaPipeUsage))
|
|
{
|
|
Alignment = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
|
|
}
|
|
|
|
// Calculate the overall Block height...Mip0Height + Max(Mip1Height, Sum of Mip2Height..MipnHeight)
|
|
BlockHeight = Get2DMipMapTotalHeight(pTexInfo);
|
|
BlockHeight = GFX_ALIGN_NP2(BlockHeight, Alignment);
|
|
|
|
// GMM internally uses QPitch as the logical distance between slices, but translates
|
|
// as appropriate to service client queries in GmmResGetQPitch.
|
|
pTexInfo->Alignment.QPitch = BlockHeight;
|
|
|
|
if(Compress)
|
|
{
|
|
BlockHeight = GFX_CEIL_DIV(BlockHeight, CompressHeight);
|
|
|
|
BlockHeight = GetAligned3DBlockHeight(pTexInfo, BlockHeight, ExpandedArraySize);
|
|
}
|
|
else
|
|
{
|
|
BlockHeight = ScaleTextureHeight(pTexInfo, BlockHeight);
|
|
}
|
|
|
|
BlockHeight *= ExpandedArraySize;
|
|
}
|
|
else
|
|
{
|
|
pTexInfo->Alignment.QPitch = 0;
|
|
|
|
BlockHeight = Get2DMipMapHeight(pTexInfo);
|
|
BlockHeight = ScaleTextureHeight(pTexInfo, BlockHeight);
|
|
}
|
|
|
|
///////////////////////////////////
|
|
// Calculate Pitch
|
|
///////////////////////////////////
|
|
|
|
AlignedWidth = __GMM_EXPAND_WIDTH(this, Width, HAlign, pTexInfo);
|
|
|
|
// Calculate special pitch case of small dimensions where LOD1 + LOD2 widths
|
|
// are greater than LOD0. e.g. dimensions 4x4 and MinPitch == 1
|
|
if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
|
|
(pTexInfo->Alignment.MipTailStartLod < 2))
|
|
{
|
|
// Do nothing -- all mips are in LOD0/LOD1, which is already width aligned.
|
|
}
|
|
else if(pTexInfo->MaxLod >= 2)
|
|
{
|
|
uint32_t AlignedWidthLod1, AlignedWidthLod2;
|
|
|
|
AlignedWidthLod1 = __GMM_EXPAND_WIDTH(this, Width >> 1, HAlign, pTexInfo);
|
|
AlignedWidthLod2 = __GMM_EXPAND_WIDTH(this, Width >> 2, HAlign, pTexInfo);
|
|
|
|
AlignedWidth = GFX_MAX(AlignedWidth, AlignedWidthLod1 + AlignedWidthLod2);
|
|
}
|
|
|
|
if(Compress)
|
|
{
|
|
AlignedWidth = GFX_CEIL_DIV(AlignedWidth, CompressWidth);
|
|
}
|
|
else
|
|
{
|
|
AlignedWidth = ScaleTextureWidth(pTexInfo, AlignedWidth);
|
|
}
|
|
|
|
// Default pitch
|
|
Pitch = AlignedWidth * BitsPerPixel >> 3;
|
|
|
|
// Make sure the pitch satisfy linear min pitch requirment
|
|
Pitch = GFX_MAX(Pitch, pRestrictions->MinPitch);
|
|
|
|
// Make sure pitch satisfy alignment restriction
|
|
Pitch = GFX_ALIGN(Pitch, pRestrictions->PitchAlignment);
|
|
|
|
////////////////////
|
|
// Adjust for Tiling
|
|
////////////////////
|
|
|
|
if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
|
|
{
|
|
Pitch = GFX_ALIGN(Pitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth);
|
|
BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
|
|
}
|
|
|
|
GMM_ASSERTDPF(pTexInfo->Flags.Info.LayoutBelow || !pTexInfo->Flags.Info.LayoutRight, "MIPLAYOUT_RIGHT not supported after Gen6!");
|
|
pTexInfo->Flags.Info.LayoutBelow = 1;
|
|
pTexInfo->Flags.Info.LayoutRight = 0;
|
|
|
|
// If a texture is YUV packed, 96, or 48 bpp then one row plus 16 bytes of
|
|
// padding needs to be added. Since this will create a none pitch aligned
|
|
// surface the padding is aligned to the next row
|
|
if(GmmIsYUVPacked(pTexInfo->Format) ||
|
|
(pTexInfo->BitsPerPixel == GMM_BITS(96)) ||
|
|
(pTexInfo->BitsPerPixel == GMM_BITS(48)))
|
|
{
|
|
BlockHeight += GMM_SCANLINES(1) + GFX_CEIL_DIV(GMM_BYTES(16), Pitch);
|
|
}
|
|
|
|
// For Non-planar surfaces, the alignment is done on the entire height of the allocation
|
|
if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU &&
|
|
GmmIsYUVFormatLCUAligned(pTexInfo->Format) &&
|
|
!GmmIsPlanar(pTexInfo->Format))
|
|
{
|
|
BlockHeight = GFX_ALIGN(BlockHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
|
|
}
|
|
|
|
// Align height to even row to avoid hang if HW over-fetch
|
|
BlockHeight = GFX_ALIGN(BlockHeight, __GMM_EVEN_ROW);
|
|
|
|
if((Status = // <-- Note assignment.
|
|
FillTexPitchAndSize(
|
|
pTexInfo, Pitch, BlockHeight, pRestrictions)) == GMM_SUCCESS)
|
|
{
|
|
Fill2DTexOffsetAddress(pTexInfo);
|
|
}
|
|
|
|
GMM_DPF_EXIT;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// This function will Setup a planar surface allocation.
|
|
///
|
|
/// @param[in] pTexInfo: Reference to ::GMM_TEXTURE_INFO
|
|
/// @param[in] pRestrictions: Reference to surface alignment and size restrictions.
|
|
///
|
|
/// @return ::GMM_STATUS
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,
|
|
__GMM_BUFFER_TYPE *pRestrictions)
|
|
{
|
|
uint32_t WidthBytesPhysical, Height, YHeight, VHeight;
|
|
uint32_t AdjustedVHeight = 0;
|
|
GMM_STATUS Status;
|
|
bool UVPacked = false;
|
|
uint32_t BitsPerPixel, AlignedWidth;
|
|
|
|
GMM_DPF_ENTER;
|
|
|
|
__GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
|
|
__GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
|
|
__GMM_ASSERT(!pTexInfo->Flags.Info.TiledW);
|
|
const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
|
|
|
|
BitsPerPixel = pTexInfo->BitsPerPixel;
|
|
AlignedWidth = GFX_ULONG_CAST(pTexInfo->BaseWidth);
|
|
if(!pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
pTexInfo->TileMode = TILE_NONE;
|
|
}
|
|
else
|
|
{
|
|
pTexInfo->TileMode = LEGACY_TILE_Y;
|
|
}
|
|
|
|
WidthBytesPhysical = AlignedWidth * BitsPerPixel >> 3;
|
|
Height = VHeight = 0;
|
|
|
|
YHeight = pTexInfo->BaseHeight;
|
|
|
|
switch(pTexInfo->Format)
|
|
{
|
|
case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
|
|
case GMM_FORMAT_IMC3:
|
|
case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UUUU
|
|
// UUUU
|
|
// VVVV
|
|
// VVVV
|
|
case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UUUUUUUU
|
|
// UUUUUUUU
|
|
// VVVVVVVV
|
|
// VVVVVVVV
|
|
{
|
|
VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
|
|
YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
|
|
Height = YHeight + 2 * VHeight; // One VHeight for V and one for U.
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
|
|
break;
|
|
}
|
|
case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
|
|
//YYYYYYYY
|
|
//YYYYYYYY
|
|
//YYYYYYYY
|
|
//YYYYYYYY
|
|
//UUUUUUUU
|
|
//VVVVVVVV
|
|
{
|
|
VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
|
|
YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
|
|
Height = YHeight + 2 * VHeight;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
|
|
break;
|
|
}
|
|
case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UU
|
|
// UU
|
|
// UU
|
|
// UU
|
|
// VV
|
|
// VV
|
|
// VV
|
|
// VV
|
|
case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UUUU
|
|
// UUUU
|
|
// UUUU
|
|
// UUUU
|
|
// VVVV
|
|
// VVVV
|
|
// VVVV
|
|
// VVVV
|
|
case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
|
|
#if _WIN32
|
|
case GMM_FORMAT_WGBOX_YUV444:
|
|
case GMM_FORMAT_WGBOX_PLANAR_YUV444:
|
|
#endif
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UUUUUUUU
|
|
// UUUUUUUU
|
|
// UUUUUUUU
|
|
// UUUUUUUU
|
|
// VVVVVVVV
|
|
// VVVVVVVV
|
|
// VVVVVVVV
|
|
// VVVVVVVV
|
|
{
|
|
YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
VHeight = YHeight;
|
|
|
|
Height = YHeight + 2 * VHeight;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
|
|
break;
|
|
}
|
|
case GMM_FORMAT_BGRP:
|
|
case GMM_FORMAT_RGBP:
|
|
{
|
|
//For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
|
|
if(pTexInfo->Flags.Info.Linear)
|
|
{
|
|
VHeight = YHeight;
|
|
|
|
Height = YHeight + 2 * VHeight;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
|
|
}
|
|
else
|
|
{
|
|
YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
VHeight = YHeight;
|
|
|
|
Height = YHeight + 2 * VHeight;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
|
|
}
|
|
break;
|
|
}
|
|
case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
|
|
case GMM_FORMAT_IMC4:
|
|
{
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// UUUUVVVV
|
|
// UUUUVVVV
|
|
|
|
YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
|
|
VHeight = GFX_CEIL_DIV(YHeight, 2);
|
|
|
|
WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
|
|
|
|
Height = YHeight + VHeight;
|
|
|
|
// With SURFACE_STATE.XOffset support, the U-V interface has
|
|
// much lighter restrictions--which will be naturally met by
|
|
// surface pitch restrictions (i.e. dividing an IMC2/4 pitch
|
|
// by 2--to get the U/V interface--will always produce a safe
|
|
// XOffset value).
|
|
// Not technically UV packed but sizing works out the same
|
|
// if the resource is std swizzled
|
|
UVPacked = true;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
|
|
break;
|
|
}
|
|
case GMM_FORMAT_NV12:
|
|
case GMM_FORMAT_NV21:
|
|
case GMM_FORMAT_NV11:
|
|
case GMM_FORMAT_P010:
|
|
case GMM_FORMAT_P012:
|
|
case GMM_FORMAT_P016:
|
|
case GMM_FORMAT_P208:
|
|
case GMM_FORMAT_P216:
|
|
{
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// [UV-Packing]
|
|
|
|
if((pTexInfo->Format == GMM_FORMAT_NV12) ||
|
|
(pTexInfo->Format == GMM_FORMAT_NV21) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P010) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P012) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P016))
|
|
{
|
|
VHeight = GFX_CEIL_DIV(YHeight, 2); // U/V plane half of Y
|
|
Height = YHeight + VHeight;
|
|
}
|
|
else
|
|
{
|
|
VHeight = YHeight; // U/V plane is same as Y
|
|
Height = YHeight + VHeight;
|
|
}
|
|
|
|
if((pTexInfo->Format == GMM_FORMAT_NV12) ||
|
|
(pTexInfo->Format == GMM_FORMAT_NV21) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P010) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P012) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P016) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P208) ||
|
|
(pTexInfo->Format == GMM_FORMAT_P216))
|
|
{
|
|
WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
|
|
}
|
|
else //if(pTexInfo->Format == GMM_FORMAT_NV11)
|
|
{
|
|
// Tiling not supported, since YPitch != UVPitch...
|
|
pTexInfo->Flags.Info.TiledYf = 0;
|
|
pTexInfo->Flags.Info.TiledX = 0;
|
|
pTexInfo->Flags.Info.Linear = 1;
|
|
GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
|
|
GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
|
|
}
|
|
|
|
UVPacked = true;
|
|
break;
|
|
}
|
|
case GMM_FORMAT_I420: // IYUV & I420: are identical to YV12 except,
|
|
case GMM_FORMAT_IYUV: // U & V pl.s are reversed.
|
|
case GMM_FORMAT_YV12:
|
|
case GMM_FORMAT_YVU9:
|
|
{
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// YYYYYYYY
|
|
// VVVVVV.. <-- V and U planes follow the Y plane, as linear
|
|
// ..UUUUUU arrays--without respect to pitch.
|
|
|
|
uint32_t YSize, UVSize, YVSizeRShift;
|
|
uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
|
|
|
|
YSize = WidthBytesPhysical * YHeight;
|
|
|
|
// YVU9 has one U/V pixel for each 4x4 Y block.
|
|
// The others have one U/V pixel for each 2x2 Y block.
|
|
|
|
// YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
|
|
// The others have a ratio of 4 (2x2 --> 1).
|
|
YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
|
|
|
|
// If a Y plane isn't fully-aligned to its Y-->U/V block size, the
|
|
// extra/unaligned Y pixels still need corresponding U/V pixels--So
|
|
// for the purpose of computing the UVSize, we must consider a
|
|
// dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
|
|
// require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
|
|
YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
|
|
YSizeForUVPurposes =
|
|
GFX_ALIGN(WidthBytesPhysical, YSizeForUVPurposesDimensionalAlignment) *
|
|
GFX_ALIGN(YHeight, YSizeForUVPurposesDimensionalAlignment);
|
|
|
|
UVSize = 2 * // <-- U + V
|
|
(YSizeForUVPurposes >> YVSizeRShift);
|
|
|
|
Height = GFX_CEIL_DIV(YSize + UVSize, WidthBytesPhysical);
|
|
|
|
// Tiling not supported, since YPitch != UVPitch...
|
|
pTexInfo->Flags.Info.TiledYf = 0;
|
|
pTexInfo->Flags.Info.TiledX = 0;
|
|
pTexInfo->Flags.Info.Linear = 1;
|
|
pTexInfo->OffsetInfo.Plane.NoOfPlanes = 1;
|
|
GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
|
|
GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
GMM_ASSERTDPF(0, "Unexpected format");
|
|
return GMM_ERROR;
|
|
}
|
|
}
|
|
|
|
// Align Height to even row to avoid hang if HW over-fetch
|
|
Height = GFX_ALIGN(Height, __GMM_EVEN_ROW);
|
|
|
|
SetTileMode(pTexInfo);
|
|
|
|
// If the Surface has Odd height dimension, we will fall back to Linear Format.
|
|
// If MMC is enabled, disable MMC during such cases.
|
|
if(pTexInfo->Flags.Gpu.MMC)
|
|
{
|
|
if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)))
|
|
{
|
|
pTexInfo->Flags.Gpu.MMC = 0;
|
|
}
|
|
}
|
|
|
|
// If the Surface has Odd height dimension, we will fall back to Linear Format.
|
|
// If MMC is enabled, disable .CCS/UnifiedAuxSurface during such cases.
|
|
if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
|
|
!(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs && GMM_IS_4KB_TILE(pTexInfo->Flags)))
|
|
{
|
|
pTexInfo->Flags.Gpu.MMC = 0;
|
|
pTexInfo->Flags.Gpu.CCS = 0;
|
|
pTexInfo->Flags.Gpu.UnifiedAuxSurface = 0;
|
|
pTexInfo->Flags.Gpu.__NonMsaaTileYCcs = 0;
|
|
}
|
|
}
|
|
|
|
// Legacy Planar "Linear Video" Restrictions...
|
|
if(pTexInfo->Flags.Info.Linear && !pTexInfo->Flags.Wa.NoLegacyPlanarLinearVideoRestrictions)
|
|
{
|
|
pRestrictions->LockPitchAlignment = GFX_MAX(pRestrictions->LockPitchAlignment, GMM_BYTES(64));
|
|
pRestrictions->MinPitch = GFX_MAX(pRestrictions->MinPitch, GMM_BYTES(64));
|
|
pRestrictions->PitchAlignment = GFX_MAX(pRestrictions->PitchAlignment, GMM_BYTES(64));
|
|
pRestrictions->RenderPitchAlignment = GFX_MAX(pRestrictions->RenderPitchAlignment, GMM_BYTES(64));
|
|
}
|
|
|
|
// Multiply overall pitch alignment for surfaces whose U/V planes have a
|
|
// pitch down-scaled from that of Y--Since the U/V pitches must meet the
|
|
// original restriction, the Y pitch must meet a scaled-up multiple.
|
|
if((pTexInfo->Format == GMM_FORMAT_I420) ||
|
|
(pTexInfo->Format == GMM_FORMAT_IYUV) ||
|
|
(pTexInfo->Format == GMM_FORMAT_NV11) ||
|
|
(pTexInfo->Format == GMM_FORMAT_YV12) ||
|
|
(pTexInfo->Format == GMM_FORMAT_YVU9))
|
|
{
|
|
uint32_t LShift =
|
|
(pTexInfo->Format != GMM_FORMAT_YVU9) ?
|
|
1 : // UVPitch = 1/2 YPitch
|
|
2; // UVPitch = 1/4 YPitch
|
|
|
|
pRestrictions->LockPitchAlignment <<= LShift;
|
|
pRestrictions->MinPitch <<= LShift;
|
|
pRestrictions->PitchAlignment <<= LShift;
|
|
pRestrictions->RenderPitchAlignment <<= LShift;
|
|
}
|
|
|
|
AdjustedVHeight = VHeight;
|
|
|
|
FindMipTailStartLod(pTexInfo);
|
|
|
|
// In case of Planar surfaces, only the last Plane has to be aligned to 64 for LCU access
|
|
if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU && GmmIsYUVFormatLCUAligned(pTexInfo->Format) && VHeight > 0)
|
|
{
|
|
AdjustedVHeight = GFX_ALIGN(VHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
|
|
Height += AdjustedVHeight - VHeight;
|
|
}
|
|
|
|
// For std swizzled and UV packed tile Ys/Yf cases, the planes
|
|
// must be tile-boundary aligned. Actual alignment is handled
|
|
// in FillPlanarOffsetAddress, but height and width must
|
|
// be adjusted for correct size calculation
|
|
if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) &&
|
|
!pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
|
|
uint32_t TileWidth = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
|
|
|
|
pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
|
|
|
|
if(pTexInfo->Flags.Gpu.CCS && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS) // alignment adjustment needed only for aux tables
|
|
{
|
|
if(GMM_IS_64KB_TILE(pTexInfo->Flags))
|
|
{
|
|
TileHeight *= (!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext)) ? 16 : 1; // For 64Kb Tile mode: Multiply TileHeight by 16 for 1 MB alignment
|
|
}
|
|
else
|
|
{
|
|
TileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 64); // For 4k Tile: Multiply TileHeight by 4 and Pitch by 4 for 64kb alignment, multiply TileHeight by 64 and Pitch by 4 for 1 MB alignment
|
|
}
|
|
}
|
|
|
|
if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
|
|
pTexInfo->Format == GMM_FORMAT_IMC4)
|
|
{
|
|
// If the U & V planes are side-by-side then the surface pitch must be
|
|
// padded out so that U and V planes will being on a tile boundary.
|
|
// This means that an odd Y plane width must be padded out
|
|
// with an additional tile. Even widths do not need padding
|
|
uint32_t TileCols = GFX_CEIL_DIV(WidthBytesPhysical, TileWidth);
|
|
if(TileCols % 2)
|
|
{
|
|
WidthBytesPhysical = (TileCols + 1) * TileWidth;
|
|
}
|
|
}
|
|
|
|
Height = GFX_ALIGN(YHeight, TileHeight) + (UVPacked ? GFX_ALIGN(AdjustedVHeight, TileHeight) :
|
|
(GFX_ALIGN(VHeight, TileHeight) + GFX_ALIGN(AdjustedVHeight, TileHeight)));
|
|
|
|
if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)
|
|
{
|
|
pTexInfo->Flags.Info.RedecribedPlanes = true;
|
|
}
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
|
|
|
|
BitsPerPixel = 8;
|
|
|
|
if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
|
|
pTexInfo->Format == GMM_FORMAT_IMC4)
|
|
{
|
|
// If the U & V planes are side-by-side then the surface pitch must be
|
|
// padded out so that U and V planes will being on a tile boundary.
|
|
// This means that an odd Y plane width must be padded out
|
|
// with an additional tile. Even widths do not need padding
|
|
|
|
// CCS must use padded main surface width, so get main surface TileWidth
|
|
#define CCSMODE_TO_TILEMODE(y) ((y + TILE_YF_2D_8bpe) < TILE_YS_1D_8bpe) ? (y + TILE_YF_2D_8bpe) : \
|
|
((y + TILE_YF_2D_8bpe + 5) >= TILE_YS_1D_128bpe) ? (y + TILE_YF_2D_8bpe + 5) : TILE_NONE
|
|
|
|
uint32_t BaseTileWidth = pPlatform->TileInfo[CCSMODE_TO_TILEMODE(pTexInfo->CCSModeAlign)].LogicalTileWidth;
|
|
WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2 * BaseTileWidth);
|
|
}
|
|
|
|
AlignedWidth = GFX_ULONG_CAST(WidthBytesPhysical / (pTexInfo->BitsPerPixel >> 3));
|
|
|
|
WidthBytesPhysical = __GMM_EXPAND_WIDTH(this, AlignedWidth, pTexInfo->Alignment.HAlign, pTexInfo);
|
|
WidthBytesPhysical = ScaleTextureWidth(pTexInfo, WidthBytesPhysical); //Should both YAux and UVAux use same CCModeALign (ie using common bpe?)
|
|
//If different, then copy Aux info from per-plane Aux? HW has separate bpe or common?
|
|
YHeight = __GMM_EXPAND_HEIGHT(this, YHeight, pTexInfo->Alignment.VAlign, pTexInfo);
|
|
YHeight = ScaleTextureHeight(pTexInfo, YHeight);
|
|
YHeight = GFX_ALIGN(YHeight, TileHeight);
|
|
|
|
VHeight = __GMM_EXPAND_HEIGHT(this, VHeight, pTexInfo->Alignment.VAlign, pTexInfo);
|
|
VHeight = ScaleTextureHeight(pTexInfo, VHeight);
|
|
VHeight = GFX_ALIGN(VHeight, TileHeight);
|
|
|
|
Height = YHeight + VHeight;
|
|
}
|
|
|
|
if(pTexInfo->Flags.Info.RedecribedPlanes)
|
|
{
|
|
if(false == RedescribeTexturePlanes(pTexInfo, &WidthBytesPhysical))
|
|
{
|
|
__GMM_ASSERT(false);
|
|
}
|
|
}
|
|
|
|
if((Status = // <-- Note assignment.
|
|
FillTexPitchAndSize(
|
|
pTexInfo, WidthBytesPhysical, Height, pRestrictions)) == GMM_SUCCESS)
|
|
{
|
|
FillPlanarOffsetAddress(pTexInfo);
|
|
}
|
|
|
|
// Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
|
|
// is defined by SW requirements; Y plane must be 4KB aligned.
|
|
if(pTexInfo->ArraySize > 1)
|
|
{
|
|
GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
|
|
int64_t LargeSize;
|
|
|
|
// Size should always be page aligned.
|
|
__GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
|
|
|
|
if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
|
|
{
|
|
pTexInfo->OffsetInfo.Plane.ArrayQPitch = ElementSizeBytes;
|
|
pTexInfo->Size = LargeSize;
|
|
}
|
|
else
|
|
{
|
|
GMM_ASSERTDPF(0, "Surface too large!");
|
|
Status = GMM_ERROR;
|
|
}
|
|
}
|
|
|
|
GMM_DPF_EXIT;
|
|
return (Status);
|
|
} // FillTexPlanar
|
|
|
|
GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::GetCCSScaleFactor(GMM_TEXTURE_INFO *pTexInfo,
|
|
CCS_UNIT & ScaleFactor)
|
|
{
|
|
GMM_STATUS Status = GMM_SUCCESS;
|
|
GMM_TEXTURE_ALIGN_EX TexAlignEx = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetExTextureAlign();
|
|
uint32_t CCSModeIdx = 0;
|
|
|
|
if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) //pTexInfo is RT Surf
|
|
{
|
|
CCSModeIdx = CCS_MODE(pTexInfo->TileMode);
|
|
__GMM_ASSERT(pTexInfo->TileMode < GMM_TILE_MODES);
|
|
}
|
|
else //pTexInfo is CCS Surf
|
|
{
|
|
CCSModeIdx = pTexInfo->CCSModeAlign;
|
|
}
|
|
|
|
if(!(CCSModeIdx < CCS_MODES))
|
|
{
|
|
__GMM_ASSERT(0); //indicates something wrong w/ H/V/D Align Filling function or Wrong TileMode set
|
|
return GMM_ERROR;
|
|
}
|
|
|
|
ScaleFactor = TexAlignEx.CCSEx[CCSModeIdx];
|
|
|
|
return (Status);
|
|
}
|
|
|
|
GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::GetCCSExMode(GMM_TEXTURE_INFO *AuxSurf)
|
|
{
|
|
if(GMM_IS_4KB_TILE(AuxSurf->Flags) || GMM_IS_64KB_TILE(AuxSurf->Flags) || AuxSurf->Flags.Info.Linear)
|
|
{
|
|
if(pGmmLibContext->GetSkuTable().FtrLinearCCS)
|
|
{
|
|
AuxSurf->Flags.Gpu.__NonMsaaLinearCCS = 1;
|
|
}
|
|
else
|
|
{
|
|
AuxSurf->Flags.Gpu.__NonMsaaTileYCcs = 1;
|
|
//CCS is always 2D, even for 3D surface
|
|
if(AuxSurf->Type == RESOURCE_CUBE)
|
|
{
|
|
AuxSurf->ArraySize = 6;
|
|
}
|
|
AuxSurf->Type = RESOURCE_2D;
|
|
}
|
|
if(AuxSurf->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
AuxSurf->CCSModeAlign = 0;
|
|
SetTileMode(AuxSurf);
|
|
/*if (AuxSurf->Flags.Gpu.UnifiedAuxSurface)*/
|
|
{
|
|
AuxSurf->CCSModeAlign = CCS_MODE(AuxSurf->TileMode);
|
|
}
|
|
AuxSurf->TileMode = TILE_NONE;
|
|
|
|
__GMM_ASSERT(AuxSurf->CCSModeAlign < CCS_MODES);
|
|
return (AuxSurf->CCSModeAlign < CCS_MODES) ? GMM_SUCCESS : GMM_INVALIDPARAM;
|
|
}
|
|
}
|
|
return GMM_SUCCESS;
|
|
}
|
|
|
|
uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleTextureHeight(GMM_TEXTURE_INFO *pTexInfo, uint32_t Height)
|
|
{
|
|
uint32_t ScaledHeight = Height;
|
|
if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
CCS_UNIT ScaleFactor;
|
|
GetCCSScaleFactor(pTexInfo, ScaleFactor);
|
|
|
|
ScaledHeight /= ScaleFactor.Downscale.Height;
|
|
}
|
|
|
|
return ScaledHeight;
|
|
}
|
|
|
|
uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleTextureWidth(GMM_TEXTURE_INFO *pTexInfo, uint32_t Width)
|
|
{
|
|
uint32_t ScaledWidth = Width;
|
|
|
|
if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
CCS_UNIT ScaleFactor;
|
|
GetCCSScaleFactor(pTexInfo, ScaleFactor);
|
|
|
|
|
|
if(ScaleFactor.Downscale.Width < 0)
|
|
{
|
|
ScaledWidth *= ((-1) * ScaleFactor.Downscale.Width);
|
|
}
|
|
else
|
|
{
|
|
ScaledWidth /= ScaleFactor.Downscale.Width;
|
|
}
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.ColorSeparation)
|
|
{
|
|
ScaledWidth *= pTexInfo->ArraySize;
|
|
__GMM_ASSERT(0 == (ScaledWidth % GMM_COLOR_SEPARATION_WIDTH_DIVISION));
|
|
ScaledWidth /= GMM_COLOR_SEPARATION_WIDTH_DIVISION;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.ColorSeparationRGBX)
|
|
{
|
|
ScaledWidth *= pTexInfo->ArraySize;
|
|
__GMM_ASSERT(0 == (ScaledWidth % GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION));
|
|
ScaledWidth /= GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION;
|
|
}
|
|
|
|
return ScaledWidth;
|
|
}
|
|
|
|
uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleFCRectHeight(GMM_TEXTURE_INFO *pTexInfo, uint32_t Height)
|
|
{
|
|
uint32_t ScaledHeight = Height;
|
|
if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
|
|
uint8_t index = FCMaxModes;
|
|
if((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
|
|
{
|
|
ScaledHeight = GFX_ALIGN(ScaledHeight, FCRectAlign[index].Align.Height);
|
|
ScaledHeight /= FCRectAlign[index].Downscale.Height;
|
|
}
|
|
else
|
|
{
|
|
__GMM_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
return ScaledHeight;
|
|
}
|
|
|
|
uint64_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleFCRectWidth(GMM_TEXTURE_INFO *pTexInfo, uint64_t Width)
|
|
{
|
|
uint64_t ScaledWidth = Width;
|
|
if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
|
|
uint8_t index = FCMaxModes;
|
|
if((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
|
|
{
|
|
ScaledWidth = GFX_ALIGN(ScaledWidth, FCRectAlign[index].Align.Width);
|
|
ScaledWidth /= FCRectAlign[index].Downscale.Width;
|
|
}
|
|
else
|
|
{
|
|
//Unsupported tiling-type for FastClear
|
|
__GMM_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
return ScaledWidth;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// This function does any special-case conversion from client-provided pseudo creation
|
|
/// parameters to actual parameters for CCS.
|
|
///
|
|
/// @param[in] pTexInfo: Reference to ::GMM_TEXTURE_INFO
|
|
///
|
|
/// @return ::GMM_STATUS
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::MSAACCSUsage(GMM_TEXTURE_INFO *pTexInfo)
|
|
{
|
|
GMM_STATUS Status = GMM_SUCCESS;
|
|
|
|
if(pTexInfo->MSAA.NumSamples > 1 && (pTexInfo->Flags.Gpu.MCS)) // CCS for MSAA Compression
|
|
{
|
|
Status = MSAACompression(pTexInfo);
|
|
}
|
|
else // Non-MSAA CCS Use (i.e. Render Target Fast Clear)
|
|
{
|
|
if(!pTexInfo->Flags.Info.TiledW &&
|
|
(!pTexInfo->Flags.Info.TiledX) &&
|
|
((GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags) ||
|
|
(pTexInfo->Type == RESOURCE_BUFFER && pTexInfo->Flags.Info.Linear)))) //!Yf - deprecate Yf)
|
|
{
|
|
// For non-MSAA CCS usage, the Doc has four tables of
|
|
// requirements:
|
|
// (1) RT Alignment (GMM Don't Care: Occurs Naturally)
|
|
// (2) ClearRect Alignment
|
|
// (3) ClearRect Scaling (GMM Don't Care: GHAL3D Matter)
|
|
// (4) Non-MSAA CCS Sizing
|
|
|
|
// Gen8+:
|
|
// Since mip-mapped and arrayed surfaces are supported, we
|
|
// deal with alignment later at per mip level. Here, we set
|
|
// tiling type only. TileX is not supported on Gen9+.
|
|
// Pre-Gen8:
|
|
// (!) For all the above, the doc has separate entries for
|
|
// 32/64/128bpp--and then deals with PIXEL widths--Here,
|
|
// though, we will unify by considering 8bpp table entries
|
|
// (unlisted--i.e. do the math)--and deal with BYTE widths.
|
|
|
|
// (1) RT Alignment -- The surface width and height don't
|
|
// need to be padded to RT CL granularity. On HSW, all tiled
|
|
// RT's will have appropriate alignment (given 4KB surface
|
|
// base and no mip-map support) and appropriate padding
|
|
// (due to tile padding). On BDW+, GMM uses H/VALIGN that
|
|
// will guarantee the MCS RT alignment for all subresources.
|
|
|
|
// (2) ClearRect Alignment -- I.e. FastClears must be done
|
|
// with certain granularity:
|
|
// TileY: 512 Bytes x 128 Lines
|
|
// TileX: 1024 Bytes x 64 Lines
|
|
// So a CCS must be sized to match that granularity (though
|
|
// the RT itself need not be fully padded to that
|
|
// granularity to use FastClear).
|
|
|
|
// (4) Non-MSAA CCS Sizing -- CCS sizing is based on the
|
|
// size of the FastClear (with granularity padding) for the
|
|
// paired RT. CCS's (byte widths and heights) are scaled
|
|
// down from their RT's by:
|
|
// TileY: 32 x 32
|
|
// TileX: 64 x 16
|
|
|
|
// ### Example #############################################
|
|
// RT: 800x600, 32bpp, TileY
|
|
// 8bpp: 3200x600
|
|
// FastClear: 3584x640 (for TileY FastClear Granularity of 512x128)
|
|
// CCS: 112x20 (for TileY RT:CCS Sizing Downscale of 32x32)
|
|
|
|
GetCCSExMode(pTexInfo);
|
|
}
|
|
else
|
|
{
|
|
GMM_ASSERTDPF(0, "Illegal CCS creation parameters!");
|
|
Status = GMM_ERROR;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Returns the mip offset of given LOD in Mip Tail
|
|
///
|
|
/// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
|
|
/// MipLevel: mip-map level
|
|
///
|
|
/// @return offset value of LOD in bytes
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
uint32_t GmmLib::GmmGen12TextureCalc::GetMipTailByteOffset(GMM_TEXTURE_INFO *pTexInfo,
|
|
uint32_t MipLevel)
|
|
{
|
|
uint32_t ByteOffset = 0, Slot = 0xff;
|
|
|
|
GMM_DPF_ENTER;
|
|
|
|
if(pGmmLibContext->GetSkuTable().FtrTileY)
|
|
{
|
|
return GmmGen11TextureCalc::GetMipTailByteOffset(pTexInfo, MipLevel);
|
|
}
|
|
// 3D textures follow the Gen10 mip tail format
|
|
if(!pGmmLibContext->GetSkuTable().FtrStandardMipTailFormat)
|
|
{
|
|
return GmmGen9TextureCalc::GetMipTailByteOffset(pTexInfo, MipLevel);
|
|
}
|
|
|
|
// Til64 is the only format which supports MipTail on FtrTileY disabled platforms
|
|
__GMM_ASSERT(pTexInfo->Flags.Info.Tile64);
|
|
// Mipped MSAA is not supported for Tile64
|
|
__GMM_ASSERT(pTexInfo->MSAA.NumSamples <= 1);
|
|
|
|
if((pTexInfo->Type == RESOURCE_1D) || (pTexInfo->Type == RESOURCE_3D) || (pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE))
|
|
{
|
|
Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
|
|
}
|
|
|
|
// Miptail Slot layout in Tile64: as per specifications
|
|
// Byteoffset varies based on bpp for tile64 format, so any caller who needs to use byteoffset needs to call cpuswizzle with corresponding geomteric offsets
|
|
// Returning ByteOffset as 0 for Tile64 always
|
|
|
|
// GMM_DPF_CRITICAL("Miptail byte offset requested for Tile64 \r\n");
|
|
GMM_DPF_EXIT;
|
|
|
|
// return ByteOffset=0, i.e return start of miptail for any address within packed miptail
|
|
return (ByteOffset);
|
|
}
|
|
|
|
void GmmLib::GmmGen12TextureCalc::GetMipTailGeometryOffset(GMM_TEXTURE_INFO *pTexInfo,
|
|
uint32_t MipLevel,
|
|
uint32_t * OffsetX,
|
|
uint32_t * OffsetY,
|
|
uint32_t * OffsetZ)
|
|
{
|
|
uint32_t ArrayIndex = 0;
|
|
uint32_t Slot = 0;
|
|
|
|
GMM_DPF_ENTER;
|
|
|
|
if(pGmmLibContext->GetSkuTable().FtrTileY)
|
|
{
|
|
return GmmGen11TextureCalc::GetMipTailGeometryOffset(pTexInfo, MipLevel, OffsetX, OffsetY, OffsetZ);
|
|
}
|
|
|
|
// Til64 is the only format which supports MipTail on FtrTileY disabled platforms
|
|
__GMM_ASSERT(pTexInfo->Flags.Info.Tile64);
|
|
// Mipped MSAA is not supported for Tile64
|
|
__GMM_ASSERT(pTexInfo->MSAA.NumSamples <= 1);
|
|
|
|
switch(pTexInfo->BitsPerPixel)
|
|
{
|
|
case 128:
|
|
ArrayIndex = 0;
|
|
break;
|
|
case 64:
|
|
ArrayIndex = 1;
|
|
break;
|
|
case 32:
|
|
ArrayIndex = 2;
|
|
break;
|
|
case 16:
|
|
ArrayIndex = 3;
|
|
break;
|
|
case 8:
|
|
ArrayIndex = 4;
|
|
break;
|
|
default:
|
|
__GMM_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
|
|
// FtrTileY disabled platforms: platforms which support Tile4/Tile64 tiled formats
|
|
if(pTexInfo->Type == RESOURCE_1D)
|
|
{
|
|
Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
|
|
|
|
*OffsetX = MipTailSlotOffset1DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
|
|
*OffsetY = MipTailSlotOffset1DSurface[Slot][ArrayIndex].Y;
|
|
*OffsetZ = MipTailSlotOffset1DSurface[Slot][ArrayIndex].Z;
|
|
}
|
|
else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
|
|
{
|
|
// Mipped MSAA is not supported on Tile64, so need not account for MSAA here
|
|
Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
|
|
|
|
*OffsetX = MipTailSlotOffset2DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
|
|
*OffsetY = MipTailSlotOffset2DSurface[Slot][ArrayIndex].Y;
|
|
*OffsetZ = MipTailSlotOffset2DSurface[Slot][ArrayIndex].Z;
|
|
}
|
|
else if(pTexInfo->Type == RESOURCE_3D)
|
|
{
|
|
Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
|
|
|
|
*OffsetX = MipTailSlotOffset3DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
|
|
*OffsetY = MipTailSlotOffset3DSurface[Slot][ArrayIndex].Y;
|
|
*OffsetZ = MipTailSlotOffset3DSurface[Slot][ArrayIndex].Z;
|
|
}
|
|
|
|
GMM_DPF_EXIT;
|
|
return;
|
|
}
|
|
|