1 /* 2 * Copyright (c) 2018-2021, Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 //! 24 //! \file encode_huc.cpp 25 //! \brief Defines the common interface for encode huc implementation 26 //! \details The encode huc interface is further sub-divided by different huc usage, 27 //! this file is for the base interface which is shared by all. 28 //! 29 30 #include "encode_huc.h" 31 #include "codechal_debug.h" 32 #include <algorithm> 33 34 namespace encode 35 { Init()36 MOS_STATUS EncodeHucPkt::Init() 37 { 38 HUC_CHK_STATUS_RETURN(CmdPacket::Init()); 39 m_allocator = m_pipeline->GetEncodeAllocator(); 40 HUC_CHK_STATUS_RETURN(AllocateResources()); 41 42 ENCODE_CHK_NULL_RETURN(m_pipeline); 43 m_statusReport = m_pipeline->GetStatusReportInstance(); 44 ENCODE_CHK_NULL_RETURN(m_statusReport); 45 ENCODE_CHK_STATUS_RETURN(m_statusReport->RegistObserver(this)); 46 47 HUC_CHK_NULL_RETURN(m_hwInterface); 48 m_skuFtrEnableMediaKernels = MEDIA_IS_SKU(m_hwInterface->GetSkuTable(), FtrEnableMediaKernels); 49 m_hucItf = m_hwInterface->GetHucInterfaceNext(); 50 HUC_CHK_NULL_RETURN(m_hucItf); 51 m_hucStatus2ImemLoadedMask = m_hucItf->GetHucStatus2ImemLoadedMask(); 52 53 return MOS_STATUS_SUCCESS; 54 } 55 IsHuCStsUpdNeeded()56 bool EncodeHucPkt::IsHuCStsUpdNeeded() 57 { 58 bool enabled = false; 59 #if _SW_BRC 60 enabled = m_swBrc && m_swBrc->SwBrcEnabled(); 61 #endif // !_SW_BRC 62 return enabled; 63 } 64 AllocateResources()65 MOS_STATUS EncodeHucPkt::AllocateResources() 66 { 67 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; 68 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 69 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; 70 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; 71 allocParamsForBufferLinear.Format = Format_Buffer; 72 73 // HUC STATUS 2 Buffer for HuC status check in COND_BB_END 74 allocParamsForBufferLinear.dwBytes = sizeof(uint64_t); 75 allocParamsForBufferLinear.pBufName = "HUC STATUS 2 Buffer"; 76 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; 77 PMOS_RESOURCE allocatedbuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 78 ENCODE_CHK_NULL_RETURN(allocatedbuffer); 79 m_resHucStatus2Buffer = allocatedbuffer; 80 81 return MOS_STATUS_SUCCESS; 82 } 83 StoreHuCStatus2Register(PMOS_COMMAND_BUFFER cmdBuffer,bool storeHucStatus2Needed)84 MOS_STATUS EncodeHucPkt::StoreHuCStatus2Register(PMOS_COMMAND_BUFFER cmdBuffer, bool storeHucStatus2Needed) 85 { 86 HUC_CHK_NULL_RETURN(cmdBuffer); 87 HUC_CHK_NULL_RETURN(m_statusReport); 88 89 auto mmioRegisters = m_hucItf->GetMmioRegisters(m_vdboxIndex); 90 HUC_CHK_NULL_RETURN(mmioRegisters); 91 92 PMOS_RESOURCE osResource = nullptr; 93 uint32_t offset = 0; 94 95 ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(statusReportHucStatus2Reg, osResource, offset)); 96 97 auto &storeRegParams = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)(); 98 storeRegParams = {}; 99 storeRegParams.presStoreBuffer = osResource; 100 storeRegParams.dwOffset = offset; 101 storeRegParams.dwRegister = mmioRegisters->hucStatus2RegOffset; 102 HUC_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(cmdBuffer)); 103 104 if (storeHucStatus2Needed) 105 { 106 // Write HUC_STATUS2 mask - bit 6 - valid IMEM loaded 107 auto &storeDataParams = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)(); 108 storeDataParams = {}; 109 storeDataParams.pOsResource = m_resHucStatus2Buffer; 110 storeDataParams.dwResourceOffset = 0; 111 storeDataParams.dwValue = m_hucItf->GetHucStatus2ImemLoadedMask(); 112 HUC_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(cmdBuffer)); 113 114 // Store HUC_STATUS2 register 115 auto &storeRegParams = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)(); 116 storeRegParams = {}; 117 storeRegParams.presStoreBuffer = m_resHucStatus2Buffer; 118 storeRegParams.dwOffset = sizeof(uint32_t); 119 storeRegParams.dwRegister = mmioRegisters->hucStatus2RegOffset; 120 HUC_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(cmdBuffer)); 121 } 122 123 return MOS_STATUS_SUCCESS; 124 } 125 SendPrologCmds(MOS_COMMAND_BUFFER & cmdBuffer)126 MOS_STATUS EncodeHucPkt::SendPrologCmds( 127 MOS_COMMAND_BUFFER &cmdBuffer) 128 { 129 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 130 131 ENCODE_FUNC_CALL(); 132 bool mmcEnabled = false; 133 #ifdef _MMC_SUPPORTED 134 EncodeMemComp *mmcState = m_pipeline->GetMmcState(); 135 ENCODE_CHK_NULL_RETURN(mmcState); 136 mmcEnabled = mmcState->IsMmcEnabled(); 137 ENCODE_CHK_STATUS_RETURN(mmcState->SendPrologCmd(&cmdBuffer, false)); 138 #endif 139 140 MHW_GENERIC_PROLOG_PARAMS genericPrologParams; 141 MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams)); 142 ENCODE_CHK_NULL_RETURN(m_hwInterface); 143 genericPrologParams.pOsInterface = m_hwInterface->GetOsInterface(); 144 std::shared_ptr<void> m_miItf = m_hwInterface->GetMiInterfaceNext(); 145 genericPrologParams.pvMiInterface = nullptr; 146 genericPrologParams.bMmcEnabled = mmcEnabled; 147 ENCODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf)); 148 149 return eStatus; 150 } 151 AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)152 MOS_STATUS EncodeHucPkt::AddForceWakeup(MOS_COMMAND_BUFFER &cmdBuffer) 153 { 154 ENCODE_FUNC_CALL(); 155 156 auto &forceWakeupParams = m_miItf->MHW_GETPAR_F(MI_FORCE_WAKEUP)(); 157 forceWakeupParams = {}; 158 forceWakeupParams.bMFXPowerWellControl = true; 159 forceWakeupParams.bMFXPowerWellControlMask = true; 160 forceWakeupParams.bHEVCPowerWellControl = true; 161 forceWakeupParams.bHEVCPowerWellControlMask = true; 162 163 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FORCE_WAKEUP)(&cmdBuffer)); 164 165 return MOS_STATUS_SUCCESS; 166 } 167 SetPerfTag(uint16_t type,uint16_t mode,uint16_t picCodingType)168 void EncodeHucPkt::SetPerfTag(uint16_t type, uint16_t mode, uint16_t picCodingType) 169 { 170 ENCODE_FUNC_CALL(); 171 172 PerfTagSetting perfTag; 173 perfTag.Value = 0; 174 perfTag.Mode = mode & CODECHAL_ENCODE_MODE_BIT_MASK; 175 perfTag.CallType = type; 176 perfTag.PictureCodingType = picCodingType > 3 ? 0 : picCodingType; 177 m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); 178 m_osInterface->pfnIncPerfBufferID(m_osInterface); 179 } 180 StartPerfCollect(MOS_COMMAND_BUFFER & cmdBuffer)181 MOS_STATUS EncodeHucPkt::StartPerfCollect(MOS_COMMAND_BUFFER& cmdBuffer) 182 { 183 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance(); 184 ENCODE_CHK_NULL_RETURN(perfProfiler); 185 ENCODE_CHK_STATUS_RETURN(perfProfiler->AddPerfCollectStartCmd( 186 (void *)m_pipeline, m_osInterface, m_miItf, &cmdBuffer)); 187 188 return MOS_STATUS_SUCCESS; 189 } 190 EndPerfCollect(MOS_COMMAND_BUFFER & cmdBuffer)191 MOS_STATUS EncodeHucPkt::EndPerfCollect(MOS_COMMAND_BUFFER& cmdBuffer) 192 { 193 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance(); 194 ENCODE_CHK_NULL_RETURN(perfProfiler); 195 ENCODE_CHK_STATUS_RETURN(perfProfiler->AddPerfCollectEndCmd( 196 (void *)m_pipeline, m_osInterface, m_miItf, &cmdBuffer)); 197 198 return MOS_STATUS_SUCCESS; 199 } 200 AddAllCmds_HUC_PIPE_MODE_SELECT(PMOS_COMMAND_BUFFER cmdBuffer) const201 MOS_STATUS EncodeHucPkt::AddAllCmds_HUC_PIPE_MODE_SELECT(PMOS_COMMAND_BUFFER cmdBuffer) const 202 { 203 MHW_MI_CHK_NULL(cmdBuffer); 204 205 //for gen 11, we need to add MFX wait for both KIN and VRT before and after HUC Pipemode select... 206 auto &mfxWaitParams = m_miItf->MHW_GETPAR_F(MFX_WAIT)(); 207 mfxWaitParams = {}; 208 mfxWaitParams.iStallVdboxPipeline = true; 209 MHW_MI_CHK_STATUS(m_miItf->MHW_ADDCMD_F(MFX_WAIT)(cmdBuffer)); 210 211 SETPAR_AND_ADDCMD(HUC_PIPE_MODE_SELECT, m_hucItf, cmdBuffer); 212 213 //for gen 11, we need to add MFX wait for both KIN and VRT before and after HUC Pipemode select... 214 mfxWaitParams = {}; 215 mfxWaitParams.iStallVdboxPipeline = true; 216 MHW_MI_CHK_STATUS(m_miItf->MHW_ADDCMD_F(MFX_WAIT)(cmdBuffer)); 217 218 return MOS_STATUS_SUCCESS; 219 } 220 AddAllCmds_HUC_IMEM_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const221 MOS_STATUS EncodeHucPkt::AddAllCmds_HUC_IMEM_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const 222 { 223 MHW_MI_CHK_NULL(cmdBuffer); 224 225 SETPAR_AND_ADDCMD(HUC_IMEM_STATE, m_hucItf, cmdBuffer); 226 227 auto &mfxWaitParams = m_miItf->MHW_GETPAR_F(MFX_WAIT)(); 228 mfxWaitParams = {}; 229 mfxWaitParams.iStallVdboxPipeline = true; 230 MHW_MI_CHK_STATUS(m_miItf->MHW_ADDCMD_F(MFX_WAIT)(cmdBuffer)); 231 232 return MOS_STATUS_SUCCESS; 233 } 234 Execute(PMOS_COMMAND_BUFFER cmdBuffer,bool storeHucStatus2Needed,bool prologNeeded,HuCFunction function)235 MOS_STATUS EncodeHucPkt::Execute(PMOS_COMMAND_BUFFER cmdBuffer, bool storeHucStatus2Needed, bool prologNeeded, HuCFunction function) 236 { 237 HUC_CHK_NULL_RETURN(cmdBuffer); 238 239 #if _SW_BRC 240 HUC_CHK_STATUS_RETURN(InitSwBrc(function)); 241 if (function != NONE_BRC && m_swBrc && m_swBrc->SwBrcEnabled()) 242 { 243 SETPAR(HUC_DMEM_STATE, m_hucItf); 244 SETPAR(HUC_VIRTUAL_ADDR_STATE, m_hucItf); 245 246 auto &virtualAddrParams = m_hucItf->MHW_GETPAR_F(HUC_VIRTUAL_ADDR_STATE)(); 247 auto &dmemParams = m_hucItf->MHW_GETPAR_F(HUC_DMEM_STATE)(); 248 249 CODECHAL_DEBUG_TOOL( 250 ENCODE_CHK_STATUS_RETURN(DumpInput());) 251 252 EncodeBasicFeature *basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature)); 253 HUC_CHK_NULL_RETURN(basicFeature); 254 return m_swBrc->SwBrcImpl( 255 function, 256 virtualAddrParams, 257 dmemParams, 258 basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0)); 259 } 260 #endif // !_SW_BRC 261 262 if (prologNeeded) 263 { 264 ENCODE_CHK_STATUS_RETURN(AddForceWakeup(*cmdBuffer)); 265 ENCODE_CHK_STATUS_RETURN(SendPrologCmds(*cmdBuffer)); 266 } 267 268 ENCODE_CHK_STATUS_RETURN(StartPerfCollect(*cmdBuffer)); 269 270 AddAllCmds_HUC_IMEM_STATE(cmdBuffer); 271 AddAllCmds_HUC_PIPE_MODE_SELECT(cmdBuffer); 272 273 SETPAR_AND_ADDCMD(HUC_DMEM_STATE, m_hucItf, cmdBuffer); 274 SETPAR_AND_ADDCMD(HUC_VIRTUAL_ADDR_STATE, m_hucItf, cmdBuffer); 275 276 m_enableHucStatusReport = true; 277 HUC_CHK_STATUS_RETURN(StoreHuCStatus2Register(cmdBuffer, storeHucStatus2Needed)); 278 279 SETPAR_AND_ADDCMD(HUC_START, m_hucItf, cmdBuffer); 280 281 CODECHAL_DEBUG_TOOL( 282 ENCODE_CHK_STATUS_RETURN(DumpInput());) 283 284 SETPAR_AND_ADDCMD(VD_PIPELINE_FLUSH, m_vdencItf, cmdBuffer); 285 286 // Flush the engine to ensure memory written out 287 auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)(); 288 flushDwParams = {}; 289 flushDwParams.bVideoPipelineCacheInvalidate = true; 290 HUC_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer)); 291 292 ENCODE_CHK_STATUS_RETURN(EndPerfCollect(*cmdBuffer)); 293 HUC_CHK_STATUS_RETURN(StoreHuCStatusRegister(cmdBuffer)); 294 295 return MOS_STATUS_SUCCESS; 296 } 297 MHW_SETPAR_DECL_SRC(VD_PIPELINE_FLUSH,EncodeHucPkt)298 MHW_SETPAR_DECL_SRC(VD_PIPELINE_FLUSH, EncodeHucPkt) 299 { 300 params.waitDoneHEVC = true; 301 params.flushHEVC = true; 302 return MOS_STATUS_SUCCESS; 303 } 304 Completed(void * mfxStatus,void * rcsStatus,void * statusReport)305 MOS_STATUS EncodeHucPkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport) 306 { 307 ENCODE_FUNC_CALL(); 308 309 if (!m_enableHucStatusReport) 310 { 311 return MOS_STATUS_SUCCESS; 312 } 313 314 ENCODE_CHK_NULL_RETURN(mfxStatus); 315 ENCODE_CHK_NULL_RETURN(statusReport); 316 317 EncodeStatusMfx *encodeStatusMfx = (EncodeStatusMfx *)mfxStatus; 318 319 MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData; 320 MOS_ZeroMemory(&userFeatureWriteData, sizeof(MOS_USER_FEATURE_VALUE_WRITE_DATA)); 321 322 if (!m_skuFtrEnableMediaKernels) 323 { 324 ENCODE_ASSERTMESSAGE("Failed to load HuC firmware!"); 325 326 // Reporting 327 ReportUserSetting( 328 m_userSettingPtr, 329 "HuC Firmware Load Failed", 330 1, 331 MediaUserSetting::Group::Sequence); 332 333 return MOS_STATUS_HUC_KERNEL_FAILED; 334 } 335 else if (!(encodeStatusMfx->hucStatus2Reg & m_hucStatus2ImemLoadedMask)) 336 { 337 ENCODE_ASSERTMESSAGE("HuC status2 indicates Valid Imem Load failed!"); 338 339 // Reporting 340 ReportUserSetting( 341 m_userSettingPtr, 342 "HuC Valid Imem Load Failed", 343 1, 344 MediaUserSetting::Group::Sequence); 345 346 #if (_DEBUG || _RELEASE_INTERNAL) 347 ReportUserSettingForDebug( 348 m_userSettingPtr, 349 "Huc Status2 Value", 350 encodeStatusMfx->hucStatus2Reg, 351 MediaUserSetting::Group::Sequence); 352 #endif 353 354 return MOS_STATUS_HUC_KERNEL_FAILED; 355 } 356 #if (_DEBUG || _RELEASE_INTERNAL) 357 else 358 { 359 EncodeStatusReportData* encodeStatusReport = (EncodeStatusReportData *)statusReport; 360 std::string hucStatusReport = "HuC Status Value is " + std::to_string(encodeStatusMfx->hucStatusReg) + 361 " for Frame number #" + std::to_string(encodeStatusReport->statusReportNumber) + "."; 362 ENCODE_NORMALMESSAGE(hucStatusReport.c_str()); 363 } 364 #endif 365 366 return MOS_STATUS_SUCCESS; 367 } 368 StoreHuCStatusRegister(PMOS_COMMAND_BUFFER cmdBuffer)369 MOS_STATUS EncodeHucPkt::StoreHuCStatusRegister(PMOS_COMMAND_BUFFER cmdBuffer) 370 { 371 HUC_CHK_NULL_RETURN(cmdBuffer); 372 HUC_CHK_NULL_RETURN(m_statusReport); 373 374 auto mmioRegisters = m_hucItf->GetMmioRegisters(m_vdboxIndex); 375 HUC_CHK_NULL_RETURN(mmioRegisters); 376 377 PMOS_RESOURCE osResource = nullptr; 378 uint32_t offset = 0; 379 380 ENCODE_CHK_STATUS_RETURN(m_statusReport->GetAddress(statusReportHucStatusReg, osResource, offset)); 381 382 // Store HUC_STATUS register 383 auto &storeRegParams = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)(); 384 storeRegParams = {}; 385 storeRegParams.presStoreBuffer = osResource; 386 storeRegParams.dwOffset = offset; 387 storeRegParams.dwRegister = mmioRegisters->hucStatusRegOffset; 388 HUC_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(cmdBuffer)); 389 390 return MOS_STATUS_SUCCESS; 391 } 392 393 #if _SW_BRC InitSwBrc(HuCFunction function)394 MOS_STATUS EncodeHucPkt::InitSwBrc(HuCFunction function) 395 { 396 if (m_swBrc == nullptr) 397 { 398 EncodeBasicFeature* basicFeature = dynamic_cast<EncodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature)); 399 HUC_CHK_NULL_RETURN(basicFeature); 400 m_swBrc = EncodeSwBrc::CreateFactory(basicFeature->m_mode, m_allocator, m_hwInterface->GetOsInterface(), function); 401 } 402 return MOS_STATUS_SUCCESS; 403 } 404 #endif // !_SW_BRC 405 406 #if USE_CODECHAL_DEBUG_TOOL DumpRegion(uint32_t regionNum,const char * regionName,bool inputBuffer,CodechalHucRegionDumpType dumpType,uint32_t size)407 MOS_STATUS EncodeHucPkt::DumpRegion( 408 uint32_t regionNum, 409 const char *regionName, 410 bool inputBuffer, 411 CodechalHucRegionDumpType dumpType, 412 uint32_t size) 413 { 414 auto virtualAddrParams = m_hucItf->MHW_GETPAR_F(HUC_VIRTUAL_ADDR_STATE)(); 415 auto bufferToDump = virtualAddrParams.regionParams[regionNum].presRegion; 416 auto offset = virtualAddrParams.regionParams[regionNum].dwOffset; 417 418 CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface(); 419 ENCODE_CHK_NULL_RETURN(debugInterface); 420 421 if (bufferToDump) 422 { 423 // Dump the full region when size = 0 or exceed the region size, else dump the size indicated 424 GMM_SIZE_PARAM GmmSizeParam = GMM_MAIN_SURF; 425 uint32_t bufferSize = (uint32_t)bufferToDump->pGmmResInfo->GetSize(GmmSizeParam); 426 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion( 427 bufferToDump, 428 offset, 429 size ? size : bufferSize, 430 regionNum, 431 regionName, 432 inputBuffer, 433 m_pipeline->GetCurrentPass(), 434 dumpType)); 435 } 436 437 return MOS_STATUS_SUCCESS; 438 } 439 #endif 440 } 441