mirror of https://github.com/intel/gmmlib.git
499 lines
19 KiB
C++
499 lines
19 KiB
C++
/*==============================================================================
|
|
Copyright(c) 2017 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"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// 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::GmmGen8TextureCalc::FillTex2D(GMM_TEXTURE_INFO * pTexInfo,
|
|
__GMM_BUFFER_TYPE *pRestrictions)
|
|
{
|
|
uint32_t Width, Height, BitsPerPixel;
|
|
uint32_t HAlign, VAlign;
|
|
uint32_t 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;
|
|
Height = pTexInfo->BaseHeight;
|
|
Width = GFX_ULONG_CAST(pTexInfo->BaseWidth);
|
|
|
|
pTexInfo->MSAA.NumSamples = GFX_MAX(pTexInfo->MSAA.NumSamples, 1);
|
|
|
|
ExpandedArraySize =
|
|
GFX_MAX(pTexInfo->ArraySize, 1) *
|
|
((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1) * // Cubemaps simply 6-element, 2D arrays.
|
|
((pTexInfo->Flags.Gpu.Depth || pTexInfo->Flags.Gpu.SeparateStencil) ?
|
|
1 :
|
|
pTexInfo->MSAA.NumSamples); // MSAA (non-Depth/Stencil) RT samples stored as array planes.
|
|
|
|
//
|
|
// 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;
|
|
GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
|
|
|
|
Compress = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
|
|
|
|
// Calculate Block Surface Height
|
|
/////////////////////////////////
|
|
|
|
if(ExpandedArraySize > 1)
|
|
{
|
|
uint32_t Height0, Height1, Mip0BlockHeight, Slice0Delta = 0;
|
|
|
|
Height0 = __GMM_EXPAND_HEIGHT(this, Height, VAlign, pTexInfo);
|
|
Height1 = __GMM_EXPAND_HEIGHT(this, Height >> 1, VAlign, pTexInfo);
|
|
|
|
Mip0BlockHeight = BlockHeight = (pTexInfo->MaxLod > 0) ?
|
|
Height0 + Height1 + 12 * VAlign :
|
|
Height0;
|
|
BlockHeight -= (pTexInfo->Flags.Wa.CHVAstcSkipVirtualMips) ? Height0 : 0;
|
|
|
|
if(pTexInfo->Flags.Gpu.S3dDx && pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d)
|
|
{
|
|
BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
|
|
}
|
|
|
|
// QPitch for compressed surface must be multiple of BlockHeight and 4...
|
|
if(Compress && (CompressHeight % 4))
|
|
{
|
|
uint32_t LCM = CompressHeight * ((CompressHeight % 2) ? 4 : 2);
|
|
BlockHeight = GFX_ALIGN_NP2(BlockHeight, LCM);
|
|
Mip0BlockHeight = GFX_ALIGN_NP2(Mip0BlockHeight, LCM);
|
|
}
|
|
|
|
// Gen8 QPitch programming refers to the logical view, not physical.
|
|
pTexInfo->Alignment.QPitch = BlockHeight;
|
|
|
|
if(Compress)
|
|
{
|
|
BlockHeight /= CompressHeight;
|
|
Mip0BlockHeight /= CompressHeight;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.SeparateStencil)
|
|
{
|
|
BlockHeight /= 2;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
BlockHeight /= 32;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.__NonMsaaTileXCcs)
|
|
{
|
|
BlockHeight /= 16;
|
|
}
|
|
}
|
|
|
|
Slice0Delta = (pTexInfo->Flags.Wa.CHVAstcSkipVirtualMips) ? (Mip0BlockHeight - BlockHeight) : 0;
|
|
BlockHeight *= ExpandedArraySize;
|
|
BlockHeight += Slice0Delta;
|
|
}
|
|
else
|
|
{
|
|
pTexInfo->Alignment.QPitch = 0;
|
|
|
|
BlockHeight = Get2DMipMapHeight(pTexInfo);
|
|
}
|
|
|
|
///////////////////////////////////
|
|
// 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->MaxLod >= 2)
|
|
{
|
|
uint32_t AlignedWidthLod1, AlignedWidthLod2;
|
|
|
|
AlignedWidthLod1 = __GMM_EXPAND_WIDTH(this, Width >> 1, HAlign, pTexInfo);
|
|
AlignedWidthLod2 = __GMM_EXPAND_WIDTH(this, Width >> 2, HAlign, pTexInfo);
|
|
|
|
if((pGmmLibContext->GetWaTable().WaAstcCorruptionForOddCompressedBlockSizeX || pTexInfo->Flags.Wa.CHVAstcSkipVirtualMips) && pPlatform->FormatTable[pTexInfo->Format].ASTC && CompressWidth == 5)
|
|
{
|
|
uint32_t Width1 = (Width == 1) ? 1 : (Width >> 1);
|
|
uint32_t Modulo10 = Width1 % 10;
|
|
if(Modulo10 >= 1 && Modulo10 <= CompressWidth)
|
|
{
|
|
AlignedWidthLod2 += 3 * CompressWidth;
|
|
}
|
|
}
|
|
AlignedWidth = GFX_MAX(AlignedWidth, AlignedWidthLod1 + AlignedWidthLod2);
|
|
}
|
|
|
|
if(Compress)
|
|
{
|
|
AlignedWidth /= CompressWidth;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.SeparateStencil)
|
|
{
|
|
AlignedWidth *= 2;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
switch(pTexInfo->BitsPerPixel)
|
|
{
|
|
case 32:
|
|
AlignedWidth /= 8;
|
|
break;
|
|
case 64:
|
|
AlignedWidth /= 4;
|
|
break;
|
|
case 128:
|
|
AlignedWidth /= 2;
|
|
break;
|
|
default:
|
|
__GMM_ASSERT(0);
|
|
}
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.__NonMsaaTileXCcs)
|
|
{
|
|
switch(pTexInfo->BitsPerPixel)
|
|
{
|
|
case 32:
|
|
AlignedWidth /= 16;
|
|
break;
|
|
case 64:
|
|
AlignedWidth /= 8;
|
|
break;
|
|
case 128:
|
|
AlignedWidth /= 4;
|
|
break;
|
|
default:
|
|
__GMM_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.ColorSeparation)
|
|
{
|
|
AlignedWidth *= pTexInfo->ArraySize;
|
|
__GMM_ASSERT(0 == (AlignedWidth % GMM_COLOR_SEPARATION_WIDTH_DIVISION));
|
|
AlignedWidth /= GMM_COLOR_SEPARATION_WIDTH_DIVISION;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.ColorSeparationRGBX)
|
|
{
|
|
AlignedWidth *= pTexInfo->ArraySize;
|
|
__GMM_ASSERT(0 == (AlignedWidth % GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION));
|
|
AlignedWidth /= GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION;
|
|
}
|
|
|
|
// 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);
|
|
|
|
// If Tiled Resource or Undefined64KBSwizzle resource, align to 64KB tile size
|
|
if((pTexInfo->Flags.Gpu.TiledResource || pTexInfo->Flags.Info.Undefined64KBSwizzle) &&
|
|
(pTexInfo->Flags.Info.TiledY))
|
|
{
|
|
uint32_t ColFactor = 0, RowFactor = 0;
|
|
uint32_t TRTileWidth = 0, TRTileHeight = 0;
|
|
|
|
GmmGetD3DToHwTileConversion(pTexInfo, &ColFactor, &RowFactor);
|
|
TRTileWidth = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth * ColFactor;
|
|
TRTileHeight = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight * RowFactor;
|
|
|
|
Pitch = GFX_ALIGN(Pitch, TRTileWidth);
|
|
BlockHeight = GFX_ALIGN(BlockHeight, TRTileHeight);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// Align height to even row to cover for HW over-fetch
|
|
BlockHeight = GFX_ALIGN(BlockHeight, __GMM_EVEN_ROW);
|
|
|
|
if((Status = // <-- Note assignment.
|
|
FillTexPitchAndSize(
|
|
pTexInfo, Pitch, BlockHeight, pRestrictions)) == GMM_SUCCESS)
|
|
{
|
|
Fill2DTexOffsetAddress(pTexInfo);
|
|
|
|
// Init to no-packed mips. It'll be initialized when app calls to get packed
|
|
// mips. Calculate packed mips here if there's a chance apps won't call to
|
|
// get packed mips.
|
|
pTexInfo->Alignment.PackedMipStartLod = GMM_TILED_RESOURCE_NO_PACKED_MIPS;
|
|
}
|
|
|
|
if(pTexInfo->Flags.Wa.CHVAstcSkipVirtualMips)
|
|
{
|
|
uint32_t i = 0;
|
|
uint64_t SkipMip0Tiles = 0;
|
|
SkipMip0Tiles = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[1] /
|
|
(pTexInfo->Pitch * pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
|
|
SkipMip0Tiles *= pTexInfo->Pitch * pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
|
|
pTexInfo->Size -= SkipMip0Tiles;
|
|
for(i = 0; i <= pTexInfo->MaxLod; i++)
|
|
{
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[i] -= SkipMip0Tiles;
|
|
}
|
|
}
|
|
GMM_DPF_EXIT;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Calculates the address offset for each mip map of 2D texture and store them into
|
|
/// the GMM_TEXTURE_INFO for surf state programming.
|
|
///
|
|
/// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
void GmmLib::GmmGen8TextureCalc::Fill2DTexOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
|
|
{
|
|
uint32_t i;
|
|
|
|
GMM_DPF_ENTER;
|
|
|
|
// QPitch: Array Element-to-Element, or Cube Face-to-Face Pitch...
|
|
if((pTexInfo->ArraySize <= 1) &&
|
|
(pTexInfo->Type != RESOURCE_CUBE) &&
|
|
!(pTexInfo->Flags.Gpu.ColorSeparation ||
|
|
pTexInfo->Flags.Gpu.ColorSeparationRGBX))
|
|
{
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender = 0;
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = 0;
|
|
}
|
|
else
|
|
{
|
|
uint32_t ArrayQPitch;
|
|
uint32_t CompressHeight, CompressWidth, CompressDepth;
|
|
|
|
GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
|
|
|
|
ArrayQPitch = pTexInfo->Alignment.QPitch;
|
|
|
|
if(GmmIsCompressed(pGmmLibContext, pTexInfo->Format))
|
|
{
|
|
ArrayQPitch /= CompressHeight;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.SeparateStencil)
|
|
{
|
|
ArrayQPitch /= 2;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.CCS)
|
|
{
|
|
if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
|
|
{
|
|
ArrayQPitch /= 32;
|
|
}
|
|
else if(pTexInfo->Flags.Gpu.__NonMsaaTileXCcs)
|
|
{
|
|
ArrayQPitch /= 16;
|
|
}
|
|
}
|
|
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender = ArrayQPitch * pTexInfo->Pitch;
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = ArrayQPitch * pTexInfo->Pitch;
|
|
}
|
|
|
|
for(i = 0; i <= pTexInfo->MaxLod; i++)
|
|
{
|
|
pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[i] = Get2DTexOffsetAddressPerMip(pTexInfo, i);
|
|
}
|
|
|
|
GMM_DPF_EXIT;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Allocates the 1D 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::GmmGen8TextureCalc::FillTex1D(GMM_TEXTURE_INFO * pTexInfo,
|
|
__GMM_BUFFER_TYPE *pRestrictions)
|
|
{
|
|
return FillTex2D(pTexInfo, pRestrictions);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// Calculates the cube 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::GmmGen8TextureCalc::FillTexCube(GMM_TEXTURE_INFO * pTexInfo,
|
|
__GMM_BUFFER_TYPE *pRestrictions)
|
|
{
|
|
return FillTex2D(pTexInfo, pRestrictions);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// 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::GmmGen8TextureCalc::MSAACCSUsage(GMM_TEXTURE_INFO *pTexInfo)
|
|
{
|
|
GMM_STATUS Status = GMM_SUCCESS;
|
|
|
|
if(pTexInfo->MSAA.NumSamples > 1) // 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.Linear) ||
|
|
(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags) ||
|
|
(pTexInfo->Type == RESOURCE_BUFFER && pTexInfo->Flags.Info.Linear))) && //!Yf - deprecate Yf
|
|
((pTexInfo->BitsPerPixel == 32) ||
|
|
(pTexInfo->BitsPerPixel == 64) ||
|
|
(pTexInfo->BitsPerPixel == 128)))
|
|
{
|
|
// For non-MSAA CCS usage, the 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, there are 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)
|
|
|
|
pTexInfo->Flags.Gpu.__NonMsaaTileYCcs = pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs;
|
|
pTexInfo->Flags.Gpu.__NonMsaaTileXCcs = pTexInfo->Flags.Info.TiledX;
|
|
}
|
|
else
|
|
{
|
|
GMM_ASSERTDPF(0, "Illegal CCS creation parameters!");
|
|
Status = GMM_ERROR;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|