blob: 47347b264316b5700653d6b6bdd893b1f7c603a3 [file] [log] [blame]
/*==============================================================================
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"
/////////////////////////////////////////////////////////////////////////////////////
/// This function does any special-case conversion from client-provided pseudo creation
/// parameters to actual parameters for Hiz, CCS, SeparateStencil and Depth buffers.
///
/// @param[in] pTexInfo: Reference to ::GMM_TEXTURE_INFO
///
/////////////////////////////////////////////////////////////////////////////////////
GMM_STATUS GmmLib::GmmTextureCalc::PreProcessTexSpecialCases(GMM_TEXTURE_INFO *pTexInfo)
{
GMM_STATUS Status = GMM_SUCCESS;
const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo);
if(!pTexInfo->Flags.Gpu.CCS &&
!pTexInfo->Flags.Gpu.MCS &&
!pTexInfo->Flags.Gpu.HiZ &&
!pTexInfo->Flags.Gpu.SeparateStencil &&
!pTexInfo->Flags.Gpu.MMC)
{
// Fast-out for non-special-cases.
}
else if(pTexInfo->Flags.Gpu.HiZ) // ######################################
{
// With HiZ surface creation, clients send the size/etc. parameters of
// the associated Depth Buffer--and here we convert to the appropriate
// HiZ creation parameters...
if((pTexInfo->BaseWidth > 0) &&
(pTexInfo->BaseWidth <= pPlatform->HiZ.MaxWidth) &&
(pTexInfo->BaseHeight > 0) &&
(pTexInfo->BaseHeight <= pPlatform->HiZ.MaxHeight) &&
(pTexInfo->Depth <= ((pTexInfo->Type == RESOURCE_3D) ?
pPlatform->HiZ.MaxDepth :
1)) &&
(pTexInfo->ArraySize <= ((pTexInfo->Type == RESOURCE_3D) ?
1 :
(pTexInfo->Type == RESOURCE_CUBE) ?
pPlatform->HiZ.MaxArraySize / 6 :
pPlatform->HiZ.MaxArraySize)) &&
// SKL+ does not support HiZ surfaces for 1D and 3D surfaces
((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) < IGFX_GEN9_CORE) ||
(pTexInfo->Type != RESOURCE_1D && pTexInfo->Type != RESOURCE_3D)))
{
uint32_t Z_Width, Z_Height, Z_Depth;
// Latch Z_[Width/Height/Depth]...
Z_Width = GFX_ULONG_CAST(pTexInfo->BaseWidth);
Z_Height = pTexInfo->BaseHeight;
if((pTexInfo->Type == RESOURCE_1D) ||
(pTexInfo->Type == RESOURCE_2D))
{
Z_Depth = GFX_MAX(pTexInfo->ArraySize, 1);
}
else if(pTexInfo->Type == RESOURCE_3D)
{
Z_Depth = pTexInfo->Depth;
}
else if(pTexInfo->Type == RESOURCE_CUBE)
{
// HW doesn't allow HiZ cube arrays, but GMM is allowing because
// clients will redescribe depth/HiZ cube arrays as 2D arrays.
Z_Depth = 6 * GFX_MAX(pTexInfo->ArraySize, 1);
}
else
{
__GMM_ASSERT(0); // Illegal--Should have caught at upper IF check.
Z_Depth = 0;
}
// HZ_[Width/Height/QPitch] Calculation...
{
uint32_t h0, h1, hL, i, NumSamples, QPitch, Z_HeightL;
uint32_t HZ_HAlign = 16, HZ_VAlign = 8;
uint8_t HZ_DepthRows = pPlatform->HiZPixelsPerByte;
// HZ operates in pixel space starting from SKL. So, it does not care
// whether the depth buffer is in MSAA mode or not.
NumSamples =
(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE) ?
1 :
pTexInfo->MSAA.NumSamples;
pTexInfo->BaseWidth = ExpandWidth(Z_Width, HZ_HAlign, NumSamples);
h0 = ExpandHeight(Z_Height, HZ_VAlign, NumSamples);
Z_Height = GmmTexGetMipHeight(pTexInfo, 1);
h1 = ExpandHeight(Z_Height, HZ_VAlign, NumSamples);
if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE)
{
if(pTexInfo->Type == RESOURCE_3D)
{
for(i = 0, Z_HeightL = 0; i <= pTexInfo->MaxLod; i++)
{
Z_Height = GmmTexGetMipHeight(pTexInfo, i);
hL = ExpandHeight(Z_Height, HZ_VAlign, NumSamples);
Z_HeightL += (hL * GFX_MAX(1, (Z_Depth / GFX_2_TO_POWER_OF(i))));
}
pTexInfo->ArraySize = 0;
pTexInfo->BaseHeight = Z_HeightL / 2;
}
else
{
for(i = 2, Z_HeightL = 0; i <= pTexInfo->MaxLod; i++)
{
Z_Height = GmmTexGetMipHeight(pTexInfo, i);
Z_HeightL += ExpandHeight(Z_Height, HZ_VAlign, NumSamples);
}
QPitch =
(pTexInfo->MaxLod > 0) ?
(h0 + GFX_MAX(h1, Z_HeightL)) :
h0;
QPitch /= HZ_DepthRows;
pTexInfo->ArraySize = Z_Depth;
pTexInfo->BaseHeight = QPitch;
}
pTexInfo->Alignment.HAlign = HZ_HAlign;
pTexInfo->Alignment.VAlign = HZ_VAlign / HZ_DepthRows;
}
else //if (GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN7_CORE)
{
if(pTexInfo->Type == RESOURCE_3D)
{
for(i = 0, Z_HeightL = 0; i <= pTexInfo->MaxLod; i++)
{
hL = ExpandHeight(Z_Height >> i, HZ_VAlign, NumSamples);
Z_HeightL += (hL * GFX_MAX(1, (Z_Depth / GFX_2_TO_POWER_OF(i))));
}
pTexInfo->BaseHeight = Z_HeightL / 2;
}
else
{
QPitch = h0 + h1 + 12 * HZ_VAlign;
pTexInfo->BaseHeight = GFX_CEIL_DIV((QPitch * Z_Depth / 2), 8) * 8;
}
pTexInfo->ArraySize = 1;
}
}
/// Native HZ Params //////////////////////////////////////////////////
pTexInfo->BitsPerPixel = 8;
pTexInfo->Depth = 1;
pTexInfo->Format = GMM_FORMAT_GENERIC_8BIT;
pTexInfo->MaxLod = 0;
pTexInfo->MSAA.NumSamples = 1;
pTexInfo->MSAA.SamplePattern = GMM_MSAA_DISABLED;
pTexInfo->Type = RESOURCE_2D;
// HiZ Always Tile-Y
pTexInfo->Flags.Info.Linear = 0;
pTexInfo->Flags.Info.TiledW = 0;
pTexInfo->Flags.Info.TiledX = 0;
pTexInfo->Flags.Info.TiledYf = 0;
GMM_SET_64KB_TILE(pTexInfo->Flags, 0);
GMM_SET_4KB_TILE(pTexInfo->Flags, 1);
}
else
{
GMM_ASSERTDPF(0, "Illegal HiZ creation parameters!");
Status = GMM_ERROR;
}
} // HiZ
else if(pTexInfo->Flags.Gpu.CCS ||
pTexInfo->Flags.Gpu.MCS) // ######################################
{
// With CCS surface creation, clients send height, width, depth, etc. of
// the associated RenderTarget--and here we convert to the appropriate CCS
// creation parameters...
__GMM_ASSERT((!pGmmLibContext->GetSkuTable().FtrTileY ||
(pTexInfo->Flags.Info.Linear + pTexInfo->Flags.Info.TiledW + pTexInfo->Flags.Info.TiledX + pTexInfo->Flags.Info.TiledY)) == 1);
__GMM_ASSERT((pGmmLibContext->GetSkuTable().FtrTileY || (pTexInfo->Flags.Info.Linear + pTexInfo->Flags.Info.Tile4 + pTexInfo->Flags.Info.Tile64)) == 1);
__GMM_ASSERT((pTexInfo->MSAA.NumSamples == 1) || (pTexInfo->MSAA.NumSamples == 2) || (pTexInfo->MSAA.NumSamples == 4) ||
(pTexInfo->MSAA.NumSamples == 8) || (pTexInfo->MSAA.NumSamples == 16));
Status = pGmmGlobalContext->GetTextureCalc()->MSAACCSUsage(pTexInfo);
if(!pTexInfo->Flags.Gpu.__NonMsaaLinearCCS)
{
// CCS Always Tile-Y (Even for Non-MSAA FastClear.)
pTexInfo->Flags.Info.Linear = 0;
pTexInfo->Flags.Info.TiledW = 0;
pTexInfo->Flags.Info.TiledX = 0;
pTexInfo->Flags.Info.TiledYf = 0;
GMM_SET_64KB_TILE(pTexInfo->Flags, 0);
GMM_SET_4KB_TILE(pTexInfo->Flags, 1);
//Clear compression request in CCS
pTexInfo->Flags.Info.RenderCompressed = 0;
pTexInfo->Flags.Info.MediaCompressed = 0;
}
} // CCS
else if(pTexInfo->Flags.Gpu.SeparateStencil) // ##########################
{
// Seperate stencil sizing is based on the associated depth buffer
// size, however UMD manages this sizing, and GMM will allocate any
// arbitrarily sized stencil. Stencils do have specific tiling
// requirements however, which is handled below.
if((pTexInfo->BaseWidth > 0) &&
(pTexInfo->BaseHeight > 0))
{
__GMM_ASSERT(pTexInfo->BitsPerPixel == 8);
if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) < IGFX_GEN7_CORE)
{
GMM_ASSERTDPF((pTexInfo->MaxLod == 0), "Stencil Buffer LOD's not supported!");
}
if(pGmmGlobalContext->GetSkuTable().FtrTileY)
{
// Separate Stencil Tile-W Gen8-Gen11, otherwise Tile-Y
pTexInfo->Flags.Info.Linear = 0;
pTexInfo->Flags.Info.TiledX = 0;
pTexInfo->Flags.Info.TiledYf = 0;
pTexInfo->Flags.Info.TiledW = 0;
GMM_SET_4KB_TILE(pTexInfo->Flags, 0);
GMM_SET_64KB_TILE(pTexInfo->Flags, 0);
if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE &&
GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) <= IGFX_GEN11_CORE)
{
pTexInfo->Flags.Info.TiledW = 1;
}
else
{
GMM_SET_4KB_TILE(pTexInfo->Flags, 1);
}
}
else
{
__GMM_ASSERT(pTexInfo->Flags.Info.Tile4 + pTexInfo->Flags.Info.Tile64 == 1);
}
}
else
{
GMM_ASSERTDPF(0, "Illegal Separate Stencil creation parameters!");
Status = GMM_ERROR;
}
} // Separate Stencil
else if(pTexInfo->Flags.Gpu.MMC && pTexInfo->Flags.Gpu.UnifiedAuxSurface)
{
pTexInfo->Flags.Gpu.__NonMsaaLinearCCS = 1;
pTexInfo->Flags.Info.Linear = 1;
}
return Status;
}