1 /*
2 * Copyright (c) 2020-2023, 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 //! \file     encode_avc_huc_brc_update_packet.cpp
24 //! \brief    Defines the implementation of avc huc update packet
25 //!
26 
27 #include "encode_avc_huc_brc_update_packet.h"
28 #include "encode_avc_vdenc_stream_in_feature.h"
29 #include "encode_avc_basic_feature.h"
30 #include "encode_avc_brc.h"
31 #include "encode_avc_vdenc_const_settings.h"
32 #include "media_avc_feature_defs.h"
33 #include "mos_os_cp_interface_specific.h"
34 
35 namespace encode {
36 
37 #define VDENC_AVC_STATIC_FRAME_INTRACOSTSCLRatioP   240
38 #define VDENC_AVC_BRC_HUC_STATUS_REENCODE_MASK      (1 << 31)
39 
Init()40 MOS_STATUS AvcHucBrcUpdatePkt::Init()
41 {
42     ENCODE_FUNC_CALL();
43 
44     ENCODE_CHK_NULL_RETURN(m_featureManager);
45     m_basicFeature = dynamic_cast<AvcBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
46     ENCODE_CHK_NULL_RETURN(m_basicFeature);
47 
48     m_brcFeature = dynamic_cast<AvcEncodeBRC *>(m_featureManager->GetFeature(AvcFeatureIDs::avcBrcFeature));
49     ENCODE_CHK_NULL_RETURN(m_brcFeature);
50 
51     ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::Init());
52 
53     return MOS_STATUS_SUCCESS;
54 }
55 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)56 MOS_STATUS AvcHucBrcUpdatePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
57 {
58     ENCODE_FUNC_CALL();
59 
60     auto osInterface = m_hwInterface->GetOsInterface();
61     ENCODE_CHK_NULL_RETURN(osInterface);
62 
63     uint32_t hucCommandsSize = 0;
64     uint32_t hucPatchListSize = 0;
65     MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
66 
67     ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize(
68         m_basicFeature->m_mode, (uint32_t*)&hucCommandsSize, (uint32_t*)&hucPatchListSize, &stateCmdSizeParams));
69 
70     commandBufferSize = hucCommandsSize;
71     requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0;
72 
73     if (m_pipeline->IsSingleTaskPhaseSupported())
74     {
75         commandBufferSize *= m_pipeline->GetPassNum();
76     }
77 
78     // 4K align since allocation is in chunks of 4K bytes.
79     commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE);
80 
81     return MOS_STATUS_SUCCESS;
82 }
83 
SetDmemBuffer() const84 MOS_STATUS AvcHucBrcUpdatePkt::SetDmemBuffer()const
85 {
86     ENCODE_FUNC_CALL();
87 
88     // Program update DMEM
89     auto hucVdencBrcUpdateDmem = (VdencAvcHucBrcUpdateDmem*)m_allocator->LockResourceForWrite(
90         m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]);
91     ENCODE_CHK_NULL_RETURN(hucVdencBrcUpdateDmem);
92 
93     RUN_FEATURE_INTERFACE_RETURN(AvcEncodeBRC, AvcFeatureIDs::avcBrcFeature, SetDmemForUpdate, hucVdencBrcUpdateDmem, m_pipeline->GetCurrentPass(), m_pipeline->IsLastPass());
94 
95     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(
96         m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]));
97 
98     return MOS_STATUS_SUCCESS;
99 }
100 
DumpOutput()101 MOS_STATUS AvcHucBrcUpdatePkt::DumpOutput()
102 {
103     ENCODE_FUNC_CALL();
104 
105 #if USE_CODECHAL_DEBUG_TOOL
106     ENCODE_CHK_STATUS_RETURN(DumpHucBrcUpdate(false));
107     ENCODE_CHK_STATUS_RETURN(DumpEncodeImgStats(nullptr));
108 #endif
109 
110     return MOS_STATUS_SUCCESS;
111 }
112 
AllocateResources()113 MOS_STATUS AvcHucBrcUpdatePkt::AllocateResources()
114 {
115     ENCODE_FUNC_CALL();
116 
117     PMOS_RESOURCE allocatedbuffer;
118 
119     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
120     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
121     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
122     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
123     allocParamsForBufferLinear.Format   = Format_Buffer;
124 
125     // Const Data buffer
126     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_vdencBrcConstDataBufferSize, CODECHAL_PAGE_SIZE);
127     allocParamsForBufferLinear.pBufName = "VDENC BRC Const Data Buffer";
128     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
129     for (uint32_t i = 0; i < CODECHAL_ENCODE_VDENC_BRC_CONST_BUFFER_NUM; i++)
130     {
131         allocatedbuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
132         ENCODE_CHK_NULL_RETURN(allocatedbuffer);
133         m_vdencBrcConstDataBuffer[i] = allocatedbuffer;
134     }
135 
136     for (uint32_t k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++)
137     {
138         // VDENC IMG STATE read buffer
139         allocParamsForBufferLinear.dwBytes  = m_brcFeature->GetVdencBRCImgStateBufferSize();
140         allocParamsForBufferLinear.pBufName = "VDENC BRC IMG State Read Buffer";
141         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
142         allocatedbuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
143         ENCODE_CHK_NULL_RETURN(allocatedbuffer);
144         m_vdencBrcImageStatesReadBuffer[k] = allocatedbuffer;
145 
146         for (auto i = 0; i < VDENC_BRC_NUM_OF_PASSES; i++)
147         {
148             // BRC update DMEM
149             allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
150             allocParamsForBufferLinear.pBufName = "VDENC BrcUpdate DmemBuffer";
151             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
152             allocatedbuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
153             ENCODE_CHK_NULL_RETURN(allocatedbuffer);
154             m_vdencBrcUpdateDmemBuffer[k][i] = allocatedbuffer;
155         }
156     }
157 
158     // PAK statistics output buffer
159     allocParamsForBufferLinear.dwBytes  = CODECHAL_PAGE_SIZE;
160     allocParamsForBufferLinear.pBufName = "VDENC PAK Statistics MMIO Registers Output Buffer";
161     allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
162     ENCODE_CHK_NULL_RETURN(allocatedbuffer);
163     m_resPakOutputViaMmioBuffer = allocatedbuffer;
164 
165     return MOS_STATUS_SUCCESS;
166 }
167 
SetConstDataHuCBrcUpdate() const168 MOS_STATUS AvcHucBrcUpdatePkt::SetConstDataHuCBrcUpdate()const
169 {
170     ENCODE_FUNC_CALL();
171 
172     // Set VDENC BRC constant buffer, data remains the same till BRC Init is called
173     if (m_brcFeature->IsBRCInit())
174     {
175         for (uint8_t picType = 0; picType < CODECHAL_ENCODE_VDENC_BRC_CONST_BUFFER_NUM; picType++)
176         {
177             auto hucConstData = (uint8_t *)m_allocator->LockResourceForWrite(m_vdencBrcConstDataBuffer[picType]);
178             ENCODE_CHK_NULL_RETURN(hucConstData);
179 
180             RUN_FEATURE_INTERFACE_RETURN(AvcEncodeBRC, AvcFeatureIDs::avcBrcFeature, FillHucConstData, hucConstData, picType);
181 
182             m_allocator->UnLock(m_vdencBrcConstDataBuffer[picType]);
183         }
184     }
185 
186     if (m_vdencStaticFrame)
187     {
188         auto hucConstData = (VdencAvcHucBrcConstantData *)m_allocator->LockResourceForWrite(m_vdencBrcConstDataBuffer[GetCurrConstDataBufIdx()]);
189         ENCODE_CHK_NULL_RETURN(hucConstData);
190 
191         auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
192         ENCODE_CHK_NULL_RETURN(settings);
193 
194         const auto &constTable4 = settings->vdencCMD3Table->AvcVdencCMD3ConstSettings_4;
195 
196         for (int j = 0; j < 42; j++)
197         {
198             hucConstData->UPD_P_Intra16x16[j] = constTable4[10 + j];
199         }
200 
201         m_allocator->UnLock(m_vdencBrcConstDataBuffer[GetCurrConstDataBufIdx()]);
202     }
203 
204     return MOS_STATUS_SUCCESS;
205 }
206 
Execute(PMOS_COMMAND_BUFFER cmdBuffer,bool storeHucStatus2Needed,bool prologNeeded,HuCFunction function)207 MOS_STATUS AvcHucBrcUpdatePkt::Execute(PMOS_COMMAND_BUFFER cmdBuffer, bool storeHucStatus2Needed, bool prologNeeded, HuCFunction function)
208 {
209     HUC_CHK_NULL_RETURN(cmdBuffer);
210 
211 #if _SW_BRC
212     HUC_CHK_STATUS_RETURN(InitSwBrc(function));
213     if (m_swBrc && m_swBrc->SwBrcEnabled())
214     {
215         m_brcFeature->m_swBrc = m_swBrc;
216         SETPAR(HUC_DMEM_STATE, m_hucItf);
217         SETPAR(HUC_VIRTUAL_ADDR_STATE, m_hucItf);
218 
219         auto virtualAddrParams = m_hucItf->MHW_GETPAR_F(HUC_VIRTUAL_ADDR_STATE)();
220         auto dmemParams        = m_hucItf->MHW_GETPAR_F(HUC_DMEM_STATE)();
221 
222         EncodeBasicFeature* basicFeature = dynamic_cast<EncodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
223         HUC_CHK_NULL_RETURN(basicFeature);
224         return m_swBrc->SwBrcImpl(
225             function,
226             virtualAddrParams,
227             dmemParams,
228             basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0));
229     }
230 #endif // !_SW_BRC
231 
232     if (prologNeeded)
233     {
234         SETPAR_AND_ADDCMD(MI_FORCE_WAKEUP, m_miItf, cmdBuffer);
235         ENCODE_CHK_STATUS_RETURN(SendPrologCmds(*cmdBuffer));
236     }
237 
238     if (m_brcFeature->IsBRCInitRequired())
239     {
240         m_resHucStatus2Buffer = m_brcFeature->GetHucStatus2Buffer();
241 
242         // Insert conditional batch buffer end for HuC valid IMEM loaded check
243         auto &miConditionalBatchBufferEndParams               = m_miItf->MHW_GETPAR_F(MI_CONDITIONAL_BATCH_BUFFER_END)();
244         miConditionalBatchBufferEndParams                     = {};
245         miConditionalBatchBufferEndParams.presSemaphoreBuffer = m_resHucStatus2Buffer;
246         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_CONDITIONAL_BATCH_BUFFER_END)(cmdBuffer));
247     }
248 
249     SetPerfTag(m_pipeline->IsFirstPass() ? CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE : CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE_SECOND_PASS,
250         (uint16_t)m_basicFeature->m_mode,
251         m_basicFeature->m_pictureCodingType);
252     ENCODE_CHK_STATUS_RETURN(StartPerfCollect(*cmdBuffer));
253     if (m_pipeline->IsSingleTaskPhaseSupported())
254     {
255         auto &miCpyMemMemParams       = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)();
256         miCpyMemMemParams             = {};
257         miCpyMemMemParams.presSrc     = m_resPakOutputViaMmioBuffer;
258         miCpyMemMemParams.presDst     = (m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]);
259         miCpyMemMemParams.dwSrcOffset = miCpyMemMemParams.dwDstOffset = CODECHAL_OFFSETOF(VdencAvcHucBrcUpdateDmem, FrameByteCount);
260         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
261 
262         miCpyMemMemParams.dwSrcOffset = miCpyMemMemParams.dwDstOffset = CODECHAL_OFFSETOF(VdencAvcHucBrcUpdateDmem, ImgStatusCtrl);
263         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
264 
265         miCpyMemMemParams.dwSrcOffset = miCpyMemMemParams.dwDstOffset = CODECHAL_OFFSETOF(VdencAvcHucBrcUpdateDmem, NumOfSlice);
266         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
267     }
268 
269     // load kernel from WOPCM into L2 storage RAM
270     AddAllCmds_HUC_IMEM_STATE(cmdBuffer);
271 
272     // pipe mode select
273     AddAllCmds_HUC_PIPE_MODE_SELECT(cmdBuffer);
274 
275     // set HuC DMEM param
276     SETPAR_AND_ADDCMD(HUC_DMEM_STATE, m_hucItf, cmdBuffer);
277 
278     // Copy data from BrcPakStatisticBufferFull to BrcPakStatisticBuffer if m_perMBStreamOutEnable is true
279     if (m_basicFeature->m_perMBStreamOutEnable)
280     {
281         CodechalHucStreamoutParams hucStreamOutParams;
282         MOS_ZeroMemory(&hucStreamOutParams, sizeof(hucStreamOutParams));
283 
284         auto setting = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
285         ENCODE_CHK_NULL_RETURN(setting);
286 
287         PMOS_RESOURCE sourceSurface = m_basicFeature->m_recycleBuf->GetBuffer(BrcPakStatisticBufferFull, m_basicFeature->m_frameNum);
288         PMOS_RESOURCE destSurface   = m_basicFeature->m_recycleBuf->GetBuffer(BrcPakStatisticBuffer, 0);
289         uint32_t      copySize      = setting->brcSettings.vdencBrcPakStatsBufferSize;
290         uint32_t      sourceOffset  = m_basicFeature->m_picWidthInMb * m_basicFeature->m_picHeightInMb * 64;
291         uint32_t      destOffset    = 0;
292 
293         // Ind Obj Addr command
294         hucStreamOutParams.dataBuffer            = sourceSurface;
295         hucStreamOutParams.dataSize              = copySize + sourceOffset;
296         hucStreamOutParams.dataOffset            = MOS_ALIGN_FLOOR(sourceOffset, CODECHAL_PAGE_SIZE);
297         hucStreamOutParams.streamOutObjectBuffer = destSurface;
298         hucStreamOutParams.streamOutObjectSize   = copySize + destOffset;
299         hucStreamOutParams.streamOutObjectOffset = MOS_ALIGN_FLOOR(destOffset, CODECHAL_PAGE_SIZE);
300 
301         // Stream object params
302         hucStreamOutParams.indStreamInLength    = copySize;
303         hucStreamOutParams.inputRelativeOffset  = sourceOffset - hucStreamOutParams.dataOffset;
304         hucStreamOutParams.outputRelativeOffset = destOffset - hucStreamOutParams.streamOutObjectOffset;
305 
306         ENCODE_CHK_STATUS_RETURN(m_hwInterface->PerformHucStreamOut(
307             &hucStreamOutParams,
308             cmdBuffer));
309     }
310 
311     SETPAR_AND_ADDCMD(HUC_VIRTUAL_ADDR_STATE, m_hucItf, cmdBuffer);
312 
313     HUC_CHK_STATUS_RETURN(StoreHuCStatus2Register(cmdBuffer, storeHucStatus2Needed));
314 
315     SETPAR_AND_ADDCMD(HUC_START, m_hucItf, cmdBuffer);
316 
317     CODECHAL_DEBUG_TOOL(
318         ENCODE_CHK_STATUS_RETURN(DumpInput()))
319 
320     //TODO: double confirm why need Vdenc pipe flush
321     SETPAR_AND_ADDCMD(VD_PIPELINE_FLUSH, m_vdencItf, cmdBuffer);
322 
323     // Flush the engine to ensure memory written out
324     auto &flushDwParams                         = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
325     flushDwParams                               = {};
326     flushDwParams.bVideoPipelineCacheInvalidate = true;
327     ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer));
328 
329     ENCODE_CHK_STATUS_RETURN(EndPerfCollect(*cmdBuffer));
330 
331     return MOS_STATUS_SUCCESS;
332 }
333 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)334 MOS_STATUS AvcHucBrcUpdatePkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
335 {
336     ENCODE_FUNC_CALL();
337 
338     ENCODE_CHK_STATUS_RETURN(ConstructImageStateReadBuffer(m_vdencBrcImageStatesReadBuffer[m_pipeline->m_currRecycledBufIdx]));
339 
340     bool firstTaskInPhase = packetPhase & firstPacket;
341     bool requestProlog = false;
342 
343     if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
344     {
345         // Send command buffer header at the beginning (OS dependent)
346         requestProlog = true;
347     }
348 
349     ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog, BRC_UPDATE));
350 
351     ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_mfxItf->GetMaxVdboxIndex()),
352                            "ERROR - vdbox index exceed the maximum");
353     auto mmioRegisters = m_hucItf->GetMmioRegisters(m_vdboxIndex);
354 
355 #if _SW_BRC
356     if (!m_swBrc->SwBrcEnabled())
357 #endif
358     {
359         // Write HUC_STATUS mask
360         auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
361         storeDataParams                  = {};
362         storeDataParams.pOsResource      = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
363         storeDataParams.dwResourceOffset = sizeof(uint32_t);
364         storeDataParams.dwValue          = VDENC_AVC_BRC_HUC_STATUS_REENCODE_MASK;
365         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(commandBuffer));
366 
367         // store HUC_STATUS register
368         auto &storeRegMemParams           = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
369         storeRegMemParams                 = {};
370         storeRegMemParams.presStoreBuffer = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
371         storeRegMemParams.dwOffset        = 0;
372         storeRegMemParams.dwRegister      = mmioRegisters->hucStatusRegOffset;
373         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(commandBuffer));
374     }
375 
376     CODECHAL_DEBUG_TOOL(
377         ENCODE_CHK_STATUS_RETURN(DumpHucBrcUpdate(true));)
378 
379     // Set HuC DMEM buffers which need to be updated.
380     // They are first pass of next frame and next pass of current frame, as the 2nd VDEnc+PAK pass may not be triggered.
381     uint32_t nextRecycledBufIdx = (m_pipeline->m_currRecycledBufIdx + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
382     uint32_t nextPass           = (m_pipeline->GetCurrentPass() + 1) % CODECHAL_VDENC_BRC_NUM_OF_PASSES;
383 
384     PMOS_RESOURCE vdencBrcUpdateDmemBuffer0 = m_vdencBrcUpdateDmemBuffer[nextRecycledBufIdx][0];
385     PMOS_RESOURCE vdencBrcUpdateDmemBuffer1 = m_pipeline->IsLastPass() ? nullptr : m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][nextPass];
386 
387 #if _SW_BRC
388     if (!m_swBrc->SwBrcEnabled())
389 #endif
390     {
391         if (m_pipeline->IsSingleTaskPhaseSupported())
392         {
393             vdencBrcUpdateDmemBuffer0 = m_resPakOutputViaMmioBuffer;
394             vdencBrcUpdateDmemBuffer1 = nullptr;
395         }
396     }
397 
398     RUN_FEATURE_INTERFACE_NO_RETURN(AvcEncodeBRC, AvcFeatureIDs::avcBrcFeature, SaveBrcUpdateDmemBufferPtr, vdencBrcUpdateDmemBuffer0, vdencBrcUpdateDmemBuffer1);
399 
400     // Disable Brc Init/reset  here after init cmd executed, APP will re-trigger the reset by DDI params m_seqParam->bResetBRC
401     RUN_FEATURE_INTERFACE_NO_RETURN(AvcEncodeBRC, AvcFeatureIDs::avcBrcFeature, DisableBrcInitReset);
402 
403     return MOS_STATUS_SUCCESS;
404 }
405 
ConstructImageStateReadBuffer(PMOS_RESOURCE imageStateBuffer)406 MOS_STATUS AvcHucBrcUpdatePkt::ConstructImageStateReadBuffer(PMOS_RESOURCE imageStateBuffer)
407 {
408     ENCODE_FUNC_CALL();
409 
410     ENCODE_CHK_NULL_RETURN(m_mfxItf);
411     ENCODE_CHK_NULL_RETURN(m_vdencItf);
412 
413     uint32_t mfxAvcImgStateSize = m_mfxItf->MHW_GETSIZE_F(MFX_AVC_IMG_STATE)();
414     uint32_t vdencAvcCostStateSize = m_vdencItf->MHW_GETSIZE_F(VDENC_CMD3)();
415     uint32_t vdencAvcImgStateSize  = m_vdencItf->MHW_GETSIZE_F(VDENC_AVC_IMG_STATE)();
416     uint32_t miBatchBufferEndSize = m_miItf->MHW_GETSIZE_F(MI_BATCH_BUFFER_END)();
417 
418     uint8_t *data = (uint8_t*)m_allocator->LockResourceForWrite(imageStateBuffer);
419 
420     MOS_COMMAND_BUFFER constructedCmdBuf;
421     MOS_ZeroMemory(&constructedCmdBuf, sizeof(MOS_COMMAND_BUFFER));
422     constructedCmdBuf.pCmdBase   = constructedCmdBuf.pCmdPtr = (uint32_t *) data;
423     constructedCmdBuf.iRemaining = m_brcFeature->GetVdencBRCImgStateBufferSize();
424 
425     // Set MFX_AVC_IMG_STATE command
426     SETPAR_AND_ADDCMD(MFX_AVC_IMG_STATE, m_mfxItf, &constructedCmdBuf);
427 
428     // Set VDENC_CMD3 command
429     SETPAR_AND_ADDCMD(VDENC_CMD3, m_vdencItf, &constructedCmdBuf);
430 
431     // Set VDENC_AVC_IMG_STATE command
432     SETPAR_AND_ADDCMD(VDENC_AVC_IMG_STATE, m_vdencItf, &constructedCmdBuf);
433 
434     // Add batch buffer end insertion flag
435     ENCODE_CHK_STATUS_RETURN(m_miItf->AddBatchBufferEndInsertionFlag(constructedCmdBuf));
436 
437     // AddBatchBufferEndInsertionFlag doesn't modify pCmdPtr + iOffset
438     constructedCmdBuf.pCmdPtr += miBatchBufferEndSize / sizeof(uint32_t);
439     constructedCmdBuf.iOffset += miBatchBufferEndSize;
440     constructedCmdBuf.iRemaining -= miBatchBufferEndSize;
441 
442     // Add MI_NOOPs to align to CODECHAL_CACHELINE_SIZE
443     uint32_t size = (MOS_ALIGN_CEIL(constructedCmdBuf.iOffset, CODECHAL_CACHELINE_SIZE) - constructedCmdBuf.iOffset) / sizeof(uint32_t);
444     for (uint32_t i = 0; i < size; i++)
445         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&constructedCmdBuf));
446 
447     for (uint16_t slcCount = 0; slcCount < m_basicFeature->m_numSlices; slcCount++)
448     {
449         size = constructedCmdBuf.iOffset;
450 
451         // Set MFX_AVC_SLICE_STATE command
452         SETPAR_AND_ADDCMD(MFX_AVC_SLICE_STATE, m_mfxItf, &constructedCmdBuf);
453 
454         // Set VDENC_AVC_SLICE_STATE command
455         SETPAR_AND_ADDCMD(VDENC_AVC_SLICE_STATE, m_vdencItf, &constructedCmdBuf);
456 
457         m_miItf->AddBatchBufferEndInsertionFlag(constructedCmdBuf);
458         constructedCmdBuf.pCmdPtr += miBatchBufferEndSize / sizeof(uint32_t);
459         constructedCmdBuf.iOffset += miBatchBufferEndSize;
460         constructedCmdBuf.iRemaining -= miBatchBufferEndSize;
461 
462         ENCODE_ASSERT(constructedCmdBuf.iOffset - size % CODECHAL_CACHELINE_SIZE != 0);
463     }
464 
465     if (data)
466     {
467         m_allocator->UnLock(imageStateBuffer);
468     }
469 
470     CODECHAL_DEBUG_TOOL(
471         ENCODE_CHK_STATUS_RETURN(PopulatePakParam(
472             nullptr,
473             nullptr));
474 
475         ENCODE_CHK_STATUS_RETURN(PopulateEncParam(
476             0,
477             nullptr));)
478 
479     return MOS_STATUS_SUCCESS;
480 }
481 
GetCurrConstDataBufIdx() const482 uint32_t AvcHucBrcUpdatePkt::GetCurrConstDataBufIdx() const
483 {
484     return m_basicFeature->m_picParam->CodingType == B_TYPE && m_basicFeature->m_picParam->RefPicFlag ? m_basicFeature->m_picParam->CodingType  // refB
485                                                                                                       : m_basicFeature->m_picParam->CodingType - 1;
486 }
487 
MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE,AvcHucBrcUpdatePkt)488 MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE, AvcHucBrcUpdatePkt)
489 {
490     bool bIPCMPass = m_pipeline->GetCurrentPass() && m_pipeline->IsLastPass() && (!m_brcFeature->IsVdencBrcEnabled());
491     params.mbstatenabled = bIPCMPass ? true : false; // Disable for the first pass
492 
493     return MOS_STATUS_SUCCESS;
494 }
495 
MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,AvcHucBrcUpdatePkt)496 MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, AvcHucBrcUpdatePkt)
497 {
498     auto setting = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
499     ENCODE_CHK_NULL_RETURN(setting);
500 
501     params.kernelDescriptor = setting->brcSettings.vdboxHucVdencBrcUpdateKernelDescriptor;
502 
503     return MOS_STATUS_SUCCESS;
504 }
505 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,AvcHucBrcUpdatePkt)506 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, AvcHucBrcUpdatePkt)
507 {
508     ENCODE_CHK_STATUS_RETURN(SetDmemBuffer());
509 
510     params.function      = BRC_UPDATE;
511     params.hucDataSource = m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()];
512     params.dataLength    = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
513     params.dmemOffset    = HUC_DMEM_OFFSET_RTOS_GEMS;
514 
515     return MOS_STATUS_SUCCESS;
516 }
517 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,AvcHucBrcUpdatePkt)518 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, AvcHucBrcUpdatePkt)
519 {
520     params.function = BRC_UPDATE;
521 
522     // Set Const Data buffer
523     ENCODE_CHK_STATUS_RETURN(SetConstDataHuCBrcUpdate());
524 
525     // Input regions
526     params.regionParams[1].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencStatsBuffer, 0);
527     params.regionParams[2].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(BrcPakStatisticBuffer, 0);
528     params.regionParams[3].presRegion = m_vdencBrcImageStatesReadBuffer[m_pipeline->m_currRecycledBufIdx];
529     params.regionParams[5].presRegion = m_vdencBrcConstDataBuffer[GetCurrConstDataBufIdx()];
530     params.regionParams[7].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(PakSliceSizeStreamOutBuffer, m_pipeline->GetCurrentPass() ?
531         m_basicFeature->m_frameNum : m_basicFeature->m_frameNum ? m_basicFeature->m_frameNum-1 : 0);   // use stats from previous frame for pass 0
532                                                                                                        // use stats from pass 0 for pass 1
533 
534     if (m_basicFeature->m_picParam->NumROI && !m_basicFeature->m_picParam->bNativeROI)  // Only for BRC non-native ROI
535     {
536         if (m_hwInterface->GetOsInterface()->osCpInterface != nullptr &&
537             m_hwInterface->GetOsInterface()->osCpInterface->IsCpEnabled())
538         {
539             ENCODE_ASSERTMESSAGE("Non-native BRC ROI doesn't supports in CP case");
540             return MOS_STATUS_UNIMPLEMENTED;
541         }
542         params.regionParams[8].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::HucRoiMapBuffer, m_basicFeature->m_frameNum);
543     }
544 
545     return MOS_STATUS_SUCCESS;
546 }
547 
548 #if USE_CODECHAL_DEBUG_TOOL
DumpHucBrcUpdate(bool isInput)549 MOS_STATUS AvcHucBrcUpdatePkt::DumpHucBrcUpdate(bool isInput)
550 {
551     ENCODE_FUNC_CALL();
552 
553     CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
554     ENCODE_CHK_NULL_RETURN(debugInterface);
555 
556     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
557     ENCODE_CHK_NULL_RETURN(settings);
558 
559     auto brcSettings = settings->brcSettings;
560 
561     uint16_t currentPass = m_pipeline->GetCurrentPass();
562 
563     auto virtualAddrParams = m_hucItf->MHW_GETPAR_F(HUC_VIRTUAL_ADDR_STATE)();
564 
565     if (isInput)
566     {
567         //HUC DMEM dump
568         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem(
569             m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][currentPass],
570             m_vdencBrcUpdateDmemBufferSize,
571             currentPass,
572             hucRegionDumpUpdate));
573 
574         // History Buffer dump
575         ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_History", isInput, hucRegionDumpUpdate, brcSettings.vdencBrcHistoryBufferSize));
576 
577         // Constant Data Buffer dump
578         ENCODE_CHK_STATUS_RETURN(DumpRegion(5, "_ConstData", isInput, hucRegionDumpUpdate, m_vdencBrcConstDataBufferSize));
579 
580         // VDENC Statistics Buffer dump
581         ENCODE_CHK_STATUS_RETURN(DumpRegion(1, "_VdencStats", isInput, hucRegionDumpUpdate, brcSettings.vdencBrcStatsBufferSize));
582 
583         // PAK Statistics Buffer dump
584         ENCODE_CHK_STATUS_RETURN(DumpRegion(2, "_PakStats", isInput, hucRegionDumpUpdate, brcSettings.vdencBrcPakStatsBufferSize));
585 
586         // VDENC Img State Read Buffer dump
587         ENCODE_CHK_STATUS_RETURN(DumpRegion(3, "_ImageStateRead", isInput, hucRegionDumpUpdate, m_brcFeature->GetVdencBRCImgStateBufferSize()));
588 
589         // Slice size Buffer dump
590         ENCODE_CHK_STATUS_RETURN(DumpRegion(7, "_SliceSizeStreamOut", isInput, hucRegionDumpUpdate, CODECHAL_ENCODE_SLICESIZE_BUF_SIZE));
591 
592         // BRC non-native ROI
593         if (m_basicFeature->m_picParam->NumROI && !m_basicFeature->m_picParam->bNativeROI)
594         {
595             ENCODE_CHK_STATUS_RETURN(DumpRegion(8, "_BrcROI_idxs", isInput, hucRegionDumpUpdate, m_basicFeature->m_picWidthInMb * m_basicFeature->m_picHeightInMb));
596         }
597 
598         // VDEnc StreamIn
599         if (m_basicFeature->m_picParam->NumROI && !m_basicFeature->m_picParam->bNativeROI)
600         {
601             ENCODE_CHK_STATUS_RETURN(DumpRegion(9, "_VDEnc_StreamIn", isInput, hucRegionDumpUpdate, m_basicFeature->m_picWidthInMb * m_basicFeature->m_picHeightInMb * CODECHAL_CACHELINE_SIZE));
602         }
603     }
604     else
605     {
606         // History Buffer dump
607         ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_History", isInput, hucRegionDumpUpdate, brcSettings.vdencBrcHistoryBufferSize));
608 
609         // VDENC Img State Write Buffer dump
610         ENCODE_CHK_STATUS_RETURN(DumpRegion(6, "_ImageStateWrite", isInput, hucRegionDumpUpdate, m_brcFeature->GetVdencBRCImgStateBufferSize()));
611 
612         // VDEnc StreamIn
613         if (m_basicFeature->m_picParam->NumROI && !m_basicFeature->m_picParam->bNativeROI)
614         {
615             ENCODE_CHK_STATUS_RETURN(DumpRegion(10, "_VDEnc_StreamIn", isInput, hucRegionDumpUpdate, m_basicFeature->m_picWidthInMb * m_basicFeature->m_picHeightInMb * CODECHAL_CACHELINE_SIZE));
616         }
617 
618         ENCODE_CHK_STATUS_RETURN(DumpRegion(15, "_Debug", isInput, hucRegionDumpUpdate, brcSettings.vdencBrcDbgBufferSize));
619     }
620 
621     return MOS_STATUS_SUCCESS;
622 }
623 
DumpEncodeImgStats(PMOS_COMMAND_BUFFER cmdbuffer)624 MOS_STATUS AvcHucBrcUpdatePkt::DumpEncodeImgStats(
625     PMOS_COMMAND_BUFFER cmdbuffer)
626 {
627     ENCODE_FUNC_CALL();
628 
629     CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
630     ENCODE_CHK_NULL_RETURN(debugInterface);
631 
632     if (!debugInterface->DumpIsEnabled(CodechalDbgAttr::attrImageState))
633     {
634         return MOS_STATUS_SUCCESS;
635     }
636 
637     std::string SurfName = "Pak_VDEnc_Pass[" + std::to_string(static_cast<uint32_t>(m_pipeline->GetCurrentPass())) + "]";
638 
639     // MFX_AVC_IMG_STATE
640     if (m_brcFeature->IsVdencBrcEnabled())
641     {
642         // BRC case: both MFX_AVC_IMG_STATE and VDENC_IMG_STATE are updated by HuC FW
643         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
644             &(m_brcFeature->GetBatchBufferForVdencImgStat()->OsResource),
645             CodechalDbgAttr::attrImageState,
646             SurfName.c_str(),
647             m_hwInterface->m_vdencBrcImgStateBufferSize,
648             0,
649             CODECHAL_NUM_MEDIA_STATES));
650     }
651 
652     return MOS_STATUS_SUCCESS;
653 }
654 #endif
655 
656 }
657