| /* |
| * Copyright (c) 2017-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 codechal_encode_wp.cpp |
| //! \brief Defines base class for weighted prediction kernel |
| //! |
| |
| #include "codechal_encoder_base.h" |
| #include "codechal_encode_wp.h" |
| #include "hal_oca_interface.h" |
| |
| MOS_STATUS CodechalEncodeWP::AllocateResources() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| if (Mos_ResourceIsNull(&m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx].OsResource)) |
| { |
| MOS_ZeroMemory(&m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx], sizeof(MOS_SURFACE)); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferNV12; |
| MOS_ZeroMemory(&allocParamsForBufferNV12, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferNV12.Type = MOS_GFXRES_2D; |
| allocParamsForBufferNV12.TileType = MOS_TILE_Y; |
| allocParamsForBufferNV12.Format = Format_NV12; |
| allocParamsForBufferNV12.dwWidth = m_frameWidth; |
| allocParamsForBufferNV12.dwHeight = m_frameHeight; |
| allocParamsForBufferNV12.pBufName = "WP Scaled output Buffer"; |
| CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferNV12, |
| &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx].OsResource), |
| "Failed to allocate WP Scaled output Buffer."); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, |
| &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx])); |
| } |
| |
| return eStatus; |
| } |
| |
| void CodechalEncodeWP::ReleaseResources() |
| { |
| for (auto i = 0; i < CODEC_NUM_WP_FRAME; i++) |
| { |
| if (!Mos_ResourceIsNull(&m_surfaceParams.weightedPredOutputPicList[i].OsResource)) |
| { |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_surfaceParams.weightedPredOutputPicList[i].OsResource); |
| } |
| } |
| } |
| |
| uint8_t CodechalEncodeWP::GetBTCount() |
| { |
| return (uint8_t)wpNumSurfaces; |
| } |
| |
| MOS_STATUS CodechalEncodeWP::InitKernelState() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| if (!m_kernelState) |
| { |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_kernelState = MOS_New(MHW_KERNEL_STATE)); |
| } |
| |
| uint8_t* binary; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetKernelBinaryAndSize( |
| m_kernelBase, |
| m_kernelUID, |
| &binary, |
| &m_combinedKernelSize)); |
| |
| auto kernelSize = m_combinedKernelSize; |
| CODECHAL_KERNEL_HEADER currKrnHeader; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnGetKernelHeaderAndSize( |
| binary, |
| ENC_WP, |
| 0, |
| &currKrnHeader, |
| &kernelSize)); |
| |
| m_kernelState->KernelParams.iBTCount = wpNumSurfaces; |
| m_kernelState->KernelParams.iThreadCount = m_renderInterface->GetHwCaps()->dwMaxThreads; |
| m_kernelState->KernelParams.iCurbeLength = m_curbeLength; |
| m_kernelState->KernelParams.iBlockWidth = CODECHAL_MACROBLOCK_WIDTH; |
| m_kernelState->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT; |
| m_kernelState->KernelParams.iIdCount = 1; |
| m_kernelState->KernelParams.iInlineDataLength = 0; |
| m_kernelState->dwCurbeOffset = m_stateHeapInterface->GetSizeofCmdInterfaceDescriptorData(); |
| m_kernelState->KernelParams.pBinary = binary + (currKrnHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT); |
| m_kernelState->KernelParams.iSize = kernelSize; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->CalculateSshAndBtSizesRequested( |
| m_kernelState->KernelParams.iBTCount, |
| &m_kernelState->dwSshSize, |
| &m_kernelState->dwBindingTableSize)); |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_renderInterface->m_stateHeapInterface); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_renderInterface->m_stateHeapInterface, m_kernelState)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeWP::SetCurbe() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| CurbeData curbe; |
| |
| MOS_ZeroMemory(&curbe, sizeof(CurbeData)); |
| /* Weights[i][j][k][m] is interpreted as: |
| |
| i refers to reference picture list 0 or 1; |
| j refers to reference list entry 0-31; |
| k refers to data for the luma (Y) component when it is 0, the Cb chroma component when it is 1 and the Cr chroma component when it is 2; |
| m refers to weight when it is 0 and offset when it is 1 |
| */ |
| //C Model hard code log2WeightDenom = 6. No need to send WD paramters to WP Kernel. |
| curbe.DW0.defaultWeight = m_curbeParams.slcParams->weights[m_curbeParams.refPicListIdx][m_curbeParams.wpIdx][0][0]; |
| curbe.DW0.defaultOffset = m_curbeParams.slcParams->weights[m_curbeParams.refPicListIdx][m_curbeParams.wpIdx][0][1]; |
| |
| curbe.DW49.inputSurface = wpInputRefSurface; |
| curbe.DW50.outputSurface = wpOutputScaledSurface; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_kernelState->m_dshRegion.AddData( |
| &curbe, |
| m_kernelState->dwCurbeOffset, |
| sizeof(curbe))); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeWP::SendSurface(PMOS_COMMAND_BUFFER cmdBuffer) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); |
| |
| auto currFieldPicture = CodecHal_PictureIsField(m_currOriginalPic); |
| // Program the surface based on current picture's field/frame mode |
| uint32_t refBindingTableOffset; |
| uint32_t refVerticalLineStride; |
| uint32_t refVerticalLineStrideOffset; |
| uint8_t refVDirection; |
| if (currFieldPicture) // if current picture is field |
| { |
| if (m_surfaceParams.refIsBottomField) |
| { |
| refVDirection = CODECHAL_VDIRECTION_BOT_FIELD; |
| refVerticalLineStride = CODECHAL_VLINESTRIDE_FIELD; |
| refVerticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_BOT_FIELD; |
| } |
| else |
| { |
| refVDirection = CODECHAL_VDIRECTION_TOP_FIELD; |
| refVerticalLineStride = CODECHAL_VLINESTRIDE_FIELD; |
| refVerticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_TOP_FIELD; |
| } |
| } |
| else // if current picture is frame |
| { |
| refVDirection = CODECHAL_VDIRECTION_FRAME; |
| refVerticalLineStride = CODECHAL_VLINESTRIDE_FRAME; |
| refVerticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_TOP_FIELD; |
| } |
| |
| CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams; |
| MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams)); |
| surfaceCodecParams.bIs2DSurface = true; |
| surfaceCodecParams.bMediaBlockRW = true; |
| surfaceCodecParams.psSurface = m_surfaceParams.refFrameInput; // Input surface |
| surfaceCodecParams.bIsWritable = false; |
| surfaceCodecParams.bRenderTarget = false; |
| surfaceCodecParams.dwBindingTableOffset = wpInputRefSurface; |
| surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_WP_DOWNSAMPLED_ENCODE].Value; |
| surfaceCodecParams.dwVerticalLineStride = refVerticalLineStride; |
| surfaceCodecParams.dwVerticalLineStrideOffset = refVerticalLineStrideOffset; |
| surfaceCodecParams.ucVDirection = refVDirection; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( |
| m_hwInterface, |
| cmdBuffer, |
| &surfaceCodecParams, |
| m_kernelState)); |
| |
| MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams)); |
| surfaceCodecParams.bIs2DSurface = true; |
| surfaceCodecParams.bMediaBlockRW = true; |
| surfaceCodecParams.psSurface = &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx]; // output surface |
| surfaceCodecParams.bIsWritable = true; |
| surfaceCodecParams.bRenderTarget = true; |
| surfaceCodecParams.dwBindingTableOffset = wpOutputScaledSurface; |
| surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_WP_DOWNSAMPLED_ENCODE].Value; |
| surfaceCodecParams.dwVerticalLineStride = refVerticalLineStride; |
| surfaceCodecParams.dwVerticalLineStrideOffset = refVerticalLineStrideOffset; |
| surfaceCodecParams.ucVDirection = refVDirection; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( |
| m_hwInterface, |
| cmdBuffer, |
| &surfaceCodecParams, |
| m_kernelState)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeWP::Execute(KernelParams *params) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| if (params->slcWPParams && params->slcWPParams->luma_log2_weight_denom != 6) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| CODECHAL_ENCODE_ASSERTMESSAGE("Weighted Prediction Kernel does not support Log2LumaWeightDenom != 6!"); |
| return eStatus; |
| } |
| |
| PerfTagSetting perfTag; |
| CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_WP_KERNEL); |
| |
| if (params->useRefPicList1) |
| { |
| *(params->useWeightedSurfaceForL1) = true; |
| m_surfaceParams.wpOutListIdx = CODEC_WP_OUTPUT_L1_START + params->wpIndex; |
| } |
| else |
| { |
| *(params->useWeightedSurfaceForL0) = true; |
| m_surfaceParams.wpOutListIdx = CODEC_WP_OUTPUT_L0_START + params->wpIndex; |
| } |
| if (m_surfaceParams.wpOutListIdx >= CODEC_NUM_WP_FRAME) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| CODECHAL_ENCODE_ASSERTMESSAGE("index exceeds maximum value of array weightedPredOutputPicList."); |
| return eStatus; |
| } |
| |
| // Allocate output surface |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources()); |
| |
| // If Single Task Phase is not enabled, use BT count for the kernel state. |
| if (m_firstTaskInPhase == true || !m_singleTaskPhaseSupported) |
| { |
| auto maxBtCount = m_singleTaskPhaseSupported ? |
| m_maxBtCount : m_kernelState->KernelParams.iBTCount; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->RequestSshSpaceForCmdBuf(maxBtCount)); |
| m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->VerifySpaceAvailable()); |
| } |
| |
| // setup DSH and Interface Descriptor |
| auto stateHeapInterface = m_renderInterface->m_stateHeapInterface; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(stateHeapInterface); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( |
| stateHeapInterface, |
| m_kernelState, |
| false, |
| 0, |
| false, |
| m_storeData)); |
| |
| MHW_INTERFACE_DESCRIPTOR_PARAMS idParams; |
| MOS_ZeroMemory(&idParams, sizeof(idParams)); |
| idParams.pKernelState = m_kernelState; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SetInterfaceDescriptor(1, &idParams)); |
| |
| // Setup Curbe |
| m_curbeParams.refPicListIdx = (params->useRefPicList1) ? LIST_1 : LIST_0; |
| m_curbeParams.wpIdx = params->wpIndex; |
| m_curbeParams.slcParams = params->slcWPParams; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbe()); |
| |
| auto encFunctionType = CODECHAL_MEDIA_STATE_ENC_WP; |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_DSH_TYPE, |
| m_kernelState)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( |
| encFunctionType, |
| m_kernelState)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_ISH_TYPE, |
| m_kernelState)); |
| ) |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); |
| |
| SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams(); |
| sendKernelCmdsParams.EncFunctionType = encFunctionType; |
| sendKernelCmdsParams.pKernelState = m_kernelState; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams)); |
| |
| // add binding table |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SetBindingTable(m_kernelState)); |
| |
| (params->useRefPicList1) ? (*params->useWeightedSurfaceForL1 = true) : (*params->useWeightedSurfaceForL0 = true); |
| CodecHalGetResourceInfo(m_osInterface, params->refFrameInput); |
| |
| //Set Surface States |
| m_surfaceParams.refFrameInput = params->refFrameInput; |
| m_surfaceParams.refIsBottomField = params->refIsBottomField; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SendSurface(&cmdBuffer)); |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_SSH_TYPE, |
| m_kernelState)); |
| ) |
| |
| // Thread Dispatch Pattern - MEDIA OBJECT WALKER |
| if (m_hwWalker) |
| { |
| auto resolutionX = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth); |
| auto resolutionY = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight); |
| |
| CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams; |
| MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams)); |
| walkerCodecParams.WalkerMode = m_walkerMode; |
| walkerCodecParams.bUseScoreboard = m_useHwScoreboard; |
| walkerCodecParams.dwResolutionX = resolutionX; |
| walkerCodecParams.dwResolutionY = resolutionY; |
| walkerCodecParams.bGroupIdSelectSupported = m_groupIdSelectSupported; |
| walkerCodecParams.ucGroupId = m_groupId; |
| walkerCodecParams.bNoDependency = true; |
| |
| MHW_WALKER_PARAMS walkerParams; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams(m_hwInterface, &walkerParams, &walkerCodecParams)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderInterface->AddMediaObjectWalkerCmd(&cmdBuffer, &walkerParams)); |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->EndStatusReport(&cmdBuffer, encFunctionType)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SubmitBlocks(m_kernelState)); |
| if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->UpdateGlobalCmdBufId()); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); |
| } |
| |
| CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( |
| &cmdBuffer, |
| encFunctionType, |
| nullptr))); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer( |
| &cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase)); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) |
| { |
| HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); |
| m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw); |
| m_lastTaskInPhase = false; |
| } |
| |
| return eStatus; |
| } |
| |
| CodechalEncodeWP::CodechalEncodeWP(CodechalEncoderState *encoder) |
| : m_useHwScoreboard(encoder->m_useHwScoreboard), |
| m_renderContextUsesNullHw(encoder->m_renderContextUsesNullHw), |
| m_groupIdSelectSupported(encoder->m_groupIdSelectSupported), |
| m_singleTaskPhaseSupported(encoder->m_singleTaskPhaseSupported), |
| m_firstTaskInPhase(encoder->m_firstTaskInPhase), |
| m_lastTaskInPhase(encoder->m_lastTaskInPhase), |
| m_hwWalker(encoder->m_hwWalker), |
| m_groupId(encoder->m_groupId), |
| m_pictureCodingType(encoder->m_pictureCodingType), |
| m_mode(encoder->m_mode), |
| m_verticalLineStride(encoder->m_verticalLineStride), |
| m_maxBtCount(encoder->m_maxBtCount), |
| m_vmeStatesSize(encoder->m_vmeStatesSize), |
| m_storeData(encoder->m_storeData), |
| m_frameWidth(encoder->m_frameWidth), |
| m_frameHeight(encoder->m_frameHeight), |
| m_frameFieldHeight(encoder->m_frameFieldHeight), |
| m_currOriginalPic(encoder->m_currOriginalPic), |
| m_walkerMode(encoder->m_walkerMode) |
| { |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(encoder); |
| |
| // Initilize interface pointers |
| m_encoder = encoder; |
| m_osInterface = encoder->GetOsInterface(); |
| m_hwInterface = encoder->GetHwInterface(); |
| m_debugInterface = encoder->GetDebugInterface(); |
| m_miInterface = m_hwInterface->GetMiInterface(); |
| m_renderInterface = m_hwInterface->GetRenderInterface(); |
| m_stateHeapInterface = m_renderInterface->m_stateHeapInterface->pStateHeapInterface; |
| m_curbeLength = sizeof(CurbeData); |
| } |
| |
| CodechalEncodeWP::~CodechalEncodeWP() |
| { |
| // free weighted prediction surface |
| ReleaseResources(); |
| |
| MOS_Delete(m_kernelState); |
| m_kernelState = nullptr; |
| } |