blob: 14ffab64dfcd18dfa89807228d29fdecf3e324f2 [file] [log] [blame]
/*
* Copyright (c) 2015-2020, 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_common.c
//! \brief The file of common utilities definitions shared by low level renderers
//! \details Common utilities for different renderers, e.g. DNDI or Comp
//!
#include "vphal_render_common.h"
#include "vphal_render_composite.h"
#include "mos_os.h"
#include "mos_solo_generic.h"
#include "hal_oca_interface.h"
extern const MEDIA_OBJECT_KA2_INLINE_DATA g_cInit_MEDIA_OBJECT_KA2_INLINE_DATA =
{
// DWORD 0
{
0, // DestinationBlockHorizontalOrigin
0 // DestinationBlockVerticalOrigin
},
// DWORD 1
{
0, // HorizontalBlockCompositeMaskLayer0
0 // VerticalBlockCompositeMaskLayer0
},
// DWORD 2
{
0, // HorizontalBlockCompositeMaskLayer1
0 // VerticalBlockCompositeMaskLayer1
},
// DWORD 3
{
0, // HorizontalBlockCompositeMaskLayer2
0 // VerticalBlockCompositeMaskLayer2
},
// DWORD 4
0.0F, // VideoXScalingStep
// DWORD 5
0.0F, // VideoStepDelta
// DWORD 6
{
0, // VerticalBlockNumber
0 // AreaOfInterest
},
// DWORD 7
{
0, // GroupIDNumber
},
// DWORD 8
{
0, // HorizontalBlockCompositeMaskLayer3
0 // VerticalBlockCompositeMaskLayer3
},
// DWORD 9
{
0, // HorizontalBlockCompositeMaskLayer4
0 // VerticalBlockCompositeMaskLayer4
},
// DWORD 10
{
0, // HorizontalBlockCompositeMaskLayer5
0 // VerticalBlockCompositeMaskLayer5
},
// DWORD 11
{
0, // HorizontalBlockCompositeMaskLayer6
0 // VerticalBlockCompositeMaskLayer6
},
// DWORD 12
{
0, // HorizontalBlockCompositeMaskLayer7
0 // VerticalBlockCompositeMaskLayer7
},
// DWORD 13
0, // Reserved
// DWORD 14
0, // Reserved
// DWORD 15
0 // Reserved
};
//!
//! \brief Initialized RenderHal Surface Type
//! \details Initialized RenderHal Surface Type according to input VPHAL Surface Type
//! \param [in] vpSurfType
//! VPHAL surface type
//! \return RENDERHAL_SURFACE_TYPE
//!
static inline RENDERHAL_SURFACE_TYPE VpHal_RndrInitRenderHalSurfType(VPHAL_SURFACE_TYPE vpSurfType)
{
switch (vpSurfType)
{
case SURF_IN_BACKGROUND:
return RENDERHAL_SURF_IN_BACKGROUND;
case SURF_IN_PRIMARY:
return RENDERHAL_SURF_IN_PRIMARY;
case SURF_IN_SUBSTREAM:
return RENDERHAL_SURF_IN_SUBSTREAM;
case SURF_IN_REFERENCE:
return RENDERHAL_SURF_IN_REFERENCE;
case SURF_OUT_RENDERTARGET:
return RENDERHAL_SURF_OUT_RENDERTARGET;
case SURF_NONE:
default:
return RENDERHAL_SURF_NONE;
}
}
//!
//! \brief Initialized RenderHal Scaling Mode
//! \details Initialized RenderHal Scaling Mode according to input VPHAL Scaling Mode
//! \param [in] vpScalingMode
//! VPHAL Scaling Mode
//! \return RENDERHAL_SCALING_MODE
//!
static inline RENDERHAL_SCALING_MODE VpHal_RndrInitRenderHalScalingMode(VPHAL_SCALING_MODE vpScalingMode)
{
switch (vpScalingMode)
{
case VPHAL_SCALING_NEAREST:
return RENDERHAL_SCALING_NEAREST;
case VPHAL_SCALING_BILINEAR:
return RENDERHAL_SCALING_BILINEAR;
case VPHAL_SCALING_AVS:
return RENDERHAL_SCALING_AVS;
default:
VPHAL_RENDER_ASSERTMESSAGE("Invalid VPHAL_SCALING_MODE %d, force to nearest mode.", vpScalingMode);
return RENDERHAL_SCALING_NEAREST;
}
}
//!
//! \brief Get VpHal Scaling Mode
//! \details Get VpHal Scaling Mode according to RenderHal Scaling Mode
//! \param [in] RenderHalScalingMode
//! RENDERHAL Scaling Mode
//! \return VPHAL_SCALING_MODE
//!
static inline VPHAL_SCALING_MODE VpHal_RndrGetVpHalScalingMode(RENDERHAL_SCALING_MODE RenderHalScalingMode)
{
switch (RenderHalScalingMode)
{
case RENDERHAL_SCALING_NEAREST:
return VPHAL_SCALING_NEAREST;
case RENDERHAL_SCALING_BILINEAR:
return VPHAL_SCALING_BILINEAR;
case RENDERHAL_SCALING_AVS:
return VPHAL_SCALING_AVS;
default:
VPHAL_RENDER_ASSERTMESSAGE("Invalid RENDERHAL_SCALING_MODE %d, force to nearest mode.", RenderHalScalingMode);
return VPHAL_SCALING_NEAREST;
}
}
//!
//! \brief Initialized RenderHal Sample Type
//! \details Initialized RenderHal Sample Type according to input VPHAL Sample Type
//! \param [in] SampleType
//! VPHAL Sample Type
//! \return RENDERHAL_SAMPLE_TYPE
//!
static inline RENDERHAL_SAMPLE_TYPE VpHal_RndrInitRenderHalSampleType(VPHAL_SAMPLE_TYPE SampleType)
{
switch (SampleType)
{
case SAMPLE_PROGRESSIVE:
return RENDERHAL_SAMPLE_PROGRESSIVE;
case SAMPLE_SINGLE_TOP_FIELD:
return RENDERHAL_SAMPLE_SINGLE_TOP_FIELD;
case SAMPLE_SINGLE_BOTTOM_FIELD:
return RENDERHAL_SAMPLE_SINGLE_BOTTOM_FIELD;
case SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD:
return RENDERHAL_SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD;
case SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD:
return RENDERHAL_SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD;
case SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD:
return RENDERHAL_SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD;
case SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD:
return RENDERHAL_SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD;
case SAMPLE_INVALID:
default:
VPHAL_RENDER_ASSERTMESSAGE("Invalid VPHAL_SAMPLE_TYPE %d.\n", SampleType);
return RENDERHAL_SAMPLE_INVALID;
}
}
static inline void VpHal_RndrInitPlaneOffset(
PMOS_PLANE_OFFSET pMosPlaneOffset,
PVPHAL_PLANE_OFFSET pVpPlaneOffset)
{
pMosPlaneOffset->iSurfaceOffset = pVpPlaneOffset->iSurfaceOffset;
pMosPlaneOffset->iXOffset = pVpPlaneOffset->iXOffset;
pMosPlaneOffset->iYOffset = pVpPlaneOffset->iYOffset;
pMosPlaneOffset->iLockSurfaceOffset = pVpPlaneOffset->iLockSurfaceOffset;
}
//!
//! \brief Initialized MHW Rotation mode
//! \details Initialized MHW Rotation mode according to input VPHAL Rotation Type
//! \param [in] Rotation
//! VPHAL Rotation mode
//! \return MHW_ROTATION
//!
static inline MHW_ROTATION VpHal_RndrInitRotationMode(VPHAL_ROTATION Rotation)
{
MHW_ROTATION Mode = MHW_ROTATION_IDENTITY;
switch (Rotation)
{
case VPHAL_ROTATION_IDENTITY:
Mode = MHW_ROTATION_IDENTITY;
break;
case VPHAL_ROTATION_90:
Mode = MHW_ROTATION_90;
break;
case VPHAL_ROTATION_180:
Mode = MHW_ROTATION_180;
break;
case VPHAL_ROTATION_270:
Mode = MHW_ROTATION_270;
break;
case VPHAL_MIRROR_HORIZONTAL:
Mode = MHW_MIRROR_HORIZONTAL;
break;
case VPHAL_MIRROR_VERTICAL:
Mode = MHW_MIRROR_VERTICAL;
break;
case VPHAL_ROTATE_90_MIRROR_VERTICAL:
Mode = MHW_ROTATE_90_MIRROR_VERTICAL;
break;
case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
Mode = MHW_ROTATE_90_MIRROR_HORIZONTAL;
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Invalid Rotation Angle.");
break;
}
return Mode;
}
//!
//! \brief Set the numbers of Slice, Sub-slice, EUs for power mode
//! \details Set the numbers of Slice, Sub-slice, EUs recommended for
//! the given kernel type for power mode
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] KernelID
//! VP render Kernel ID
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success. Error code otherwise
//!
MOS_STATUS VpHal_RndrCommonSetPowerMode(
PRENDERHAL_INTERFACE pRenderHal,
VpKernelID KernelID)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint16_t wNumRequestedEUSlices = 1; // Default to 1 slice
uint16_t wNumRequestedSubSlices = 3; // Default to 3 subslice
uint16_t wNumRequestedEUs = 8; // Default to 8 EUs
RENDERHAL_POWEROPTION PowerOption;
bool bSetRequestedSlices = false;
const VphalSseuSetting *pcSSEUTable = nullptr;
VPHAL_RENDER_CHK_NULL(pRenderHal);
if ((pRenderHal->bRequestSingleSlice) || (pRenderHal->bEUSaturationNoSSD))
{
bSetRequestedSlices = true;
// bEUSaturationNoSSD: No slice shutdown, must request 2 slices [CM EU saturation on].
// bRequestSingleSlice: Always single slice.
wNumRequestedEUSlices = (pRenderHal->bEUSaturationNoSSD) ? 2 : 1;
}
else
{
bSetRequestedSlices = false;
}
if (pRenderHal->sseuTable)
{
pcSSEUTable = (const VphalSseuSetting*)pRenderHal->sseuTable;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("SSEU Table not valid.");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
VPHAL_RENDER_CHK_NULL(pcSSEUTable);
pcSSEUTable += KernelID;
if (!bSetRequestedSlices) // If num Slices is already programmed, then don't change it
{
if (wNumRequestedEUSlices < pcSSEUTable->numSlices)
{
wNumRequestedEUSlices = pcSSEUTable->numSlices;
}
}
wNumRequestedSubSlices = pcSSEUTable->numSubSlices;
wNumRequestedEUs = pcSSEUTable->numEUs;
#if (_DEBUG || _RELEASE_INTERNAL)
// User feature key reads
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_SSEU_SETTING_OVERRIDE_ID,
&UserFeatureData,
pRenderHal->pOsInterface->pOsContext);
if (UserFeatureData.u32Data != 0xDEADC0DE)
{
wNumRequestedEUSlices = UserFeatureData.u32Data & 0xFF; // Bits 0-7
wNumRequestedSubSlices = (UserFeatureData.u32Data >> 8) & 0xFF; // Bits 8-15
wNumRequestedEUs = (UserFeatureData.u32Data >> 16) & 0xFFFF; // Bits 16-31
}
#endif
PowerOption.nSlice = wNumRequestedEUSlices;
PowerOption.nSubSlice = wNumRequestedSubSlices;
PowerOption.nEU = wNumRequestedEUs;
pRenderHal->pfnSetPowerOptionMode(pRenderHal, &PowerOption);
finish:
return eStatus;
}
// so will enable other renderers like frc and istab support status report.
//!
//! \brief Submit commands for rendering
//! \details Submit commands for rendering. The KMD related fields in pGenericPrologParam might be modified by this
//! function in order to maintain the synchronization mechanism for resource.
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pBatchBuffer
//! Pointer to batch buffer
//! \param [in] bNullRendering
//! Indicate whether is Null rendering
//! \param [in] pWalkerParams
//! Pointer to walker parameters
//! \param [in] pGpGpuWalkerParams
//! Pointer to GPGPU walker parameters
//! \param [in] KernelID
//! VP Kernel ID
//! \param [in] bLastSubmission
//! Is last submission
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_RndrCommonSubmitCommands(
PRENDERHAL_INTERFACE pRenderHal,
PMHW_BATCH_BUFFER pBatchBuffer,
bool bNullRendering,
PMHW_WALKER_PARAMS pWalkerParams,
PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams,
VpKernelID KernelID,
bool bLastSubmission)
{
PMOS_INTERFACE pOsInterface = nullptr;
MOS_COMMAND_BUFFER CmdBuffer = {};
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t dwSyncTag = 0;
int32_t i = 0, iRemaining = 0;
PMHW_MI_INTERFACE pMhwMiInterface = nullptr;
MhwRenderInterface *pMhwRender = nullptr;
MHW_MEDIA_STATE_FLUSH_PARAM FlushParam = {};
bool bEnableSLM = false;
RENDERHAL_GENERIC_PROLOG_PARAMS GenericPrologParams = {};
PMOS_RESOURCE gpuStatusBuffer = nullptr;
MediaPerfProfiler *pPerfProfiler = nullptr;
MOS_CONTEXT *pOsContext = nullptr;
PMHW_MI_MMIOREGISTERS pMmioRegisters = nullptr;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwMiInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface->GetMmioRegisters());
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface->pOsContext);
eStatus = MOS_STATUS_UNKNOWN;
pOsInterface = pRenderHal->pOsInterface;
pMhwMiInterface = pRenderHal->pMhwMiInterface;
pMhwRender = pRenderHal->pMhwRenderInterface;
iRemaining = 0;
FlushParam = g_cRenderHal_InitMediaStateFlushParams;
MOS_ZeroMemory(&CmdBuffer, sizeof(CmdBuffer));
pPerfProfiler = pRenderHal->pPerfProfiler;
pOsContext = pOsInterface->pOsContext;
pMmioRegisters = pMhwRender->GetMmioRegisters();
// Allocate all available space, unused buffer will be returned later
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetCommandBuffer(pOsInterface, &CmdBuffer, 0));
// Set initial state
iRemaining = CmdBuffer.iRemaining;
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonSetPowerMode(
pRenderHal,
KernelID));
#ifndef EMUL
if (bLastSubmission && pOsInterface->bEnableKmdMediaFrameTracking)
{
// 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
HalOcaInterface::On1stLevelBBStart(CmdBuffer, *pOsContext, pOsInterface->CurrentGpuContextHandle,
*pRenderHal->pMhwMiInterface, *pMmioRegisters);
// Add kernel info to log.
HalOcaInterface::DumpVpKernelInfo(CmdBuffer, *pOsContext, KernelID, 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, &GenericPrologParams));
// Write timing data for 3P budget
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendTimingData(pRenderHal, &CmdBuffer, true));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectStartCmd((void*)pRenderHal, pOsInterface, pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(NullHW::StartPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
bEnableSLM = (pGpGpuWalkerParams && pGpGpuWalkerParams->SLMSize > 0)? true : false;
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetCacheOverrideParams(
pRenderHal,
&pRenderHal->L3CacheSettings,
bEnableSLM));
// Flush media states
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendMediaStates(
pRenderHal,
&CmdBuffer,
pWalkerParams,
pGpGpuWalkerParams));
if (pBatchBuffer)
{
// Register batch buffer for rendering
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pBatchBuffer->OsResource,
false,
true));
HalOcaInterface::OnSubLevelBBStart(CmdBuffer, *pOsContext, &pBatchBuffer->OsResource, 0, true, 0);
// Send Start 2nd level batch buffer command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferStartCmd(
&CmdBuffer,
pBatchBuffer));
}
// Write back GPU Status tag
if (!pOsInterface->bEnableKmdMediaFrameTracking)
{
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendRcsStatusTag(pRenderHal, &CmdBuffer));
}
VPHAL_RENDER_CHK_STATUS(NullHW::StopPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectEndCmd((void*)pRenderHal, pOsInterface, pMhwMiInterface, &CmdBuffer));
// Write timing data for 3P budget
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendTimingData(pRenderHal, &CmdBuffer, false));
if (GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform))
{
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
if (MEDIA_IS_WA(pRenderHal->pWaTable, WaMSFWithNoWatermarkTSGHang))
{
FlushParam.bFlushToGo = true;
if (pWalkerParams)
{
FlushParam.ui8InterfaceDescriptorOffset = pWalkerParams->InterfaceDescriptorOffset;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("ERROR, pWalkerParams is nullptr and cannot get InterfaceDescriptorOffset.");
}
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));
}
}
HalOcaInterface::On1stLevelBBEnd(CmdBuffer, *pOsInterface);
if (pBatchBuffer)
{
// Send Batch Buffer end command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
else if (VpHal_RndrCommonIsMiBBEndNeeded(pOsInterface))
{
// Send Batch Buffer end command for 1st level Batch Buffer
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
else if (GFX_IS_GEN_8_OR_LATER(pRenderHal->Platform) &&
Mos_Solo_IsInUse(pOsInterface) &&
pRenderHal->pOsInterface->bNoParsingAssistanceInKmd)
{
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
// Return unused command buffer space to OS
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
// VPHAL_DBG_STATE_DUMPPER_DUMP_COMMAND_BUFFER(pRenderHal, &CmdBuffer);
// Submit command buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnSubmitCommandBuffer(pOsInterface, &CmdBuffer, bNullRendering));
if (bNullRendering == false)
{
dwSyncTag = pRenderHal->pStateHeap->dwNextTag++;
// Set media state and batch buffer as busy
pRenderHal->pStateHeap->pCurMediaState->bBusy = true;
if (pBatchBuffer)
{
pBatchBuffer->bBusy = true;
pBatchBuffer->dwSyncTag = dwSyncTag;
}
}
eStatus = MOS_STATUS_SUCCESS;
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);
// Return unused command buffer space to OS
if (pOsInterface)
{
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
}
}
return eStatus;
}
//!
//! \brief Submit commands for rendering
//! \details Submit commands for rendering with status table update enabling
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pBatchBuffer
//! Pointer to batch buffer
//! \param [in] bNullRendering
//! Indicate whether is Null rendering
//! \param [in] pWalkerParams
//! Pointer to walker parameters
//! \param [in] pGpGpuWalkerParams
//! Pointer to GPGPU walker parameters
//! \param [in] pStatusTableUpdateParams
//! Pointer to pStatusTableUpdateParams
//! \param [in] KernelID
//! VP Kernel ID
//! \param [in] FcKernelCount
//! VP FC Kernel Count
//! \param [in] FcKernelList
//! VP FC Kernel List
//! \param [in] bLastSubmission
//! Is last submission
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_RndrSubmitCommands(
PRENDERHAL_INTERFACE pRenderHal,
PMHW_BATCH_BUFFER pBatchBuffer,
bool bNullRendering,
PMHW_WALKER_PARAMS pWalkerParams,
PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams,
PSTATUS_TABLE_UPDATE_PARAMS pStatusTableUpdateParams,
VpKernelID KernelID,
int FcKernelCount,
int *FcKernelList,
bool bLastSubmission)
{
PMOS_INTERFACE pOsInterface = nullptr;
MOS_COMMAND_BUFFER CmdBuffer = {};
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t dwSyncTag = 0;
int32_t i = 0, iRemaining = 0;
PMHW_MI_INTERFACE pMhwMiInterface = nullptr;
MhwRenderInterface *pMhwRender = nullptr;
MHW_MEDIA_STATE_FLUSH_PARAM FlushParam = {};
bool bEnableSLM = false;
RENDERHAL_GENERIC_PROLOG_PARAMS GenericPrologParams = {};
PMOS_RESOURCE gpuStatusBuffer = nullptr;
MediaPerfProfiler *pPerfProfiler = nullptr;
MOS_CONTEXT *pOsContext = nullptr;
PMHW_MI_MMIOREGISTERS pMmioRegisters = nullptr;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwMiInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface->GetMmioRegisters());
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface->pOsContext);
eStatus = MOS_STATUS_UNKNOWN;
pOsInterface = pRenderHal->pOsInterface;
pMhwMiInterface = pRenderHal->pMhwMiInterface;
pMhwRender = pRenderHal->pMhwRenderInterface;
iRemaining = 0;
FlushParam = g_cRenderHal_InitMediaStateFlushParams;
MOS_ZeroMemory(&CmdBuffer, sizeof(CmdBuffer));
pPerfProfiler = pRenderHal->pPerfProfiler;
pOsContext = pOsInterface->pOsContext;
pMmioRegisters = pMhwRender->GetMmioRegisters();
// Allocate all available space, unused buffer will be returned later
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetCommandBuffer(pOsInterface, &CmdBuffer, 0));
// Set initial state
iRemaining = CmdBuffer.iRemaining;
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonSetPowerMode(
pRenderHal,
KernelID));
#ifndef EMUL
if (bLastSubmission && pOsInterface->bEnableKmdMediaFrameTracking)
{
// 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
HalOcaInterface::On1stLevelBBStart(CmdBuffer, *pOsContext, pOsInterface->CurrentGpuContextHandle,
*pRenderHal->pMhwMiInterface, *pMmioRegisters);
// Add kernel info to log.
HalOcaInterface::DumpVpKernelInfo(CmdBuffer, *pOsContext, KernelID, FcKernelCount, FcKernelList);
// 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, &GenericPrologParams));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectStartCmd((void*)pRenderHal, pOsInterface, pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(NullHW::StartPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
// Write timing data for 3P budget
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendTimingData(pRenderHal, &CmdBuffer, true));
bEnableSLM = (pGpGpuWalkerParams && pGpGpuWalkerParams->SLMSize > 0)? true : false;
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetCacheOverrideParams(
pRenderHal,
&pRenderHal->L3CacheSettings,
bEnableSLM));
if (pRenderHal->bCmfcCoeffUpdate)
{
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendCscCoeffSurface(pRenderHal,
&CmdBuffer,
pRenderHal->pCmfcCoeffSurface,
pRenderHal->pStateHeap->pKernelAllocation[pRenderHal->iKernelAllocationID].pKernelEntry));
}
// Flush media states
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendMediaStates(
pRenderHal,
&CmdBuffer,
pWalkerParams,
pGpGpuWalkerParams));
if (pBatchBuffer)
{
// Register batch buffer for rendering
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pBatchBuffer->OsResource,
false,
true));
HalOcaInterface::OnSubLevelBBStart(CmdBuffer, *pOsContext, &pBatchBuffer->OsResource, 0, true, 0);
// Send Start 2nd level batch buffer command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferStartCmd(
&CmdBuffer,
pBatchBuffer));
}
// Write back GPU Status tag
if (!pOsInterface->bEnableKmdMediaFrameTracking)
{
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendRcsStatusTag(pRenderHal, &CmdBuffer));
}
VPHAL_RENDER_CHK_STATUS(NullHW::StopPredicate(pRenderHal->pMhwMiInterface, &CmdBuffer));
VPHAL_RENDER_CHK_STATUS(pPerfProfiler->AddPerfCollectEndCmd((void*)pRenderHal, pOsInterface, pMhwMiInterface, &CmdBuffer));
// Write timing data for 3P budget
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSendTimingData(pRenderHal, &CmdBuffer, false));
if (GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform))
{
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
if (MEDIA_IS_WA(pRenderHal->pWaTable, WaMSFWithNoWatermarkTSGHang))
{
FlushParam.bFlushToGo = true;
if (pWalkerParams)
{
FlushParam.ui8InterfaceDescriptorOffset = pWalkerParams->InterfaceDescriptorOffset;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("ERROR, pWalkerParams is nullptr and cannot get InterfaceDescriptorOffset.");
}
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));
}
}
HalOcaInterface::On1stLevelBBEnd(CmdBuffer, *pOsInterface);
if (pBatchBuffer)
{
// Send Batch Buffer end command (HW/OS dependent)
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
else if (VpHal_RndrCommonIsMiBBEndNeeded(pOsInterface))
{
// Send Batch Buffer end command for 1st level Batch Buffer
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
else if (GFX_IS_GEN_8_OR_LATER(pRenderHal->Platform) &&
Mos_Solo_IsInUse(pOsInterface) &&
pRenderHal->pOsInterface->bNoParsingAssistanceInKmd)
{
VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(&CmdBuffer, nullptr));
}
// Return unused command buffer space to OS
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
// VPHAL_DBG_STATE_DUMPPER_DUMP_COMMAND_BUFFER(pRenderHal, &CmdBuffer);
#if (_DEBUG || _RELEASE_INTERNAL)
if (pStatusTableUpdateParams->bTriggerGPUHang == true)
{
// Set the GPU HANG Trigger flag here
pOsInterface->bTriggerVPHang = true;
pStatusTableUpdateParams->bTriggerGPUHang = false;
}
#endif
// Submit command buffer
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnSubmitCommandBuffer(pOsInterface, &CmdBuffer, bNullRendering));
if (bNullRendering == false)
{
dwSyncTag = pRenderHal->pStateHeap->dwNextTag++;
// Set media state and batch buffer as busy
pRenderHal->pStateHeap->pCurMediaState->bBusy = true;
if (pBatchBuffer)
{
pBatchBuffer->bBusy = true;
pBatchBuffer->dwSyncTag = dwSyncTag;
}
}
eStatus = MOS_STATUS_SUCCESS;
finish:
if (pStatusTableUpdateParams && pOsInterface)
{
VpHal_RndrUpdateStatusTableAfterSubmit(pOsInterface, pStatusTableUpdateParams, pOsInterface->CurrentGpuContextOrdinal, 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
if (pOsInterface)
{
pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
}
}
return eStatus;
}
//!
//! \brief Initialized RenderHal Surface according to incoming VPHAL Surface
//! \param [in] pVpSurface
//! Pointer to the VPHAL surface
//! \param [out] pRenderHalSurface
//! Pointer to the RenderHal surface
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_RndrCommonInitRenderHalSurface(
PVPHAL_SURFACE pVpSurface,
PRENDERHAL_SURFACE pRenderHalSurface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//---------------------------------------
VPHAL_RENDER_CHK_NULL(pVpSurface);
VPHAL_RENDER_CHK_NULL(pRenderHalSurface);
//---------------------------------------
MOS_ZeroMemory(pRenderHalSurface, sizeof(*pRenderHalSurface));
pRenderHalSurface->OsSurface.OsResource = pVpSurface->OsResource;
pRenderHalSurface->OsSurface.dwWidth = pVpSurface->dwWidth;
pRenderHalSurface->OsSurface.dwHeight = pVpSurface->dwHeight;
pRenderHalSurface->OsSurface.dwPitch = pVpSurface->dwPitch;
pRenderHalSurface->OsSurface.Format = pVpSurface->Format;
pRenderHalSurface->OsSurface.TileType = pVpSurface->TileType;
pRenderHalSurface->OsSurface.TileModeGMM = pVpSurface->TileModeGMM;
pRenderHalSurface->OsSurface.bGMMTileEnabled = pVpSurface->bGMMTileEnabled;
pRenderHalSurface->OsSurface.dwOffset = pVpSurface->dwOffset;
pRenderHalSurface->OsSurface.bIsCompressed = pVpSurface->bIsCompressed;
pRenderHalSurface->OsSurface.bCompressible = pVpSurface->bCompressible;
pRenderHalSurface->OsSurface.CompressionMode = pVpSurface->CompressionMode;
pRenderHalSurface->OsSurface.dwDepth = pVpSurface->dwDepth;
pRenderHalSurface->OsSurface.dwQPitch = pVpSurface->dwHeight;
pRenderHalSurface->OsSurface.MmcState = (MOS_MEMCOMP_STATE)pVpSurface->CompressionMode;
pRenderHalSurface->OsSurface.CompressionFormat = pVpSurface->CompressionFormat;
VpHal_RndrInitPlaneOffset(
&pRenderHalSurface->OsSurface.YPlaneOffset,
&pVpSurface->YPlaneOffset);
VpHal_RndrInitPlaneOffset(
&pRenderHalSurface->OsSurface.UPlaneOffset,
&pVpSurface->UPlaneOffset);
VpHal_RndrInitPlaneOffset(
&pRenderHalSurface->OsSurface.VPlaneOffset,
&pVpSurface->VPlaneOffset);
pRenderHalSurface->rcSrc = pVpSurface->rcSrc;
pRenderHalSurface->rcDst = pVpSurface->rcDst;
pRenderHalSurface->rcMaxSrc = pVpSurface->rcMaxSrc;
pRenderHalSurface->SurfType =
VpHal_RndrInitRenderHalSurfType(pVpSurface->SurfType);
pRenderHalSurface->ScalingMode =
VpHal_RndrInitRenderHalScalingMode(pVpSurface->ScalingMode);
pRenderHalSurface->ChromaSiting = pVpSurface->ChromaSiting;
if (pVpSurface->pDeinterlaceParams != nullptr)
{
pRenderHalSurface->bDeinterlaceEnable = true;
}
else
{
pRenderHalSurface->bDeinterlaceEnable = false;
}
pRenderHalSurface->iPaletteID = pVpSurface->iPalette;
pRenderHalSurface->bQueryVariance = pVpSurface->bQueryVariance;
pRenderHalSurface->bInterlacedScaling = pVpSurface->bInterlacedScaling;
pRenderHalSurface->pDeinterlaceParams = (void *)pVpSurface->pDeinterlaceParams;
pRenderHalSurface->SampleType =
VpHal_RndrInitRenderHalSampleType(pVpSurface->SampleType);
pRenderHalSurface->Rotation =
VpHal_RndrInitRotationMode(pVpSurface->Rotation);
finish:
return eStatus;
}
//!
//! \brief Get output RenderHal Surface parameters back to VPHAL Surface
//! \param [in] pRenderHalSurface
//! Pointer to the RenderHal surface
//! \param [in,out] pVpSurface
//! Pointer to the VPHAL surface
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_RndrCommonGetBackVpSurfaceParams(
PRENDERHAL_SURFACE pRenderHalSurface,
PVPHAL_SURFACE pVpSurface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//---------------------------------------
VPHAL_RENDER_CHK_NULL(pVpSurface);
VPHAL_RENDER_CHK_NULL(pRenderHalSurface);
//---------------------------------------
// The following params are mostly for b32MWColorFillKern on Gen75/Gen8 only
pVpSurface->dwHeight = pRenderHalSurface->OsSurface.dwHeight;
pVpSurface->dwPitch = pRenderHalSurface->OsSurface.dwPitch;
pVpSurface->Format = pRenderHalSurface->OsSurface.Format;
pVpSurface->dwOffset = pRenderHalSurface->OsSurface.dwOffset;
pVpSurface->YPlaneOffset.iXOffset = pRenderHalSurface->OsSurface.YPlaneOffset.iXOffset;
pVpSurface->YPlaneOffset.iYOffset = pRenderHalSurface->OsSurface.YPlaneOffset.iYOffset;
pVpSurface->UPlaneOffset.iSurfaceOffset = pRenderHalSurface->OsSurface.UPlaneOffset.iSurfaceOffset;
pVpSurface->VPlaneOffset.iSurfaceOffset = pRenderHalSurface->OsSurface.VPlaneOffset.iSurfaceOffset;
pVpSurface->rcDst = pRenderHalSurface->rcDst;
pVpSurface->dwWidth = pRenderHalSurface->OsSurface.dwWidth;
pVpSurface->ScalingMode =
VpHal_RndrGetVpHalScalingMode(pRenderHalSurface->ScalingMode);
finish:
return eStatus;
}
//!
//! \brief Set Surface for HW Access
//! \details Common Function for setting up surface state, if render would
//! use CP HM, need use VpHal_CommonSetSurfaceForHwAccess instead
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pSurface
//! Pointer to Surface
//! \param [in] pSurfaceParams
//! Pointer to RenderHal Surface Params
//! \param [in] iBindingTable
//! Binding Table to bind surface
//! \param [in] iBTEntry
//! Binding Table Entry index
//! \param [in] bWrite
//! Write mode flag
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success. Error code otherwise
//!
MOS_STATUS VpHal_RndrCommonSetSurfaceForHwAccess(
PRENDERHAL_INTERFACE pRenderHal,
PVPHAL_SURFACE pSurface,
PRENDERHAL_SURFACE_STATE_PARAMS pSurfaceParams,
int32_t iBindingTable,
int32_t iBTEntry,
bool bWrite)
{
PMOS_INTERFACE pOsInterface;
PRENDERHAL_SURFACE_STATE_ENTRY pSurfaceEntries[MHW_MAX_SURFACE_PLANES];
int32_t iSurfaceEntries;
RENDERHAL_SURFACE RenderHalSurface;
int32_t i;
MOS_STATUS eStatus;
// Initialize Variables
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pRenderHal->pOsInterface;
if (pOsInterface->osCpInterface->IsHMEnabled())
{
VPHAL_RENDER_ASSERTMESSAGE("ERROR, need to use VpHal_CommonSetSurfaceForHwAccess if under CP HM.");
}
// Register surfaces for rendering (GfxAddress/Allocation index)
// Register resource
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pSurface->OsResource,
bWrite,
true));
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(
pSurface,
&RenderHalSurface));
// Setup surface states-----------------------------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetupSurfaceState(
pRenderHal,
&RenderHalSurface,
pSurfaceParams,
&iSurfaceEntries,
pSurfaceEntries,
nullptr));
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonGetBackVpSurfaceParams(
&RenderHalSurface,
pSurface));
// Bind surface states------------------------------------------------------
for (i = 0; i < iSurfaceEntries; i++, iBTEntry++)
{
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnBindSurfaceState(
pRenderHal,
iBindingTable,
iBTEntry,
pSurfaceEntries[i]));
}
finish:
return eStatus;
}
//!
//! \brief Set Buffer Surface for HW Access
//! \details Common Function for setting up buffer surface state, if render would
//! use CP HM, need use VpHal_CommonSetBufferSurfaceForHwAccess instead
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pSurface
//! Pointer to Surface
//! \param [in,out] pSurfaceParams
//! Pointer to RenderHal Surface Params
//! \param [in] iBindingTable
//! Binding Table to Bind Surface
//! \param [in] iBTEntry
//! Binding Table Entry index
//! \param [in] bWrite
//! Write mode flag
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success. Error code otherwise
//!
MOS_STATUS VpHal_RndrCommonSetBufferSurfaceForHwAccess(
PRENDERHAL_INTERFACE pRenderHal,
PVPHAL_SURFACE pSurface,
PRENDERHAL_SURFACE_STATE_PARAMS pSurfaceParams,
int32_t iBindingTable,
int32_t iBTEntry,
bool bWrite)
{
PMOS_INTERFACE pOsInterface;
RENDERHAL_SURFACE RenderHalSurface;
RENDERHAL_SURFACE_STATE_PARAMS SurfaceParam;
PRENDERHAL_SURFACE_STATE_ENTRY pSurfaceEntry;
MOS_STATUS eStatus;
// Initialize Variables
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pRenderHal->pOsInterface;
if (pOsInterface->osCpInterface->IsHMEnabled())
{
VPHAL_RENDER_ASSERTMESSAGE("ERROR, need to use VpHal_CommonSetBufferSurfaceForHwAccess if under CP HM.");
}
// Register surfaces for rendering (GfxAddress/Allocation index)
// Register resource
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pSurface->OsResource,
bWrite,
true));
// Setup Buffer surface-----------------------------------------------------
if (pSurfaceParams == nullptr)
{
MOS_ZeroMemory(&SurfaceParam, sizeof(SurfaceParam));
pSurfaceParams = &SurfaceParam;
}
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(
pSurface,
&RenderHalSurface));
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetupBufferSurfaceState(
pRenderHal,
&RenderHalSurface,
pSurfaceParams,
&pSurfaceEntry));
// Bind surface state-------------------------------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnBindSurfaceState(
pRenderHal,
iBindingTable,
iBTEntry,
pSurfaceEntry));
finish:
return eStatus;
}
//!
//! \brief Set Surface for HW Access for CP HM
//! \details Common Function for setting up surface state, need to use this function
//! if render would use CP HM
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pSurface
//! Pointer to Surface
//! \param [in] pRenderSurface
//! Pointer to Render Surface
//! \param [in] pSurfaceParams
//! Pointer to RenderHal Surface Params
//! \param [in] iBindingTable
//! Binding Table to bind surface
//! \param [in] iBTEntry
//! Binding Table Entry index
//! \param [in] bWrite
//! Write mode flag
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success. Error code otherwise
//!
MOS_STATUS VpHal_CommonSetSurfaceForHwAccess(
PRENDERHAL_INTERFACE pRenderHal,
PVPHAL_SURFACE pSurface,
PRENDERHAL_SURFACE pRenderSurface,
PRENDERHAL_SURFACE_STATE_PARAMS pSurfaceParams,
int32_t iBindingTable,
int32_t iBTEntry,
bool bWrite)
{
PMOS_INTERFACE pOsInterface;
PRENDERHAL_SURFACE_STATE_ENTRY pSurfaceEntries[MHW_MAX_SURFACE_PLANES];
int32_t iSurfaceEntries;
int32_t i;
MOS_STATUS eStatus;
// Initialize Variables
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pRenderHal->pOsInterface;
// Register surfaces for rendering (GfxAddress/Allocation index)
// Register resource
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pSurface->OsResource,
bWrite,
true));
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(
pSurface,
pRenderSurface));
// Setup surface states-----------------------------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetupSurfaceState(
pRenderHal,
pRenderSurface,
pSurfaceParams,
&iSurfaceEntries,
pSurfaceEntries,
nullptr));
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonGetBackVpSurfaceParams(
pRenderSurface,
pSurface));
// Bind surface states------------------------------------------------------
for (i = 0; i < iSurfaceEntries; i++, iBTEntry++)
{
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnBindSurfaceState(
pRenderHal,
iBindingTable,
iBTEntry,
pSurfaceEntries[i]));
}
finish:
return eStatus;
}
//!
//! \brief Set Buffer Surface for HW Access for CP HM
//! \details Common Function for setting up buffer surface state, need to use this function
//! if render would use CP HM
//! \param [in] pRenderHal
//! Pointer to RenderHal Interface Structure
//! \param [in] pSurface
//! Pointer to Surface
//! \param [in] pRenderSurface
//! Pointer to Render Surface
//! \param [in,out] pSurfaceParams
//! Pointer to RenderHal Surface Params
//! \param [in] iBindingTable
//! Binding Table to Bind Surface
//! \param [in] iBTEntry
//! Binding Table Entry index
//! \param [in] bWrite
//! Write mode flag
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if success. Error code otherwise
//!
MOS_STATUS VpHal_CommonSetBufferSurfaceForHwAccess(
PRENDERHAL_INTERFACE pRenderHal,
PVPHAL_SURFACE pSurface,
PRENDERHAL_SURFACE pRenderSurface,
PRENDERHAL_SURFACE_STATE_PARAMS pSurfaceParams,
int32_t iBindingTable,
int32_t iBTEntry,
bool bWrite)
{
PMOS_INTERFACE pOsInterface;
RENDERHAL_SURFACE_STATE_PARAMS SurfaceParam;
PRENDERHAL_SURFACE_STATE_ENTRY pSurfaceEntry;
MOS_STATUS eStatus;
// Initialize Variables
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = pRenderHal->pOsInterface;
// Register surfaces for rendering (GfxAddress/Allocation index)
// Register resource
VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnRegisterResource(
pOsInterface,
&pSurface->OsResource,
bWrite,
true));
// Setup Buffer surface-----------------------------------------------------
if (pSurfaceParams == nullptr)
{
MOS_ZeroMemory(&SurfaceParam, sizeof(SurfaceParam));
pSurfaceParams = &SurfaceParam;
}
VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(
pSurface,
pRenderSurface));
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetupBufferSurfaceState(
pRenderHal,
pRenderSurface,
pSurfaceParams,
&pSurfaceEntry));
// Bind surface state-------------------------------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnBindSurfaceState(
pRenderHal,
iBindingTable,
iBTEntry,
pSurfaceEntry));
finish:
return eStatus;
}
//!
//! \brief Is Alignment WA needed
//! \details Decide WA is needed for VEBOX/Render engine
//! RENDER limitation with composition BOB:
//! Height should be a multiple of 4, otherwise disable DI in Comp
//! VEBOX limitation with TiledY NV12 input(Gen75):
//! Height should be a multiple of 4, otherwise bypass adv render
//! VEBOX limitation with TiledY NV12 input(Gen8/9):
//! 3D/GMM regresses to allocate linear surface when height is not
//! a multiple of 4, no need to bypass adv render
//! \param [in] pSurface
//! Input surface
//! \param [in] GpuContext
//! GpuContext to indicate Render/Vebox
//! \return bool
//! true - Solution is needed; false - Solution is not needed
//!
bool VpHal_RndrCommonIsAlignmentWANeeded(
PVPHAL_SURFACE pSurface,
MOS_GPU_CONTEXT GpuContext)
{
bool bRetVal;
switch (GpuContext)
{
case MOS_GPU_CONTEXT_RENDER:
case MOS_GPU_CONTEXT_VEBOX:
case MOS_GPU_CONTEXT_RENDER3:
case MOS_GPU_CONTEXT_RENDER4:
case MOS_GPU_CONTEXT_COMPUTE:
case MOS_GPU_CONTEXT_COMPUTE_RA:
case MOS_GPU_CONTEXT_RENDER_RA:
if (!(MOS_IS_ALIGNED(MOS_MIN((uint32_t)pSurface->dwHeight, (uint32_t)pSurface->rcMaxSrc.bottom), 4)) &&
(pSurface->Format == Format_NV12))
{
bRetVal = true;
}
else
{
bRetVal = false;
}
break;
default:
VPHAL_RENDER_ASSERTMESSAGE("Incorrect GPU context: %d.", GpuContext);
bRetVal = false;
break;
}
return bRetVal;
}
//!
//! \brief Sets AVS table
//! \details Set 4-tap or 8-tap filtering AVS table
//! \param [in] pAvsParams
//! Pointer to avs parameter
//! \param [in,out] pMhwSamplerAvsTableParam
//! Pointer to avs table parameter
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_RenderCommonSetAVSTableParam(
PMHW_AVS_PARAMS pAvsParams,
PMHW_SAMPLER_AVS_TABLE_PARAM pMhwSamplerAvsTableParam)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t iCoeffTableIdx;
int32_t iFilterCoeffIdx;
int32_t* piYCoefsX;
int32_t* piYCoefsY;
int32_t* piUVCoefsX;
int32_t* piUVCoefsY;
VPHAL_RENDER_CHK_NULL(pAvsParams);
VPHAL_RENDER_CHK_NULL(pMhwSamplerAvsTableParam);
VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsX);
VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsY);
VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsX);
VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsY);
piYCoefsX = pAvsParams->piYCoefsX;
piYCoefsY = pAvsParams->piYCoefsY;
piUVCoefsX = pAvsParams->piUVCoefsX;
piUVCoefsY = pAvsParams->piUVCoefsY;
for (iCoeffTableIdx = 0; iCoeffTableIdx < MHW_NUM_HW_POLYPHASE_TABLES; iCoeffTableIdx++)
{
PMHW_AVS_COEFFICIENT_PARAM pCoeffTable = &pMhwSamplerAvsTableParam->paMhwAvsCoeffParam[iCoeffTableIdx];
// 4-tap filtering for G-channel, update only center 4 coeffs.
if (pMhwSamplerAvsTableParam->b4TapGY)
{
pCoeffTable->ZeroXFilterCoefficient[0] = 0;
pCoeffTable->ZeroXFilterCoefficient[1] = 0;
pCoeffTable->ZeroXFilterCoefficient[2] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[3] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[4] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[5] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[6] = 0;
pCoeffTable->ZeroXFilterCoefficient[7] = 0;
pCoeffTable->ZeroYFilterCoefficient[0] = 0;
pCoeffTable->ZeroYFilterCoefficient[1] = 0;
pCoeffTable->ZeroYFilterCoefficient[2] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[3] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[4] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[5] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[6] = 0;
pCoeffTable->ZeroYFilterCoefficient[7] = 0;
}
else // for gen8+, using 8-tap filter
{
for (iFilterCoeffIdx = 0; iFilterCoeffIdx < 8; iFilterCoeffIdx++)
{
pCoeffTable->ZeroXFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroYFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piYCoefsY++);
}
}
// If 8-tap adaptive filter is enabled, then UV/RB will share the same coefficients with Y/G
if (pMhwSamplerAvsTableParam->b4TapRBUV)
{
// [0..3] maps to filter coefficients [2..5], in actual table [0..1] are reserved
for (iFilterCoeffIdx = 0; iFilterCoeffIdx < 4; iFilterCoeffIdx++)
{
pCoeffTable->OneXFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piUVCoefsX++);
pCoeffTable->OneYFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piUVCoefsY++);
}
}
}
if (pMhwSamplerAvsTableParam->bIsCoeffExtraEnabled)
{
for (iCoeffTableIdx = 0; iCoeffTableIdx < MHW_NUM_HW_POLYPHASE_EXTRA_TABLES_G9; iCoeffTableIdx++)
{
PMHW_AVS_COEFFICIENT_PARAM pCoeffTable = &pMhwSamplerAvsTableParam->paMhwAvsCoeffParamExtra[iCoeffTableIdx];
// 4-tap filtering for G-channel, update only center 4 coeffs.
if (pMhwSamplerAvsTableParam->b4TapGY)
{
pCoeffTable->ZeroXFilterCoefficient[0] = 0;
pCoeffTable->ZeroXFilterCoefficient[1] = 0;
pCoeffTable->ZeroXFilterCoefficient[2] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[3] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[4] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[5] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroXFilterCoefficient[6] = 0;
pCoeffTable->ZeroXFilterCoefficient[7] = 0;
pCoeffTable->ZeroYFilterCoefficient[0] = 0;
pCoeffTable->ZeroYFilterCoefficient[1] = 0;
pCoeffTable->ZeroYFilterCoefficient[2] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[3] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[4] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[5] = (int8_t)*(piYCoefsY++);
pCoeffTable->ZeroYFilterCoefficient[6] = 0;
pCoeffTable->ZeroYFilterCoefficient[7] = 0;
}
else
{
for (iFilterCoeffIdx = 0; iFilterCoeffIdx < 8; iFilterCoeffIdx++)
{
pCoeffTable->ZeroXFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piYCoefsX++);
pCoeffTable->ZeroYFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piYCoefsY++);
}
}
// If 8-tap adaptive filter is enabled, then UV/RB will share the same coefficients with Y/G
if (pMhwSamplerAvsTableParam->b4TapRBUV)
{
for (iFilterCoeffIdx = 0; iFilterCoeffIdx < 4; iFilterCoeffIdx++)
{
// [0..3] maps to filter coefficients [2..5], in actual table [0..1] are reserved
pCoeffTable->OneXFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piUVCoefsX++);
pCoeffTable->OneYFilterCoefficient[iFilterCoeffIdx] = (int8_t)*(piUVCoefsY++);
}
}
}
}
finish:
return eStatus;
}
//!
//! \brief Initialize AVS parameters shared by Renderers
//! \details Initialize the members of the AVS parameter and allocate memory for its coefficient tables
//! \param [in,out] pAVS_Params
//! Pointer to MHW AVS parameter
//! \param [in] uiYCoeffTableSize
//! Size of the Y coefficient table
//! \param [in] uiUVCoeffTableSize
//! Size of the UV coefficient table
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_RndrCommonInitAVSParams(
PMHW_AVS_PARAMS pAVS_Params,
uint32_t uiYCoeffTableSize,
uint32_t uiUVCoeffTableSize)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t size;
char* ptr;
VPHAL_RENDER_CHK_NULL(pAVS_Params);
VPHAL_RENDER_CHK_NULL((void*)(uiYCoeffTableSize > 0));
VPHAL_RENDER_CHK_NULL((void*)(uiUVCoeffTableSize > 0));
// Init AVS parameters
pAVS_Params->Format = Format_None;
pAVS_Params->fScaleX = 0.0F;
pAVS_Params->fScaleY = 0.0F;
pAVS_Params->piYCoefsX = nullptr;
// Allocate AVS coefficients, One set each for X and Y
size = (uiYCoeffTableSize + uiUVCoeffTableSize) * 2;
ptr = (char*)MOS_AllocAndZeroMemory(size);
if (ptr == nullptr)
{
VPHAL_RENDER_ASSERTMESSAGE("No memory to allocate AVS coefficient tables.");
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pAVS_Params->piYCoefsX = (int32_t*)ptr;
ptr += uiYCoeffTableSize;
pAVS_Params->piUVCoefsX = (int32_t*)ptr;
ptr += uiUVCoeffTableSize;
pAVS_Params->piYCoefsY = (int32_t*)ptr;
ptr += uiYCoeffTableSize;
pAVS_Params->piUVCoefsY = (int32_t*)ptr;
finish:
return eStatus;
}
//!
//! \brief Destroy AVS parameters shared by Renderers
//! \details Free the memory of AVS parameter's coefficient tables
//! \param [in,out] pAVS_Params
//! Pointer to VPHAL AVS parameter
//! \return void
//!
void VpHal_RndrCommonDestroyAVSParams(
PMHW_AVS_PARAMS pAVS_Params)
{
VPHAL_RENDER_ASSERT(pAVS_Params);
MOS_SafeFreeMemory(pAVS_Params->piYCoefsX);
pAVS_Params->piYCoefsX = nullptr;
}
//!
//! \brief update status report rely on command buffer sync tag
//! \param [in] pOsInterface
//! pointer to os interface
//! \param [in,out] pStatusTableUpdateParams
//! pointer to STATUS_TABLE_UPDATE_PARAMS for updating status table
//! \param [in] eMosGpuContext
//! current mos contexnt enum
//! \param [in] eLastStatus
//! indicating last submition is successful or not
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_RndrUpdateStatusTableAfterSubmit(
PMOS_INTERFACE pOsInterface,
PSTATUS_TABLE_UPDATE_PARAMS pStatusTableUpdateParams,
MOS_GPU_CONTEXT eMosGpuContext,
MOS_STATUS eLastStatus)
{
PVPHAL_STATUS_ENTRY pStatusEntry;
bool bEmptyTable;
MOS_STATUS eStatus;
uint32_t dwLastTag;
PVPHAL_STATUS_TABLE pStatusTable;
uint32_t dwStatusFeedBackID;
VPHAL_RENDER_CHK_NULL(pStatusTableUpdateParams);
eStatus = MOS_STATUS_SUCCESS;
if (!pStatusTableUpdateParams->bReportStatus ||
!pStatusTableUpdateParams->bSurfIsRenderTarget)
{
goto finish;
}
VPHAL_RENDER_CHK_NULL(pStatusTableUpdateParams->pStatusTable);
VPHAL_RENDER_CHK_NULL(pOsInterface);
pStatusTable = pStatusTableUpdateParams->pStatusTable;
dwStatusFeedBackID = pStatusTableUpdateParams->StatusFeedBackID;
VPHAL_RENDER_ASSERT(pStatusTable->uiHead < VPHAL_STATUS_TABLE_MAX_SIZE);
VPHAL_RENDER_ASSERT(pStatusTable->uiCurrent < VPHAL_STATUS_TABLE_MAX_SIZE);
bEmptyTable = (pStatusTable->uiCurrent == pStatusTable->uiHead);
if (!bEmptyTable)
{
uint32_t uiLast = (pStatusTable->uiCurrent - 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
bool bSameFrameIdWithLastRender = (pStatusTable->aTableEntries[uiLast].StatusFeedBackID == dwStatusFeedBackID);
if (bSameFrameIdWithLastRender)
{
pStatusTable->uiCurrent = uiLast;
}
}
pStatusEntry = &pStatusTable->aTableEntries[pStatusTable->uiCurrent];
pStatusEntry->StatusFeedBackID = dwStatusFeedBackID;
pStatusEntry->GpuContextOrdinal = eMosGpuContext;
dwLastTag = pOsInterface->pfnGetGpuStatusTag(pOsInterface, eMosGpuContext) - 1;
pStatusEntry->dwTag = dwLastTag;
pStatusEntry->dwStatus = (eLastStatus == MOS_STATUS_SUCCESS)? VPREP_NOTREADY : VPREP_ERROR;
pStatusTable->uiCurrent = (pStatusTable->uiCurrent + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
// CM may use a different streamIndex, record it here
if (pStatusTableUpdateParams->bUpdateStreamIndex)
{
pStatusEntry->isStreamIndexSet = true;
pStatusEntry->streamIndex = (uint16_t)pOsInterface->streamIndex;
}
else
{
pStatusEntry->isStreamIndexSet = false;
}
finish:
return eStatus;
}