blob: 31ee4387d2a0cf77979d8f775a859beaefa8d18b [file] [log] [blame]
/*
* Copyright (c) 2011-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 vphal_render_vebox_base.cpp
//! \brief Common interface used in Vebox
//! \details Common interface used in Vebox which are platform independent
//!
#include "vphal.h"
#include "vphal_render_vebox_base.h"
#include "vphal_debug.h"
#include "vphal_renderer.h"
#include "vphal_render_vebox_util_base.h"
#include "vphal_render_common.h"
#include "renderhal_platform_interface.h"
#include "hal_oca_interface.h"
#include <string>
extern const Kdll_Layer g_cSurfaceType_Layer[];
extern const VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION g_cInit_VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION =
{
// DWORD 0
{
{NOISE_BLF_RANGE_THRESHOLD_S0_DEFAULT}, // RangeThrStart0
},
// DWORD 1
{
{NOISE_BLF_RANGE_THRESHOLD_S1_DEFAULT}, // RangeThrStart1
},
// DWORD 2
{
{NOISE_BLF_RANGE_THRESHOLD_S2_DEFAULT}, // RangeThrStart2
},
// DWORD 3
{
{NOISE_BLF_RANGE_THRESHOLD_S3_DEFAULT}, // RangeThrStart3
},
// DWORD 4
{
{NOISE_BLF_RANGE_THRESHOLD_S4_DEFAULT}, // RangeThrStart4
},
// DWORD 5
{
{NOISE_BLF_RANGE_THRESHOLD_S5_DEFAULT}, // RangeThrStart5
},
// DWORD 6
{
{0}, // Reserved
},
// DWORD 7
{
{0}, // Reserved
},
// DWORD 8
{
{NOISE_BLF_RANGE_WGTS0_DEFAULT}, // RangeWgt0
},
// DWORD 9
{
{NOISE_BLF_RANGE_WGTS1_DEFAULT}, // RangeWgt1
},
// DWORD 10
{
{NOISE_BLF_RANGE_WGTS2_DEFAULT}, // RangeWgt2
},
// DWORD 11
{
{NOISE_BLF_RANGE_WGTS3_DEFAULT}, // RangeWgt3
},
// DWORD 12
{
{NOISE_BLF_RANGE_WGTS4_DEFAULT}, // RangeWgt4
},
// DWORD 13
{
{NOISE_BLF_RANGE_WGTS5_DEFAULT}, // RangeWgt5
},
// DWORD 14
{
{0}, // Reserved
},
// DWORD 15
{
{0}, // Reserved
},
// DWORD 16 - 41: DistWgt[5][5]
{
{NOISE_BLF_DISTANCE_WGTS00_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS02_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS00_DEFAULT},
{NOISE_BLF_DISTANCE_WGTS10_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS12_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS10_DEFAULT},
{NOISE_BLF_DISTANCE_WGTS20_DEFAULT, NOISE_BLF_DISTANCE_WGTS21_DEFAULT, NOISE_BLF_DISTANCE_WGTS22_DEFAULT, NOISE_BLF_DISTANCE_WGTS21_DEFAULT, NOISE_BLF_DISTANCE_WGTS20_DEFAULT},
{NOISE_BLF_DISTANCE_WGTS10_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS12_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS10_DEFAULT},
{NOISE_BLF_DISTANCE_WGTS00_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS02_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS00_DEFAULT},
},
// Padding
{
0, // Padding
0, // Padding
0, // Padding
0, // Padding
0, // Padding
0, // Padding
0, // Padding
}
};
//!
//! \brief Send Vecs Status Tag
//! \details Add MI Flush with write back into command buffer for GPU to write
//! back GPU Tag. This should be the last command in 1st level batch.
//! This ensures sync tag will be written after rendering is complete.
//! \param [in] pMhwMiInterface
//! MHW MI interface
//! \param [in] pOsInterface
//! Pointer to OS Interface
//! \param [out] pCmdBuffer
//! Pointer to Command Buffer
//! \return MOS_STATUS
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSendVecsStatusTag(
PMHW_MI_INTERFACE pMhwMiInterface,
PMOS_INTERFACE pOsInterface,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
PMOS_RESOURCE gpuStatusBuffer = nullptr;
MHW_MI_FLUSH_DW_PARAMS FlushDwParams;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//------------------------------------
VPHAL_RENDER_CHK_NULL(pMhwMiInterface);
VPHAL_RENDER_CHK_NULL(pOsInterface);
VPHAL_RENDER_CHK_NULL(pCmdBuffer);
//------------------------------------
#if EMUL
// Dummy function for VpSolo, since no sync b/w GPU contexts
goto finish;
#endif
// Get GPU Status buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetGpuStatusBufferResource(
pOsInterface,
gpuStatusBuffer));
VPHAL_RENDER_CHK_NULL(gpuStatusBuffer);
// Register the buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
gpuStatusBuffer,
true,
true));
MOS_ZeroMemory(&FlushDwParams, sizeof(FlushDwParams));
FlushDwParams.pOsResource = gpuStatusBuffer;
FlushDwParams.dwResourceOffset = pOsInterface->pfnGetGpuStatusTagOffset(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
FlushDwParams.dwDataDW1 = pOsInterface->pfnGetGpuStatusTag(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiFlushDwCmd(
pCmdBuffer,
&FlushDwParams));
// Increase buffer tag for next usage
pOsInterface->pfnIncrementGpuStatusTag(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
finish:
return eStatus;
}
//!
//! \brief Initialize VEBOX state
//! \param [in] pSettings
//! Pointer to VPHAL settings
//! \param [in] pKernelDllState
//! Pointer to KDLL state
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::Initialize(
const VphalSettings *pSettings,
Kdll_State *pKernelDllState)
{
MOS_STATUS eStatus;
PRENDERHAL_INTERFACE pRenderHal;
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
MOS_NULL_RENDERING_FLAGS NullRenderingFlags;
PVPHAL_VEBOX_STATE pVeboxState = this;
eStatus = MOS_STATUS_SUCCESS;
pRenderHal = pVeboxState->m_pRenderHal;
if (m_reporting == nullptr)
{
m_reporting = MOS_New(VphalFeatureReport);
}
if (pRenderHal == nullptr)
{
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
if (!m_currentSurface)
{
m_currentSurface = (VPHAL_SURFACE*)MOS_AllocAndZeroMemory(sizeof(VPHAL_SURFACE));
if (!m_currentSurface)
{
return MOS_STATUS_NO_SPACE;
}
}
if (!m_previousSurface)
{
m_previousSurface = (VPHAL_SURFACE*)MOS_AllocAndZeroMemory(sizeof(VPHAL_SURFACE));
if (!m_previousSurface)
{
return MOS_STATUS_NO_SPACE;
}
}
for (uint32_t i = 0; i < VPHAL_NUM_FFDN_SURFACES; i++)
{
if (!FFDNSurfaces[i])
{
FFDNSurfaces[i] = (VPHAL_SURFACE*)MOS_AllocAndZeroMemory(sizeof(VPHAL_SURFACE));
if (!FFDNSurfaces[i])
{
return MOS_STATUS_NO_SPACE;
}
}
}
for (uint32_t i = 0; i < VPHAL_MAX_NUM_FFDI_SURFACES; i++)
{
if (!FFDISurfaces[i])
{
FFDISurfaces[i] = (VPHAL_SURFACE*)MOS_AllocAndZeroMemory(sizeof(VPHAL_SURFACE));
if (!FFDISurfaces[i])
{
return MOS_STATUS_NO_SPACE;
}
}
}
// Initial IECP modules
if (!m_IECP)
{
m_IECP = MOS_New(VPHAL_VEBOX_IECP_RENDERER);
if (!m_IECP)
{
return MOS_STATUS_NO_SPACE;
}
}
m_IECP->m_veboxState = this;
m_IECP->m_renderData = pVeboxState->GetLastExecRenderData();
if (MEDIA_IS_SKU(m_pSkuTable, FtrSFCPipe) && !m_sfcPipeState)
{
#if __VPHAL_SFC_SUPPORTED
m_sfcPipeState = CreateSfcState();
#else
m_sfcPipeState = MOS_New(VphalSfcState, m_pOsInterface, m_pRenderHal, m_pSfcInterface);
#endif
if (!m_sfcPipeState)
{
return MOS_STATUS_NO_SPACE;
}
}
// Vebox Comp Bypass is on by default
pVeboxState->dwCompBypassMode = VPHAL_COMP_BYPASS_ENABLED;
// Read user feature key to get the Composition Bypass mode
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
UserFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
// Vebox Comp Bypass is on by default
UserFeatureData.u32Data = VPHAL_COMP_BYPASS_ENABLED;
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_BYPASS_COMPOSITION_ID,
&UserFeatureData,
m_pOsInterface->pOsContext));
pVeboxState->dwCompBypassMode = UserFeatureData.u32Data;
if (MEDIA_IS_SKU(pVeboxState->m_pSkuTable, FtrSFCPipe) &&
m_sfcPipeState)
{
// Read user feature key to Disable SFC
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_VEBOX_DISABLE_SFC_ID,
&UserFeatureData,
m_pOsInterface->pOsContext));
m_sfcPipeState->SetDisable(UserFeatureData.bData ? true : false);
}
pVeboxState->bEnableMMC = 0;
pVeboxState->bDisableTemporalDenoiseFilter = 0;
pVeboxState->bDisableTemporalDenoiseFilterUserKey = 0;
NullRenderingFlags = pVeboxState->m_pOsInterface->pfnGetNullHWRenderFlags(
pVeboxState->m_pOsInterface);
pVeboxState->bNullHwRenderDnDi =
NullRenderingFlags.VPDnDi ||
NullRenderingFlags.VPGobal;
// Setup disable render flag controlled by a user feature key for validation purpose
pVeboxState->SetRenderDisableFlag( pSettings->disableDnDi == false ? false : true );
// Enable/Disable kernel Copy/Update for VEBox
pVeboxState->dwKernelUpdate = pSettings->kernelUpdate;
// Setup Same Sample Threshold for VEBOX
pVeboxState->iSameSampleThreshold = pSettings->sameSampleThreshold;
// Setup interface to KDLL
pVeboxState->m_pKernelDllState = pKernelDllState;
// Initialize State variables
pVeboxState->iCurFrameID = FIRST_FRAME;
pVeboxState->iPrvFrameID = FIRST_FRAME;
pVeboxState->bFirstFrame = true;
// Initialize Front End CSC
pVeboxState->fFeCscCoeff = (float*)MOS_AllocAndZeroMemory(sizeof(float)*9);
pVeboxState->fFeCscInOffset = (float*)MOS_AllocAndZeroMemory(sizeof(float)*3);
pVeboxState->fFeCscOutOffset = (float*)MOS_AllocAndZeroMemory(sizeof(float)*3);
finish:
return eStatus;
}
//!
//! \brief Destroy function
//! \details Release all VEBOX related resources
//! that needs virtual function and thus cannot be done in destructors
//! \return void
//!
void VPHAL_VEBOX_STATE::Destroy()
{
PVPHAL_VEBOX_STATE pVeboxState = this;
if (pVeboxState)
{
MOS_SafeFreeMemory(pVeboxState->fFeCscCoeff);
MOS_SafeFreeMemory(pVeboxState->fFeCscInOffset);
MOS_SafeFreeMemory(pVeboxState->fFeCscOutOffset);
// Free VEBOX allocations
if (MEDIA_IS_SKU(pVeboxState->m_pSkuTable, FtrVERing))
{
pVeboxState->FreeResources();
}
}
}
//!
//! \brief Copy Dndi Surface Params
//! \details Copies surface params to output surface
//! based on src and temp surfaces
//! \param [in] pSrcSurface
//! Pointer to Source Surface
//! \param [in] pTempSurface
//! Pointer to Temporary Surface
//! \param [in,out] pOutSurface
//! Pointer to Out Surface
//! \return void
//!
void VPHAL_VEBOX_STATE::VeboxCopySurfaceParams(
const PVPHAL_SURFACE pSrcSurface,
const PVPHAL_SURFACE pTempSurface,
PVPHAL_SURFACE pOutSurface)
{
PMOS_INTERFACE pOsInterface = nullptr;
const PVPHAL_VEBOX_STATE pVeboxState = this;
const PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
pOsInterface = pVeboxState->m_pOsInterface;
VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrcSurface);
VPHAL_RENDER_CHK_NULL_NO_STATUS(pTempSurface);
VPHAL_RENDER_CHK_NULL_NO_STATUS(pOutSurface);
VPHAL_RENDER_CHK_NULL_NO_STATUS(pOsInterface);
// Copy all parameters from SrcSurface to Output Surface
CopySurfaceValue(pOutSurface, pSrcSurface);
// Disable variance query if applicable
if (pVeboxState->IsQueryVarianceEnabled())
{
pOutSurface->bQueryVariance = false;
}
// Use original input as AdvProc's output (may occur in Variance)
if (pSrcSurface == pTempSurface)
{
goto finish;
}
// Copy relevant surf params from Temp Surface to Output surface
pOutSurface->OsResource = pTempSurface->OsResource;
pOutSurface->Format = pTempSurface->Format;
pOutSurface->dwHeight = pTempSurface->dwHeight;
pOutSurface->dwWidth = pTempSurface->dwWidth;
pOutSurface->dwPitch = pTempSurface->dwPitch;
pOutSurface->TileType = pTempSurface->TileType;
pOutSurface->TileModeGMM = pTempSurface->TileModeGMM;
pOutSurface->bGMMTileEnabled = pTempSurface->bGMMTileEnabled;
pOutSurface->SampleType = pTempSurface->SampleType;
pOutSurface->ColorSpace = pTempSurface->ColorSpace;
pOutSurface->dwOffset = pTempSurface->dwOffset;
pOutSurface->YPlaneOffset = pTempSurface->YPlaneOffset;
pOutSurface->UPlaneOffset = pTempSurface->UPlaneOffset;
pOutSurface->VPlaneOffset = pTempSurface->VPlaneOffset;
pOutSurface->bCompressible = pTempSurface->bCompressible;
pOutSurface->bIsCompressed = pTempSurface->bIsCompressed;
pOutSurface->CompressionMode = pTempSurface->CompressionMode;
// Reset deinterlace params if applicable
if (pRenderData->bDeinterlace)
{
pOutSurface->pDeinterlaceParams = nullptr;
}
// Reset Allocations
pOsInterface->pfnResetResourceAllocationIndex(
pOsInterface,
&pOutSurface->OsResource);
finish:
return;
}
//!
//! \brief Setup reference surfaces
//! \details Setup reference surfaces for app feeds reference case and
//! no reference frame case
//! \param [in] pSrcSurface
//! Pointer to Source Surface
//! \return PVPHAL_SURFACE
//! Pointer to Reference surface or nullptr if no reference
//!
PVPHAL_SURFACE VPHAL_VEBOX_STATE::VeboxSetReference(
PVPHAL_SURFACE pSrcSurface)
{
PVPHAL_SURFACE pRefSurface = nullptr;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
if (pRenderData->bRefValid)
{
// Set the Reference surface
if (IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState))
{
// Vebox defines reference as previous input frame.
// In this mode, treat current as the previous
pRefSurface = pSrcSurface;
}
else
{
pRefSurface = pSrcSurface->pBwdRef;
VPHAL_RENDER_ASSERT( pRefSurface && pSrcSurface->uBwdRefCount > 0);
}
// Discontinuity - hence can't reuse previous surfaces
if (!pRenderData->bSameSamples && pRenderData->bOutOfBound)
{
if (pRenderData->bDenoise &&
!Mos_ResourceIsNull(&pVeboxState->m_currentSurface->OsResource))
{
// Save prev call's current sample as prev sample for current call
CopySurfaceValue(pVeboxState->m_previousSurface, pVeboxState->m_currentSurface);
pVeboxState->m_previousSurface->FrameID = pRefSurface->FrameID;
}
else if ((pRenderData->bEnableMMC || IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData)) &&
pRenderData->bDenoise &&
pRenderData->bDeinterlace &&
Mos_ResourceIsNull(&pVeboxState->m_currentSurface->OsResource))
{
// In WHCK test, there is a special test.Test app will set future / post reference frame for frame 0.
// Then, frame 0 will do deinterlace using uncompressed reference frame instead of denoised compressed frames if MMC on.
// If using reference frame to do ADI deinterlace, there is corruption with previous DI frame of the VEBOX output which output by SFC.
pRenderData->bRefValid = false;
}
else
{
// Save cur sample as prev for next call
CopySurfaceValue(pVeboxState->m_previousSurface, pRefSurface);
}
pVeboxState->VeboxClearFmdStates();
VPHAL_RENDER_NORMALMESSAGE("Discontinuity.");
}
else
{
if (Mos_ResourceIsNull(&pVeboxState->m_currentSurface->OsResource))
{
// If Current Resource is not valid, always set the
// previous surface as Reference surface
CopySurfaceValue(pVeboxState->m_previousSurface, pRefSurface);
}
else
{
if (pRenderData->bDenoise)
{
// Save prev call's current sample as prev sample for current call
CopySurfaceValue(pVeboxState->m_previousSurface, pVeboxState->m_currentSurface);
pVeboxState->m_previousSurface->FrameID = pRefSurface->FrameID;
}
else
{
// Use application supplied reference frame
CopySurfaceValue(pVeboxState->m_previousSurface, pRefSurface);
}
}
}
}
if (!pRenderData->bRefValid) // No Reference frame provided.
{
// Disable FMD.
if (!IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
pVeboxState->VeboxClearFmdStates();
}
if (pRenderData->bDenoise &&
(pSrcSurface->SampleType == SAMPLE_PROGRESSIVE))
{
// The first "current" frame may not have a resource (i.e. no
// memory has been allocated for this image surface.
// All subsequent frames should have a resource.
if (!Mos_ResourceIsNull(&pVeboxState->m_currentSurface->OsResource))
{
// At this stage, the CurrentSurface contains the Denoise output
// from the previous iteration.
CopySurfaceValue(pVeboxState->m_previousSurface, pVeboxState->m_currentSurface);
pRefSurface = pVeboxState->m_previousSurface;
pRenderData->bRefValid = true;
}
}
else if (pRenderData->bDeinterlace)
{
// Force DI when there is no ref sample
// Update Surfaces DI params
pSrcSurface->pDeinterlaceParams->bSingleField = true;
pRenderData->bSingleField = true;
VPHAL_RENDER_NORMALMESSAGE("BOB using VEBOX h/w (no ref sample).");
}
}
return pRefSurface;
}
//!
//! \brief Set DI output sample
//! \details Set DI sample to be used for compositing stage followed by VEBOX
//! feature reporting
//! \param [in] pSrcSurface
//! Pointer to Source Surface
//! \param [in,out] pOutputSurface
//! Pointer to Output Surface
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if no error else MOS_STATUS_UNKNOWN
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetDiOutput(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pOutputSurface)
{
PVPHAL_SURFACE pDstSurface;
int32_t iFrame0;
int32_t iFrame1;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
if (pRenderData->bDeinterlace)
{
if (pVeboxState->m_pVeboxExecState->bDIOutputPair01)
{
iFrame0 = 0;
iFrame1 = 1;
}
else
{
iFrame0 = 2;
iFrame1 = 3;
}
// for 30i->60fps + Comp
if (pRenderData->b60fpsDi)
{
// Output 1st field of current frame according to DDI flag
if (pRenderData->bSingleField ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_SINGLE_BOTTOM_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_PROGRESSIVE))
{
pDstSurface = pVeboxState->FFDISurfaces[iFrame1];
}
else
{
// First sample output - 2nd field of the previous frame
pDstSurface = pVeboxState->FFDISurfaces[iFrame0];
}
}
// for 30i->30fps + Comp, which differentiates from 30i->60fps for the correct
// output according to SampleType input
// eg. TF/BF matches with {0,2,4,6...}/{0,1,3,5...} output
else
{
// Output 1st field of current frame according to DDI flag
if (pRenderData->bSingleField ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_SINGLE_TOP_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_PROGRESSIVE))
{
pDstSurface = pVeboxState->FFDISurfaces[iFrame1];
}
else
{
// First sample output - 2nd field of the previous frame
pDstSurface = pVeboxState->FFDISurfaces[iFrame0];
}
}
}
else if (pRenderData->bIECP)
{
// IECP output
pDstSurface = pVeboxState->FFDISurfaces[pRenderData->iCurDNOut];
}
else if (pRenderData->bDenoise)
{
// Denoise output
pDstSurface = pVeboxState->FFDNSurfaces[pRenderData->iCurDNOut];
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("incorrect dndi output.");
return MOS_STATUS_UNKNOWN;
}
//----------------------------
// VEBOX feature reporting
//----------------------------
m_reporting->IECP = IsIECPEnabled();
m_reporting->Denoise = pRenderData->bDenoise;
if (pRenderData->bDeinterlace)
{
m_reporting->DeinterlaceMode =
(pRenderData->bSingleField && !pRenderData->bRefValid ) ?
VPHAL_DI_REPORT_ADI_BOB : // VEBOX BOB
VPHAL_DI_REPORT_ADI; // ADI
}
// Copy relevant surf params from pDst to pOutput
VeboxCopySurfaceParams(
pSrcSurface,
pDstSurface,
pOutputSurface);
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Vebox Set PerfTag
//! \details Set Vebox PerfTag: DN, DI and IECP
//! \param [in] srcFmt
//! Source surface format of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetPerfTag(
MOS_FORMAT srcFmt)
{
MOS_STATUS eStatus;
PVPHAL_PERFTAG pPerfTag;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
eStatus = MOS_STATUS_INVALID_PARAMETER;
pPerfTag = &pRenderData->PerfTag;
switch (srcFmt)
{
case Format_NV12:
if (pRenderData->bDeinterlace ||
IsQueryVarianceEnabled())
{
if (pRenderData->bDenoise ||
pRenderData->bChromaDenoise)
{
if (IsIECPEnabled())
{
*pPerfTag = VPHAL_NV12_DNDI_422CP;
}
else
{
*pPerfTag = VPHAL_NV12_DNDI_PA;
}
}
else
{
if (IsIECPEnabled())
{
*pPerfTag = VPHAL_PL_DI_422CP;
}
else
{
*pPerfTag = VPHAL_PL_DI_PA;
}
}
}
else
{
if (pRenderData->bDenoise ||
pRenderData->bChromaDenoise)
{
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
switch (pRenderData->pRenderTarget->Format)
{
case Format_NV12:
*pPerfTag = VPHAL_NV12_DN_420CP;
break;
CASE_PA_FORMAT:
*pPerfTag = VPHAL_NV12_DN_422CP;
break;
case Format_RGB32:
*pPerfTag = VPHAL_NV12_DN_RGB32CP;
case Format_A8R8G8B8:
case Format_A8B8G8R8:
*pPerfTag = VPHAL_NV12_DN_RGB32CP;
break;
case Format_P010:
case Format_P016:
case Format_Y410:
case Format_Y416:
case Format_Y210:
case Format_Y216:
case Format_AYUV:
case Format_Y8:
case Format_Y16S:
case Format_Y16U:
*pPerfTag = VPHAL_NONE;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Output Format Not found.");
goto finish;
}
}
else if (IsIECPEnabled())
{
*pPerfTag = VPHAL_NV12_DN_420CP;
}
else
{
*pPerfTag = VPHAL_NV12_DN_NV12;
}
}
else
{
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
switch (pRenderData->pRenderTarget->Format)
{
case Format_NV12:
*pPerfTag = VPHAL_NV12_420CP;
break;
CASE_PA_FORMAT:
*pPerfTag = VPHAL_NV12_422CP;
break;
case Format_RGB32:
*pPerfTag = VPHAL_NV12_RGB32CP;
case Format_A8R8G8B8:
case Format_A8B8G8R8:
case Format_R10G10B10A2:
case Format_B10G10R10A2:
*pPerfTag = VPHAL_NV12_RGB32CP;
break;
case Format_P010:
case Format_P016:
case Format_Y410:
case Format_Y416:
case Format_Y210:
case Format_Y216:
case Format_AYUV:
case Format_Y8:
case Format_Y16S:
case Format_Y16U:
*pPerfTag = VPHAL_NONE;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Output Format Not found.");
goto finish;
}
}
else
{
*pPerfTag = VPHAL_NV12_420CP;
}
}
}
break;
CASE_PA_FORMAT:
if (pRenderData->bDeinterlace ||
IsQueryVarianceEnabled())
{
if (pRenderData->bDenoise ||
pRenderData->bChromaDenoise)
{
if (IsIECPEnabled())
{
*pPerfTag = VPHAL_PA_DNDI_422CP;
}
else
{
*pPerfTag = VPHAL_PA_DNDI_PA;
}
}
else
{
if (IsIECPEnabled())
{
*pPerfTag = VPHAL_PA_DI_422CP;
}
else
{
*pPerfTag = VPHAL_PA_DI_PA;
}
}
}
else
{
if (pRenderData->bDenoise ||
pRenderData->bChromaDenoise)
{
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
switch (pRenderData->pRenderTarget->Format)
{
case Format_NV12:
*pPerfTag = VPHAL_PA_DN_420CP;
break;
CASE_PA_FORMAT:
*pPerfTag = VPHAL_PA_DN_422CP;
break;
case Format_RGB32:
*pPerfTag = VPHAL_PA_DN_RGB32CP;
break;
case Format_P010:
case Format_P016:
case Format_Y410:
case Format_Y416:
case Format_Y210:
case Format_Y216:
case Format_AYUV:
case Format_Y8:
case Format_Y16S:
case Format_Y16U:
*pPerfTag = VPHAL_NONE;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Output Format Not found.");
goto finish;
}
}
else if (IsIECPEnabled())
{
*pPerfTag = VPHAL_PA_DN_422CP;
}
else
{
*pPerfTag = VPHAL_PA_DN_PA;
}
}
else
{
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
switch (pRenderData->pRenderTarget->Format)
{
case Format_NV12:
*pPerfTag = VPHAL_PA_420CP;
break;
CASE_PA_FORMAT:
*pPerfTag = VPHAL_PA_422CP;
break;
case Format_RGB32:
*pPerfTag = VPHAL_PA_RGB32CP;
break;
case Format_A8R8G8B8:
case Format_A8B8G8R8:
case Format_R10G10B10A2:
case Format_B10G10R10A2:
*pPerfTag = VPHAL_PA_RGB32CP;
break;
case Format_P010:
case Format_P016:
case Format_Y410:
case Format_Y416:
case Format_Y210:
case Format_Y216:
case Format_AYUV:
case Format_Y8:
case Format_Y16S:
case Format_Y16U:
*pPerfTag = VPHAL_NONE;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Output Format Not found.");
goto finish;
}
}
else
{
*pPerfTag = VPHAL_PA_422CP;
}
}
}
break;
case Format_AYUV:
break;
CASE_RGB32_FORMAT:
// RGB Input Support for SFC
*pPerfTag = VPHAL_NONE;
break;
case Format_P010:
// P010 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_P010;
break;
case Format_P016:
// P016 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_P016;
break;
case Format_P210:
// P210 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_P210;
break;
case Format_P216:
// P216 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_P216;
break;
case Format_Y210:
// Y210 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_Y210;
break;
case Format_Y216:
// Y216 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_Y216;
break;
case Format_Y410:
// Y410 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_Y410;
break;
case Format_Y416:
// Y416 Input Support for VEBOX, SFC
*pPerfTag = VPHAL_VEBOX_Y416;
break;
case Format_A16B16G16R16:
case Format_A16R16G16B16:
case Format_A16B16G16R16F:
case Format_A16R16G16B16F:
*pPerfTag = VPHAL_NONE;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Format Not found.");
goto finish;
} // switch (srcFmt)
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Vebox Populate VEBOX parameters
//! \details Populate the Vebox VEBOX state parameters to VEBOX RenderData
//! \param [in] pLumaParams
//! Pointer to Luma DN and DI parameter
//! \param [in] pChromaParams
//! Pointer to Chroma DN parameter
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxPopulateDNDIParams(
PVPHAL_SAMPLER_STATE_DNDI_PARAM pLumaParams,
PVPHAL_DNUV_PARAMS pChromaParams)
{
PMHW_VEBOX_DNDI_PARAMS pVeboxDNDIParams;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
// Populate the VEBOX VEBOX parameters
pVeboxDNDIParams = &pRenderData->VeboxDNDIParams;
// DI and Luma Denoise Params
if (pLumaParams != nullptr)
{
VPHAL_RENDER_NORMALMESSAGE("bProgressiveDN %d, bDNDITopFirst %d", pLumaParams->bProgressiveDN, pLumaParams->bDNDITopFirst);
if (pRenderData->bDenoise)
{
pVeboxDNDIParams->dwDenoiseASDThreshold = pLumaParams->dwDenoiseASDThreshold;
pVeboxDNDIParams->dwDenoiseHistoryDelta = pLumaParams->dwDenoiseHistoryDelta;
pVeboxDNDIParams->dwDenoiseMaximumHistory = pLumaParams->dwDenoiseMaximumHistory;
pVeboxDNDIParams->dwDenoiseSTADThreshold = pLumaParams->dwDenoiseSTADThreshold;
pVeboxDNDIParams->dwDenoiseSCMThreshold = pLumaParams->dwDenoiseSCMThreshold;
pVeboxDNDIParams->dwDenoiseMPThreshold = pLumaParams->dwDenoiseMPThreshold;
pVeboxDNDIParams->dwLTDThreshold = pLumaParams->dwLTDThreshold;
pVeboxDNDIParams->dwTDThreshold = pLumaParams->dwTDThreshold;
pVeboxDNDIParams->dwGoodNeighborThreshold = pLumaParams->dwGoodNeighborThreshold;
pVeboxDNDIParams->bProgressiveDN = pLumaParams->bProgressiveDN;
}
pVeboxDNDIParams->dwFMDFirstFieldCurrFrame = pLumaParams->dwFMDFirstFieldCurrFrame;
pVeboxDNDIParams->dwFMDSecondFieldPrevFrame = pLumaParams->dwFMDSecondFieldPrevFrame;
pVeboxDNDIParams->bDNDITopFirst = pLumaParams->bDNDITopFirst;
}
// Only need to reverse bDNDITopFirst for no reference case, no need to reverse it for having refrenece case
if (!pRenderData->bRefValid)
{
pVeboxDNDIParams->bDNDITopFirst = pRenderData->bTopField;
}
// Chroma Denoise Params
if (pRenderData->bChromaDenoise && pChromaParams != nullptr)
{
VPHAL_RENDER_NORMALMESSAGE("bChromaDNEnable %d", pRenderData->bChromaDenoise);
pVeboxDNDIParams->dwChromaSTADThreshold = pChromaParams->dwSTADThresholdU; // Use U threshold for now
pVeboxDNDIParams->dwChromaLTDThreshold = pChromaParams->dwLTDThresholdU; // Use U threshold for now
pVeboxDNDIParams->dwChromaTDThreshold = pChromaParams->dwTDThresholdU; // Use U threshold for now
pVeboxDNDIParams->bChromaDNEnable = pRenderData->bChromaDenoise;
}
pRenderData->GetVeboxStateParams()->pVphalVeboxDndiParams = pVeboxDNDIParams;
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Vebox Set FMD parameter
//! \details Set up the FMD parameters for DNDI State
//! \param [out] pLumaParams
//! Pointer to DNDI Param for set FMD parameters
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetFMDParams(
PVPHAL_SAMPLER_STATE_DNDI_PARAM pLumaParams)
{
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_RENDER_CHK_NULL(pLumaParams);
#if VEBOX_AUTO_DENOISE_SUPPORTED
if (pRenderData->bProgressive && pRenderData->bAutoDenoise)
{
// out1 = Cur1st + Cur2nd
pLumaParams->dwFMDFirstFieldCurrFrame =
MEDIASTATE_DNDI_FIELDCOPY_NEXT;
// out2 = Prv1st + Prv2nd
pLumaParams->dwFMDSecondFieldPrevFrame =
MEDIASTATE_DNDI_FIELDCOPY_PREV;
}
else
#endif
{
pLumaParams->dwFMDFirstFieldCurrFrame =
MEDIASTATE_DNDI_DEINTERLACE;
pLumaParams->dwFMDSecondFieldPrevFrame =
MEDIASTATE_DNDI_DEINTERLACE;
}
finish:
return eStatus;
}
//!
//! \brief Vebox Set VEBOX parameter
//! \details Set up the VEBOX parameter value
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetDNDIParams(
PVPHAL_SURFACE pSrcSurface)
{
MOS_STATUS eStatus;
VPHAL_SAMPLER_STATE_DNDI_PARAM lumaParams;
VPHAL_DNUV_PARAMS chromaParams;
PVPHAL_SAMPLER_STATE_DNDI_PARAM pLumaParams;
PVPHAL_DNUV_PARAMS pChromaParams;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
eStatus = MOS_STATUS_SUCCESS;
pLumaParams = &lumaParams; // Params for DI and LumaDN
pChromaParams = &chromaParams; // Params for ChromaDN
MOS_ZeroMemory(pLumaParams, sizeof(VPHAL_SAMPLER_STATE_DNDI_PARAM));
MOS_ZeroMemory(pChromaParams, sizeof(VPHAL_DNUV_PARAMS));
// Set Luma and Chroma DNDI params
VPHAL_RENDER_CHK_STATUS(pVeboxState->SetDNDIParams(
pSrcSurface,
pLumaParams,
pChromaParams));
if (!pRenderData->bRefValid)
{
// setting LTDThreshold = TDThreshold = 0 forces SpatialDenoiseOnly
pLumaParams->dwLTDThreshold = 0;
pLumaParams->dwTDThreshold = 0;
}
if (pRenderData->bDenoise)
{
pLumaParams->bDNEnable = true;
if (pRenderData->bProgressive)
{
pLumaParams->bProgressiveDN = true;
}
}
if (pRenderData->bDeinterlace || IsQueryVarianceEnabled())
{
pLumaParams->bDIEnable = true;
pLumaParams->bDNDITopFirst = pRenderData->bTFF;
}
VeboxSetFMDParams(pLumaParams);
VeboxPopulateDNDIParams(
pLumaParams,
pChromaParams);
finish:
return eStatus;
}
//!
//! \brief Flush command buffer for update kernels
//! \details Flush the command buffer for Update kernels
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxFlushUpdateStateCmdBuffer()
{
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PRENDERHAL_STATE_HEAP pStateHeap = nullptr;
MhwRenderInterface *pMhwRender = nullptr;
PMOS_INTERFACE pOsInterface = nullptr;
MOS_COMMAND_BUFFER CmdBuffer = {};
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t i = 0, iRemaining = 0;
PMHW_MI_INTERFACE pMhwMiInterface = nullptr;
MHW_MEDIA_OBJECT_PARAMS MediaObjectParams = {};
MEDIA_OBJECT_KA2_INLINE_DATA InlineData = {};
int32_t iInlineSize = 0;
MHW_PIPE_CONTROL_PARAMS PipeCtlParams = {};
MHW_ID_LOAD_PARAMS IdLoadParams = {};
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MediaPerfProfiler *pPerfProfiler = nullptr;
MOS_CONTEXT *pOsContext = nullptr;
PMHW_MI_MMIOREGISTERS pMmioRegisters = nullptr;
VPHAL_RENDER_CHK_NULL(pVeboxState);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pMhwMiInterface);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pMhwRenderInterface);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pMhwRenderInterface->GetMmioRegisters());
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pOsInterface);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pOsInterface->pOsContext);
pRenderHal = pVeboxState->m_pRenderHal;
pStateHeap = pRenderHal->pStateHeap;
pMhwRender = pRenderHal->pMhwRenderInterface;
pMhwMiInterface = pRenderHal->pMhwMiInterface;
pOsInterface = pRenderHal->pOsInterface;
pPerfProfiler = pRenderHal->pPerfProfiler;
pOsContext = pOsInterface->pOsContext;
pMmioRegisters = pMhwRender->GetMmioRegisters();
iRemaining = 0;
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetCommandBuffer(pOsInterface, &CmdBuffer, 0));
// Set initial state
iRemaining = CmdBuffer.iRemaining;
HalOcaInterface::On1stLevelBBStart(CmdBuffer, *pOsContext, pOsInterface->CurrentGpuContextHandle,
*pMhwMiInterface, *pMmioRegisters);
// Add kernel info to log.
HalOcaInterface::DumpVpKernelInfo(CmdBuffer, *pOsContext, kernelVeboxUpdateDnState, 0, nullptr);
// Add vphal param to log.
HalOcaInterface::DumpVphalParam(CmdBuffer, *pOsContext, pRenderHal->pVphalOcaDumper);
// Initialize command buffer and insert prolog
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnInitCommandBuffer(pRenderHal, &CmdBuffer, nullptr));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectStartCmd((void*)pRenderHal, pOsInterface, pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(NullHW::StartPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendSyncTag(pRenderHal, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pMhwRender->EnablePreemption(&CmdBuffer));
// Send Media Pipeline Select command
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddPipelineSelectCmd(
&CmdBuffer,
false));
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddStateBaseAddrCmd(
&CmdBuffer,
&pRenderHal->StateBaseAddressParams));
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendSurfaces(pRenderHal, &CmdBuffer));
VPHAL_RENDER_CHK_NULL(pRenderHal->pRenderHalPltInterface);
if(!pRenderHal->bComputeContextInUse)
{// Set VFE
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddMediaVfeCmd(
&CmdBuffer,
pRenderHal->pRenderHalPltInterface->GetVfeStateParameters()));
}
else
{// Set CFE
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddCfeStateCmd(
&CmdBuffer,
pRenderHal->pRenderHalPltInterface->GetVfeStateParameters()));
}
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendCurbeLoad(pRenderHal, &CmdBuffer));
// Send Interface Descriptor Load
MOS_ZeroMemory(&IdLoadParams, sizeof(IdLoadParams));
IdLoadParams.pKernelState = nullptr;
IdLoadParams.dwInterfaceDescriptorStartOffset = pStateHeap->pCurMediaState->dwOffset + pStateHeap->dwOffsetMediaID;
IdLoadParams.dwInterfaceDescriptorLength = pRenderHal->StateHeapSettings.iMediaIDs * pStateHeap->dwSizeMediaID;
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddMediaIDLoadCmd(&CmdBuffer, &IdLoadParams));
// Each media obj include header (no inline data is needed,
// however add 1 DW dummy inline to avoid HW Hang)
iInlineSize = 1 * sizeof(uint32_t);
InlineData = g_cInit_MEDIA_OBJECT_KA2_INLINE_DATA;
MOS_ZeroMemory(&MediaObjectParams, sizeof(MediaObjectParams));
MediaObjectParams.dwInlineDataSize = iInlineSize;
MediaObjectParams.pInlineData = &InlineData;
HalOcaInterface::OnDispatch(CmdBuffer, *pOsContext, *pMhwMiInterface, *pMmioRegisters);
#if VEBOX_AUTO_DENOISE_SUPPORTED
// Launch Interface Descriptor for DN Update kernel
if (pRenderData->bAutoDenoise)
{
MediaObjectParams.dwInterfaceDescriptorOffset = pRenderData->iMediaID0;
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddMediaObject(
&CmdBuffer,
nullptr,
&MediaObjectParams));
pVeboxState->m_currKernelId = kernelVeboxUpdateDnState;
}
#endif
VPHAL_RENDER_CHK_STATUS(VeboxFlushUpdateStateAddExtraKernels(
CmdBuffer,
MediaObjectParams));
if (GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform))
{
// Add a pipe_control and vfe to clear the media state to fix PF issue.
MHW_PIPE_CONTROL_PARAMS PipeControlParams;
MOS_ZeroMemory(&PipeControlParams, sizeof(PipeControlParams));
PipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
PipeControlParams.bGenericMediaStateClear = true;
PipeControlParams.bIndirectStatePointersDisable = true;
PipeControlParams.bDisableCSStall = false;
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddPipeControl(&CmdBuffer, nullptr, &PipeControlParams));
if (MEDIA_IS_WA(pRenderHal->pWaTable, WaSendDummyVFEafterPipelineSelect))
{
MHW_VFE_PARAMS VfeStateParams = {};
VfeStateParams.dwNumberofURBEntries = 1;
VPHAL_RENDER_CHK_STATUS(pMhwRender->AddMediaVfeCmd(&CmdBuffer, &VfeStateParams));
}
}
if (GFX_IS_GEN_8_OR_LATER(pRenderHal->Platform))
{
// Add media flush command in case HW not cleaning the media state
// On CHV A Stepping, use MSFlush with Watermark or FlushToGo
MHW_MEDIA_STATE_FLUSH_PARAM FlushParam = g_cRenderHal_InitMediaStateFlushParams;
if (MEDIA_IS_WA(pRenderHal->pWaTable, WaMSFWithNoWatermarkTSGHang))
{
FlushParam.bFlushToGo = true;
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMediaStateFlush(&CmdBuffer, nullptr, &FlushParam));
}
else if (MEDIA_IS_WA(pRenderHal->pWaTable, WaAddMediaStateFlushCmd))
{
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMediaStateFlush(&CmdBuffer, nullptr, &FlushParam));
}
}
VPHAL_RENDER_CHK_STATUS(NullHW::StopPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectEndCmd((void*)pRenderHal, pOsInterface, pRenderHal->pMhwMiInterface, &CmdBuffer));
HalOcaInterface::On1stLevelBBEnd(CmdBuffer, *pOsInterface);
if (VpHal_RndrCommonIsMiBBEndNeeded(pOsInterface))
{
// Add Batch Buffer end command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
finish:
if (nullptr == CmdBuffer.pCmdBase || nullptr == pOsInterface)
{
return eStatus;
}
// Failed -> discard all changes in Command Buffer
if (eStatus != MOS_STATUS_SUCCESS)
{
// Buffer overflow - display overflow size
if (CmdBuffer.iRemaining < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("Command Buffer overflow by %d bytes", -CmdBuffer.iRemaining);
}
// Move command buffer back to beginning
i = iRemaining - CmdBuffer.iRemaining;
CmdBuffer.iRemaining = iRemaining;
CmdBuffer.iOffset -= i;
CmdBuffer.pCmdPtr = CmdBuffer.pCmdBase + CmdBuffer.iOffset/sizeof(uint32_t);
}
// Return unused command buffer space to OS
pOsInterface->pfnReturnCommandBuffer(
pOsInterface,
&CmdBuffer,
0);
// Flush the command buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnSubmitCommandBuffer(
pOsInterface,
&CmdBuffer,
pVeboxState->bNullHwRenderDnDi));
return eStatus;
}
//!
//! \brief Vebox Copy Vebox state heap, intended for HM or IDM
//! \details Copy Vebox state heap between different memory
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxCopyVeboxStates()
{
return MOS_STATUS_SUCCESS; // no need to copy, always use driver resource in clear memory
}
//!
//! \brief Calculate offsets of statistics surface address based on the
//! functions which were enabled in the previous call,
//! and store the width and height of the per-block statistics into DNDI_STATE
//! \details
//! Layout of Statistics surface when Temporal DI enabled
//! --------------------------------------------------------------\n
//! | 16 bytes for x=0, Y=0 | 16 bytes for x=16, Y=0 | ...\n
//! |-------------------------------------------------------------\n
//! | 16 bytes for x=0, Y=4 | ...\n
//! |------------------------------\n
//! | ...\n
//! |------------------------------\n
//! | 16 bytes for x=0, Y=height-4| ...\n
//! |-----------------------------------------------Pitch----------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 0 (Previous)| 17 DW Reserved | 2 DW STD0 | 2 DW GCC0 | 11 DW Reserved |\n
//! |--------------------------------------------------------------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 0 (Current) | 11 DW FMD0 | 6 DW GNE0 | 2 DW STD0 | 2 DW GCC0 | 11 DW Reserved |\n
//! |--------------------------------------------------------------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 1 (Previous)| 17 DW Reserved | 2 DW STD1 | 2 DW GCC1 | 11 DW Reserved |\n
//! |--------------------------------------------------------------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 1 (Current) | 11 DW FMD1 | 6 DW GNE1 | 2 DW STD1 | 2 DW GCC1 | 11 DW Reserved |\n
//! ---------------------------------------------------------------------------------------------------------------\n
//!
//! Layout of Statistics surface when DN or Spatial DI enabled (and Temporal DI disabled)
//! --------------------------------------------------------------\n
//! | 16 bytes for x=0, Y=0 | 16 bytes for x=16, Y=0 | ...\n
//! |-------------------------------------------------------------\n
//! | 16 bytes for x=0, Y=4 | ...\n
//! |------------------------------\n
//! | ...\n
//! |------------------------------\n
//! | 16 bytes for x=0, Y=height-4| ...\n
//! |-----------------------------------------------Pitch----------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 0 (Input) | 11 DW FMD0 | 6 DW GNE0 | 2 DW STD0 | 2 DW GCC0 | 11 DW Reserved |\n
//! |--------------------------------------------------------------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 1 (Input) | 11 DW FMD1 | 6 DW GNE1 | 2 DW STD1 | 2 DW GCC1 | 11 DW Reserved |\n
//! ---------------------------------------------------------------------------------------------------------------\n
//!
//! Layout of Statistics surface when both DN and DI are disabled
//! ------------------------------------------------Pitch----------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 0 (Input) | 17 DW Reserved | 2 DW STD0 | 2 DW GCC0 | 11 DW Reserved |\n
//! |--------------------------------------------------------------------------------------------------------------\n
//! | 256 DW of ACE histogram Slice 1 (Input) | 17 DW Reserved | 2 DW STD1 | 2 DW GCC1 | 11 DW Reserved |\n
//! ---------------------------------------------------------------------------------------------------------------\n
//! \param [out] pStatSlice0Offset
//! Statistics surface Slice 0 base pointer
//! \param [out] pStatSlice1Offset
//! Statistics surface Slice 1 base pointer
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxGetStatisticsSurfaceOffsets(
int32_t* pStatSlice0Offset,
int32_t* pStatSlice1Offset)
{
PVPHAL_VEBOX_STATE pVeboxState = this;
uint32_t uiPitch;
int32_t iOffset;
MOS_STATUS eStatus;
eStatus = MOS_STATUS_UNKNOWN;
uiPitch = 0;
// Query platform dependent size of per frame information
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxQueryStatLayout(
VEBOX_STAT_QUERY_PER_FRAME_SIZE, &uiPitch));
// Get the base address of Frame based statistics for each slice
if (pVeboxState->bDIEnabled) // VEBOX, VEBOX+IECP
{
// Frame based statistics begins after Encoder statistics
iOffset = pVeboxState->dwVeboxPerBlockStatisticsWidth *
pVeboxState->dwVeboxPerBlockStatisticsHeight;
*pStatSlice0Offset = iOffset + uiPitch; // Slice 0 current frame
*pStatSlice1Offset = iOffset + uiPitch * 3; // Slice 1 current frame
}
else if (pVeboxState->bDNEnabled) // DN, DN_IECP, SpatialDI
{
// Frame based statistics begins after Encoder statistics
iOffset = pVeboxState->dwVeboxPerBlockStatisticsWidth *
pVeboxState->dwVeboxPerBlockStatisticsHeight;
*pStatSlice0Offset = iOffset; // Slice 0 input frame
*pStatSlice1Offset = iOffset + uiPitch; // Slice 1 input frame
}
else // IECP only
{
*pStatSlice0Offset = 0; // Slice 0 input frame
*pStatSlice1Offset = uiPitch; // Slice 1 input frame
}
finish:
return eStatus;
}
//!
//! \brief Vebox state heap update for auto mode features
//! \details Update Vebox indirect states for auto mode features
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxUpdateVeboxStates(
PVPHAL_SURFACE pSrcSurface)
{
#if VEBOX_AUTO_DENOISE_SUPPORTED
PRENDERHAL_INTERFACE pRenderHal;
PMOS_INTERFACE pOsInterface;
MOS_STATUS eStatus;
int32_t iCurbeOffsetDN;
int32_t iKrnAllocation;
MHW_KERNEL_PARAM MhwKernelParam;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
eStatus = MOS_STATUS_SUCCESS;
pRenderHal = pVeboxState->m_pRenderHal;
pOsInterface = pVeboxState->m_pOsInterface;
if (!pRenderData->bAutoDenoise)
{
// only when auto denoise is on do we need to update VEBOX states
return MOS_STATUS_SUCCESS;
}
// Switch GPU Context to Render Engine
pOsInterface->pfnSetGpuContext(pOsInterface, RenderGpuContext);
// Reset allocation list and house keeping
pOsInterface->pfnResetOsStates(pOsInterface);
// Register the resource of GSH
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));
// Set up UpdateDNState kernel
if (pRenderData->bAutoDenoise)
{
pVeboxState->SetupVeboxKernel(KERNEL_UPDATEDNSTATE);
}
//----------------------------------
// Allocate and reset media state
//----------------------------------
pRenderData->pMediaState = pRenderHal->pfnAssignMediaState(pRenderHal, RENDERHAL_COMPONENT_VEBOX);
VPHAL_RENDER_CHK_NULL(pRenderData->pMediaState);
//----------------------------------
//Allocate and reset SSH instance
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignSshInstance(pRenderHal));
//----------------------------------
// Assign and Reset Binding Table
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignBindingTable(
pRenderHal,
&pRenderData->iBindingTable));
//------------------------------------------
// Setup Surface states for DN Update kernel
//------------------------------------------
if (pRenderData->bAutoDenoise)
{
VPHAL_RENDER_CHK_STATUS(SetupSurfaceStatesForDenoise());
}
//----------------------------------
// Load static data (platform specific)
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxState->LoadUpdateDenoiseKernelStaticData(
&iCurbeOffsetDN));
//----------------------------------
// Setup VFE State params. Each Renderer MUST call pfnSetVfeStateParams().
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetVfeStateParams(
pRenderHal,
MEDIASTATE_DEBUG_COUNTER_FREE_RUNNING,
pVeboxState->pKernelParamTable[KERNEL_UPDATEDNSTATE].Thread_Count,
pRenderData->iCurbeLength,
pRenderData->iInlineLength,
nullptr));
//----------------------------------
// Load DN update kernel to GSH
//----------------------------------
if (pRenderData->bAutoDenoise)
{
INIT_MHW_KERNEL_PARAM(MhwKernelParam, &pRenderData->KernelEntry[KERNEL_UPDATEDNSTATE]);
iKrnAllocation = pRenderHal->pfnLoadKernel(
pRenderHal,
pRenderData->pKernelParam[KERNEL_UPDATEDNSTATE],
&MhwKernelParam,
nullptr);
if (iKrnAllocation < 0)
{
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
//----------------------------------
// Allocate Media ID, link to kernel
//----------------------------------
pRenderData->iMediaID0 = pRenderHal->pfnAllocateMediaID(
pRenderHal,
iKrnAllocation,
pRenderData->iBindingTable,
iCurbeOffsetDN,
pRenderData->pKernelParam[KERNEL_UPDATEDNSTATE]->CURBE_Length << 5,
0,
nullptr);
if (pRenderData->iMediaID0 < 0)
{
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
}
//---------------------------
// Render Batch Buffer (Submit commands to HW)
//---------------------------
VPHAL_RENDER_CHK_STATUS(VeboxFlushUpdateStateCmdBuffer());
finish:
return eStatus;
#else
return MOS_STATUS_SUCCESS;
#endif
}
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetupIndirectStates(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pOutSurface)
{
PMOS_INTERFACE pOsInterface = nullptr;
PMHW_VEBOX_INTERFACE pVeboxInterface = nullptr;
MOS_STATUS eStatus;
MHW_VEBOX_IECP_PARAMS VeboxIecpParams = {};
MHW_VEBOX_GAMUT_PARAMS VeboxGamutParams = {};
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pVeboxState);
VPHAL_RENDER_CHK_NULL(pSrcSurface);
pOsInterface = pVeboxState->m_pOsInterface;
pVeboxInterface = pVeboxState->m_pVeboxInterface;
VPHAL_RENDER_CHK_NULL(pOsInterface);
// Initialize structure before using
MOS_ZeroMemory(&VeboxIecpParams, sizeof(MHW_VEBOX_IECP_PARAMS));
MOS_ZeroMemory(&VeboxGamutParams, sizeof(MHW_VEBOX_GAMUT_PARAMS));
// Gamma is default to 2.2 since SDR uses 2.2
VeboxGamutParams.InputGammaValue = MHW_GAMMA_2P2;
VeboxGamutParams.OutputGammaValue = MHW_GAMMA_2P2;
//----------------------------------
// Allocate and reset VEBOX state
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AssignVeboxState());
// Set VEBOX State Params
if (pRenderData->bDeinterlace ||
pRenderData->bDenoise ||
pRenderData->bChromaDenoise)
{
VPHAL_RENDER_CHK_STATUS(VeboxSetDNDIParams(pSrcSurface));
}
if (pRenderData->GetVeboxStateParams()->pVphalVeboxDndiParams)
{
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxDndiState(
pRenderData->GetVeboxStateParams()->pVphalVeboxDndiParams));
}
// Set IECP State Params
if (pRenderData->bIECP ||
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData) ||
IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
m_IECP->SetParams(pSrcSurface, pOutSurface);
}
// Set IECP State Params
if (pRenderData->GetVeboxStateParams()->pVphalVeboxIecpParams)
{
VPHAL_RENDER_CHK_STATUS(m_IECP->InitParams(
pSrcSurface->ColorSpace,
&VeboxIecpParams));
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxIecpState(
&VeboxIecpParams));
}
// Set Gamma Parameters
if (pRenderData->bHdr3DLut)
{
VeboxGamutParams.bGammaCorr = true;
VeboxGamutParams.ColorSpace = VPHal_VpHalCspace2MhwCspace(pSrcSurface->ColorSpace);
VeboxGamutParams.InputGammaValue = MHW_GAMMA_1P0;
VeboxGamutParams.OutputGammaValue = MHW_GAMMA_1P0;
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxGamutState(
&VeboxIecpParams,
&VeboxGamutParams));
}
if (pRenderData->bBT2020TosRGB)
{
VeboxGamutParams.ColorSpace = VPHal_VpHalCspace2MhwCspace(pSrcSurface->ColorSpace);
VeboxGamutParams.dstColorSpace = VPHal_VpHalCspace2MhwCspace(pRenderData->BT2020DstColorSpace);
VeboxGamutParams.srcFormat = pSrcSurface->Format;
VeboxGamutParams.dstFormat = pOutSurface->Format;
VeboxGamutParams.GCompMode = MHW_GAMUT_MODE_NONE;
VeboxGamutParams.GExpMode = MHW_GAMUT_MODE_NONE;
VeboxGamutParams.bGammaCorr = false;
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxGamutState(
&VeboxIecpParams,
&VeboxGamutParams));
}
finish:
return eStatus;
}
//!
//! \brief Doing prepare stage tasks for VeboxSendVeboxCmd
//! Parameters might remain unchanged in case
//! \param [out] CmdBuffer
//! reference to Cmd buffer control struct
//! \param [out] GenericPrologParams
//! Generic prolog params struct to be set
//! \param [out] iRemaining
//! integer showing initial cmd buffer usage
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSendVeboxCmd_Prepare(
MOS_COMMAND_BUFFER& CmdBuffer,
RENDERHAL_GENERIC_PROLOG_PARAMS& GenericPrologParams,
int32_t& iRemaining)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PMOS_INTERFACE pOsInterface = m_pOsInterface;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
// Switch GPU context to VEBOX
pOsInterface->pfnSetGpuContext(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
// Reset allocation list and house keeping
pOsInterface->pfnResetOsStates(pOsInterface);
// initialize the command buffer struct
MOS_ZeroMemory(&CmdBuffer, sizeof(MOS_COMMAND_BUFFER));
GenericPrologParams = {};
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetCommandBuffer(pOsInterface, &CmdBuffer, 0));
// Set initial state
iRemaining = CmdBuffer.iRemaining;
//---------------------------
// Set Performance Tags
//---------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSetPerfTag(pVeboxState->m_currentSurface->Format));
pOsInterface->pfnResetPerfBufferID(pOsInterface);
pOsInterface->pfnSetPerfTag(pOsInterface, pRenderData->PerfTag);
// Linux will do nothing here since currently no frame tracking support
#ifndef EMUL
// Don't enable MediaFrame Track on Vebox if one VPBlit Still need to do compostion. It can avoid the kmd notify
// the frame be handling finished twice for one VPBLIT.
// For VE+Render colorfill case, don't enable MediaFrame Track on vebox to avoid twice notification for one VP Blt.
// We need to refactor decision code of bCompNeeded by setting bCompNeeded flag before Vebox/SFC processing in the future.
if ((pRenderData->OutputPipe != VPHAL_OUTPUT_PIPE_MODE_COMP &&
!pRenderData->pRenderTarget->bFastColorFill) &&
(pVeboxState->m_sfcPipeState != nullptr && !pVeboxState->m_sfcPipeState->m_bSFC2Pass) &&
pOsInterface->bEnableKmdMediaFrameTracking)
{
PMOS_RESOURCE gpuStatusBuffer = nullptr;
// Get GPU Status buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetGpuStatusBufferResource(pOsInterface, gpuStatusBuffer));
VPHAL_RENDER_CHK_NULL(gpuStatusBuffer);
// Register the buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(pOsInterface, gpuStatusBuffer, true, true));
GenericPrologParams.bEnableMediaFrameTracking = true;
GenericPrologParams.presMediaFrameTrackingSurface = gpuStatusBuffer;
GenericPrologParams.dwMediaFrameTrackingTag = pOsInterface->pfnGetGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
GenericPrologParams.dwMediaFrameTrackingAddrOffset = pOsInterface->pfnGetGpuStatusTagOffset(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
// Increment GPU Status Tag
pOsInterface->pfnIncrementGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
}
#endif
finish:
return eStatus;
}
//!
//! \brief Check whether the Vebox command parameters are correct
//! \param [in] VeboxStateCmdParams
//! MHW vebox state cmd params
//! \param [in] VeboxDiIecpCmdParams
//! DiIecpCmd params struct
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxIsCmdParamsValid(
const MHW_VEBOX_STATE_CMD_PARAMS &VeboxStateCmdParams,
const MHW_VEBOX_DI_IECP_CMD_PARAMS &VeboxDiIecpCmdParams,
const VPHAL_VEBOX_SURFACE_STATE_CMD_PARAMS &VeboxSurfaceStateCmdParams)
{
const MHW_VEBOX_MODE &veboxMode = VeboxStateCmdParams.VeboxMode;
if (veboxMode.DIEnable)
{
if (nullptr == VeboxDiIecpCmdParams.pOsResPrevOutput &&
(MEDIA_VEBOX_DI_OUTPUT_PREVIOUS == veboxMode.DIOutputFrames || MEDIA_VEBOX_DI_OUTPUT_BOTH == veboxMode.DIOutputFrames))
{
return MOS_STATUS_INVALID_PARAMETER;
}
if (nullptr == VeboxDiIecpCmdParams.pOsResCurrOutput &&
(MEDIA_VEBOX_DI_OUTPUT_CURRENT == veboxMode.DIOutputFrames || MEDIA_VEBOX_DI_OUTPUT_BOTH == veboxMode.DIOutputFrames))
{
return MOS_STATUS_INVALID_PARAMETER;
}
}
if (IsDNOnly())
{
VPHAL_RENDER_CHK_NULL_RETURN(VeboxSurfaceStateCmdParams.pSurfInput);
VPHAL_RENDER_CHK_NULL_RETURN(VeboxSurfaceStateCmdParams.pSurfDNOutput);
if ((VeboxSurfaceStateCmdParams.pSurfInput->TileModeGMM == VeboxSurfaceStateCmdParams.pSurfDNOutput->TileModeGMM) &&
(VeboxSurfaceStateCmdParams.pSurfInput->dwPitch != VeboxSurfaceStateCmdParams.pSurfDNOutput->dwPitch))
{
return MOS_STATUS_INVALID_PARAMETER;
}
}
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Render the Vebox Cmd buffer for VeboxSendVeboxCmd
//! Parameters might remain unchanged in case
//! \param [in,out] CmdBuffer
//! reference to Cmd buffer control struct
//! \param [out] VeboxDiIecpCmdParams
//! DiIecpCmd params struct to be set
//! \param [out] VeboxSurfaceStateCmdParams
//! VPHAL surface state cmd to be set
//! \param [out] MhwVeboxSurfaceStateCmdParams
//! MHW surface state cmd to be set
//! \param [out] VeboxStateCmdParams
//! MHW vebox state cmd to be set
//! \param [out] FlushDwParams
//! MHW MI_FLUSH_DW cmd to be set
//! \param [in] pGenericPrologParams
//! pointer to Generic prolog params struct to send to cmd buffer header
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxRenderVeboxCmd(
MOS_COMMAND_BUFFER& CmdBuffer,
MHW_VEBOX_DI_IECP_CMD_PARAMS& VeboxDiIecpCmdParams,
VPHAL_VEBOX_SURFACE_STATE_CMD_PARAMS& VeboxSurfaceStateCmdParams,
MHW_VEBOX_SURFACE_STATE_CMD_PARAMS& MhwVeboxSurfaceStateCmdParams,
MHW_VEBOX_STATE_CMD_PARAMS& VeboxStateCmdParams,
MHW_MI_FLUSH_DW_PARAMS& FlushDwParams,
PRENDERHAL_GENERIC_PROLOG_PARAMS pGenericPrologParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PMOS_INTERFACE pOsInterface = nullptr;
PMHW_MI_INTERFACE pMhwMiInterface = nullptr;
PMHW_VEBOX_INTERFACE pVeboxInterface = nullptr;
bool bDiVarianceEnable = false;
const MHW_VEBOX_HEAP *pVeboxHeap = nullptr;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MediaPerfProfiler *pPerfProfiler = nullptr;
MOS_CONTEXT *pOsContext = nullptr;
PMHW_MI_MMIOREGISTERS pMmioRegisters = nullptr;
VPHAL_RENDER_CHK_NULL(pVeboxState);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pMhwMiInterface);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pMhwMiInterface->GetMmioRegisters());
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pOsInterface);
VPHAL_RENDER_CHK_NULL(pVeboxState->m_pRenderHal->pOsInterface->pOsContext);
eStatus = MOS_STATUS_SUCCESS;
pRenderHal = pVeboxState->m_pRenderHal;
pMhwMiInterface = pRenderHal->pMhwMiInterface;
pOsInterface = pVeboxState->m_pOsInterface;
pVeboxInterface = pVeboxState->m_pVeboxInterface;
pPerfProfiler = pRenderHal->pPerfProfiler;
pOsContext = pOsInterface->pOsContext;
pMmioRegisters = pMhwMiInterface->GetMmioRegisters();
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->GetVeboxHeapInfo(
&pVeboxHeap));
VPHAL_RENDER_CHK_NULL(pVeboxHeap);
HalOcaInterface::On1stLevelBBStart(CmdBuffer, *pOsContext, pOsInterface->CurrentGpuContextHandle,
*pRenderHal->pMhwMiInterface, *pMmioRegisters);
// Add vphal param to log.
HalOcaInterface::DumpVphalParam(CmdBuffer, *pOsContext, pRenderHal->pVphalOcaDumper);
// Initialize command buffer and insert prolog
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnInitCommandBuffer(pRenderHal, &CmdBuffer, pGenericPrologParams));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectStartCmd((void*)pRenderHal, pOsInterface, pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(NullHW::StartPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
bDiVarianceEnable = pRenderData->bDeinterlace || IsQueryVarianceEnabled();
pVeboxState->SetupSurfaceStates(
bDiVarianceEnable,
&VeboxSurfaceStateCmdParams);
// Add compressible info of input/output surface to log
if( this->m_currentSurface && VeboxSurfaceStateCmdParams.pSurfOutput)
{
std::string info = "in_comps = " + std::to_string(int(this->m_currentSurface->bCompressible)) + ", out_comps = " + std::to_string(int(VeboxSurfaceStateCmdParams.pSurfOutput->bCompressible));
const char* ocaLog = info.c_str();
HalOcaInterface::TraceMessage(CmdBuffer, *pOsContext, ocaLog, info.size());
}
VPHAL_RENDER_CHK_STATUS(pVeboxState->SetupVeboxState(
bDiVarianceEnable,
&VeboxStateCmdParams));
// Ensure LACE LUT table is ready to be written
if (VeboxStateCmdParams.pLaceLookUpTables)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
VeboxStateCmdParams.pLaceLookUpTables,
MOS_GPU_CONTEXT_VEBOX,
false);
}
VPHAL_RENDER_CHK_STATUS(pVeboxState->SetupDiIecpState(
bDiVarianceEnable,
&VeboxDiIecpCmdParams));
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxIsCmdParamsValid(
VeboxStateCmdParams,
VeboxDiIecpCmdParams,
VeboxSurfaceStateCmdParams));
// Ensure output is ready to be written
if (VeboxDiIecpCmdParams.pOsResCurrOutput)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
VeboxDiIecpCmdParams.pOsResCurrOutput,
MOS_GPU_CONTEXT_VEBOX,
true);
// Synchronize overlay if overlay is used because output could be Render Target
if (VeboxSurfaceStateCmdParams.pSurfOutput &&
VeboxSurfaceStateCmdParams.pSurfOutput->bOverlay)
{
pOsInterface->pfnSyncOnOverlayResource(
pOsInterface,
VeboxDiIecpCmdParams.pOsResCurrOutput,
MOS_GPU_CONTEXT_VEBOX);
}
}
if (VeboxDiIecpCmdParams.pOsResPrevOutput)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
VeboxDiIecpCmdParams.pOsResPrevOutput,
MOS_GPU_CONTEXT_VEBOX,
true);
}
if (VeboxDiIecpCmdParams.pOsResDenoisedCurrOutput)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
VeboxDiIecpCmdParams.pOsResDenoisedCurrOutput,
MOS_GPU_CONTEXT_VEBOX,
true);
}
if (VeboxDiIecpCmdParams.pOsResStatisticsOutput)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
VeboxDiIecpCmdParams.pOsResStatisticsOutput,
MOS_GPU_CONTEXT_VEBOX,
true);
}
//---------------------------------
// Initialize Vebox Surface State Params
//---------------------------------
VPHAL_RENDER_CHK_STATUS(VpHal_InitVeboxSurfaceStateCmdParams(
&VeboxSurfaceStateCmdParams, &MhwVeboxSurfaceStateCmdParams));
//---------------------------------
// Send MMC CMD
//---------------------------------
VPHAL_RENDER_CHK_STATUS_RETURN(VeboxRenderMMCPipeCmd(
pVeboxInterface,
pMhwMiInterface,
&(MhwVeboxSurfaceStateCmdParams),
&VeboxDiIecpCmdParams,
&CmdBuffer));
//---------------------------------
// Send CMD: Vebox_State
//---------------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxState(
&CmdBuffer,
&VeboxStateCmdParams,
0));
//---------------------------------
// Send CMD: Vebox_Surface_State
//---------------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxSurfaces(
&CmdBuffer,
&MhwVeboxSurfaceStateCmdParams));
//---------------------------------
// Send CMD: SFC pipe commands
//---------------------------------
if (IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
VPHAL_RENDER_CHK_STATUS(m_sfcPipeState->SendSfcCmd(
pRenderData,
&CmdBuffer));
}
HalOcaInterface::OnDispatch(CmdBuffer, *pOsContext, *pRenderHal->pMhwMiInterface, *pMmioRegisters);
//---------------------------------
// Send CMD: Vebox_DI_IECP
//---------------------------------
VPHAL_RENDER_CHK_STATUS(pVeboxInterface->AddVeboxDiIecp(
&CmdBuffer,
&VeboxDiIecpCmdParams));
//---------------------------------
// Write GPU Status Tag for Tag based synchronization
//---------------------------------
if (!pOsInterface->bEnableKmdMediaFrameTracking)
{
VPHAL_RENDER_CHK_STATUS(VeboxSendVecsStatusTag(
pMhwMiInterface,
pOsInterface,
&CmdBuffer));
}
//---------------------------------
// Write Sync tag for Vebox Heap Synchronization
// If KMD frame tracking is on, the synchronization of Vebox Heap will use Status tag which
// is updated using KMD frame tracking.
//---------------------------------
if (!pOsInterface->bEnableKmdMediaFrameTracking)
{
MOS_ZeroMemory(&FlushDwParams, sizeof(FlushDwParams));
FlushDwParams.pOsResource = (PMOS_RESOURCE)&pVeboxHeap->DriverResource;
FlushDwParams.dwResourceOffset = pVeboxHeap->uiOffsetSync;
FlushDwParams.dwDataDW1 = pVeboxHeap->dwNextTag;
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiFlushDwCmd(
&CmdBuffer,
&FlushDwParams));
}
VPHAL_RENDER_CHK_STATUS(NullHW::StopPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectEndCmd((void*)pRenderHal, pOsInterface, pRenderHal->pMhwMiInterface, &CmdBuffer));
HalOcaInterface::On1stLevelBBEnd(CmdBuffer, *pOsInterface);
if (pOsInterface->bNoParsingAssistanceInKmd)
{
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(
&CmdBuffer,
nullptr));
}
else if (VpHal_RndrCommonIsMiBBEndNeeded(pOsInterface))
{
// Add Batch Buffer end command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(
&CmdBuffer,
nullptr));
}
VPHAL_DBG_STATE_DUMPPER_DUMP_COMMAND_BUFFER(pRenderHal, &CmdBuffer);
finish:
return eStatus;
}
//!
//! \brief Vebox send Vebox ring HW commands
//! \details Send Vebox ring Commands.
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSendVeboxCmd()
{
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PMOS_INTERFACE pOsInterface = {};
MOS_COMMAND_BUFFER CmdBuffer = {};
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t iRemaining = 0;
int32_t i = 0;
MHW_VEBOX_DI_IECP_CMD_PARAMS VeboxDiIecpCmdParams = {};
VPHAL_VEBOX_SURFACE_STATE_CMD_PARAMS VeboxSurfaceStateCmdParams = {};
MHW_VEBOX_SURFACE_STATE_CMD_PARAMS MhwVeboxSurfaceStateCmdParams = {};
MHW_VEBOX_STATE_CMD_PARAMS VeboxStateCmdParams = {};
MHW_MI_FLUSH_DW_PARAMS FlushDwParams = {};
PMHW_VEBOX_INTERFACE pVeboxInterface = {};
RENDERHAL_GENERIC_PROLOG_PARAMS GenericPrologParams = {};
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
if (pVeboxState == nullptr)
{
VPHAL_RENDER_ASSERTMESSAGE("pVeboxState not available.");
return MOS_STATUS_INVALID_PARAMETER;
}
pRenderHal = pVeboxState->m_pRenderHal;
pOsInterface = pVeboxState->m_pOsInterface;
iRemaining = 0;
pVeboxInterface = pVeboxState->m_pVeboxInterface;
if (!pRenderData) {
VPHAL_RENDER_ASSERTMESSAGE("pRenderData is NULL");
return MOS_STATUS_NULL_POINTER;
}
VPHAL_RENDER_CHK_STATUS(VeboxSendVeboxCmd_Prepare(
CmdBuffer,
GenericPrologParams,
iRemaining));
VPHAL_RENDER_CHK_STATUS(VeboxRenderVeboxCmd(
CmdBuffer,
VeboxDiIecpCmdParams,
VeboxSurfaceStateCmdParams,
MhwVeboxSurfaceStateCmdParams,
VeboxStateCmdParams,
FlushDwParams,
&GenericPrologParams));
// Return unused command buffer space to OS
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
VPHAL_RENDER_CHK_STATUS(VeboxSyncIndirectStateCmd());
VPHAL_RENDER_CHK_STATUS(VeboxSendVeboxCmdSetParamBeforeSubmit());
// Flush the command buffer
if (!bPhasedSubmission)
{
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnSubmitCommandBuffer(
pOsInterface,
&CmdBuffer,
pVeboxState->bNullHwRenderDnDi));
}
if (pVeboxState->bNullHwRenderDnDi == false)
{
pVeboxInterface->UpdateVeboxSync();
}
finish:
// Failed -> discard all changes in Command Buffer
if (eStatus != MOS_STATUS_SUCCESS)
{
// Buffer overflow - display overflow size
if (CmdBuffer.iRemaining < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("Command Buffer overflow by %d bytes", -CmdBuffer.iRemaining);
}
// Move command buffer back to beginning
i = iRemaining - CmdBuffer.iRemaining;
CmdBuffer.iRemaining = iRemaining;
CmdBuffer.iOffset -= i;
CmdBuffer.pCmdPtr = CmdBuffer.pCmdBase + CmdBuffer.iOffset/sizeof(uint32_t);
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
}
VpHal_RndrUpdateStatusTableAfterSubmit(pOsInterface, &m_StatusTableUpdateParams, MOS_GPU_CONTEXT_VEBOX, eStatus);
return eStatus;
}
//!
//! \brief Sync for Indirect state Copy and Update Kernels
//! \details Sync for Indirect state Copy and Update Kernels before Send Vebox ring Commands.
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSyncIndirectStateCmd()
{
#if VEBOX_AUTO_DENOISE_SUPPORTED
if (GetLastExecRenderData()->bAutoDenoise)
{
// Make sure copy kernel and update kernels are finished before submitting
// VEBOX commands
m_pOsInterface->pfnSyncGpuContext(
m_pOsInterface,
RenderGpuContext,
MOS_GPU_CONTEXT_VEBOX);
}
#endif
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Vebox set common rendering flag
//! \details Common flags should be set before other flags,
//! and it should be independent with other flags
//! \param [in] pSrc
//! Pointer to input surface of Vebox
//! \param [in] pRenderTarget
//! Pointer to Render targe surface of VPP BLT
//! \return void
//!
void VPHAL_VEBOX_STATE::VeboxSetCommonRenderingFlags(
PVPHAL_SURFACE pSrc,
PVPHAL_SURFACE pRenderTarget)
{
PVPHAL_SURFACE pRef;
PVPHAL_SURFACE pCurSurf;
PVPHAL_SURFACE pPrvSurf;
int32_t iSameSampleThreshold;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
if (IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState))
{
// Treat forward frame as current frame input to vebox
// and current frame as previous frame input to vebox
pRef = pSrc->pFwdRef;
pCurSurf = pRef;
pPrvSurf = pSrc;
VPHAL_RENDER_ASSERT(pRef && pSrc->uFwdRefCount > 0);
}
else
{
// In serial mode (mode0) or transition mode (mode0to2),
// treat current frame as current frame input to vebox
// and previous frame as previous frame input to vebox
// if a previous exists.
// It is valid case to have no previous frame reference
pRef = (pSrc->uBwdRefCount > 0) ? pSrc->pBwdRef : nullptr;
pCurSurf = pSrc;
pPrvSurf = pRef;
}
iSameSampleThreshold = pVeboxState->iSameSampleThreshold;
VpHal_GetScalingRatio(pSrc, pRenderTarget, &pRenderData->fScaleX, &pRenderData->fScaleY);
pRenderData->bProgressive = (pSrc->SampleType == SAMPLE_PROGRESSIVE);
pRenderData->bDenoise = (pSrc->pDenoiseParams &&
(pSrc->pDenoiseParams->bEnableLuma ||
pSrc->pDenoiseParams->bEnableSlimIPUDenoise ||
pSrc->pDenoiseParams->bEnableHVSDenoise) &&
pVeboxState->IsDnFormatSupported(pSrc));
pRenderData->bChromaDenoise = (pSrc->pDenoiseParams &&
pSrc->pDenoiseParams->bEnableChroma &&
pSrc->pDenoiseParams->bEnableLuma &&
pVeboxState->IsDnFormatSupported(pSrc));
#if VEBOX_AUTO_DENOISE_SUPPORTED
pRenderData->bAutoDenoise = (pRenderData->bDenoise &&
pSrc->pDenoiseParams &&
pSrc->pDenoiseParams->bAutoDetect &&
pVeboxState->IsDnFormatSupported(pSrc));
#endif
// Free dDenoiseParams when DN don`t support source format
// to avoid the possible using by mistake, 8 alignement for DN in renderhal
if ((!pRenderData->bDenoise) && (pSrc->pDenoiseParams != nullptr))
{
MOS_FreeMemAndSetNull(pSrc->pDenoiseParams);
}
pRenderData->bDeinterlace = (pVeboxState->IsDiFormatSupported(pSrc) &&
((pSrc->pDeinterlaceParams &&
pSrc->pDeinterlaceParams->DIMode == DI_MODE_ADI) ||
(IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData) &&
pSrc->pDeinterlaceParams &&
pSrc->pDeinterlaceParams->DIMode == DI_MODE_BOB)));
pRenderData->bRefValid = (pRef &&
(pSrc->Format == pRef->Format) &&
(pSrc->dwWidth == pRef->dwWidth) &&
(pSrc->dwHeight == pRef->dwHeight) &&
(pSrc->FrameID != pRef->FrameID) &&
(pSrc->InterlacedScalingType == ISCALING_NONE));
// Flags needs to be set if the reference sample is valid
if (pRenderData->bRefValid)
{
pRenderData->bSameSamples =
WITHIN_BOUNDS(
pCurSurf->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold) &&
WITHIN_BOUNDS(
pPrvSurf->FrameID - pVeboxState->iPrvFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
pRenderData->bOutOfBound =
OUT_OF_BOUNDS(
pPrvSurf->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
}
// bSameSamples flag also needs to be set for no reference case
else
{
pRenderData->bSameSamples =
WITHIN_BOUNDS(
pCurSurf->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
}
pVeboxState->bSameSamples = pRenderData->bSameSamples;
// Cache Render Target pointer
pRenderData->pRenderTarget = pRenderTarget;
}
//!
//! \brief Vebox set Field related rendering flag
//! \details Set Field related flags for interlaced or related features
//! \param [in] pSrc
//! Pointer to input surface of Vebox
//! \return void
//!
void VPHAL_VEBOX_STATE::VeboxSetFieldRenderingFlags(
PVPHAL_SURFACE pSrc)
{
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
// No need to check future surface for Mode2 here
// Because only current frame will change the field setting.
// And whether current blt are top or bottom field doesn't matter here
pRenderData->bTFF =
(pSrc->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD) ||
(pSrc->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD);
// Seting bTopField flag
pRenderData->bTopField =
(pSrc->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD) ||
(pSrc->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD);
}
//!
//! \brief Vebox set rendering flag
//! \details Setup Rendering Flags due to different usage case
//! \param [in] pSrc
//! Pointer to input surface of Vebox
//! \param [in] pRenderTarget
//! Pointer to Render targe surface of VPP BLT
//! \return void
//!
void VPHAL_VEBOX_STATE::VeboxSetRenderingFlags(
PVPHAL_SURFACE pSrc,
PVPHAL_SURFACE pRenderTarget)
{
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrc);
VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderTarget);
VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderData);
pRenderHal = pVeboxState->m_pRenderHal;
// VEBOX needed to be bypass for VE+COMP/SFC cases when no vebox feature.
if (MEDIA_IS_SKU(pVeboxState->GetSkuTable(), FtrDisableVEBoxFeatures) &&
!IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
pRenderData->bVeboxBypass = true;
return;
}
VeboxSetCommonRenderingFlags(pSrc, pRenderTarget);
// surface height should be a multiple of 4 when DN/DI is enabled and input format is Planar 420
if ((IS_VEBOX_SURFACE_HEIGHT_UNALIGNED(pSrc, 4)) &&
(pSrc->Format == Format_P010 ||
pSrc->Format == Format_P016 ||
pSrc->Format == Format_NV12))
{
pRenderData->bDenoise = false;
pRenderData->bDeinterlace = false;
}
// surface height should be a multiple of 2 for all format
// when Denoise is enabled and progressiveDN is disabled
if (IS_VEBOX_SURFACE_HEIGHT_UNALIGNED(pSrc, 2) &&
pRenderData->bDenoise &&
(!pRenderData->bProgressive))
{
pRenderData->bDenoise = false;
}
// Flags only needs to be set if deinterlacing is needed
if (pRenderData->bDeinterlace)
{
VeboxSetFieldRenderingFlags(pSrc);
pRenderData->bSingleField = (pRenderData->bRefValid &&
pSrc->pDeinterlaceParams->DIMode != DI_MODE_BOB) ?
pSrc->pDeinterlaceParams->bSingleField :
true;
// Detect ADI mode (30i->30fps or 30i->60fps) according to DDI
pRenderData->b60fpsDi = !pSrc->pDeinterlaceParams->bSingleField;
}
pRenderData->b2PassesCSC = VeboxIs2PassesCSCNeeded(pSrc, pRenderTarget);
pRenderData->bBT2020TosRGB = (pVeboxState->IsFormatSupported(pSrc) &&
(GFX_IS_GEN_9_OR_LATER(pVeboxState->m_pRenderHal->Platform)) &&
(IS_COLOR_SPACE_BT2020_YUV(pSrc->ColorSpace)) &&
(pRenderTarget->ColorSpace != pSrc->ColorSpace) &&
(!IS_COLOR_SPACE_BT2020_RGB(pRenderTarget->ColorSpace)));
pRenderData->BT2020DstColorSpace = pRenderTarget->ColorSpace;
// Need to refine later
// Actually, behind CSC can do nothing which is related to degamma/gamma
pRenderData->bBeCsc = (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData) &&
pSrc->ColorSpace != pRenderTarget->ColorSpace);
pRenderData->bProcamp = ((IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData) ||
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData)) &&
pSrc->pProcampParams &&
pSrc->pProcampParams->bEnabled);
pRenderData->bColorPipe = (pSrc->pColorPipeParams &&
(pSrc->pColorPipeParams->bEnableSTE ||
pSrc->pColorPipeParams->bEnableTCC));
pRenderData->bIECP = ((pSrc->pColorPipeParams &&
(pSrc->pColorPipeParams->bEnableSTE ||
pSrc->pColorPipeParams->bEnableTCC)) ||
pRenderData->bBeCsc ||
pRenderData->bProcamp);
// Vebox can be bypassed if no feature is needed
if (!(pRenderData->bDenoise ||
pRenderData->bDeinterlace ||
pRenderData->bIECP ||
pRenderData->bHdr3DLut ||
IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData)))
{
pRenderData->bVeboxBypass = true;
}
if (pSrc->pHDRParams)
{
pRenderData->bBT2020TosRGB = false;
pRenderData->b2PassesCSC = false;
// For H2S, it is possible that there is no HDR params for render target.
pRenderData->uiMaxContentLevelLum = pSrc->pHDRParams->MaxCLL;
if (pSrc->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084)
{
pRenderData->hdrMode = VPHAL_HDR_MODE_TONE_MAPPING;
if (pRenderTarget->pHDRParams)
{
pRenderData->uiMaxDisplayLum = pRenderTarget->pHDRParams->max_display_mastering_luminance;
if (pRenderTarget->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084)
{
pRenderData->hdrMode = VPHAL_HDR_MODE_H2H;
}
}
}
}
if (pSrc->p3DLutParams)
{
pRenderData->bBT2020TosRGB = false;
pRenderData->b2PassesCSC = false;
}
finish:
return;
}
//!
//! \brief Vebox initialize STMM History
//! \details Initialize STMM History surface
//! Description:
//! This function is used by VEBox for initializing
//! the STMM surface. The STMM / Denoise history is a custom surface used
//! for both input and output. Each cache line contains data for 4 4x4s.
//! The STMM for each 4x4 is 8 bytes, while the denoise history is 1 byte
//! and the chroma denoise history is 1 byte for each U and V.
//! Byte Data\n
//! 0 STMM for 2 luma values at luma Y=0, X=0 to 1\n
//! 1 STMM for 2 luma values at luma Y=0, X=2 to 3\n
//! 2 Luma Denoise History for 4x4 at 0,0\n
//! 3 Not Used\n
//! 4-5 STMM for luma from X=4 to 7\n
//! 6 Luma Denoise History for 4x4 at 0,4\n
//! 7 Not Used\n
//! 8-15 Repeat for 4x4s at 0,8 and 0,12\n
//! 16 STMM for 2 luma values at luma Y=1,X=0 to 1\n
//! 17 STMM for 2 luma values at luma Y=1, X=2 to 3\n
//! 18 U Chroma Denoise History\n
//! 19 Not Used\n
//! 20-31 Repeat for 3 4x4s at 1,4, 1,8 and 1,12\n
//! 32 STMM for 2 luma values at luma Y=2,X=0 to 1\n
//! 33 STMM for 2 luma values at luma Y=2, X=2 to 3\n
//! 34 V Chroma Denoise History\n
//! 35 Not Used\n
//! 36-47 Repeat for 3 4x4s at 2,4, 2,8 and 2,12\n
//! 48 STMM for 2 luma values at luma Y=3,X=0 to 1\n
//! 49 STMM for 2 luma values at luma Y=3, X=2 to 3\n
//! 50-51 Not Used\n
//! 36-47 Repeat for 3 4x4s at 3,4, 3,8 and 3,12\n
//! \param [in] iSurfaceIndex
//! Index of STMM surface array
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxInitSTMMHistory(
int32_t iSurfaceIndex)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface;
uint32_t dwSize;
int32_t x, y;
uint8_t* pByte;
MOS_LOCK_PARAMS LockFlags;
PVPHAL_VEBOX_STATE pVeboxState = this;
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pVeboxState->m_pOsInterface;
MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
LockFlags.WriteOnly = 1;
LockFlags.TiledAsTiled = 1; // Set TiledAsTiled flag for STMM surface initialization.
// Lock the surface for writing
pByte = (uint8_t*)pOsInterface->pfnLockResource(
pOsInterface,
&(pVeboxState->STMMSurfaces[iSurfaceIndex].OsResource),
&LockFlags);
VPHAL_RENDER_CHK_NULL(pByte);
dwSize = pVeboxState->STMMSurfaces[iSurfaceIndex].dwWidth >> 2;
// Fill STMM surface with DN history init values.
for (y = 0; y < (int32_t)pVeboxState->STMMSurfaces[iSurfaceIndex].dwHeight; y++)
{
for (x = 0; x < (int32_t)dwSize; x++)
{
MOS_FillMemory(pByte, 2, DNDI_HISTORY_INITVALUE);
// skip denosie history init.
pByte += 4;
}
pByte += pVeboxState->STMMSurfaces[iSurfaceIndex].dwPitch - pVeboxState->STMMSurfaces[iSurfaceIndex].dwWidth;
}
// Unlock the surface
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnUnlockResource(
pOsInterface,
&(pVeboxState->STMMSurfaces[iSurfaceIndex].OsResource)));
finish:
return eStatus;
}
#if VEBOX_AUTO_DENOISE_SUPPORTED
//!
//! \brief Vebox initialize Spatial Configuration Surface
//! \details Initialize Spatial Configuration surface
//! Description:
//! This function is used by VEBox for initializing
//! the Spatial Attributes Configuration surface.
//! The GEN9+ DN kernel will use the init data in this surface and write back output data
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxInitSpatialAttributesConfiguration()
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface;
VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION *pSpatialAttributesConfiguration;
MOS_LOCK_PARAMS LockFlags;
PVPHAL_VEBOX_STATE pVeboxState = this;
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pVeboxState->m_pOsInterface;
MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
LockFlags.WriteOnly = 1;
// Lock the surface for writing
pSpatialAttributesConfiguration = (VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION*)pOsInterface->pfnLockResource(
pOsInterface,
&(pVeboxState->VeboxSpatialAttributesConfigurationSurface.OsResource),
&LockFlags);
VPHAL_RENDER_CHK_NULL(pSpatialAttributesConfiguration);
*pSpatialAttributesConfiguration = g_cInit_VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION;
// Unlock the surface
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnUnlockResource(
pOsInterface,
&(pVeboxState->VeboxSpatialAttributesConfigurationSurface.OsResource)));
finish:
return eStatus;
}
#endif
//!
//! \brief Update Vebox Execution State for Vebox/Render parallelism
//! \details
//! Purpose : Handle Vebox execution state machine transitions
//!
//! Mode0: Enter or stay in this state as long has (a) there are no future
//! frames present or (b) FRC is active. Parallel execution is
//! handled different in FRC mode. (c) Vebox/SFC output path is
//! applied. Parallel execution is not needed when it is Vebox/SFC
//! to output. Mode0 is considered the legacy serial vebox execution mode.
//! Mode0To2: Enter this state when a future frame becomes present. In this
//! state, perform a one time start up sequence in order to transistion
//! to Mode2 parallel execution state.
//! Mode2: Enter this state as long a future frame is present. This is the
//! steady parallel execution state where we process 1 frame ahead.
//! i.e. On BLT(N), we do vebox on the future frame N+1 and composite
//! frame N in the same BLT().
//! Mode2To0: Enter this state when in Mode2 and no future frame is present.
//! Transition back to Mode0.
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \param [in] OutputPipe
//! The output path the driver uses to write the RenderTarget
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::UpdateVeboxExecutionState(
PVPHAL_SURFACE pSrcSurface,
VPHAL_OUTPUT_PIPE_MODE OutputPipe)
{
MOS_STATUS eStatus;
bool bSameSamples;
bool bOutOfBound;
int32_t iSameSampleThreshold;
PVPHAL_VEBOX_STATE pVeboxState = this;
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pSrcSurface);
eStatus = MOS_STATUS_SUCCESS;
bSameSamples = false;
bOutOfBound = false;
iSameSampleThreshold = pVeboxState->iSameSampleThreshold;;
if (IS_VEBOX_EXECUTION_MODE_PARALLEL_CAPABLE(pVeboxState->m_pVeboxExecState))
{
if ((pVeboxState->m_pVeboxExecState->bFrcActive) ||
(OutputPipe != VPHAL_OUTPUT_PIPE_MODE_COMP))
{
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_0);
}
else if (pSrcSurface->uFwdRefCount == 0)
{
// Transition Mode2 to Mode0
if (IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState))
{
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_2_TO_0);
// In the following case
// Blt# Bwd Curr Fwd Field bSameSample
// ----------------------------------------------------------
// Blt0 F1 F2 F3 Top false
// Blt1 F2 F3 nullptr Bot true -> No render
// Driver will still output last blt result through the SameSample flow.
// Since mode 2 has already toggled the output pair,
// we need to toggle the output pair back.
// For other cases that introduce new render, RenderMode0() will reset the outputpair.
pVeboxState->m_pVeboxExecState->bDIOutputPair01 = !pVeboxState->m_pVeboxExecState->bDIOutputPair01;
if (IS_VEBOX_EXECUTION_MODE_2_TO_0(pVeboxState->m_pVeboxExecState))
{
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_0);
}
}
else // Steady Mode0 state
{
VPHAL_RENDER_ASSERT(
IS_VEBOX_EXECUTION_MODE_0(pVeboxState->m_pVeboxExecState) ||
IS_VEBOX_EXECUTION_MODE_2_TO_0(pVeboxState->m_pVeboxExecState));
}
}
else // Future Frame present
{
// Transition Mode0 to Mode2
if (IS_VEBOX_EXECUTION_MODE_0(pVeboxState->m_pVeboxExecState))
{
// Raise the FFDI surface number for mode 2 use.
pVeboxState->iNumFFDISurfaces = 4;
// When previous blt is Mode0,
// pVeboxState->iCurFrameID are previous blt's current frame
// pVeboxState->iPrvFrameID are previous blt's bwd frame
bSameSamples =
(pSrcSurface->uBwdRefCount > 0 && pSrcSurface->pBwdRef) &&
WITHIN_BOUNDS(
pSrcSurface->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold) &&
WITHIN_BOUNDS(
pSrcSurface->pBwdRef->FrameID - pVeboxState->iPrvFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
bOutOfBound =
(pSrcSurface->uBwdRefCount > 0 && pSrcSurface->pBwdRef) &&
OUT_OF_BOUNDS(
pSrcSurface->pBwdRef->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
// Only switch to mode 2 for non-SameSample, non-frame repeat,
// and non-frame drop case.
// The case we want to switch mode are marked OK in this table:
// bSameSamples bOutOfBound Switch Note
// ----------------------------------------------------------
// true true NG Same Sample / Frame Repeat
// true false NG Self-reference frame Repeat
// false true NG Frame Drop
// false false OK Normal case
//
// 1. SameSample case in interlaced mode. Already has sample
// for output and will not do new render, and thus no way
// to switch to mode 2. Switch to Mode0To2 now will stuck
// in the state forever.
// One example that causing the issue:
// Blt# Bwd Curr Fwd Field bSameSamples
// ----------------------------------------------------------
// Blt0 F1 F2 nullptr Top false
// Blt1 F1 F2 F3 Bot true -> No render
// 2. Frame Reapt case in both progressive/interlaced modes.
// Future frame might stay future for a while and not in use
// as next blt's current.
// And, in mode 2 driver will output the previous blt's future frame.
// In repeating frame scene it is not expected to do so.
// Keep in mode 0 until new frames are received.
// 3. Frame-drop case, the player or hw resource might not
// rich enough yet, another frame drop might occur immediately.
// To help smooth playback, only switch to mode2 when the player
// can provide consecutive two blts without frame drop.
if (!bSameSamples && !bOutOfBound)
{
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_0_TO_2);
}
}
else // Steady Mode2 state
{
VPHAL_RENDER_ASSERT(
IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState) ||
IS_VEBOX_EXECUTION_MODE_0_TO_2(pVeboxState->m_pVeboxExecState));
VPHAL_RENDER_ASSERT(pSrcSurface->pFwdRef);
// When previous blt is Mode2,
// pVeboxState->iCurFrameID are previous blt's future frame
// pVeboxState->iPrvFrameID are previous blt's current frame
bSameSamples =
WITHIN_BOUNDS(
pSrcSurface->pFwdRef->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold) &&
WITHIN_BOUNDS(
pSrcSurface->FrameID - pVeboxState->iPrvFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
bOutOfBound =
OUT_OF_BOUNDS(
pSrcSurface->FrameID - pVeboxState->iCurFrameID,
-iSameSampleThreshold,
iSameSampleThreshold);
// If previous blt's future frame are not coming as this blt's
// current frame, we cannot use the pre-rendered results.
// Two possibilities:
// Case 1: SameSameples.
// Current remains current, future remains future.
// a. For interlaced, Keep in Mode 2, can reuse the previous output.
// b. For progressive, current flow is to render with new parameters.
// Cannot stay in mode2, to avoid output the previous blt's
// future frame as current.
// Case 2: Discontinuity - hence can't reuse previous surfaces
// i.e !bSameSamples && OutOfBound.
// Nothing can be reused.
//
// Both cases can switch back to mode 0To2 for render new current frame
// as well as new future frame.
// But such abnormal condition often due to player's intended bahavior.
// It may outputing static menu, or wrong reference frame given.
// The extra render of furture frame in Mode0To2 might not be
// used in next blt.
// So switch to mode0 to save bandwidth.
// If the player can keep providing future frame without repeating
// or frame drop, we can resume to mode 2 in next blt.
if ((!bSameSamples && bOutOfBound) ||
(bSameSamples && !pSrcSurface->pDeinterlaceParams))
{
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_0);
}
}
}
}
return eStatus;
}
//!
//! \brief Copy and update vebox state
//! \details Copy and update vebox state for input frame.
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxCopyAndUpdateVeboxState(
PVPHAL_SURFACE pSrcSurface)
{
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pRenderData);
VPHAL_RENDER_ASSERT(pSrcSurface);
// Setup VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSetupIndirectStates(
pSrcSurface,
IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData) ?
pRenderData->pRenderTarget :
pVeboxState->FFDISurfaces[0]));
// Copy VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyVeboxStates());
// Update VEBOX State
VPHAL_RENDER_CHK_STATUS(VeboxUpdateVeboxStates(pSrcSurface));
finish:
return eStatus;
}
//!
//! \brief Vebox render mode2
//! \details VEBOX/IECP Rendering for future frame
//! [Flow] 1. For future frame; send cmd.
//! 2. setup state for next vebox operation.
//! 3. Request "speculative" copy state, update state.
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \param [in] pOutputSurface
//! Pointer to output surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxRenderMode2(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pOutputSurface)
{
PMOS_INTERFACE pOsInterface;
PVPHAL_SURFACE pRefSurface;
MOS_STATUS eStatus;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MOS_UNUSED(pOutputSurface);
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pRenderData);
VPHAL_RENDER_ASSERT(pSrcSurface);
VPHAL_RENDER_ASSERT(pOutputSurface);
VPHAL_RENDER_ASSERT((IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState) == true));
// Initialize Variables
pOsInterface = pVeboxState->m_pOsInterface;
eStatus = MOS_STATUS_SUCCESS;
// Ensure the input is ready to be read
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
if (pRenderData->bRefValid)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->pFwdRef->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
}
// Set up reference surfaces. Should pick up future frame
pRefSurface = VeboxSetReference(pSrcSurface);
// Set current DN output buffer
pRenderData->iCurDNOut = pVeboxState->iCurDNIndex;
// Set the FMD output frames
if (pVeboxState->m_pVeboxExecState->bDIOutputPair01 == true)
{
pRenderData->iFrame0 = 0;
pRenderData->iFrame1 = 1;
pVeboxState->m_pVeboxExecState->bDIOutputPair01 = false;
}
else
{
pRenderData->iFrame0 = 2;
pRenderData->iFrame1 = 3;
pVeboxState->m_pVeboxExecState->bDIOutputPair01 = true;
}
// Setup Motion history for DI
// for ffDI, ffDN and ffDNDI cases
pRenderData->iCurHistIn = (pVeboxState->iCurStmmIndex) & 1;
pRenderData->iCurHistOut = (pVeboxState->iCurStmmIndex + 1) & 1;
// Set current frame. Previous frame is set in VeboxSetReference()
CopySurfaceValue(pVeboxState->m_currentSurface, pSrcSurface->pFwdRef);
// Set current/previous timestamps for next call
pVeboxState->iCurFrameID = pSrcSurface->pFwdRef->FrameID;
pVeboxState->iPrvFrameID = pSrcSurface->FrameID;
// Allocate Resources if needed
VPHAL_RENDER_CHK_STATUS(pVeboxState->AllocateResources());
// For CP HM which requires to use render engine for copy and
// update Vebox heap, speculative copy has already been done in previous
// blt call to increase the Vebox & Render engine parallelism.
// For LM, CPU can lock & update the resource quickly here because
// previous blt's Vebox workload should be already done.
// Thus, here we do the copy & update only for LM.
if (!pOsInterface->osCpInterface->IsHMEnabled())
{
// Setup, Copy and Update VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyAndUpdateVeboxState(pSrcSurface));
}
// Send VEBOX Command Buffer
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSendVeboxCmd());
#if 0
// FMD Calc extra variances has been moved to after composition
// to prevent blocking Vebox / Composition parallelism.
REQUEST_VEBOX_POSTPONED_FMD_CALC(pVeboxState->m_pVeboxExecState);
#endif
//--------------------------------------------------------------------------
// ffDN and ffDNDI cases
//--------------------------------------------------------------------------
if (pRenderData->bDenoise)
{
CopySurfaceValue(pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[pRenderData->iCurDNOut]);
}
//--------------------------------------------------------------------------
// Swap buffers for next iteration
//--------------------------------------------------------------------------
pVeboxState->iCurDNIndex = (pRenderData->iCurDNOut + 1) & 1;
pVeboxState->iCurStmmIndex = (pVeboxState->iCurStmmIndex + 1) & 1;
finish:
return eStatus;
}
//!
//! \brief Vebox render mode0to2
//! \details Purpose : VEBOX/IECP Rendering for current and future frame
//! [Flow] 1. For current frame; setup state, copy state, update state, send cmd.
//! 2. For future frame; setup state, copy state, update state, send cmd.
//! 3. setup state for next vebox operation.
//! 4. Request "speculative" copy state, update state.
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \param [in] pOutputSurface
//! Pointer to output surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxRenderMode0To2(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pOutputSurface)
{
PMOS_INTERFACE pOsInterface;
PVPHAL_SURFACE pRefSurface;
MOS_STATUS eStatus;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MOS_UNUSED(pOutputSurface);
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pRenderData);
VPHAL_RENDER_ASSERT(pSrcSurface);
VPHAL_RENDER_ASSERT(pOutputSurface);
VPHAL_RENDER_ASSERT((IS_VEBOX_EXECUTION_MODE_0_TO_2(pVeboxState->m_pVeboxExecState) == true));
// Initialize Variables
pOsInterface = pVeboxState->m_pOsInterface;
eStatus = MOS_STATUS_SUCCESS;
// =========================================================================
// 1st operation (frame 1 - current surface)
// =========================================================================
// Ensure the input is ready to be read
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
if (pRenderData->bRefValid)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->pBwdRef->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
}
// Set up reference surfaces
pRefSurface = VeboxSetReference(pSrcSurface);
// Set current DN output buffer
pRenderData->iCurDNOut = pVeboxState->iCurDNIndex;
// To avoid ambiguity, for Mode0To2,
// Always render 1st frame to 01 pair,
// render 2nd frame to 23 pair,
// and use 01 pair as output in mode0To2.
// No need to toggle the DIOutputPair01 flag here.
pVeboxState->m_pVeboxExecState->bDIOutputPair01 = true;
// Set the FMD output frames
pRenderData->iFrame0 = 0;
pRenderData->iFrame1 = 1;
// Setup Motion history for DI
// for ffDI, ffDN and ffDNDI cases
pRenderData->iCurHistIn = (pVeboxState->iCurStmmIndex) & 1;
pRenderData->iCurHistOut = (pVeboxState->iCurStmmIndex + 1) & 1;
// Set current src = current primary input
CopySurfaceValue(pVeboxState->m_currentSurface, pSrcSurface);
// Allocate Resources if needed
VPHAL_RENDER_CHK_STATUS(pVeboxState->AllocateResources());
// Set current/previous timestamps for next call
pVeboxState->iCurFrameID = pSrcSurface->FrameID;
if (pRenderData->bRefValid)
{
VPHAL_RENDER_CHK_NULL(pRefSurface);
pVeboxState->iPrvFrameID = pRefSurface->FrameID;
}
else
{
pVeboxState->iPrvFrameID = -1;
}
// Setup, Copy and Update VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyAndUpdateVeboxState(pSrcSurface));
// Send VEBOX Command Buffer
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSendVeboxCmd());
// Next phase synchronization with Render Engine
pOsInterface->pfnSyncGpuContext(
pOsInterface,
MOS_GPU_CONTEXT_VEBOX,
RenderGpuContext);
//--------------------------------------------------------------------------
// ffDN and ffDNDI cases
//--------------------------------------------------------------------------
if (pRenderData->bDenoise)
{
CopySurfaceValue(pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[pRenderData->iCurDNOut]);
}
//--------------------------------------------------------------------------
// Swap buffers for next iteration
//--------------------------------------------------------------------------
pVeboxState->iCurDNIndex = (pRenderData->iCurDNOut + 1) & 1;
pVeboxState->iCurStmmIndex = (pVeboxState->iCurStmmIndex + 1) & 1;
// Set the first frame flag
if (pVeboxState->bFirstFrame)
{
pVeboxState->bFirstFrame = false;
}
// End 1st operation (frame 1 - current surface)
// Switch state
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_2);
// In VpHal_VeboxGetStatisticsSurfaceOffsets, the offset of vebox statistics surface
// address is based on whether bDN/DIEnabled in the previous function call. We get
// bDN/DIEnabled here, so that bDN/DIEnabled can be used at the beginning of the next
// function call.
// When Spatial DI enabled and Temporal DI disabled, the vebox statistics surface
// layout is same as the case when only DN enabled, so use DNEnabled to include the
// case when Spatial DI enabled.
pVeboxState->bDNEnabled = pRenderData->bDenoise ||
pRenderData->bChromaDenoise ||
((pRenderData->bDeinterlace ||
pVeboxState->IsQueryVarianceEnabled()) &&
!pRenderData->bRefValid);
pVeboxState->bDIEnabled = (pRenderData->bDeinterlace ||
pVeboxState->IsQueryVarianceEnabled()) &&
pRenderData->bRefValid;
// =========================================================================
// 2nd operation (frame 2 - future surface)
// =========================================================================
// Set render flags for frame 2
pVeboxState->VeboxSetRenderingFlags(
pSrcSurface,
pRenderData->pRenderTarget);
if (pRenderData->bRefValid)
{
// Ensure the input is ready to be read
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->pFwdRef->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
}
// Set up reference surfaces.
// It set pVeboxState->PreviousSurface w/ the correct surface.
// pReference is not used.
pRefSurface = VeboxSetReference(pSrcSurface);
// Set current DN output buffer
pRenderData->iCurDNOut = pVeboxState->iCurDNIndex;
// Set the FMD output frames
pRenderData->iFrame0 = 2;
pRenderData->iFrame1 = 3;
// Setup Motion history for DI
// for ffDI, ffDN and ffDNDI cases
pRenderData->iCurHistIn = (pVeboxState->iCurStmmIndex) & 1;
pRenderData->iCurHistOut = (pVeboxState->iCurStmmIndex + 1) & 1;
// Set current frame. Previous frame is set in VeboxSetReference()
CopySurfaceValue(pVeboxState->m_currentSurface, pSrcSurface->pFwdRef);
// Set current/previous timestamps for next call
pVeboxState->iCurFrameID = pSrcSurface->pFwdRef->FrameID;
pVeboxState->iPrvFrameID = pSrcSurface->FrameID;
// Setup, Copy and Update VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyAndUpdateVeboxState(pSrcSurface));
// Send VEBOX Command Buffer
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSendVeboxCmd());
//--------------------------------------------------------------------------
// ffDN and ffDNDI cases
//--------------------------------------------------------------------------
if (pRenderData->bDenoise)
{
CopySurfaceValue(pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[pRenderData->iCurDNOut]);
}
//--------------------------------------------------------------------------
// Swap buffers for next iteration
//--------------------------------------------------------------------------
pVeboxState->iCurDNIndex = (pRenderData->iCurDNOut + 1) & 1;
pVeboxState->iCurStmmIndex = (pVeboxState->iCurStmmIndex + 1) & 1;
// End 2nd operation (frame 2 - future surface)
finish:
return eStatus;
}
//!
//! \brief Check whether DN surface limitation is satisfied
//! \param [in] bDenoise
//! Flag to indicate whether DN is enabled
//! \param [in] CurrentSurface
//! Input surface of Vebox
//! \param [in] FFDNSurface
//! DN surface of Vebox
//! \return bool
//! Return true for limitation satisfied, otherwise false
//!
bool VPHAL_VEBOX_STATE::VeboxDNSurfaceLimitationSatisfied(
bool bDenoise,
VPHAL_SURFACE *CurrentSurface,
VPHAL_SURFACE *FFDNSurface)
{
if (bDenoise == false)
{
return true;
}
else
{
if (CurrentSurface->bIsCompressed == FFDNSurface->bIsCompressed &&
CurrentSurface->bCompressible == FFDNSurface->bCompressible &&
CurrentSurface->CompressionMode == FFDNSurface->CompressionMode &&
CurrentSurface->dwWidth == FFDNSurface->dwWidth &&
CurrentSurface->dwHeight == FFDNSurface->dwHeight &&
CurrentSurface->dwPitch == FFDNSurface->dwPitch)
{
return true;
}
else
{
return false;
}
}
}
//!
//! \brief Vebox Render mode0
//! \details VEBOX/IECP Rendering for current frame
//! [Flow] 1. For current frame; setup state, copy state, update state, send cmd.
//! \param [in] pSrcSurface
//! Pointer to input surface of Vebox
//! \param [in] pOutputSurface
//! Pointer to output surface of Vebox
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::VeboxRenderMode0(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pOutputSurface)
{
PMOS_INTERFACE pOsInterface;
PVPHAL_SURFACE pRefSurface;
MOS_STATUS eStatus;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pRenderData);
VPHAL_RENDER_ASSERT(pSrcSurface);
VPHAL_RENDER_ASSERT(pOutputSurface);
VPHAL_RENDER_ASSERT((IS_VEBOX_EXECUTION_MODE_0(pVeboxState->m_pVeboxExecState) == true));
// Initialize Variables
pOsInterface = pVeboxState->m_pOsInterface;
eStatus = MOS_STATUS_SUCCESS;
// Ensure the input is ready to be read
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
if (pRenderData->bRefValid)
{
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pSrcSurface->pBwdRef->OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
}
// Set up reference surfaces
pRefSurface = VeboxSetReference(pSrcSurface);
if (pSrcSurface->bPreAPGWorkloadEnable && pRefSurface != nullptr)
{
pRefSurface->bPreAPGWorkloadEnable = false;
pRenderData->bRefValid = false;
MOS_ZeroMemory(m_previousSurface, sizeof(VPHAL_SURFACE));
}
// Set current DN output buffer
pRenderData->iCurDNOut = pVeboxState->iCurDNIndex;
// Set the FMD output frames
pRenderData->iFrame0 = 0;
pRenderData->iFrame1 = 1;
// Always use 01 pair in mode0. In Mode2, may fall back to Mode0 so need to reset.
pVeboxState->m_pVeboxExecState->bDIOutputPair01 = true;
// Setup Motion history for DI
// for ffDI, ffDN and ffDNDI cases
pRenderData->iCurHistIn = (pVeboxState->iCurStmmIndex) & 1;
pRenderData->iCurHistOut = (pVeboxState->iCurStmmIndex + 1) & 1;
// Set current src = current primary input
CopySurfaceValue(pVeboxState->m_currentSurface, pSrcSurface);
// Set current/previous timestamps for next call
// If DN surface limitation is not satisfied, e.g. input uncompressed, DN compressed, then need to re-allocate DN surfaces.
// When rcMaxSrc changed we should call AllocateResources to increase Statistics buffer size.
if (pRenderData->bSameSamples &&
!pVeboxState->m_currentSurface->bMaxRectChanged &&
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData) &&
VeboxDNSurfaceLimitationSatisfied(pRenderData->bDenoise, pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[0]))
{
// Do nothing when VEBOX+SFC scenario's BLT2 case hits here
}
else
{
// Allocate Resources if needed
VPHAL_RENDER_CHK_STATUS(pVeboxState->AllocateResources());
pVeboxState->iCurFrameID = pSrcSurface->FrameID;
}
if (pRenderData->bRefValid)
{
VPHAL_RENDER_CHK_NULL(pRefSurface);
pVeboxState->iPrvFrameID = pRefSurface->FrameID;
}
else
{
if (pRenderData->bSameSamples &&
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
// Do nothing when VEBOX+SFC scenario's BLT2 case hits here
}
else
{
pVeboxState->iPrvFrameID = -1;
}
}
// Setup, Copy and Update VEBOX State
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyAndUpdateVeboxState(pSrcSurface));
// Setup SFC State if SFC is needed for current rendering
if (IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
m_sfcPipeState->SetStereoChannel(pVeboxState->uiCurrentChannel);
VPHAL_RENDER_CHK_STATUS(m_sfcPipeState->SetupSfcState(
pSrcSurface,
pOutputSurface,
pRenderData));
}
// Send VEBOX Command Buffer
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxSendVeboxCmd());
//--------------------------------------------------------------------------
// ffDN and ffDNDI cases
//--------------------------------------------------------------------------
if (pRenderData->bDenoise)
{
CopySurfaceValue(pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[pRenderData->iCurDNOut]);
}
if ((pRenderData->bDeinterlace ||
!pRenderData->bRefValid) &&
pRenderData->bSameSamples &&
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
CopySurfaceValue(pVeboxState->m_currentSurface, pVeboxState->FFDNSurfaces[(pRenderData->iCurDNOut + 1) & 1]);
}
else
{
//--------------------------------------------------------------------------
// Swap buffers for next iteration
//--------------------------------------------------------------------------
pVeboxState->iCurDNIndex = (pRenderData->iCurDNOut + 1) & 1;
pVeboxState->iCurStmmIndex = (pVeboxState->iCurStmmIndex + 1) & 1;
}
// Set the first frame flag
if (pVeboxState->bFirstFrame)
{
pVeboxState->bFirstFrame = false;
}
finish:
return eStatus;
}
PVPHAL_SURFACE VPHAL_VEBOX_STATE::GetOutputSurfForDiSameSampleWithSFC(
PVPHAL_SURFACE pSrcSurface)
{
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = pVeboxState->GetLastExecRenderData();
PVPHAL_SURFACE pOutputSurface = pSrcSurface;
// Update rect sizes in FFDI surface if input surface rect size changes
if (pSrcSurface->rcSrc.left != pVeboxState->FFDISurfaces[0]->rcSrc.left ||
pSrcSurface->rcSrc.right != pVeboxState->FFDISurfaces[0]->rcSrc.right ||
pSrcSurface->rcSrc.top != pVeboxState->FFDISurfaces[0]->rcSrc.top ||
pSrcSurface->rcSrc.bottom != pVeboxState->FFDISurfaces[0]->rcSrc.bottom ||
pSrcSurface->rcDst.left != pVeboxState->FFDISurfaces[0]->rcDst.left ||
pSrcSurface->rcDst.right != pVeboxState->FFDISurfaces[0]->rcDst.right ||
pSrcSurface->rcDst.top != pVeboxState->FFDISurfaces[0]->rcDst.top ||
pSrcSurface->rcDst.bottom != pVeboxState->FFDISurfaces[0]->rcDst.bottom ||
pSrcSurface->rcMaxSrc.left != pVeboxState->FFDISurfaces[0]->rcMaxSrc.left ||
pSrcSurface->rcMaxSrc.right != pVeboxState->FFDISurfaces[0]->rcMaxSrc.right ||
pSrcSurface->rcMaxSrc.top != pVeboxState->FFDISurfaces[0]->rcMaxSrc.top ||
pSrcSurface->rcMaxSrc.bottom != pVeboxState->FFDISurfaces[0]->rcMaxSrc.bottom)
{
pVeboxState->FFDISurfaces[0]->rcSrc = pSrcSurface->rcSrc;
pVeboxState->FFDISurfaces[0]->rcDst = pSrcSurface->rcDst;
pVeboxState->FFDISurfaces[0]->rcMaxSrc = pSrcSurface->rcMaxSrc;
}
if (pSrcSurface->rcSrc.left != pVeboxState->FFDISurfaces[1]->rcSrc.left ||
pSrcSurface->rcSrc.right != pVeboxState->FFDISurfaces[1]->rcSrc.right ||
pSrcSurface->rcSrc.top != pVeboxState->FFDISurfaces[1]->rcSrc.top ||
pSrcSurface->rcSrc.bottom != pVeboxState->FFDISurfaces[1]->rcSrc.bottom ||
pSrcSurface->rcDst.left != pVeboxState->FFDISurfaces[1]->rcDst.left ||
pSrcSurface->rcDst.right != pVeboxState->FFDISurfaces[1]->rcDst.right ||
pSrcSurface->rcDst.top != pVeboxState->FFDISurfaces[1]->rcDst.top ||
pSrcSurface->rcDst.bottom != pVeboxState->FFDISurfaces[1]->rcDst.bottom ||
pSrcSurface->rcMaxSrc.left != pVeboxState->FFDISurfaces[1]->rcMaxSrc.left ||
pSrcSurface->rcMaxSrc.right != pVeboxState->FFDISurfaces[1]->rcMaxSrc.right ||
pSrcSurface->rcMaxSrc.top != pVeboxState->FFDISurfaces[1]->rcMaxSrc.top ||
pSrcSurface->rcMaxSrc.bottom != pVeboxState->FFDISurfaces[1]->rcMaxSrc.bottom)
{
pVeboxState->FFDISurfaces[1]->rcSrc = pSrcSurface->rcSrc;
pVeboxState->FFDISurfaces[1]->rcDst = pSrcSurface->rcDst;
pVeboxState->FFDISurfaces[1]->rcMaxSrc = pSrcSurface->rcMaxSrc;
}
// Update IEF parameters in FFDI surface
pVeboxState->FFDISurfaces[0]->pIEFParams = pSrcSurface->pIEFParams;
pVeboxState->FFDISurfaces[1]->pIEFParams = pSrcSurface->pIEFParams;
// Set BLT1's Current DI Output as BLT2's input, it is always under Mode0
// BLT1 output 1st field of current frame for the following cases:
// a) 30fps (bSingleField),
// c) 60fps 2nd field
if (pRenderData->bSingleField ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_SINGLE_BOTTOM_FIELD) ||
(pSrcSurface->SampleType == SAMPLE_PROGRESSIVE))
{
pOutputSurface = pVeboxState->FFDISurfaces[1];
}
else
{
// First sample output - 2nd field of the previous frame
pOutputSurface = pVeboxState->FFDISurfaces[0];
}
// Force vebox to bypass data on BLT2
pRenderData->bDeinterlace = false;
pRenderData->bIECP = false;
pRenderData->bDenoise = false;
pRenderData->bChromaDenoise = false;
#if VEBOX_AUTO_DENOISE_SUPPORTED
pRenderData->bAutoDenoise = false;
#endif
pRenderData->bRefValid = false;
return pOutputSurface;
}
//!
//! \brief Vebox Rendering
//! \details Vebox rendering, do all the staff for Vebox process,
//! include implementation of VEBOX/IECP features,
//! execution of Vebox/Render parallelism,
//! CPU/GPU (for CP HM) path for Vebox state heap update,
//! setup input/output/statistics/STMM surface,
//! \param [in] pcRenderParams
//! Pointer to Render parameters
//! \param [in,out] pRenderPassData
//! Pointer to Render data
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::Render(
PCVPHAL_RENDER_PARAMS pcRenderParams,
RenderpassData *pRenderPassData)
{
PRENDERHAL_INTERFACE pRenderHal;
PMOS_INTERFACE pOsInterface;
MOS_STATUS eStatus;
PVPHAL_VEBOX_RENDER_DATA pRenderData;
bool bRender;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_SURFACE pSrcSurface;
PVPHAL_SURFACE pOutputSurface;
MOS_UNUSED(pcRenderParams);
pSrcSurface = pRenderPassData->pSrcSurface;
pOutputSurface = pRenderPassData->pOutSurface;
VPHAL_RENDER_ASSERT(pVeboxState);
VPHAL_RENDER_ASSERT(pSrcSurface);
VPHAL_RENDER_ASSERT(pOutputSurface);
// Initialize Variables
pRenderHal = pVeboxState->m_pRenderHal;
pOsInterface = pVeboxState->m_pOsInterface;
eStatus = MOS_STATUS_SUCCESS;
bRender = false;
pRenderData = pVeboxState->GetLastExecRenderData();
VPHAL_DBG_STATE_DUMPPER_SET_CURRENT_STAGE(VPHAL_DBG_STAGE_VEBOX);
// Check bSameSamples only when reference is avaliable, DI, Variance Query is enabled
if (pRenderData->bRefValid &&
pRenderData->bSameSamples &&
(pRenderData->bDeinterlace || pVeboxState->IsQueryVarianceEnabled()))
{
// No frames to generate -> output frames already in buffer
if (IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData) &&
pRenderData->bDeinterlace) // Vebox + SFC
{
pSrcSurface = GetOutputSurfForDiSameSampleWithSFC(pSrcSurface);
}
else
{
// Need not submit Vebox commands, jump out accordingly
goto dndi_sample_out;
}
}
if (pcRenderParams->bAPGWorkloadEnable)
{
pSrcSurface->bPreAPGWorkloadEnable = true;
pRenderData->bRefValid = false;
}
else
{
pSrcSurface->bPreAPGWorkloadEnable = false;
}
if (IS_VEBOX_EXECUTION_MODE_0_TO_2(pVeboxState->m_pVeboxExecState))
{
// Transition from serial to parallel mode. 2 vebox operations, current
// and future frames
VPHAL_RENDER_CHK_STATUS(VeboxRenderMode0To2(
pSrcSurface,
pOutputSurface));
}
else if (IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState))
{
// Parallel mode. 1 vebox operation, future frame
VPHAL_RENDER_CHK_STATUS(VeboxRenderMode2(
pSrcSurface,
pOutputSurface));
}
else if (IS_VEBOX_EXECUTION_MODE_0(pVeboxState->m_pVeboxExecState))
{
// Legacy serial mode. 1 vebox operation, current frame
VPHAL_RENDER_CHK_STATUS(VeboxRenderMode0(
pSrcSurface,
pOutputSurface));
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Invalid VEBox state.");
goto finish;
}
VPHAL_DBG_STATE_DUMPPER_DUMP_VEBOX_STATES(pRenderHal, pVeboxState);
if (IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
goto sfc_sample_out;
}
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
goto vebox_out_in_RT;
}
dndi_sample_out:
if (IS_VEBOX_EXECUTION_MODE_2(pVeboxState->m_pVeboxExecState))
{
// Select output surface that was rendered in the previous blt
// It will be used in VpHal_VeboxSetDiOutput()
// Note: After toggling it, pRenderData->iCurDNOut does not represent
// the one that is rendered this time
pRenderData->iCurDNOut = (pRenderData->iCurDNOut + 1) & 1;
}
// Select DI sample to be used for compositing stage
VPHAL_RENDER_CHK_STATUS(VeboxSetDiOutput(pSrcSurface, pOutputSurface));
VPHAL_RENDER_EXITMESSAGE("Exit with DI output.");
goto finish;
sfc_sample_out:
if (pVeboxState->m_pVeboxExecState->bDIOutputPair01)
{
pRenderData->iFrame0 = pRenderData->bSameSamples ? 1 : 0;
}
else
{
pRenderData->iFrame0 = pRenderData->bSameSamples ? 3 : 2;
}
// Feature reporting
m_reporting->IECP = pRenderData->bIECP;
m_reporting->Denoise = pRenderData->bDenoise;
if (pRenderData->bDeinterlace)
{
m_reporting->DeinterlaceMode =
(pRenderData->bSingleField &&
(!pRenderData->bRefValid ||
pSrcSurface->pDeinterlaceParams->DIMode == DI_MODE_BOB)) ?
VPHAL_DI_REPORT_ADI_BOB : // VEBOX BOB
VPHAL_DI_REPORT_ADI; // ADI
}
// Select SFC output
VPHAL_RENDER_EXITMESSAGE("Exit with SFC output.");
goto finish;
vebox_out_in_RT:
VPHAL_RENDER_EXITMESSAGE("Exit VEBOX with CSC output.");
finish:
// In VpHal_VeboxGetStatisticsSurfaceOffsets, the offset of vebox statistics surface
// address is based on whether bDN/DIEnabled in the previous function call. We get
// bDN/DIEnabled here, so that bDN/DIEnabled can be used at the beginning of the next
// function call.
// When Spatial DI enabled and Temporal DI disabled, the vebox statistics surface
// layout is same as the case when only DN enabled, so use DNEnabled to include the
// case when Spatial DI enabled.
if (pRenderData->bSameSamples &&
IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData))
{
// Do nothing when VEBOX+SFC scenario's BLT2 case hits here
}
else
{
pVeboxState->bDNEnabled = pRenderData->bDenoise ||
pRenderData->bChromaDenoise ||
((pRenderData->bDeinterlace ||
pVeboxState->IsQueryVarianceEnabled()) &&
!pRenderData->bRefValid);
pVeboxState->bDIEnabled = (pRenderData->bDeinterlace ||
pVeboxState->IsQueryVarianceEnabled()) &&
pRenderData->bRefValid;
}
// Switch GPU Context to Render Engine
pOsInterface->pfnSetGpuContext(pOsInterface, RenderGpuContext);
// Vebox feature report -- set the output pipe
if (pRenderData->b2PassesCSC)
{ //set 2passcsc outputpipe to VPHAL_OUTPUT_PIPE_MODE_COMP for final report.
SET_VPHAL_OUTPUT_PIPE(pRenderData, VPHAL_OUTPUT_PIPE_MODE_COMP);
}
m_reporting->OutputPipeMode = pRenderData->OutputPipe;
m_reporting->VEFeatureInUse = !pRenderData->bVeboxBypass;
m_reporting->DiScdMode = pRenderData->VeboxDNDIParams.bSyntheticFrame;
return eStatus;
}
//!
//! \brief Set DI output frame
//! \details Choose 2nd Field of Previous frame, 1st Field of Current frame
//! or both frames
//! \param [in] pRenderData
//! Pointer to Render data
//! \param [in] pVeboxState
//! Pointer to Vebox State
//! \param [in] pVeboxMode
//! Pointer to Vebox Mode
//! \return GFX_MEDIA_VEBOX_DI_OUTPUT_MODE
//! Return Previous/Current/Both frames
//!
GFX_MEDIA_VEBOX_DI_OUTPUT_MODE VPHAL_VEBOX_STATE::SetDIOutputFrame(
PVPHAL_VEBOX_RENDER_DATA pRenderData,
PVPHAL_VEBOX_STATE pVeboxState,
PMHW_VEBOX_MODE pVeboxMode)
{
// for 30i->30fps + SFC
if (IS_VPHAL_OUTPUT_PIPE_SFC(pRenderData) && !pRenderData->b60fpsDi)
{
// Set BLT1's Current DI Output as BLT2's input, it is always under Mode0
// BLT1 output 1st field of current frame for the following cases:
if (pVeboxMode->DNDIFirstFrame ||
(pVeboxState->m_currentSurface->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD) ||
(pVeboxState->m_currentSurface->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD) ||
(pVeboxState->m_currentSurface->SampleType == SAMPLE_SINGLE_TOP_FIELD) ||
(pVeboxState->m_currentSurface->SampleType == SAMPLE_PROGRESSIVE))
{
return MEDIA_VEBOX_DI_OUTPUT_CURRENT;
}
else
{
// First sample output - 2nd field of the previous frame
return MEDIA_VEBOX_DI_OUTPUT_PREVIOUS;
}
}
// for 30i->60fps or other 30i->30fps cases
else
{
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
// Align with the logic in SetupDiIecpState. The previous output surface is not needed for OUTPUT_PIPE_VEBOX case.
return MEDIA_VEBOX_DI_OUTPUT_CURRENT;
}
else
{
return pVeboxMode->DNDIFirstFrame ?
MEDIA_VEBOX_DI_OUTPUT_CURRENT :
MEDIA_VEBOX_DI_OUTPUT_BOTH;
}
}
}
//!
//! \brief Vebox post-composition activity for parallel engine
//! \details update Vebox state heap, and FMD extra variances
//! \param [in] pVeboxExecState
//! Pointer to Vebox execution state
//! \param [in] pPriSurface
//! Pointer to primary surface of compostion, which was processed in last Vebox call
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::PostCompRender(
PVPHAL_VEBOX_EXEC_STATE pVeboxExecState,
PVPHAL_SURFACE pPriSurface)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface;
PVPHAL_VEBOX_STATE pVeboxState = this;
VPHAL_RENDER_ASSERT(pVeboxState);
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pVeboxState->m_pOsInterface;
// In Mode0To2 or Mode2, speculatively copy vebox state information for use
// in next vebox op based on last vebox op's state info.
if (IS_VEBOX_SPECULATIVE_COPY_REQUESTED(pVeboxExecState))
{
VPHAL_RENDER_CHK_STATUS(pVeboxState->VeboxCopyAndUpdateVeboxState(
pPriSurface));
RESET_VEBOX_SPECULATIVE_COPY(pVeboxExecState);
}
finish:
return eStatus;
}
//!
//! \brief Check if 2 passes CSC are needed
//! \param [in] pSrc
//! Pointer to input surface of Vebox
//! \param [in] pRenderTarget
//! Pointer to Render targe surface of VPP BLT
//! \return bool
//! return true if 2 Passes CSC is needed, otherwise false
//!
bool VPHAL_VEBOX_STATE::VeboxIs2PassesCSCNeeded(
PVPHAL_SURFACE pSrc,
PVPHAL_SURFACE pRenderTarget)
{
bool bRet = false;
bool b2PassesCSCNeeded = false;
bool bFormatSupported = false;
bool bPlatformSupported = false;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = GetLastExecRenderData();
MOS_OS_CHK_NULL_NO_STATUS(pVeboxState);
MOS_OS_CHK_NULL_NO_STATUS(pSrc);
MOS_OS_CHK_NULL_NO_STATUS(pRenderTarget);
MOS_OS_CHK_NULL_NO_STATUS(pRenderData);
// 2 Passes CSC is used in BT2020YUV->BT601/709YUV
// Isolate decoder require SFC output, but SFC can not support RGB input,
// so sRGB need two pass, that same as original logic.
if (IS_COLOR_SPACE_BT2020_YUV(pSrc->ColorSpace))
{
if ((pRenderTarget->ColorSpace == CSpace_BT601) ||
(pRenderTarget->ColorSpace == CSpace_BT709) ||
(pRenderTarget->ColorSpace == CSpace_BT601_FullRange) ||
(pRenderTarget->ColorSpace == CSpace_BT709_FullRange) ||
(pRenderTarget->ColorSpace == CSpace_stRGB) ||
(pRenderTarget->ColorSpace == CSpace_sRGB))
{
b2PassesCSCNeeded = (pRenderData->bHdr3DLut) ? false : true;
}
}
// VEBOX support input format
bFormatSupported = pVeboxState->IsFormatSupported(pSrc);
// Platform support 2 passes CSC
bPlatformSupported = Is2PassesCscPlatformSupported();
bRet = bFormatSupported && bPlatformSupported && b2PassesCSCNeeded;
finish:
return bRet;
}
//!
//! \brief copy Report data about features
//! \details copy Report data from this render
//! \param [out] pReporting
//! pointer to the Report data to copy data to
//!
void VPHAL_VEBOX_STATE::CopyFeatureReporting(VphalFeatureReport* pReporting)
{
pReporting->IECP = m_reporting->IECP;
pReporting->Denoise = m_reporting->Denoise;
pReporting->DeinterlaceMode = m_reporting->DeinterlaceMode;
pReporting->OutputPipeMode = m_reporting->OutputPipeMode;
pReporting->VPMMCInUse = bEnableMMC;
pReporting->VEFeatureInUse = m_reporting->VEFeatureInUse;
}
//!
//! \brief copy Report data about resources
//! \details copy Report data from this render
//! \param [out] pReporting
//! pointer to the Report data to copy data to
//!
void VPHAL_VEBOX_STATE::CopyResourceReporting(VphalFeatureReport* pReporting)
{
// Report Vebox intermediate surface
pReporting->FFDICompressible = m_reporting->FFDICompressible;
pReporting->FFDICompressMode = m_reporting->FFDICompressMode;
pReporting->FFDNCompressible = m_reporting->FFDNCompressible;
pReporting->FFDNCompressMode = m_reporting->FFDNCompressMode;
pReporting->STMMCompressible = m_reporting->STMMCompressible;
pReporting->STMMCompressMode = m_reporting->STMMCompressMode;
pReporting->ScalerCompressible = m_reporting->ScalerCompressible;
pReporting->ScalerCompressMode = m_reporting->ScalerCompressMode;
pReporting->DiScdMode = m_reporting->DiScdMode;
}
//!
//! \brief copy Report data
//! \details copy Report data from this render
//! \param [out] pReporting
//! pointer to the Report data to copy data to
//!
void VPHAL_VEBOX_STATE::CopyReporting(VphalFeatureReport* pReporting)
{
VPHAL_RENDER_ASSERT(pReporting);
CopyFeatureReporting(pReporting);
CopyResourceReporting(pReporting);
}
//!
//! \brief Allocate sfc temp surface for Vebox output
//! \details Allocate sfc temp surface for Vebox output
//! \param VphalRenderer* pRenderer
//! [in,out] VPHAL renderer pointer
//! \param PCVPHAL_RENDER_PARAMS pcRenderParams
//! [in] Const pointer to VPHAL render parameter
//! \param PVPHAL_VEBOX_RENDER_DATA pRenderData
//! [in] pointer to VPHAL VEBOX render parameter
//! \param PVPHAL_SURFACE pInSurface
//! [in] Pointer to input surface
//! \param PVPHAL_SURFACE pOutSurface
//! [in] Pointer to output surface
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPHAL_VEBOX_STATE::AllocateSfcTempSurfaces(
VphalRenderer *pRenderer,
PCVPHAL_RENDER_PARAMS pcRenderParams,
PVPHAL_VEBOX_RENDER_DATA pRenderData,
PVPHAL_SURFACE pInSurface,
PVPHAL_SURFACE pOutSurface)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface;
PVPHAL_VEBOX_STATE pVeboxState;
PVPHAL_SURFACE pInSurfaceExt;
PVPHAL_SURFACE pOutSurfaceExt;
PVPHAL_SURFACE pSfcTempSurface;
bool bAllocated;
MOS_FORMAT surfaceFormat;
uint32_t dwSurfaceWidth;
uint32_t dwSurfaceHeight;
VPHAL_RENDER_CHK_NULL(pInSurface);
VPHAL_RENDER_CHK_NULL(pOutSurface);
VPHAL_RENDER_CHK_NULL(pRenderer);
VPHAL_RENDER_CHK_NULL(pcRenderParams);
VPHAL_RENDER_CHK_NULL(pRenderData);
eStatus = MOS_STATUS_SUCCESS;
dwSurfaceWidth = pOutSurface->dwWidth;
dwSurfaceHeight = pOutSurface->dwHeight;
surfaceFormat = pInSurface->Format;
eStatus = MOS_STATUS_SUCCESS;
pVeboxState = (PVPHAL_VEBOX_STATE)pRenderer->pRender[VPHAL_RENDER_ID_VEBOX + pRenderer->uiCurrentChannel];
pOsInterface = pRenderer->GetOsInterface();
pSfcTempSurface = &pVeboxState->SfcTempSurface;
// Copy rect sizes so that if input surface state needs to adjust,
// output surface can be adjustted also.
pSfcTempSurface->rcSrc = pOutSurface->rcSrc;
pSfcTempSurface->rcDst = pOutSurface->rcDst;
// Sfc intermediate surface should be Y tile for best performance meanwhile enable MMC.
VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
pOsInterface,
pSfcTempSurface,
"VeboxSfcTempSurface",
surfaceFormat,
MOS_GFXRES_2D,
MOS_TILE_Y,
dwSurfaceWidth,
dwSurfaceHeight,
true,
MOS_MMC_MC,
&bAllocated));
// Copy max src rect
pSfcTempSurface->rcMaxSrc = pOutSurface->rcMaxSrc;
pSfcTempSurface->iPalette = pOutSurface->iPalette;
pSfcTempSurface->SampleType = pOutSurface->SampleType;
pSfcTempSurface->ColorSpace = pInSurface->ColorSpace;
pSfcTempSurface->Format = surfaceFormat;
pSfcTempSurface->SurfType = pOutSurface->SurfType;
pSfcTempSurface->FrameID = pOutSurface->FrameID;
pSfcTempSurface->ScalingMode = pOutSurface->ScalingMode;
pSfcTempSurface->ChromaSiting = pOutSurface->ChromaSiting;
if (pInSurface->pLumaKeyParams)
{
if (!pSfcTempSurface->pLumaKeyParams)
{
pSfcTempSurface->pLumaKeyParams = (PVPHAL_LUMAKEY_PARAMS)MOS_AllocAndZeroMemory(sizeof(PVPHAL_LUMAKEY_PARAMS));
VPHAL_RENDER_CHK_NULL(pSfcTempSurface->pLumaKeyParams);
}
MOS_SecureMemcpy(pSfcTempSurface->pLumaKeyParams, sizeof(PVPHAL_LUMAKEY_PARAMS),
pInSurface->pLumaKeyParams, sizeof(PVPHAL_LUMAKEY_PARAMS));
}
else
{
MOS_FreeMemory(pSfcTempSurface->pLumaKeyParams);
pSfcTempSurface->pLumaKeyParams = nullptr;
}
if (pInSurface->pBlendingParams)
{
if (!pSfcTempSurface->pBlendingParams)
{
pSfcTempSurface->pBlendingParams = (PVPHAL_BLENDING_PARAMS)MOS_AllocAndZeroMemory(sizeof(VPHAL_BLENDING_PARAMS));
VPHAL_RENDER_CHK_NULL(pSfcTempSurface->pBlendingParams);
}
MOS_SecureMemcpy(pSfcTempSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS),
pInSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS));
}
else
{
MOS_FreeMemory(pSfcTempSurface->pBlendingParams);
pSfcTempSurface->pBlendingParams = nullptr;
}
finish:
return eStatus;
}
MOS_STATUS VPHAL_VEBOX_STATE::AllocateSfc2ndTempSurfaces(
VphalRenderer *pRenderer,
PCVPHAL_RENDER_PARAMS pcRenderParams,
PVPHAL_VEBOX_RENDER_DATA pRenderData,
PVPHAL_SURFACE pInSurface,
PVPHAL_SURFACE pOutSurface)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface;
PVPHAL_VEBOX_STATE pVeboxState;
PVPHAL_SURFACE pInSurfaceExt;
PVPHAL_SURFACE pOutSurfaceExt;
PVPHAL_SURFACE pSfcTempSurface;
bool bAllocated;
MOS_FORMAT surfaceFormat;
uint32_t dwSurfaceWidth;
uint32_t dwSurfaceHeight;
VPHAL_RENDER_CHK_NULL(pInSurface);
VPHAL_RENDER_CHK_NULL(pOutSurface);
VPHAL_RENDER_CHK_NULL(pRenderer);
VPHAL_RENDER_CHK_NULL(pcRenderParams);
VPHAL_RENDER_CHK_NULL(pRenderData);
eStatus = MOS_STATUS_SUCCESS;
dwSurfaceWidth = pOutSurface->dwWidth;
dwSurfaceHeight = pOutSurface->dwHeight;
surfaceFormat = pInSurface->Format;
eStatus = MOS_STATUS_SUCCESS;
pVeboxState = (PVPHAL_VEBOX_STATE)pRenderer->pRender[VPHAL_RENDER_ID_VEBOX + pRenderer->uiCurrentChannel];
pOsInterface = pRenderer->GetOsInterface();
pSfcTempSurface = &pVeboxState->Sfc2ndTempSurface;
// Copy rect sizes so that if input surface state needs to adjust,
// output surface can be adjustted also.
pSfcTempSurface->rcSrc = pOutSurface->rcSrc;
pSfcTempSurface->rcDst = pOutSurface->rcDst;
// Sfc intermediate surface should be Y tile for best performance meanwhile enable MMC.
VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
pOsInterface,
pSfcTempSurface,
"VeboxSfcTempSurface",
surfaceFormat,
MOS_GFXRES_2D,
MOS_TILE_Y,
dwSurfaceWidth,
dwSurfaceHeight,
true,
MOS_MMC_MC,
&bAllocated));
// Copy max src rect
pSfcTempSurface->rcMaxSrc = pOutSurface->rcMaxSrc;
pSfcTempSurface->iPalette = pOutSurface->iPalette;
pSfcTempSurface->SampleType = pOutSurface->SampleType;
pSfcTempSurface->ColorSpace = pInSurface->ColorSpace;
pSfcTempSurface->Format = surfaceFormat;
pSfcTempSurface->SurfType = pOutSurface->SurfType;
pSfcTempSurface->FrameID = pOutSurface->FrameID;
if (pInSurface->pLumaKeyParams)
{
if (!pSfcTempSurface->pLumaKeyParams)
{
pSfcTempSurface->pLumaKeyParams = (PVPHAL_LUMAKEY_PARAMS)MOS_AllocAndZeroMemory(sizeof(PVPHAL_LUMAKEY_PARAMS));
VPHAL_RENDER_CHK_NULL(pSfcTempSurface->pLumaKeyParams);
}
MOS_SecureMemcpy(pSfcTempSurface->pLumaKeyParams, sizeof(PVPHAL_LUMAKEY_PARAMS),
pInSurface->pLumaKeyParams, sizeof(PVPHAL_LUMAKEY_PARAMS));
}
else
{
MOS_FreeMemory(pSfcTempSurface->pLumaKeyParams);
pSfcTempSurface->pLumaKeyParams = nullptr;
}
if (pInSurface->pBlendingParams)
{
if (!pSfcTempSurface->pBlendingParams)
{
pSfcTempSurface->pBlendingParams = (PVPHAL_BLENDING_PARAMS)MOS_AllocAndZeroMemory(sizeof(VPHAL_BLENDING_PARAMS));
VPHAL_RENDER_CHK_NULL(pSfcTempSurface->pBlendingParams);
}
MOS_SecureMemcpy(pSfcTempSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS),
pInSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS));
}
else
{
MOS_FreeMemory(pSfcTempSurface->pBlendingParams);
pSfcTempSurface->pBlendingParams = nullptr;
}
finish:
return eStatus;
}
MOS_STATUS VpHal_VeboxAllocateTempSurfaces(
VphalRenderer *pRenderer,
PCVPHAL_RENDER_PARAMS pcRenderParams,
PVPHAL_VEBOX_RENDER_DATA pRenderData,
PVPHAL_SURFACE pInSurface,
PVPHAL_SURFACE pOutSurface,
PVPHAL_SURFACE pAllocatedSurface)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface = nullptr;
PVPHAL_VEBOX_STATE pVeboxState = nullptr;
bool bAllocated;
VPHAL_CSPACE surfaceColorSpace;
MOS_FORMAT surfaceFormat;
uint32_t dwSurfaceWidth;
uint32_t dwSurfaceHeight;
VPHAL_RENDER_CHK_NULL(pInSurface);
VPHAL_RENDER_CHK_NULL(pOutSurface);
VPHAL_RENDER_CHK_NULL(pRenderer);
VPHAL_RENDER_CHK_NULL(pcRenderParams);
VPHAL_RENDER_CHK_NULL(pRenderData);
pOsInterface = pRenderer->GetOsInterface();
VPHAL_RENDER_CHK_NULL(pOsInterface);
eStatus = MOS_STATUS_SUCCESS;
dwSurfaceWidth = pInSurface->dwWidth;
dwSurfaceHeight = pInSurface->dwHeight;
surfaceFormat = pOutSurface->Format;
surfaceColorSpace = pOutSurface->ColorSpace;
// Hdr intermediate surface should be Y tile for best performance
VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
pOsInterface,
pAllocatedSurface,
"VeboxHdrOutputSurface",
surfaceFormat,
MOS_GFXRES_2D,
MOS_TILE_Y,
dwSurfaceWidth,
dwSurfaceHeight,
false,
MOS_MMC_DISABLED,
&bAllocated));
VPHAL_RENDER_CHK_NULL(pAllocatedSurface);
// Copy rect sizes so that if input surface state needs to adjust,
// output surface can be adjusted also.
pAllocatedSurface->rcSrc = pInSurface->rcSrc;
pAllocatedSurface->rcDst = pInSurface->rcSrc;
pAllocatedSurface->rcMaxSrc = pInSurface->rcSrc;
pAllocatedSurface->Rotation = pInSurface->Rotation;
pAllocatedSurface->SampleType = pInSurface->SampleType;
pAllocatedSurface->ColorSpace = surfaceColorSpace;
pAllocatedSurface->Format = surfaceFormat;
pAllocatedSurface->SurfType = pInSurface->SurfType;
pAllocatedSurface->SampleType = pInSurface->SampleType;
pAllocatedSurface->ScalingMode = pInSurface->ScalingMode;
pAllocatedSurface->bIEF = pInSurface->bIEF;
pAllocatedSurface->FrameID = pInSurface->FrameID;
if (pInSurface->pBlendingParams)
{
if (!pAllocatedSurface->pBlendingParams)
{
pAllocatedSurface->pBlendingParams = (PVPHAL_BLENDING_PARAMS)MOS_AllocAndZeroMemory(sizeof(VPHAL_BLENDING_PARAMS));
VPHAL_RENDER_CHK_NULL(pAllocatedSurface->pBlendingParams);
}
MOS_SecureMemcpy(pAllocatedSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS),
pInSurface->pBlendingParams, sizeof(VPHAL_BLENDING_PARAMS));
}
else
{
MOS_FreeMemory(pAllocatedSurface->pBlendingParams);
pAllocatedSurface->pBlendingParams = nullptr;
}
if (pInSurface->pHDRParams)
{
if (!pAllocatedSurface->pHDRParams)
{
pAllocatedSurface->pHDRParams = (PVPHAL_HDR_PARAMS)MOS_AllocAndZeroMemory(sizeof(VPHAL_HDR_PARAMS));
VPHAL_RENDER_CHK_NULL(pAllocatedSurface->pHDRParams);
}
if (pOutSurface->pHDRParams)
{
MOS_SecureMemcpy(pAllocatedSurface->pHDRParams, sizeof(VPHAL_HDR_PARAMS),
pOutSurface->pHDRParams, sizeof(VPHAL_HDR_PARAMS));
}
}
else
{
MOS_FreeMemory(pAllocatedSurface->pHDRParams);
pAllocatedSurface->pHDRParams = nullptr;
}
finish:
return eStatus;
}
//!
//! \brief Perform Rendering in VEBOX
//! \details Check whether VEBOX Rendering is enabled. When it's enabled, perform VEBOX Rendering
//! on the input surface and get the output surface
//! \param [in,out] pRenderer
//! VPHAL renderer pointer
//! \param [in] pcRenderParams
//! Const pointer to VPHAL render parameter
//! \param [in,out] pRenderPassData
//! Pointer to RenderpassData structure
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_RndrRenderVebox(
VphalRenderer *pRenderer,
PCVPHAL_RENDER_PARAMS pcRenderParams,
RenderpassData *pRenderPassData)
{
MOS_STATUS eStatus;
PMOS_INTERFACE pOsInterface = nullptr;
RenderState *pRenderState = nullptr;
VphalFeatureReport* pReport = nullptr;
PVPHAL_SURFACE pOutSurface = nullptr;
PVPHAL_SURFACE pInSurface = nullptr;
RECT rcTempOut = {};
RECT rcTemp = {};
RECT rcTempIn = {};
PVPHAL_VEBOX_STATE pVeboxState = nullptr;
PVPHAL_VEBOX_RENDER_DATA pRenderData = nullptr;
bool bVeboxOutput = false;
//------------------------------------------------------
VPHAL_RENDER_ASSERT(pRenderer);
VPHAL_RENDER_ASSERT(pcRenderParams);
VPHAL_RENDER_CHK_NULL(pRenderer->GetOsInterface());
//------------------------------------------------------
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pRenderer->GetOsInterface();
pReport = pRenderer->GetReport();
pRenderState = pRenderer->pRender[VPHAL_RENDER_ID_VEBOX + pRenderer->uiCurrentChannel];
pOutSurface = pRenderPassData->GetTempOutputSurface();
pVeboxState = (PVPHAL_VEBOX_STATE)pRenderState;
pRenderData = pVeboxState->GetLastExecRenderData();
pInSurface = (PVPHAL_SURFACE)pRenderPassData->pSrcSurface;
bVeboxOutput = false;
pRenderPassData->bOutputGenerated = false;
VPHAL_RENDER_CHK_NULL(pRenderState);
VPHAL_RENDER_CHK_NULL(pVeboxState);
VPHAL_RENDER_ASSERT(pRenderState->GetRenderHalInterface());
pRenderPassData->bCompNeeded = true;
if (!pRenderState->GetRenderDisableFlag())
{
MOS_ZeroMemory(pOutSurface, sizeof(VPHAL_SURFACE));
pRenderPassData->bCompNeeded = false;
// Check if DNDI Render can be applied
if (!pRenderState->IsNeeded(
pcRenderParams,
pRenderPassData))
{
goto finish;
}
if (pRenderData->b2PassesCSC)
{ // First step of two pass CSC in vebox for Linux BT.2020 -> BT.601/709/RGB
if (!pRenderPassData->bCompNeeded)
{ //the flage is set due to VeboxIs2PassesCSCNeeded() in GetOutputPipe()
VPHAL_RENDER_ASSERTMESSAGE(" Failed to run two pass CSC in render ");
VPHAL_RENDER_CHK_STATUS(MOS_STATUS_INVALID_PARAMETER)
}
SET_VPHAL_OUTPUT_PIPE(pRenderData, VPHAL_OUTPUT_PIPE_MODE_VEBOX);
pRenderData->pRenderTarget = &pVeboxState->m_BT2020CSCTempSurface;
//set input/output for vebox
pRenderPassData->pSrcSurface = pInSurface;
pRenderPassData->pOutSurface = &pVeboxState->m_BT2020CSCTempSurface;
VPHAL_RENDER_CHK_STATUS(pVeboxState->Render(
pcRenderParams,
pRenderPassData));
pRenderPassData->b2CSCNeeded = true;
pRenderPassData->bOutputGenerated = true;
pRenderState->CopyReporting(pReport);
goto finish;
}
if (pRenderPassData->bCompNeeded == false)
{
// Render Target is the output surface
pOutSurface = pcRenderParams->pTarget[0];
}
rcTemp = pcRenderParams->pTarget[0]->rcDst;
rcTempIn = pcRenderParams->pSrc[0]->rcDst;
if (pVeboxState->m_sfcPipeState && pVeboxState->m_sfcPipeState->m_bSFC2Pass)
{
if (0 == pRenderData->fScaleX || 0 == pRenderData->fScaleY)
{
VPHAL_RENDER_ASSERTMESSAGE("Invalid scaling ratio in pRenderData during SFC 2 pass scaling!");
}
//SFC 2 pass, here is the output surface of first pass.
float TempfScaleX = 1.0;
float TempfScaleY = 1.0;
if ((pRenderData->fScaleX >= 0.0625F) && (pRenderData->fScaleX < 0.125F))
{
if (pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
TempfScaleX = 0.125F;
}
else
{
TempfScaleX = 0.5F;
}
}
else if ((pRenderData->fScaleX > 8.0F) && (pRenderData->fScaleX <= 16.0F))
{
TempfScaleX = 2.0F;
}
if ((pRenderData->fScaleY >= 0.0625F) && (pRenderData->fScaleY < 0.125F))
{
if (pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
TempfScaleY = 0.125F;
}
else
{
TempfScaleY = 0.5F;
}
}
else if ((pRenderData->fScaleY > 8.0F) && (pRenderData->fScaleY <= 16.0F))
{
TempfScaleY = 2.0F;
}
//May Lose Precision after 0.x
if (pInSurface->Rotation == VPHAL_ROTATION_IDENTITY ||
pInSurface->Rotation == VPHAL_ROTATION_180 ||
pInSurface->Rotation == VPHAL_MIRROR_HORIZONTAL ||
pInSurface->Rotation == VPHAL_MIRROR_VERTICAL)
{
if ((TempfScaleX == 1.0F) && pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
rcTempOut.right = pInSurface->rcDst.right - pInSurface->rcDst.left;
}
else
{
rcTempOut.right = (long)((pInSurface->rcSrc.right - pInSurface->rcSrc.left) * TempfScaleX);
}
if ((TempfScaleY == 1.0F) && pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
rcTempOut.bottom = pInSurface->rcDst.bottom - pInSurface->rcDst.top;
}
else
{
rcTempOut.bottom = (long)((pInSurface->rcSrc.bottom - pInSurface->rcSrc.top) * TempfScaleY);
}
}
else
{
if ((TempfScaleX == 1.0F) && pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
rcTempOut.bottom = pInSurface->rcDst.right - pInSurface->rcDst.left;
}
else
{
rcTempOut.bottom = (long)((pInSurface->rcSrc.right - pInSurface->rcSrc.left) * TempfScaleX);
}
if ((TempfScaleY == 1.0F) && pVeboxState->m_sfcPipeState->m_bSFC2PassPerfMode)
{
rcTempOut.right = pInSurface->rcDst.bottom - pInSurface->rcDst.top;
}
else
{
rcTempOut.right = (long)((pInSurface->rcSrc.bottom - pInSurface->rcSrc.top) * TempfScaleY);
}
}
VPHAL_RENDER_NORMALMESSAGE("x scaling ratio %f, y %f, 1st pass sfc scaling ratio %f",
pRenderData->fScaleX, pRenderData->fScaleY, TempfScaleX);
}
if (pVeboxState->m_sfcPipeState && (pRenderPassData->bSFCScalingOnly || pVeboxState->m_sfcPipeState->m_bSFC2Pass))
{
if (pRenderPassData->bSFCScalingOnly && !pVeboxState->m_sfcPipeState->m_bSFC2Pass)
{
rcTempOut.right = (long)((pInSurface->rcDst.right - pInSurface->rcDst.left));
rcTempOut.bottom = (long)((pInSurface->rcDst.bottom - pInSurface->rcDst.top));
}
pOutSurface->rcDst = rcTempOut;
pOutSurface->rcSrc = rcTempOut;
pOutSurface->dwWidth = rcTempOut.right;
pOutSurface->dwHeight = rcTempOut.bottom;
pInSurface->rcDst = rcTempOut;
VPHAL_RENDER_CHK_STATUS(pVeboxState->AllocateSfcTempSurfaces(pRenderer, pcRenderParams, pRenderData, pInSurface, pOutSurface));
pOutSurface = &pVeboxState->SfcTempSurface;
// Reset rendering flags for SFC since output surface changed
pVeboxState->m_sfcPipeState->SetRenderingFlags(
pcRenderParams->pColorFillParams,
pcRenderParams->pCompAlpha,
pInSurface,
pOutSurface,
pRenderData);
}
pRenderPassData->pOutSurface = pOutSurface;
bVeboxOutput = IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData);
if (pRenderData->bHdr3DLut)
{
PVPHAL_SURFACE pTargetSurface = (PVPHAL_SURFACE)pcRenderParams->pTarget[0];
// If VEBOX output, write the output to render target
if (bVeboxOutput)
{
pRenderData->pRenderTarget = pTargetSurface;
pRenderPassData->pOutSurface = pTargetSurface;
}
else
{
VpHal_VeboxAllocateTempSurfaces(pRenderer, pcRenderParams, pRenderData, pcRenderParams->pSrc[0], pcRenderParams->pTarget[0], &pRenderer->IntermediateSurface);
SET_VPHAL_OUTPUT_PIPE(pRenderData, VPHAL_OUTPUT_PIPE_MODE_VEBOX);
SET_VEBOX_EXECUTION_MODE(pVeboxState->m_pVeboxExecState, VEBOX_EXEC_MODE_0);
pOutSurface = &pRenderer->IntermediateSurface;
pRenderData->pRenderTarget = &pRenderer->IntermediateSurface;
// If VEBOX does not output directly, write the output to intermediate surface
pRenderPassData->pOutSurface = pOutSurface;
}
}
//Disable cache for output surface in vebox only condition
if (IS_VPHAL_OUTPUT_PIPE_VEBOX(pRenderData))
{
MOS_HW_RESOURCE_DEF Usage;
MEMORY_OBJECT_CONTROL_STATE MemObjCtrl;
VPHAL_SET_SURF_MEMOBJCTL(pVeboxState->DnDiSurfMemObjCtl.CurrentOutputSurfMemObjCtl, MOS_MP_RESOURCE_USAGE_DEFAULT);
}
VPHAL_RENDER_CHK_STATUS(pRenderState->Render(
pcRenderParams,
pRenderPassData))
if (pVeboxState->m_sfcPipeState && (pRenderPassData->bSFCScalingOnly || pVeboxState->m_sfcPipeState->m_bSFC2Pass))
{
pInSurface = &pVeboxState->SfcTempSurface;
pInSurface->rcMaxSrc = pInSurface->rcSrc;
pInSurface->rcDst = rcTempIn;
pInSurface->ScalingMode = pRenderPassData->pSrcSurface->ScalingMode;
// recover the orignal rcDst for the second loop
pcRenderParams->pTarget[0]->rcDst = rcTemp;
pcRenderParams->pTarget[0]->rcSrc = rcTemp;
pcRenderParams->pTarget[0]->dwWidth = rcTemp.right;
pcRenderParams->pTarget[0]->dwHeight = rcTemp.bottom;
// Render Target is the output surface
pOutSurface = pcRenderParams->pTarget[0];
pRenderData->pRenderTarget = pOutSurface;
pRenderPassData->pSrcSurface = pInSurface;
}
//SFC second pass
if (pVeboxState->m_sfcPipeState && pVeboxState->m_sfcPipeState->m_bSFC2Pass)
{
// Second time vebox rending for scaling / colorfill/rotation on SFC, disable all other features
pVeboxState->m_sfcPipeState->m_bSFC2Pass = false;
pRenderData->bDenoise = false;
pRenderData->bDeinterlace = false;
pRenderData->bQueryVariance = false;
VPHAL_RENDER_NORMALMESSAGE("2nd pass sfc scaling ratio x = %f, y = %f",
(long)((pInSurface->rcDst.right - pInSurface->rcDst.left) / (pInSurface->rcSrc.right - pInSurface->rcSrc.left)),
(long)((pInSurface->rcDst.bottom - pInSurface->rcDst.top) / (pInSurface->rcSrc.bottom - pInSurface->rcSrc.top)));
if (pRenderPassData->bSFCScalingOnly)
{// only the multi-layers use the SFC 2pass need the second sfc tempsurfaces.
VPHAL_RENDER_CHK_STATUS(pVeboxState->AllocateSfc2ndTempSurfaces(pRenderer, pcRenderParams, pRenderData, pInSurface, pOutSurface));
pRenderPassData->pOutSurface = &pVeboxState->Sfc2ndTempSurface;
// Reset rendering flags for SFC since output surface changed
pVeboxState->m_sfcPipeState->SetRenderingFlags(
pcRenderParams->pColorFillParams,
pcRenderParams->pCompAlpha,
pInSurface,
pRenderPassData->pOutSurface,
pRenderData);
}
else
{ // reset the output surface as targetsurface.
pRenderPassData->pOutSurface = pOutSurface;
pInSurface->SurfType = SURF_IN_PRIMARY;
pVeboxState->m_sfcPipeState->SetRenderingFlags(
pcRenderParams->pColorFillParams,
pcRenderParams->pCompAlpha,
pInSurface,
pRenderPassData->pOutSurface,
pRenderData);
}
VPHAL_RENDER_CHK_STATUS(pVeboxState->Render(
pcRenderParams,
pRenderPassData));
}
pRenderState->CopyReporting(pReport);
if (pRenderPassData->bCompNeeded)
{
pRenderPassData->bOutputGenerated = true;
}
if (pRenderData->bHdr3DLut && !bVeboxOutput)
{
pRenderPassData->bOutputGenerated = true;
pRenderPassData->bCompNeeded = true;
if (pOutSurface && pcRenderParams->pSrc[0])
{
pRenderPassData->pOutSurface->rcSrc = pcRenderParams->pSrc[0]->rcSrc;
pRenderPassData->pOutSurface->rcDst = pcRenderParams->pSrc[0]->rcDst;
pRenderPassData->pOutSurface->rcMaxSrc = pcRenderParams->pSrc[0]->rcMaxSrc;
pRenderPassData->pOutSurface->iLayerID = -1;
pRenderPassData->pOutSurface->iPalette = -1;
}
}
}
finish:
VPHAL_RENDER_NORMALMESSAGE("VPOutputPipe = %d, VEFeatureInUse = %d",
pRenderer->GetReport()->OutputPipeMode, pRenderer->GetReport()->VEFeatureInUse);
return eStatus;
}
MOS_STATUS VPHAL_VEBOX_STATE::UpdateRenderGpuContext(
MOS_GPU_CONTEXT renderGpuContext)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (MOS_RCS_ENGINE_USED(renderGpuContext))
{
RenderGpuContext = renderGpuContext;
VPHAL_RENDER_NORMALMESSAGE("RenderGpuContext turns to %d", renderGpuContext);
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Invalid Render GpuContext: %d! Update RenderGpuContext Failed", renderGpuContext);
}
return eStatus;
}
VPHAL_VEBOX_STATE::VPHAL_VEBOX_STATE(
PMOS_INTERFACE pOsInterface,
PMHW_VEBOX_INTERFACE pVeboxInterface,
PMHW_SFC_INTERFACE pSfcInterface,
PRENDERHAL_INTERFACE pRenderHal,
PVPHAL_VEBOX_EXEC_STATE pVeboxExecState,
PVPHAL_RNDR_PERF_DATA pPerfData,
const VPHAL_DNDI_CACHE_CNTL &dndiCacheCntl,
MOS_STATUS *peStatus) :
RenderState(pOsInterface, pRenderHal, pPerfData, peStatus),
m_pVeboxInterface(pVeboxInterface),
m_pSfcInterface(pSfcInterface),
m_currKernelId(baseKernelMaxNumID),
m_pVeboxExecState(pVeboxExecState)
{
// External components
m_IECP = nullptr;
m_sfcPipeState = nullptr;
m_pKernelDllState = nullptr;
m_pLastExecRenderData = nullptr;
CscOutputCspace = CSpace_Any;
CscInputCspace = CSpace_Any;
m_BT2020CSCTempSurface = {};
int i;
for (i = 0; i < 9; i++)
{
fCscCoeff[i] = 0.0f;
}
for (i = 0; i < 3; i++)
{
fCscInOffset[i] = 0.0f;
fCscOutOffset[i] = 0.0f;
}
// Front End CSC
fFeCscCoeff = nullptr;
fFeCscInOffset = nullptr;
fFeCscOutOffset = nullptr;
for (i = 0; i < 2; i++)
{
SearchFilter[i] = {};
}
// Threshold for discontinuity check
iSameSampleThreshold = 0;
// Resources
m_currentSurface = nullptr; //!< Current frame
m_previousSurface = nullptr; //!< Previous frame
RenderHalCurrentSurface = {}; //!< Current frame for MHW
RenderHalPreviousSurface = {}; //!< Previous frame for MHW
for (i = 0; i < VPHAL_MAX_NUM_FFDI_SURFACES; i++)
{
FFDISurfaces[i] = nullptr;
}
VeboxRGBHistogram = {};
VeboxStatisticsSurface = {}; //!< Statistics Surface for VEBOX
RenderHalVeboxStatisticsSurface = {}; //!< Statistics Surface for VEBOX for MHW
#if VEBOX_AUTO_DENOISE_SUPPORTED
VeboxTempSurface = {}; //!< Temp Surface for Vebox State update kernels
VeboxSpatialAttributesConfigurationSurface = {}; //!< Spatial Attributes Configuration Surface for DN kernel Gen9+
RenderHalVeboxSpatialAttributesConfigurationSurface = {}; //!< Spatial Attributes Configuration Surface for DN kernel Gen9+ for MHW
VeboxHeapResource = {}; //!< Vebox Heap resource for DN kernel
tmpResource = {}; //!< Temp resource for DN kernel
RenderHalVeboxHeapResource = {}; //!< Vebox Heap resource for DN kernel for MHW
RenderHalTmpResource = {}; //!< Temp resource for DN kernel for MHW
#endif
// DNDI
for (i = 0; i < VPHAL_NUM_FFDN_SURFACES; i++)
{
FFDNSurfaces[i] = nullptr;
}
for (i = 0; i < VPHAL_NUM_STMM_SURFACES; i++)
{
STMMSurfaces[i] = {};
}
// BNE system memory pointer
pBNEData = nullptr; //!< System memory for GNE calculating
dwBNESize = 0; //!< System memory size for BNE surface
// Statistics
dwVeboxPerBlockStatisticsWidth = 0; //!< Per block statistics width
dwVeboxPerBlockStatisticsHeight = 0; //!< Per block statistics height
//!< Surface memory object control
// Get cache settings
DnDiSurfMemObjCtl = dndiCacheCntl;
// Batch Buffers
iBatchBufferCount = 0; //!< Number of batch buffers
for (i = 0; i < VPHAL_DNDI_BUFFERS_MAX; i++)
{
BatchBuffer[i] = {};
BufferParam[i] = {};
}
// Denoise output control
iCurDNIndex = 0; //!< Current index of Denoise Output
// DNDI
iNumFFDISurfaces = 0; //!< Actual number of FFDISurfaces. Is <= VPHAL_NUM_FFDI_SURFACES
iCurStmmIndex = 0; //!< Current index of Motion History Buffer
dwGlobalNoiseLevel = 0; //!< Global Noise Level
// Chroma DN
iCurHistIndex = 0; //!< Current index of Chroma Denoise History Buffer
dwGlobalNoiseLevelU = 0; //!< Global Noise Level for U
dwGlobalNoiseLevelV = 0; //!< Global Noise Level for V
bFirstFrame = false; //!< First frame case for Chroma DN
// timestamps for DI output control
iCurFrameID = 0; //!< Current Frame ID
iPrvFrameID = 0; //!< Previous Frame ID
// for Pre-Processing
bSameSamples = false; //!< True for second DI
iCallID = 0; //!< Current render call ID;
bDNEnabled = false; //!< DN was enabled in the previous call
bDIEnabled = false; //!< DI was enabled in the previous call
// Platform dependent states
pKernelParamTable = nullptr; //!< Kernel Parameter table
// HW Params
dwKernelUpdate = 0; //!< Enable/Disable kernel update
dwCompBypassMode = 0; //!< Bypass Composition Optimization read from User feature keys
// Debug parameters
pKernelName = nullptr; //!< Kernel Used for current rendering
bNullHwRenderDnDi = false; //!< Null rendering for DnDi function
bEnableMMC = false; //!< Memory compression enbale flag - read from User feature keys
bDisableTemporalDenoiseFilter = false; //!< Temporal denoise filter disable flag - read from User feature keys
bDisableTemporalDenoiseFilterUserKey = false; //!< Backup temporal denoise filter disable flag - read from User feature keys
uiCurrentChannel = 0;
RenderGpuContext = pOsInterface ? (pOsInterface->CurrentGpuContextOrdinal) : MOS_GPU_CONTEXT_RENDER;
Vebox3DLookUpTables = { };
SfcTempSurface = { };
m_hvsDenoiser = nullptr;
m_hvsKernelBinary = nullptr;
m_hvsKernelBinarySize = 0;
bPhasedSubmission = false;
}
VPHAL_VEBOX_STATE::~VPHAL_VEBOX_STATE()
{
PRENDERHAL_INTERFACE pRenderHal;
PMHW_BATCH_BUFFER pBuffer;
int32_t i;
PVPHAL_VEBOX_STATE pVeboxState = this;
VPHAL_RENDER_ASSERT(pVeboxState);
pRenderHal = pVeboxState->m_pRenderHal;
VPHAL_RENDER_ASSERT(pRenderHal);
MOS_FreeMemAndSetNull(m_currentSurface);
MOS_FreeMemAndSetNull(m_previousSurface);
for (uint32_t i = 0; i < VPHAL_NUM_FFDN_SURFACES; i++)
{
MOS_FreeMemAndSetNull(FFDNSurfaces[i]);
}
for (uint32_t i = 0; i < VPHAL_MAX_NUM_FFDI_SURFACES; i++)
{
MOS_FreeMemAndSetNull(FFDISurfaces[i]);
}
// Destroy Batch Buffers
for (i = 0; i < pVeboxState->iBatchBufferCount; i++)
{
pBuffer = &pVeboxState->BatchBuffer[i];
pRenderHal->pfnFreeBB(pRenderHal, pBuffer);
}
if (m_pLastExecRenderData)
{
MOS_Delete(m_pLastExecRenderData);
m_pLastExecRenderData = nullptr;
}
if (m_IECP)
{
MOS_Delete(m_IECP);
m_IECP = nullptr;
}
// Destroy SFC state
if (m_sfcPipeState)
{
MOS_Delete(m_sfcPipeState);
m_sfcPipeState = nullptr;
}
MOS_Delete(m_hvsDenoiser);
}
MOS_STATUS VPHAL_VEBOX_STATE::VeboxSetHVSDNParams(
PVPHAL_SURFACE pSrcSurface)
{
MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PVPHAL_VEBOX_STATE pVeboxState = this;
PVPHAL_VEBOX_RENDER_DATA pRenderData = nullptr;
pRenderHal = pVeboxState->m_pRenderHal;
pRenderData = GetLastExecRenderData();
VPHAL_RENDER_CHK_NULL_RETURN(pSrcSurface);
VPHAL_RENDER_CHK_NULL_RETURN(pSrcSurface->pDenoiseParams);
VPHAL_RENDER_CHK_NULL_RETURN(pRenderHal);
VPHAL_RENDER_CHK_NULL_RETURN(pRenderData);
if (nullptr == m_hvsDenoiser)
{
m_hvsDenoiser = MOS_New(VphalHVSDenoiser, pRenderHal);
if (m_hvsDenoiser)
{
m_hvsDenoiser->InitKernelParams(m_hvsKernelBinary, m_hvsKernelBinarySize);
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("New VphalHVSDenoiser Failed!");
eStatus = MOS_STATUS_NULL_POINTER;
return eStatus;
}
}
if (m_hvsDenoiser)
{
m_hvsDenoiser->Render(pSrcSurface);
uint32_t *pHVSDenoiseParam = (uint32_t *)m_hvsDenoiser->GetDenoiseParams();
if (pHVSDenoiseParam)
{
// Media kernel computed the HVS Denoise Parameters according to the specific mapping function.
// Programming these Parameters to VEBOX for processing.
VPHAL_RENDER_NORMALMESSAGE("Set HVS Denoised Parameters to VEBOX DNDI params");
// DW0
pRenderData->VeboxDNDIParams.dwDenoiseMPThreshold = (pHVSDenoiseParam[0] & 0x0000001f);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseMPThreshold %d", pRenderData->VeboxDNDIParams.dwDenoiseMPThreshold);
pRenderData->VeboxDNDIParams.dwDenoiseHistoryDelta = (pHVSDenoiseParam[0] & 0x00000f00) >> 8;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseHistoryDelta %d", pRenderData->VeboxDNDIParams.dwDenoiseHistoryDelta);
pRenderData->VeboxDNDIParams.dwDenoiseMaximumHistory = (pHVSDenoiseParam[0] & 0x000ff000) >> 12;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseMaximumHistory %d", pRenderData->VeboxDNDIParams.dwDenoiseMaximumHistory);
pRenderData->VeboxDNDIParams.dwDenoiseSTADThreshold = (pHVSDenoiseParam[0] & 0xfff00000) >> 20;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseSTADThreshold %d", pRenderData->VeboxDNDIParams.dwDenoiseSTADThreshold);
// DW1
pRenderData->VeboxDNDIParams.dwLTDThreshold = (pHVSDenoiseParam[1] & 0x000003ff);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwLTDThreshold %d", pRenderData->VeboxDNDIParams.dwLTDThreshold);
pRenderData->VeboxDNDIParams.dwTDThreshold = (pHVSDenoiseParam[1] & 0x000ffc00) >> 10;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwTDThreshold %d", pRenderData->VeboxDNDIParams.dwTDThreshold);
pRenderData->VeboxDNDIParams.dwDenoiseASDThreshold = (pHVSDenoiseParam[1] & 0xfff00000) >> 20;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseASDThreshold %d", pRenderData->VeboxDNDIParams.dwDenoiseASDThreshold);
// DW2
pRenderData->VeboxDNDIParams.dwDenoiseSCMThreshold = (pHVSDenoiseParam[2] & 0x0fff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwDenoiseSCMThreshold %d", pRenderData->VeboxDNDIParams.dwDenoiseSCMThreshold);
// DW4
pRenderData->VeboxDNDIParams.dwChromaLTDThreshold = (pHVSDenoiseParam[4] & 0x0000003f);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwChromaLTDThreshold %d", pRenderData->VeboxDNDIParams.dwChromaLTDThreshold);
pRenderData->VeboxDNDIParams.dwChromaTDThreshold = (pHVSDenoiseParam[4] & 0x00000fc0) >> 6;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwChromaTDThreshold %d", pRenderData->VeboxDNDIParams.dwChromaTDThreshold);
pRenderData->VeboxDNDIParams.dwChromaSTADThreshold = (pHVSDenoiseParam[4] & 0x00ff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwChromaSTADThreshold %d", pRenderData->VeboxDNDIParams.dwChromaSTADThreshold);
// DW5
pRenderData->VeboxDNDIParams.dwPixRangeWeight[0] = (pHVSDenoiseParam[5] & 0x0000001f);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[0] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[0]);
pRenderData->VeboxDNDIParams.dwPixRangeWeight[1] = (pHVSDenoiseParam[5] & 0x000003e0) >> 5;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[1] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[1]);
pRenderData->VeboxDNDIParams.dwPixRangeWeight[2] = (pHVSDenoiseParam[5] & 0x00007c00) >> 10;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[2] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[2]);
pRenderData->VeboxDNDIParams.dwPixRangeWeight[3] = (pHVSDenoiseParam[5] & 0x000f8000) >> 15;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[3] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[3]);
pRenderData->VeboxDNDIParams.dwPixRangeWeight[4] = (pHVSDenoiseParam[5] & 0x01f00000) >> 20;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[4] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[4]);
pRenderData->VeboxDNDIParams.dwPixRangeWeight[5] = (pHVSDenoiseParam[5] & 0x3e000000) >> 25;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeWeight[5] %d", pRenderData->VeboxDNDIParams.dwPixRangeWeight[5]);
// DW7
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[5] = (pHVSDenoiseParam[7] & 0x1fff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[5] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[5]);
// DW8
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[4] = (pHVSDenoiseParam[8] & 0x1fff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[4] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[4]);
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[3] = (pHVSDenoiseParam[8] & 0x00001fff);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[3] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[3]);
// DW9
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[2] = (pHVSDenoiseParam[9] & 0x1fff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[2] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[2]);
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[1] = (pHVSDenoiseParam[9] & 0x00001fff);
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[1] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[1]);
// DW10
pRenderData->VeboxDNDIParams.dwPixRangeThreshold[0] = (pHVSDenoiseParam[10] & 0x1fff0000) >> 16;
VPHAL_RENDER_NORMALMESSAGE("HVS: pRenderData->VeboxDNDIParams.dwPixRangeThreshold[0] %d", pRenderData->VeboxDNDIParams.dwPixRangeThreshold[0]);
eStatus = MOS_STATUS_SUCCESS;
}
}
return eStatus;
}
//!
//! \brief Comp can be bypassed when the following conditions are all met
//! 1. Single Layer input only
//! 2. Single render target only
//! 3. Blending Disabled
//! 4. Interlaced Scaling Disabled
//! 5. Field Weaving Disabled
//! 6. LumaKey Disabled
//! 8. Constriction Disabled
//!
bool VPHAL_VEBOX_STATE::IS_COMP_BYPASS_FEASIBLE(bool _bCompNeeded, PCVPHAL_RENDER_PARAMS _pcRenderParams, PVPHAL_SURFACE _pSrcSurface)
{
VPHAL_RENDER_NORMALMESSAGE(
"_bCompNeeded %d, \
uSrcCount %d, \
uDstCount %d, \
pBlendingParams %p, \
bInterlacedScaling %d, \
bFieldWeaving %d, \
pLumaKeyParams %p, \
pConstriction %p",
_bCompNeeded,
_pcRenderParams->uSrcCount,
_pcRenderParams->uDstCount,
_pSrcSurface->pBlendingParams,
_pSrcSurface->bInterlacedScaling,
_pSrcSurface->bFieldWeaving,
_pSrcSurface->pLumaKeyParams,
_pcRenderParams->pConstriction);
return (_bCompNeeded == false &&
_pcRenderParams->uSrcCount == 1 &&
_pcRenderParams->uDstCount == 1 &&
_pSrcSurface->pBlendingParams == nullptr &&
_pSrcSurface->bInterlacedScaling == false &&
_pSrcSurface->bFieldWeaving == false &&
_pSrcSurface->pLumaKeyParams == nullptr &&
_pcRenderParams->pConstriction == nullptr);
}
//!
//! \brief Vebox can be the output pipe when the following conditions are all met
//! 1. User feature keys value "Bypass Composition" is enabled.
//! 2. Single render target only
//! 3. Src Size = Dst Size
//! 4. Max Src Size >= Src Size
//! 5. rcSrc's top/left are zero
//! 6. No Colorfill
//! 7. IEF Disabled
//! 8. Input is progressive
//! 9. Rotation Disabled
//! 10. Variance Query is disabled
//! 11. Input format is supported by Vebox
//! 12. RT format is supported by Vebox
//! 13. 2PassCSC is not supported by Vebox only
//! 14. Alpha Fill is disabled or when it's enabled, it's not background Alpha Fill mode
//! 15. Dst parameters top/left are zero.
//!
bool VPHAL_VEBOX_STATE::IS_OUTPUT_PIPE_VEBOX_FEASIBLE(PVPHAL_VEBOX_STATE _pVeboxState, PCVPHAL_RENDER_PARAMS _pcRenderParams, PVPHAL_SURFACE _pSrcSurface)
{
VPHAL_RENDER_NORMALMESSAGE(
"dwCompBypassMode %d, \
_pcRenderParams->uDstCount %d, \
SAME_SIZE_RECT(rcSrc, rcDst) %d, \
RECT1_CONTAINS_RECT2(rcMaxSrc, rcSrc) %d, \
rcSrc.top %d \
rcSrc.left %d \
SAME_SIZE_RECT(rcDst, pTarget[0]->rcDst) %p, \
pIEFParams %d, \
SampleType %d, \
Rotation %p, \
bQueryVariance %d, \
IsFormatSupported %p, \
IsRTFormatSupported %d, \
VeboxIs2PassesCSCNeeded %d, \
AlphaMode %p, \
rcDst.top %d, \
rcDst.left %d",
_pVeboxState->dwCompBypassMode,
_pcRenderParams->uDstCount,
SAME_SIZE_RECT(_pSrcSurface->rcSrc, _pSrcSurface->rcDst),
RECT1_CONTAINS_RECT2(_pSrcSurface->rcMaxSrc, _pSrcSurface->rcSrc),
_pSrcSurface->rcSrc.top,
_pSrcSurface->rcSrc.left,
SAME_SIZE_RECT(_pSrcSurface->rcDst, _pcRenderParams->pTarget[0]->rcDst),
_pSrcSurface->pIEFParams,
_pSrcSurface->SampleType,
_pSrcSurface->Rotation,
_pSrcSurface->bQueryVariance,
_pVeboxState->IsFormatSupported(_pSrcSurface),
_pVeboxState->IsRTFormatSupported(_pSrcSurface, _pcRenderParams->pTarget[0]),
_pVeboxState->VeboxIs2PassesCSCNeeded(_pSrcSurface, _pcRenderParams->pTarget[0]),
(_pcRenderParams->pCompAlpha == nullptr || _pcRenderParams->pCompAlpha->AlphaMode != VPHAL_ALPHA_FILL_MODE_BACKGROUND),
_pSrcSurface->rcDst.top,
_pSrcSurface->rcDst.left);
return (_pVeboxState->dwCompBypassMode != VPHAL_COMP_BYPASS_DISABLED &&
_pcRenderParams->uDstCount == 1 &&
SAME_SIZE_RECT(_pSrcSurface->rcSrc, _pSrcSurface->rcDst) &&
RECT1_CONTAINS_RECT2(_pSrcSurface->rcMaxSrc, _pSrcSurface->rcSrc) &&
_pSrcSurface->rcSrc.top == 0 &&
_pSrcSurface->rcSrc.left == 0 &&
SAME_SIZE_RECT(_pSrcSurface->rcDst, _pcRenderParams->pTarget[0]->rcDst) &&
_pSrcSurface->pIEFParams == nullptr &&
_pSrcSurface->SampleType == SAMPLE_PROGRESSIVE &&
_pSrcSurface->Rotation == VPHAL_ROTATION_IDENTITY &&
_pSrcSurface->bQueryVariance == false &&
_pVeboxState->IsFormatSupported(_pSrcSurface) &&
_pVeboxState->IsRTFormatSupported(_pSrcSurface, _pcRenderParams->pTarget[0]) &&
!(_pVeboxState->VeboxIs2PassesCSCNeeded(_pSrcSurface, _pcRenderParams->pTarget[0])) &&
(_pcRenderParams->pCompAlpha == nullptr ||
_pcRenderParams->pCompAlpha->AlphaMode != VPHAL_ALPHA_FILL_MODE_BACKGROUND) &&
_pSrcSurface->rcDst.top == 0 &&
_pSrcSurface->rcDst.left == 0);
}
VPHAL_VEBOX_RENDER_DATA::~VPHAL_VEBOX_RENDER_DATA()
{
if (m_pVeboxStateParams)
{
MOS_Delete(m_pVeboxStateParams);
m_pVeboxStateParams = nullptr;
}
if (m_pVeboxIecpParams)
{
MOS_Delete(m_pVeboxIecpParams);
m_pVeboxIecpParams = nullptr;
}
}
MOS_STATUS VPHAL_VEBOX_RENDER_DATA::Init()
{
// Vebox State Parameters
// m_pVeboxStateParams needs to be set to nullptr in constructor
if (!m_pVeboxStateParams)
{
m_pVeboxStateParams = MOS_New(VPHAL_VEBOX_STATE_PARAMS);
if (!m_pVeboxStateParams)
{
return MOS_STATUS_NO_SPACE;
}
}
m_pVeboxStateParams->Init();
// Vebox IECP State Parameters
// m_pVeboxIecpParams needs to be set to nullptr in constructor
if (!m_pVeboxIecpParams)
{
m_pVeboxIecpParams = MOS_New(VPHAL_VEBOX_IECP_PARAMS);
if (!m_pVeboxIecpParams)
{
return MOS_STATUS_NO_SPACE;
}
}
m_pVeboxIecpParams->Init();
// Flags
bRefValid = false;
bSameSamples = false;
bProgressive = false;
bDenoise = false;
#if VEBOX_AUTO_DENOISE_SUPPORTED
bAutoDenoise = false;
#endif
bChromaDenoise = false;
bOutOfBound = false;
bVDIWalker = false;
bIECP = false;
bColorPipe = false;
bProcamp = false;
// DNDI/Vebox
bDeinterlace = false;
bSingleField = false;
bTFF = false;
bTopField = false;
bBeCsc = false;
bFeCsc = false;
bVeboxBypass = false;
b60fpsDi = false;
bQueryVariance = false;
// Surface Information
iFrame0 = 0;
iFrame1 = 0;
iCurDNIn = 0;
iCurDNOut = 0;
iCurHistIn = 0;
iCurHistOut = 0;
// Geometry
iBlocksX = 0;
iBlocksY = 0;
iBindingTable = 0;
iMediaID0 = 0;
iMediaID1 = 0;
// Perf
PerfTag = VPHAL_NONE;
// States
pMediaState = nullptr;
pVeboxState = nullptr;
pRenderTarget = nullptr;
SamplerStateParams = { };
VeboxDNDIParams = { };
pAlphaParams = nullptr;
// Batch Buffer rendering arguments
BbArgs = { };
// Vebox output parameters
OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
// Kernel Information
for (int i = 0; i < VPHAL_NUM_KERNEL_VEBOX; i++)
{
pKernelParam[i] = nullptr;
KernelEntry[i] = { };
}
pDNUVParams = nullptr;
iCurbeLength = 0;
iCurbeOffset = 0;
iInlineLength = 0;
// Debug parameters
pKernelName = nullptr;
Component = COMPONENT_UNKNOWN;
// Memory compression flag
bEnableMMC = false;
fScaleX = 0.0f;
fScaleY = 0.0f;
bHdr3DLut = false;
uiMaxDisplayLum = 4000;
uiMaxContentLevelLum = 1000;
hdrMode = VPHAL_HDR_MODE_NONE;
return MOS_STATUS_SUCCESS;
}