blob: f2182945c89e8346a47ea76eff013d468380d958 [file] [log] [blame]
/*
* Copyright (c) 2014-2021, 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.
*/
//!
//! \file mhw_utilities.c
//! \brief This modules implements utilities which are shared by both the HW interface and the state heap interface.
//!
#include "mhw_utilities.h"
#include "mhw_render.h"
#include "mhw_state_heap.h"
#include "hal_oca_interface.h"
#define MHW_NS_PER_TICK_RENDER_ENGINE 80 // 80 nano seconds per tick in render engine
//!
//! \brief Adds graphics address of a resource to the command buffer or indirect state
//! \details Internal MHW function to add the graphics address of resources to the
//! command buffer or indirect state
//! \param PMOS_INTERFACE pOsInterface
//! [in] OS interface
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Command buffer
//! \param PMHW_RESOURCE_PARAMS pParams
//! [in] Parameters necessary to insert the graphics address
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_AddResourceToCmd_GfxAddress(
PMOS_INTERFACE pOsInterface,
PMOS_COMMAND_BUFFER pCmdBuffer,
PMHW_RESOURCE_PARAMS pParams)
{
uint32_t dwAlign, dwMask;
uint32_t dwGfxAddrBottom, dwGfxAddrTop = 0;
uint64_t ui64GfxAddress, ui64GfxAddressUpperBound;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t iAllocationIndex = 0;
uint32_t uiPatchOffset = 0;
uint8_t *pbCmdBufBase = nullptr;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pParams);
MHW_CHK_NULL(pParams->presResource);
MHW_CHK_NULL(pCmdBuffer);
MHW_CHK_NULL(pCmdBuffer->pCmdBase);
pbCmdBufBase = (uint8_t*)pCmdBuffer->pCmdBase;
MHW_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
pParams->presResource,
pParams->bIsWritable ? true : false,
pParams->bIsWritable ? true : false));
dwAlign = ( 1 << pParams->dwLsbNum);
dwMask = (-1 << pParams->dwLsbNum);
pParams->dwOffset = MOS_ALIGN_CEIL(pParams->dwOffset, dwAlign);
ui64GfxAddress =
pOsInterface->pfnGetResourceGfxAddress(pOsInterface, pParams->presResource) + pParams->dwOffset;
MHW_CHK_COND(ui64GfxAddress == 0, "Driver can't add resource with ui64GfxAddress == 0. DW location in cmd == %d.", pParams->dwLocationInCmd);
dwGfxAddrBottom = (uint32_t)(ui64GfxAddress & 0x00000000FFFFFFFF);
dwGfxAddrTop = (uint32_t)((ui64GfxAddress & 0xFFFFFFFF00000000) >> 32);
*pParams->pdwCmd = (*pParams->pdwCmd & ~dwMask) | (dwGfxAddrBottom & dwMask);
// this is next DW for top part of the address
*(pParams->pdwCmd + 1) = dwGfxAddrTop;
#if (_DEBUG || _RELEASE_INTERNAL)
{
uint32_t evtData[4] ={(uint32_t)pParams->HwCommandType, pParams->dwLocationInCmd, pParams->dwOffset, pParams->dwSize};
MOS_TraceEventExt(EVENT_RESOURCE_REGISTER, EVENT_TYPE_INFO2, evtData, sizeof(evtData), &ui64GfxAddress, sizeof(ui64GfxAddress));
}
#endif
if (pParams->dwOffsetInSSH > 0)
{
// Calculate the patch offset to command buffer
uiPatchOffset = pParams->dwOffsetInSSH + (pParams->dwLocationInCmd * sizeof(uint32_t));
}
else
{
// Calculate the patch offset to command buffer
uiPatchOffset = pCmdBuffer->iOffset + (pParams->dwLocationInCmd * sizeof(uint32_t));
}
MOS_PATCH_ENTRY_PARAMS PatchEntryParams;
iAllocationIndex = pOsInterface->pfnGetResourceAllocationIndex(pOsInterface, pParams->presResource);
MOS_ZeroMemory(&PatchEntryParams, sizeof(PatchEntryParams));
PatchEntryParams.uiAllocationIndex = iAllocationIndex;
PatchEntryParams.uiResourceOffset = pParams->dwOffset;
PatchEntryParams.uiPatchOffset = uiPatchOffset;
PatchEntryParams.bWrite = pParams->bIsWritable;
PatchEntryParams.HwCommandType = pParams->HwCommandType;
PatchEntryParams.forceDwordOffset = pParams->dwSharedMocsOffset;
PatchEntryParams.cmdBufBase = pbCmdBufBase;
PatchEntryParams.presResource = pParams->presResource;
// Add patch entry
MHW_CHK_STATUS(pOsInterface->pfnSetPatchEntry(
pOsInterface,
&PatchEntryParams));
if (pParams->dwUpperBoundLocationOffsetFromCmd > 0)
{
pParams->dwSize = MOS_ALIGN_CEIL(pParams->dwSize, dwAlign);
ui64GfxAddressUpperBound = ui64GfxAddress + pParams->dwSize;
dwGfxAddrBottom = (uint32_t)(ui64GfxAddressUpperBound & 0x00000000FFFFFFFF);
dwGfxAddrTop = (uint32_t)((ui64GfxAddressUpperBound & 0xFFFFFFFF00000000) >> 32);
pParams->pdwCmd += pParams->dwUpperBoundLocationOffsetFromCmd;
*pParams->pdwCmd = (*pParams->pdwCmd & ~dwMask) | (dwGfxAddrBottom & dwMask);
// this is next DW for top part of the address
*(pParams->pdwCmd + 1) = dwGfxAddrTop;
MOS_PATCH_ENTRY_PARAMS PatchEntryParams;
// Calculate the patch offset to command buffer
uiPatchOffset += pParams->dwUpperBoundLocationOffsetFromCmd * sizeof(uint32_t);
MOS_ZeroMemory(&PatchEntryParams, sizeof(PatchEntryParams));
PatchEntryParams.uiAllocationIndex = iAllocationIndex;
PatchEntryParams.uiResourceOffset = pParams->dwOffset + pParams->dwSize;
PatchEntryParams.uiPatchOffset = uiPatchOffset;
PatchEntryParams.bUpperBoundPatch = true;
PatchEntryParams.presResource = pParams->presResource;
// Add patch entry (CP won't register this patch point since bUpperBoundPatch = true)
MHW_CHK_STATUS(pOsInterface->pfnSetPatchEntry(
pOsInterface,
&PatchEntryParams));
}
if (MOS_VEBOX_STATE == pParams->HwCommandType ||
MOS_VEBOX_DI_IECP == pParams->HwCommandType ||
MOS_VEBOX_TILING_CONVERT == pParams->HwCommandType ||
MOS_SFC_STATE == pParams->HwCommandType ||
MOS_STATE_BASE_ADDR == pParams->HwCommandType ||
MOS_SURFACE_STATE == pParams->HwCommandType ||
MOS_SURFACE_STATE_ADV == pParams->HwCommandType ||
MOS_MFX_PIPE_BUF_ADDR == pParams->HwCommandType ||
MOS_MFX_VP8_PIC == pParams->HwCommandType ||
MOS_MFX_BSP_BUF_BASE_ADDR == pParams->HwCommandType)
{
HalOcaInterface::DumpResourceInfo(*pCmdBuffer, *pOsInterface, *pParams->presResource, pParams->HwCommandType,
pParams->dwLocationInCmd, pParams->dwOffset);
}
finish:
return eStatus;
}
//!
//! \brief Adds resources to a patch list
//! \details Internal MHW function to put resources to be added to the command
//! buffer or indirect state into a patch list for patch later
//! \param PMOS_INTERFACE pOsInterface
//! [in] OS interface
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Command buffer
//! \param PMHW_RESOURCE_PARAMS pParams
//! [in] Parameters necessary to add the resource to the patch list
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_AddResourceToCmd_PatchList(
PMOS_INTERFACE pOsInterface,
PMOS_COMMAND_BUFFER pCmdBuffer,
PMHW_RESOURCE_PARAMS pParams)
{
MOS_GPU_CONTEXT GpuContext;
int32_t iAllocationIndex;
uint32_t dwLsbNum, dwUpperBoundOffset;
uint32_t dwOffset;
uint32_t uiPatchOffset;
MOS_PATCH_ENTRY_PARAMS PatchEntryParams;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pParams);
MHW_CHK_NULL(pParams->presResource);
MHW_CHK_NULL(pCmdBuffer);
MOS_TraceEventExt(EVENT_RESOURCE_REGISTER, EVENT_TYPE_INFO2, &pParams->HwCommandType, sizeof(uint32_t), &pParams->dwLocationInCmd, sizeof(uint32_t));
MHW_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
pParams->presResource,
pParams->bIsWritable ? true : false,
pParams->bIsWritable ? true : false));
GpuContext = pOsInterface->pfnGetGpuContext(pOsInterface);
iAllocationIndex = pOsInterface->pfnGetResourceAllocationIndex(pOsInterface, pParams->presResource);
dwLsbNum = pParams->dwLsbNum;
// Offset and command LSB parameters
dwOffset = pParams->dwOffset | ((*pParams->pdwCmd) & ((1 << dwLsbNum) - 1));
if (pParams->dwOffsetInSSH > 0)
{
// Calculate the patch offset to command buffer
uiPatchOffset = pParams->dwOffsetInSSH + (pParams->dwLocationInCmd * sizeof(uint32_t));
}
else
{
// Calculate the patch offset to command buffer
uiPatchOffset = pCmdBuffer->iOffset + (pParams->dwLocationInCmd * sizeof(uint32_t));
}
MOS_ZeroMemory(&PatchEntryParams, sizeof(PatchEntryParams));
PatchEntryParams.uiAllocationIndex = iAllocationIndex;
if(pParams->patchType == MOS_PATCH_TYPE_UV_Y_OFFSET ||
pParams->patchType == MOS_PATCH_TYPE_PITCH ||
pParams->patchType == MOS_PATCH_TYPE_V_Y_OFFSET)
{
PatchEntryParams.uiResourceOffset = *pParams->pdwCmd;
}
else
{
PatchEntryParams.uiResourceOffset = dwOffset;
}
PatchEntryParams.uiPatchOffset = uiPatchOffset;
PatchEntryParams.bWrite = pParams->bIsWritable;
PatchEntryParams.HwCommandType = pParams->HwCommandType;
PatchEntryParams.forceDwordOffset = pParams->dwSharedMocsOffset;
PatchEntryParams.cmdBufBase = (uint8_t*)pCmdBuffer->pCmdBase;
PatchEntryParams.presResource = pParams->presResource;
PatchEntryParams.patchType = pParams->patchType;
PatchEntryParams.shiftAmount = pParams->shiftAmount;
PatchEntryParams.shiftDirection = pParams->shiftDirection;
PatchEntryParams.offsetInSSH = pParams->dwOffsetInSSH;
PatchEntryParams.cmdBuffer = pCmdBuffer;
// Add patch entry to patch the address field for this command
MHW_CHK_STATUS(pOsInterface->pfnSetPatchEntry(
pOsInterface,
&PatchEntryParams));
if (pParams->dwUpperBoundLocationOffsetFromCmd > 0)
{
pParams->pdwCmd += pParams->dwUpperBoundLocationOffsetFromCmd;
dwUpperBoundOffset = pParams->dwUpperBoundLocationOffsetFromCmd;
// Offset and command LSB parameters
dwOffset = MOS_ALIGN_CEIL((pParams->dwOffset + pParams->dwSize), (1 << dwLsbNum));
dwOffset = dwOffset | ((*pParams->pdwCmd) & ((1 << dwLsbNum) - 1));
// Calculate the patch offset to command buffer
uiPatchOffset += dwUpperBoundOffset * sizeof(uint32_t);
MOS_ZeroMemory(&PatchEntryParams, sizeof(PatchEntryParams));
PatchEntryParams.uiAllocationIndex = iAllocationIndex;
PatchEntryParams.uiResourceOffset = dwOffset;
PatchEntryParams.uiPatchOffset = uiPatchOffset;
PatchEntryParams.bUpperBoundPatch = true;
PatchEntryParams.presResource = pParams->presResource;
PatchEntryParams.patchType = pParams->patchType;
PatchEntryParams.shiftAmount = pParams->shiftAmount;
PatchEntryParams.shiftDirection = pParams->shiftDirection;
PatchEntryParams.offsetInSSH = pParams->dwOffsetInSSH;
PatchEntryParams.cmdBuffer = pCmdBuffer;
if(dwLsbNum)
{
PatchEntryParams.shiftAmount = dwLsbNum;
PatchEntryParams.shiftDirection = 0;
}
// Add patch entry to patch the address field for this command
MHW_CHK_STATUS(pOsInterface->pfnSetPatchEntry(
pOsInterface,
&PatchEntryParams));
}
finish:
return eStatus;
}
//!
//! \brief Derive Surface Type from Surface Format
//! \details Internal MHW function to dervie surface type from surface format
//! \param uint32_t dwForceSurfaceFormat
//! [in] surface format information
//! \param PMOS_SURFACE psSurface
//! [in] surface which have depth information
//! \param uint32_t* pdwSurfaceType
//! [out] Surface type
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_SurfaceFormatToType(
uint32_t dwForceSurfaceFormat,
PMOS_SURFACE psSurface,
uint32_t *pdwSurfaceType)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(psSurface);
MHW_CHK_NULL(pdwSurfaceType);
switch ( dwForceSurfaceFormat )
{
// 1D Surface
case MHW_GFX3DSTATE_SURFACEFORMAT_RAW:
case MHW_GFX3DSTATE_SURFACEFORMAT_R32_UINT:
case MHW_GFX3DSTATE_SURFACEFORMAT_L8_UNORM:
*pdwSurfaceType = GFX3DSTATE_SURFACETYPE_BUFFER;
break;
// 2D Surface for Codec: GFX3DSTATE_SURFACEFORMAT_YCRCB_NORMAL, GFX3DSTATE_SURFACEFORMAT_YCRCB_SWAPY
// GFX3DSTATE_SURFACEFORMAT_R32_UNORM, GFX3DSTATE_SURFACEFORMAT_R16_UNORM, GFX3DSTATE_SURFACEFORMAT_R8_UNORM
// 2D & 3D Surface
default:
(psSurface->dwDepth > 1) ?
*pdwSurfaceType = GFX3DSTATE_SURFACETYPE_3D:
*pdwSurfaceType = GFX3DSTATE_SURFACETYPE_2D;
}
finish:
return eStatus;
}
//!
//! \brief Inserts the generic prologue command for a command buffer
//! \details Client facing function to add the generic prologue commands:
//! - the command buffer header (if necessary)
//! - flushes for the read/write caches (MI_FLUSH_DW or PIPE_CONTROL)
//! - CP prologue if necessary
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Command buffer
//! \param PMHW_GENERIC_PROLOG_PARAMS pParams
//! [in] Parameters necessary to add the generic prologue commands
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_SendGenericPrologCmd (
PMOS_COMMAND_BUFFER pCmdBuffer,
PMHW_GENERIC_PROLOG_PARAMS pParams,
MHW_MI_MMIOREGISTERS *pMmioReg)
{
PMOS_INTERFACE pOsInterface;
MhwMiInterface *pMiInterface;
MEDIA_FEATURE_TABLE *pSkuTable;
MEDIA_WA_TABLE *pWaTable;
MOS_GPU_CONTEXT GpuContext;
MHW_PIPE_CONTROL_PARAMS PipeControlParams;
MHW_MI_FLUSH_DW_PARAMS FlushDwParams;
bool bRcsEngineUsed = false;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(pCmdBuffer);
MHW_CHK_NULL(pParams);
MHW_CHK_NULL(pParams->pOsInterface);
pOsInterface = pParams->pOsInterface;
MHW_CHK_NULL(pParams->pvMiInterface);
pMiInterface = (MhwMiInterface *)pParams->pvMiInterface;
MHW_CHK_NULL(pMiInterface);
pSkuTable = pOsInterface->pfnGetSkuTable(pOsInterface);
MHW_CHK_NULL(pSkuTable);
pWaTable = pOsInterface->pfnGetWaTable(pOsInterface);
MHW_CHK_NULL(pWaTable);
GpuContext = pOsInterface->pfnGetGpuContext(pOsInterface);
if ( pOsInterface->Component != COMPONENT_CM )
{
if ( GpuContext == MOS_GPU_CONTEXT_RENDER ||
GpuContext == MOS_GPU_CONTEXT_RENDER2 ||
GpuContext == MOS_GPU_CONTEXT_RENDER3 ||
GpuContext == MOS_GPU_CONTEXT_RENDER4 ||
GpuContext == MOS_GPU_CONTEXT_VIDEO ||
GpuContext == MOS_GPU_CONTEXT_VIDEO2 ||
GpuContext == MOS_GPU_CONTEXT_VIDEO3 ||
GpuContext == MOS_GPU_CONTEXT_VIDEO4 ||
GpuContext == MOS_GPU_CONTEXT_VDBOX2_VIDEO ||
GpuContext == MOS_GPU_CONTEXT_VDBOX2_VIDEO2 ||
GpuContext == MOS_GPU_CONTEXT_VDBOX2_VIDEO3 ||
GpuContext == MOS_GPU_CONTEXT_VEBOX ||
GpuContext == MOS_GPU_CONTEXT_VIDEO5 ||
GpuContext == MOS_GPU_CONTEXT_VIDEO6 ||
GpuContext == MOS_GPU_CONTEXT_VIDEO7 )
{
MHW_CHK_STATUS(pMiInterface->AddWatchdogTimerStartCmd(pCmdBuffer));
}
}
bRcsEngineUsed = MOS_RCS_ENGINE_USED(GpuContext);
if (bRcsEngineUsed)
{
MOS_ZeroMemory(&PipeControlParams, sizeof(PipeControlParams));
PipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
MHW_CHK_STATUS(pMiInterface->AddPipeControl(
pCmdBuffer,
nullptr,
&PipeControlParams));
PipeControlParams.dwFlushMode = MHW_FLUSH_READ_CACHE;
PipeControlParams.presDest = pParams->presStoreData;
PipeControlParams.dwPostSyncOp = MHW_FLUSH_WRITE_IMMEDIATE_DATA;
PipeControlParams.dwResourceOffset = pParams->dwStoreDataOffset;
PipeControlParams.dwDataDW1 = pParams->dwStoreDataValue;
MHW_CHK_STATUS(pMiInterface->AddPipeControl(
pCmdBuffer,
nullptr,
&PipeControlParams));
if(pCmdBuffer->Attributes.bUmdSSEUEnable)
{
MHW_MI_LOAD_REGISTER_IMM_PARAMS MiLoadRegImmParams;
MHW_RENDER_PWR_CLK_STATE_PARAMS params;
MOS_ZeroMemory(&params, sizeof(params));
params.PowerClkStateEn = true;
params.SCountEn = true;
params.SSCountEn = true;
params.SliceCount = pCmdBuffer->Attributes.dwNumRequestedEUSlices;
params.SubSliceCount = pCmdBuffer->Attributes.dwNumRequestedSubSlices;
params.EUmax = pCmdBuffer->Attributes.dwNumRequestedEUs;
params.EUmin = pCmdBuffer->Attributes.dwNumRequestedEUs;
MOS_ZeroMemory(&MiLoadRegImmParams, sizeof(MiLoadRegImmParams));
MiLoadRegImmParams.dwRegister = MHW__PWR_CLK_STATE_REG;
MiLoadRegImmParams.dwData = params.Data;
MHW_CHK_STATUS(pMiInterface->AddMiLoadRegisterImmCmd(
pCmdBuffer,
&MiLoadRegImmParams));
}
}
else
{
// Send MI_FLUSH with protection bit off, which will FORCE exit protected mode for MFX
MOS_ZeroMemory(&FlushDwParams, sizeof(FlushDwParams));
FlushDwParams.bVideoPipelineCacheInvalidate = true;
FlushDwParams.pOsResource = pParams->presStoreData;
FlushDwParams.dwResourceOffset = pParams->dwStoreDataOffset;
FlushDwParams.dwDataDW1 = pParams->dwStoreDataValue;
MHW_CHK_STATUS(pMiInterface->AddMiFlushDwCmd(
pCmdBuffer,
&FlushDwParams));
}
MHW_CHK_STATUS(pMiInterface->AddProtectedProlog(pCmdBuffer));
if (pMmioReg)
{
HalOcaInterface::On1stLevelBBStart(
*pCmdBuffer,
*pOsInterface->pOsContext,
pOsInterface->CurrentGpuContextHandle,
*pMiInterface,
*pMmioReg);
}
finish:
return eStatus;
}
//!
//! \brief Sets Nearest Mode Table for Gen75/9, across SFC and Render engine to set the sampler states
//! \details This function sets Coefficients for Nearest Mode
//! \param int32_t* iCoefs
//! [out] Polyphase Table to fill
//! \param uint32_t dwPlane
//! [in] Number of Polyphase tables
//! \param bool bBalancedFilter
//! [in] If Filter is balanced, set true
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_SetNearestModeTable(
int32_t *iCoefs,
uint32_t dwPlane,
bool bBalancedFilter)
{
uint32_t dwNumEntries;
uint32_t dwOffset;
uint32_t i;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(iCoefs);
if (dwPlane == MHW_GENERIC_PLANE || dwPlane == MHW_Y_PLANE)
{
dwNumEntries = NUM_POLYPHASE_Y_ENTRIES;
dwOffset = 3;
}
else // if (dwPlane == MHW_U_PLANE || dwPlane == MHW_V_PLANE)
{
dwNumEntries = NUM_POLYPHASE_UV_ENTRIES;
dwOffset = 1;
}
for (i = 0; i <= NUM_HW_POLYPHASE_TABLES / 2; i++)
{
iCoefs[i * dwNumEntries + dwOffset] = 0x40;
}
if (bBalancedFilter)
{
// Fix offset so that filter is balanced
for (i = (NUM_HW_POLYPHASE_TABLES / 2 + 1); i < NUM_HW_POLYPHASE_TABLES; i++)
{
iCoefs[i * dwNumEntries + dwOffset + 1] = 0x40;
}
}
finish:
return eStatus;
}
//!
//! \brief Calculate Polyphase tables for Y , across SFC and Render engine to set the sampler states
//! \details Calculate Polyphase tables for Y
//! This function uses 17 phases.
//! MHW_NUM_HW_POLYPHASE_TABLES reflects the phases to program coefficients in HW, and
//! NUM_POLYPHASE_TABLES reflects the number of phases used for internal calculations.
//! \param int32_t* iCoefs
//! [out] Polyphase Table to fill
//! \param float fScaleFactor
//! [in] Scaling factor
//! \param uint32_t dwPlane
//! [in] Plane Info
//! \param MOS_FORMAT srcFmt
//! [in] Source Format
//! \param float fHPStrength
//! [in] High Pass Strength
//! \param bool bUse8x8Filter
//! [in] is 8x8 Filter used
//! \param uint32_t dwHwPhase
//! [in] Number of phases in HW
//! \param float fLanczosT
//! [in] Lanczos factor
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_CalcPolyphaseTablesY(
int32_t *iCoefs,
float fScaleFactor,
uint32_t dwPlane,
MOS_FORMAT srcFmt,
float fHPStrength,
bool bUse8x8Filter,
uint32_t dwHwPhase,
float fLanczosT)
{
uint32_t dwNumEntries;
uint32_t dwTableCoefUnit;
uint32_t i, j;
int32_t k;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
float fPhaseCoefs[NUM_POLYPHASE_Y_ENTRIES];
float fPhaseCoefsCopy[NUM_POLYPHASE_Y_ENTRIES];
float fStartOffset;
float fHPFilter[3], fHPSum, fHPHalfPhase; // Only used for Y_PLANE
float fBase, fPos, fSumCoefs;
int32_t iCenterPixel;
int32_t iSumQuantCoefs;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(iCoefs);
MHW_ASSERT((dwHwPhase == MHW_NUM_HW_POLYPHASE_TABLES) || (dwHwPhase == NUM_HW_POLYPHASE_TABLES));
if (dwPlane == MHW_GENERIC_PLANE || dwPlane == MHW_Y_PLANE)
{
dwNumEntries = NUM_POLYPHASE_Y_ENTRIES;
}
else // if (dwPlane == MHW_U_PLANE || dwPlane == MHW_V_PLANE)
{
dwNumEntries = NUM_POLYPHASE_UV_ENTRIES;
}
MOS_ZeroMemory(fPhaseCoefs , sizeof(fPhaseCoefs));
MOS_ZeroMemory(fPhaseCoefsCopy, sizeof(fPhaseCoefsCopy));
dwTableCoefUnit = 1 << MHW_AVS_TBL_COEF_PREC;
iCenterPixel = dwNumEntries / 2 - 1;
fStartOffset = (float)(-iCenterPixel);
if ((IS_YUV_FORMAT(srcFmt) &&
dwPlane != MHW_U_PLANE &&
dwPlane != MHW_V_PLANE) ||
((IS_RGB32_FORMAT(srcFmt) ||
srcFmt == Format_Y410 ||
srcFmt == Format_AYUV) &&
dwPlane == MHW_Y_PLANE))
{
if (fScaleFactor < 1.0F)
{
fLanczosT = 4.0F;
}
else
{
fLanczosT = 8.0F;
}
}
else // if (dwPlane == MHW_U_PLANE || dwPlane == MHW_V_PLANE || (IS_RGB_FORMAT(srcFmt) && dwPlane != MHW_V_PLANE))
{
fLanczosT = 2.0F;
}
for (i = 0; i < dwHwPhase; i++)
{
fBase = fStartOffset - (float)i / (float)NUM_POLYPHASE_TABLES;
fSumCoefs = 0.0F;
for (j = 0; j < dwNumEntries; j++)
{
fPos = fBase + (float)j;
if (bUse8x8Filter)
{
fPhaseCoefs[j] = fPhaseCoefsCopy[j] = MOS_Lanczos(fPos * fScaleFactor, dwNumEntries, fLanczosT);
}
else
{
fPhaseCoefs[j] = fPhaseCoefsCopy[j] = MOS_Lanczos_g(fPos * fScaleFactor, NUM_POLYPHASE_5x5_Y_ENTRIES, fLanczosT);
}
fSumCoefs += fPhaseCoefs[j];
}
// Convolve with HP
if (dwPlane == MHW_GENERIC_PLANE || dwPlane == MHW_Y_PLANE)
{
if (i <= NUM_POLYPHASE_TABLES / 2)
{
fHPHalfPhase = (float)i / (float)NUM_POLYPHASE_TABLES;
}
else
{
fHPHalfPhase = (float)(NUM_POLYPHASE_TABLES - i) / (float)NUM_POLYPHASE_TABLES;
}
fHPFilter[0] = fHPFilter[2] = -fHPStrength * MOS_Sinc(fHPHalfPhase * MOS_PI);
fHPFilter[1] = 1.0F + 2.0F * fHPStrength;
for (j = 0; j < dwNumEntries; j++)
{
fHPSum = 0.0F;
for (k = -1; k <= 1; k++)
{
if ((((long)j + k) >= 0) && (j + k < dwNumEntries))
{
fHPSum += fPhaseCoefsCopy[(int32_t)j+k] * fHPFilter[k+1];
}
fPhaseCoefs[j] = fHPSum;
}
}
}
// Normalize coefs and save
iSumQuantCoefs = 0;
for (j = 0; j < dwNumEntries; j++)
{
iCoefs[i * dwNumEntries + j] = (int32_t)floor(0.5F + (float)dwTableCoefUnit * fPhaseCoefs[j] / fSumCoefs);
iSumQuantCoefs += iCoefs[i * dwNumEntries + j];
}
// Fix center coef so that filter is balanced
if (i <= NUM_POLYPHASE_TABLES / 2)
{
iCoefs[i * dwNumEntries + iCenterPixel] -= iSumQuantCoefs - dwTableCoefUnit;
}
else
{
iCoefs[i * dwNumEntries + iCenterPixel + 1] -= iSumQuantCoefs - dwTableCoefUnit;
}
}
finish:
return eStatus;
}
//!
//! \brief Calculate Polyphase tables for UV for Gen9, across SFC and Render engine to set the sampler states
//! \details Calculate Polyphase tables for UV
//! \param int32_t* piCoefs
//! [out] Polyphase Table to fill
//! \param float fLanczosT
//! [in] Lanczos modifying factor
//! \param float fInverseScaleFactor
//! [in] Inverse scaling factor
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_CalcPolyphaseTablesUV(
int32_t *piCoefs,
float fLanczosT,
float fInverseScaleFactor)
{
int32_t phaseCount, tableCoefUnit, centerPixel, sumQuantCoefs;
double phaseCoefs[MHW_SCALER_UV_WIN_SIZE];
double startOffset, sf, base, sumCoefs, pos;
int32_t minCoef[MHW_SCALER_UV_WIN_SIZE];
int32_t maxCoef[MHW_SCALER_UV_WIN_SIZE];
int32_t i, j;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(piCoefs);
phaseCount = MHW_TABLE_PHASE_COUNT;
centerPixel = (MHW_SCALER_UV_WIN_SIZE / 2) - 1;
startOffset = (double)(-centerPixel);
tableCoefUnit = 1 << MHW_TBL_COEF_PREC;
sf = MOS_MIN(1.0, fInverseScaleFactor); // Sf isn't used for upscaling
MOS_ZeroMemory(piCoefs, sizeof(int32_t) * MHW_SCALER_UV_WIN_SIZE * phaseCount);
MOS_ZeroMemory(minCoef, sizeof(minCoef));
MOS_ZeroMemory(maxCoef, sizeof(maxCoef));
if (sf < 1.0F)
{
fLanczosT = 2.0F;
}
for(i = 0; i < phaseCount; ++i, piCoefs += MHW_SCALER_UV_WIN_SIZE)
{
// Write all
// Note - to shift by a half you need to a half to each phase.
base = startOffset - (double)(i) / (double)(phaseCount);
sumCoefs = 0.0;
for(j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
pos = base + (double) j;
phaseCoefs[j] = MOS_Lanczos((float)(pos * sf), MHW_SCALER_UV_WIN_SIZE, fLanczosT);
sumCoefs += phaseCoefs[j];
}
// Normalize coefs and save
for(j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
piCoefs[j] = (int32_t) floor((0.5 + (double)(tableCoefUnit) * (phaseCoefs[j] / sumCoefs)));
//For debug purposes:
minCoef[j] = MOS_MIN(minCoef[j], piCoefs[j]);
maxCoef[j] = MOS_MAX(maxCoef[j], piCoefs[j]);
}
// Recalc center coef
sumQuantCoefs = 0;
for(j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
sumQuantCoefs += piCoefs[j];
}
// Fix center coef so that filter is balanced
if (i <= phaseCount/2)
{
piCoefs[centerPixel] -= sumQuantCoefs - tableCoefUnit;
}
else
{
piCoefs[centerPixel + 1] -= sumQuantCoefs - tableCoefUnit;
}
}
finish:
return eStatus;
}
//!
//! \brief Calculate polyphase tables UV offset for Gen9, across SFC and Render engine to set the sampler states
//! \details Calculate Polyphase tables for UV with chroma siting for
//! 420 to 444 conversion
//! \param int32_t* piCoefs
//! [out] Polyphase Table to fill
//! \param float fLanczosT
//! [in] Lanczos modifying factor
//! \param float fInverseScaleFactor
//! [in] Inverse scaling factor
//! \param int32_t iUvPhaseOffset
//! [in] UV Phase Offset
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_CalcPolyphaseTablesUVOffset(
int32_t *piCoefs,
float fLanczosT,
float fInverseScaleFactor,
int32_t iUvPhaseOffset)
{
int32_t phaseCount, tableCoefUnit, centerPixel, sumQuantCoefs;
double phaseCoefs[MHW_SCALER_UV_WIN_SIZE];
double startOffset, sf, pos, sumCoefs, base;
int32_t minCoef[MHW_SCALER_UV_WIN_SIZE];
int32_t maxCoef[MHW_SCALER_UV_WIN_SIZE];
int32_t i, j;
int32_t adjusted_phase;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(piCoefs);
phaseCount = MHW_TABLE_PHASE_COUNT;
centerPixel = (MHW_SCALER_UV_WIN_SIZE / 2) - 1;
startOffset = (double)(-centerPixel +
(double)iUvPhaseOffset / (double)(phaseCount));
tableCoefUnit = 1 << MHW_TBL_COEF_PREC;
MOS_ZeroMemory(minCoef, sizeof(minCoef));
MOS_ZeroMemory(maxCoef, sizeof(maxCoef));
MOS_ZeroMemory(piCoefs, sizeof(int32_t)* MHW_SCALER_UV_WIN_SIZE * phaseCount);
sf = MOS_MIN(1.0, fInverseScaleFactor); // Sf isn't used for upscaling
if (sf < 1.0)
{
fLanczosT = 3.0;
}
for (i = 0; i < phaseCount; ++i, piCoefs += MHW_SCALER_UV_WIN_SIZE)
{
// Write all
// Note - to shift by a half you need to a half to each phase.
base = startOffset - (double)(i) / (double)(phaseCount);
sumCoefs = 0.0;
for (j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
pos = base + (double)j;
phaseCoefs[j] = MOS_Lanczos((float)(pos * sf), 6/*MHW_SCALER_UV_WIN_SIZE*/, fLanczosT);
sumCoefs += phaseCoefs[j];
}
// Normalize coefs and save
for (j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
piCoefs[j] = (int32_t)floor((0.5 + (double)(tableCoefUnit)* (phaseCoefs[j] / sumCoefs)));
// For debug purposes:
minCoef[j] = MOS_MIN(minCoef[j], piCoefs[j]);
maxCoef[j] = MOS_MAX(maxCoef[j], piCoefs[j]);
}
// Recalc center coef
sumQuantCoefs = 0;
for (j = 0; j < MHW_SCALER_UV_WIN_SIZE; ++j)
{
sumQuantCoefs += piCoefs[j];
}
// Fix center coef so that filter is balanced
adjusted_phase = i - iUvPhaseOffset;
if (adjusted_phase <= phaseCount / 2)
{
piCoefs[centerPixel] -= sumQuantCoefs - tableCoefUnit;
}
else // if(adjusted_phase < phaseCount)
{
piCoefs[centerPixel + 1] -= sumQuantCoefs - tableCoefUnit;
}
}
finish:
return eStatus;
}
//!
//! \brief Allocate BB
//! \details Allocated Batch Buffer
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PMHW_BATCH_BUFFER pBatchBuffer
//! [in/out] Pointer to Batch Buffer
//! \param PMHW_BATCH_BUFFER pBatchBufferList
//! [in/out] If valid, represents the batch buffer list maintained by the client
//! \param uint32_t dwSize
//! [in] Sixe of the batch vuffer to be allocated
//! \return MOS_STATUS
//! true if the Batch Buffer was successfully allocated
//! false if failed
//!
MOS_STATUS Mhw_AllocateBb(
PMOS_INTERFACE pOsInterface,
PMHW_BATCH_BUFFER pBatchBuffer,
PMHW_BATCH_BUFFER pBatchBufferList,
uint32_t dwSize,
uint32_t batchCount)
{
MOS_RESOURCE OsResource;
MOS_ALLOC_GFXRES_PARAMS AllocParams;
uint32_t allocSize;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pBatchBuffer);
MHW_FUNCTION_ENTER;
dwSize += 8 * MHW_CACHELINE_SIZE;
dwSize = MOS_ALIGN_CEIL(dwSize, MOS_PAGE_SIZE);
allocSize = dwSize * batchCount;
MOS_ZeroMemory(&OsResource, sizeof(OsResource));
MOS_ZeroMemory(&AllocParams, sizeof(AllocParams));
AllocParams.Type = MOS_GFXRES_BUFFER;
AllocParams.TileType = MOS_TILE_LINEAR;
AllocParams.Format = Format_Buffer;
AllocParams.dwBytes = allocSize;
AllocParams.pBufName = "BatchBuffer";
AllocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_MEDIA_BATCH_BUFFERS;
MHW_CHK_STATUS(pOsInterface->pfnAllocateResource(
pOsInterface,
&AllocParams,
&OsResource));
// Reset Allocation
pOsInterface->pfnResetResourceAllocationIndex(pOsInterface, &OsResource);
pBatchBuffer->OsResource = OsResource;
pBatchBuffer->iSize = (int32_t)dwSize;
pBatchBuffer->count = batchCount;
pBatchBuffer->iRemaining = pBatchBuffer->iSize;
pBatchBuffer->iCurrent = 0;
pBatchBuffer->bLocked = false;
#if (_DEBUG || _RELEASE_INTERNAL)
pBatchBuffer->iLastCurrent = 0;
#endif
// Link BB for synchronization
pBatchBuffer->bBusy = false;
pBatchBuffer->dwCmdBufId = 0;
if (pBatchBufferList)
{
pBatchBuffer->pNext = pBatchBufferList;
pBatchBufferList = pBatchBuffer;
if (pBatchBuffer->pNext)
{
pBatchBuffer->pNext->pPrev = pBatchBuffer;
}
}
finish:
return eStatus;
}
//!
//! \brief Free BB
//! \details Frees Batch Buffer
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PMHW_BATCH_BUFFER pBatchBuffer
//! [in] Pointer to Batch Buffer
//! \param PMHW_BATCH_BUFFER pBatchBufferList
//! [in/out] If valid, represents the batch buffer list maintained by the client
//! \return MOS_STATUS
//!
MOS_STATUS Mhw_FreeBb(
PMOS_INTERFACE pOsInterface,
PMHW_BATCH_BUFFER pBatchBuffer,
PMHW_BATCH_BUFFER pBatchBufferList)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pBatchBuffer);
MHW_FUNCTION_ENTER;
if (pBatchBuffer->bLocked)
{
MHW_CHK_STATUS(Mhw_UnlockBb(pOsInterface, pBatchBuffer, true));
}
pOsInterface->pfnFreeResource(pOsInterface, &pBatchBuffer->OsResource);
pBatchBuffer->dwCmdBufId = 0;
pBatchBuffer->iSize = 0;
pBatchBuffer->count = 0;
pBatchBuffer->iCurrent = 0;
#if (_DEBUG || _RELEASE_INTERNAL)
pBatchBuffer->iLastCurrent = 0;
#endif
if (pBatchBufferList)
{
// Unlink BB from synchronization list
if (pBatchBuffer->pNext)
{
pBatchBuffer->pNext->pPrev = pBatchBuffer->pPrev;
}
if (pBatchBuffer->pPrev)
{
pBatchBuffer->pPrev->pNext = pBatchBuffer->pNext;
}
else
{
pBatchBufferList = pBatchBuffer->pNext;
}
pBatchBuffer->pPrev = pBatchBuffer->pNext = nullptr;
}
finish:
return eStatus;
}
//!
//! \brief Lock BB
//! \details Locks Batch Buffer
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PMHW_BATCH_BUFFER pBatchBuffer
//! [in] Pointer to Batch Buffer
//! \return MOS_STATUS
//!
MOS_STATUS Mhw_LockBb(
PMOS_INTERFACE pOsInterface,
PMHW_BATCH_BUFFER pBatchBuffer)
{
MOS_LOCK_PARAMS LockFlags;
MOS_STATUS eStatus;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pBatchBuffer);
MHW_FUNCTION_ENTER;
eStatus = MOS_STATUS_UNKNOWN;
if (pBatchBuffer->bLocked)
{
MHW_ASSERTMESSAGE("Batch Buffer is already locked.");
goto finish;
}
MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
LockFlags.WriteOnly = 1;
pBatchBuffer->pData = (uint8_t*)pOsInterface->pfnLockResource(
pOsInterface,
&pBatchBuffer->OsResource,
&LockFlags);
MHW_CHK_NULL(pBatchBuffer->pData);
pBatchBuffer->bLocked = true;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Unlock BB
//! \details Unlocks Batch Buffer
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PMHW_BATCH_BUFFER pBatchBuffer
//! [in] Pointer to Batch Buffer
//! \param bool bResetBuffer
//! [in] Reset BB information concerning current offset and size
//! \return MOS_STATUS
//!
MOS_STATUS Mhw_UnlockBb(
PMOS_INTERFACE pOsInterface,
PMHW_BATCH_BUFFER pBatchBuffer,
bool bResetBuffer)
{
MOS_STATUS eStatus;
MHW_CHK_NULL(pOsInterface);
MHW_CHK_NULL(pBatchBuffer);
MHW_FUNCTION_ENTER;
eStatus = MOS_STATUS_UNKNOWN;
if (!pBatchBuffer->bLocked)
{
MHW_ASSERTMESSAGE("Batch buffer is locked.");
goto finish;
}
if (bResetBuffer)
{
pBatchBuffer->iRemaining = pBatchBuffer->iSize;
pBatchBuffer->iCurrent = 0;
}
MHW_CHK_STATUS(pOsInterface->pfnUnlockResource(
pOsInterface,
&pBatchBuffer->OsResource));
pBatchBuffer->bLocked = false;
pBatchBuffer->pData = nullptr;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Convert To Nano Seconds
//! \details Convert to Nano Seconds
//! \param PVPHAL_HW_int32_tERFACE pHwInterface
//! [in] Pointer to Hardware Interface Structure
//! \param uint64_t iTicks
//! [in] Ticks
//! \param uint64_t* piNs
//! [in] Nano Seconds
//! \return MOS_STATUS
//!
MOS_STATUS Mhw_ConvertToNanoSeconds(
uint64_t iTicks,
uint64_t *piNs)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_CHK_NULL(piNs);
*piNs = iTicks * MHW_NS_PER_TICK_RENDER_ENGINE;
finish:
return eStatus;
}
//!
//! \brief Convert Mos Tile Type to TR Mode
//! \details Convert Mos Tile Type to TR Mode
//! \param MOS_TILE_TYPE Type
//! [in] MOS tile type
//! \return uint32_t
//! Tile Resouece Mode
//!
uint32_t Mhw_ConvertToTRMode(MOS_TILE_TYPE Type)
{
switch (Type)
{
case MOS_TILE_YS:
return TRMODE_TILEYS;
case MOS_TILE_YF:
return TRMODE_TILEYF;
default:
return TRMODE_NONE;
}
}