1 /*
2 * Copyright (c) 2020-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_vp9_huc_brc_update_packet.cpp
25 //! \brief    Defines the implementation of huc update packet for VP9
26 //!
27 
28 #include "encode_vp9_huc_brc_update_packet.h"
29 #include <encode_vp9_vdenc_feature_manager.h>
30 #include "encode_vp9_brc.h"
31 #include "encode_vp9_segmentation.h"
32 #include "encode_vp9_pak.h"
33 
34 namespace encode
35 {
36 const uint32_t Vp9HucBrcUpdatePkt::m_brcUpdateDmem[64] =
37 {
38     0x00061A80, 0x00000000, 0x0007A120, 0x000493E0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
39     0x00000000, 0x00000000, 0x00000000, 0x0032000A, 0x00960064, 0x01680280, 0x02200000, 0x007802B8,
40     0x00000000, 0x00000000, 0x00000000, 0x02032000, 0xB4785028, 0x67614B28, 0x0101A07D, 0x28010203,
41     0x01030505, 0x00FEFCFA, 0x04060402, 0x78503C1E, 0x00FFC88C, 0x503C1E04, 0xFFC88C78, 0x28140200,
42     0xC8A08246, 0x090800FF, 0x040C0B0A, 0x07060605, 0x06060504, 0xFB650007, 0xFB0501FF, 0x000501FE,
43     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
44     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
45     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
46 };
47 
Init()48 MOS_STATUS Vp9HucBrcUpdatePkt::Init()
49 {
50     ENCODE_FUNC_CALL();
51     HUC_CHK_STATUS_RETURN(EncodeHucPkt::Init());
52     ENCODE_CHK_NULL_RETURN(m_featureManager);
53 
54     m_basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(Vp9FeatureIDs::basicFeature));
55     ENCODE_CHK_NULL_RETURN(m_basicFeature);
56 
57     return MOS_STATUS_SUCCESS;
58 }
59 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)60 MOS_STATUS Vp9HucBrcUpdatePkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
61 {
62     ENCODE_FUNC_CALL();
63     ENCODE_CHK_NULL_RETURN(m_basicFeature);
64 
65     // To match watchdog timer threshold in codechal
66     ENCODE_CHK_STATUS_RETURN(m_miItf->SetWatchdogTimerThreshold(m_basicFeature->m_frameWidth, m_basicFeature->m_frameHeight, true));
67 
68     // Construct picture state 2nd level batch buffer
69     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodePak, Vp9FeatureIDs::vp9PakFeature, ConstructPicStateBatchBuffer, m_pipeline);
70 
71     bool firstTaskInPhase = packetPhase & firstPacket;
72     bool requestProlog    = false;
73 
74     if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
75     {
76         // Send command buffer header at the beginning (OS dependent)
77         requestProlog = true;
78     }
79 
80     ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog));
81 
82     // Write HUC_STATUS mask: DW1 (mask value)
83     auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
84     storeDataParams                  = {};
85     storeDataParams.pOsResource      = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
86     storeDataParams.dwResourceOffset = sizeof(uint32_t);
87     storeDataParams.dwValue          = (1 << 31); // CODECHAL_VDENC_VP9_BRC_HUC_STATUS_REENCODE_MASK;
88     ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(commandBuffer));
89 
90     // Store HUC_STATUS register: DW0 (actual value)
91     ENCODE_CHK_COND_RETURN((m_vdboxIndex > MHW_VDBOX_NODE_1), "ERROR - vdbox index exceed the maximum");
92     ENCODE_CHK_NULL_RETURN(m_hwInterface->GetHucInterfaceNext());
93     auto  mmioRegisters                 = m_hwInterface->GetHucInterfaceNext()->GetMmioRegisters(m_vdboxIndex);
94     auto &miStoreRegMemParams           = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
95     miStoreRegMemParams                 = {};
96     miStoreRegMemParams.presStoreBuffer = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
97     miStoreRegMemParams.dwOffset        = 0;
98     miStoreRegMemParams.dwRegister      = mmioRegisters->hucStatusRegOffset;
99     ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(commandBuffer));
100 
101     CODECHAL_DEBUG_TOOL(
102         ENCODE_CHK_STATUS_RETURN(DumpInput());)
103 
104     return MOS_STATUS_SUCCESS;
105 }
106 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)107 MOS_STATUS Vp9HucBrcUpdatePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
108 {
109     ENCODE_FUNC_CALL();
110 
111     auto osInterface = m_hwInterface->GetOsInterface();
112     ENCODE_CHK_NULL_RETURN(osInterface);
113 
114     MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
115     uint32_t                       vdencHucStatesSize = 0;
116     uint32_t                       hucPatchListSize   = 0;
117 
118     ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize(
119         m_basicFeature->m_mode, (uint32_t *)&vdencHucStatesSize, (uint32_t *)&hucPatchListSize, &stateCmdSizeParams));
120 
121     commandBufferSize      = vdencHucStatesSize;
122     requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0;
123 
124     if (m_pipeline->IsSingleTaskPhaseSupported())
125     {
126         commandBufferSize *= m_pipeline->GetPassNum();
127     }
128 
129     // 4K align since allocation is in chunks of 4K bytes
130     commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE);
131 
132     return MOS_STATUS_SUCCESS;
133 }
134 
DumpOutput()135 MOS_STATUS Vp9HucBrcUpdatePkt::DumpOutput()
136 {
137     ENCODE_FUNC_CALL();
138 
139 #if USE_CODECHAL_DEBUG_TOOL
140     // Dump Huc Brc Update output
141 
142     uint32_t brcHistoryBufferSize                 = 0;
143     uint32_t vdencPicState2ndLevelBatchBufferSize = 0;
144 
145     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeBrc, Vp9FeatureIDs::vp9BrcFeature, GetBrcHistoryBufferSize, brcHistoryBufferSize);
146     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodePak, Vp9FeatureIDs::vp9PakFeature, GetVdencPictureState2ndLevelBatchBufferSize, vdencPicState2ndLevelBatchBufferSize);
147 
148     // Region 0 - BRC history buffer (In/Out)
149     ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_BrcHistory", false, hucRegionDumpUpdate, brcHistoryBufferSize));
150     // Region 4 - BRC data buffer
151     ENCODE_CHK_STATUS_RETURN(DumpRegion(4, "_BrcData", false, hucRegionDumpUpdate, CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE));
152     // Region 6 - Output second level batch (SLB) buffer
153     ENCODE_CHK_STATUS_RETURN(DumpRegion(6, "_OutputSLBB", false, hucRegionDumpUpdate, vdencPicState2ndLevelBatchBufferSize));
154     // Region 15 - For kernel debug purpose. May be used only in HuC debug build.
155     ENCODE_CHK_STATUS_RETURN(DumpRegion(15, "_BrcDebugBuffer", false, hucRegionDumpUpdate));
156 #endif
157 
158     return MOS_STATUS_SUCCESS;
159 }
160 
AllocateResources()161 MOS_STATUS Vp9HucBrcUpdatePkt::AllocateResources()
162 {
163     ENCODE_FUNC_CALL();
164     ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::AllocateResources());
165 
166     // Initiate allocation parameters and lock flags
167     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
168     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
169     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
170     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
171     allocParamsForBufferLinear.Format   = Format_Buffer;
172     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
173 
174     // BRC update DMEM
175     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(sizeof(HucBrcUpdateDmem), CODECHAL_CACHELINE_SIZE);
176     allocParamsForBufferLinear.pBufName = "VDENC BrcUpdate DmemBuffer";
177     MOS_RESOURCE *allocatedBuffer       = nullptr;
178     for (auto i = 0; i < 3; ++i)
179     {
180         for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++j)
181         {
182             allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
183             ENCODE_CHK_NULL_RETURN(allocatedBuffer);
184             m_resVdencBrcUpdateDmemBuffer[i][j] = *allocatedBuffer;
185         }
186     }
187 
188     return MOS_STATUS_SUCCESS;
189 }
190 
SetDmemBuffer() const191 MOS_STATUS Vp9HucBrcUpdatePkt::SetDmemBuffer() const
192 {
193     ENCODE_FUNC_CALL();
194 
195     auto brcFeature = dynamic_cast<Vp9EncodeBrc *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9BrcFeature));
196     ENCODE_CHK_NULL_RETURN(brcFeature);
197 
198     // Setup BRC DMEM
199     auto              currPass = m_pipeline->GetCurrentPass();
200     HucBrcUpdateDmem *dmem     = (HucBrcUpdateDmem *)m_allocator->LockResourceForWrite(const_cast<MOS_RESOURCE *>(&m_resVdencBrcUpdateDmemBuffer[currPass][m_pipeline->m_currRecycledBufIdx]));
201     ENCODE_CHK_NULL_RETURN(dmem);
202 
203     MOS_SecureMemcpy(dmem, sizeof(HucBrcUpdateDmem), m_brcUpdateDmem, sizeof(m_brcUpdateDmem));
204 
205     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeBrc, Vp9FeatureIDs::vp9BrcFeature, SetDmemForUpdate, dmem, m_pipeline->IsFirstPass());
206     RUN_FEATURE_INTERFACE_RETURN(Vp9Segmentation, Vp9FeatureIDs::vp9Segmentation, SetDmemForUpdate, dmem);
207 
208     // PAK info
209     dmem->UPD_MaxNumPAKs_U8 = m_pipeline->GetPassNum() - 1;
210     dmem->UPD_PAKPassNum_U8 = (uint8_t)currPass;
211 
212     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(const_cast<MOS_RESOURCE *>(&m_resVdencBrcUpdateDmemBuffer[currPass][m_pipeline->m_currRecycledBufIdx])));
213 
214     return MOS_STATUS_SUCCESS;
215 }
216 
217 #if USE_CODECHAL_DEBUG_TOOL
DumpInput()218 MOS_STATUS Vp9HucBrcUpdatePkt::DumpInput()
219 {
220     ENCODE_FUNC_CALL();
221 
222     CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
223     ENCODE_CHK_NULL_RETURN(debugInterface);
224 
225     uint32_t currentPass = m_pipeline->GetCurrentPass();
226     uint32_t size        = 0;
227 
228     // Dump HucBrcUpdate input buffers
229     ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem(
230         &m_resVdencBrcUpdateDmemBuffer[currentPass][m_pipeline->m_currRecycledBufIdx],
231         sizeof(HucBrcUpdateDmem),
232         currentPass,
233         hucRegionDumpUpdate));
234 
235     auto brcFeature = dynamic_cast<Vp9EncodeBrc *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9BrcFeature));
236     ENCODE_CHK_NULL_RETURN(brcFeature);
237 
238     uint32_t pakMmioBufferSize = MOS_ALIGN_CEIL(CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE, CODECHAL_PAGE_SIZE);
239 
240     uint32_t brcHistoryBufferSize                 = 0;
241     uint32_t vdencBrcStatsBufferSize              = 0;
242     uint32_t vdencBrcPakStatsBufferSize           = 0;
243     uint32_t vdencPicState2ndLevelBatchBufferSize = 0;
244 
245     brcFeature->GetBrcHistoryBufferSize(brcHistoryBufferSize);
246     brcFeature->GetVdencBrcStatsBufferSize(vdencBrcStatsBufferSize);
247     brcFeature->GetVdencBrcPakStatsBufferSize(vdencBrcPakStatsBufferSize);
248 
249     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodePak, Vp9FeatureIDs::vp9PakFeature, GetVdencPictureState2ndLevelBatchBufferSize, vdencPicState2ndLevelBatchBufferSize);
250 
251     // Region 0 - BRC history buffer (In/Out)
252     ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_BrcHistory", true, hucRegionDumpUpdate, brcHistoryBufferSize));
253     // Region 1 - VDENC statistics buffer dump
254     ENCODE_CHK_STATUS_RETURN(DumpRegion(1, "_VdencStats", true, hucRegionDumpUpdate, vdencBrcStatsBufferSize));
255     // Region 2 -  PAK statistics buffer dump
256     ENCODE_CHK_STATUS_RETURN(DumpRegion(2, "_PakStats", true, hucRegionDumpUpdate, vdencBrcPakStatsBufferSize));
257     // Region 3 - Input second level batch (SLB) buffer
258     ENCODE_CHK_STATUS_RETURN(DumpRegion(3, "_InputSLBB", true, hucRegionDumpUpdate, vdencPicState2ndLevelBatchBufferSize));
259     // Region 5 - Constant data buffer dump
260     ENCODE_CHK_STATUS_RETURN(DumpRegion(5, "_ConstData", true, hucRegionDumpUpdate, brcFeature->m_brcConstantSurfaceSize));
261     // Region 7 - PAK MMIO
262     ENCODE_CHK_STATUS_RETURN(DumpRegion(7, "_PakMmio", true, hucRegionDumpUpdate, pakMmioBufferSize));
263 
264     return MOS_STATUS_SUCCESS;
265 }
266 #endif
267 
MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,Vp9HucBrcUpdatePkt)268 MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, Vp9HucBrcUpdatePkt)
269 {
270     ENCODE_FUNC_CALL();
271 
272     params.kernelDescriptor = m_vdboxHucVp9VdencBrcUpdateKernelDescriptor;
273 
274     return MOS_STATUS_SUCCESS;
275 }
276 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,Vp9HucBrcUpdatePkt)277 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, Vp9HucBrcUpdatePkt)
278 {
279     ENCODE_FUNC_CALL();
280 
281     params.function      = BRC_UPDATE;
282 
283     ENCODE_CHK_STATUS_RETURN(SetDmemBuffer());
284 
285     params.passNum       = static_cast<uint8_t>(m_pipeline->GetPassNum());
286     params.currentPass   = static_cast<uint8_t>(m_pipeline->GetCurrentPass());
287     params.hucDataSource = const_cast<PMOS_RESOURCE>(&m_resVdencBrcUpdateDmemBuffer[m_pipeline->GetCurrentPass()][m_pipeline->m_currRecycledBufIdx]);
288     params.dataLength    = MOS_ALIGN_CEIL(sizeof(HucBrcUpdateDmem), CODECHAL_CACHELINE_SIZE);
289     params.dmemOffset    = HUC_DMEM_OFFSET_RTOS_GEMS;
290 
291     return MOS_STATUS_SUCCESS;
292 }
293 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,Vp9HucBrcUpdatePkt)294 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, Vp9HucBrcUpdatePkt)
295 {
296     ENCODE_FUNC_CALL();
297 
298     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
299 
300     int32_t currentPass = m_pipeline->GetCurrentPass();
301     if (currentPass < 0)
302     {
303         eStatus = MOS_STATUS_INVALID_PARAMETER;
304         return eStatus;
305     }
306 
307     ENCODE_CHK_NULL_RETURN(m_basicFeature);
308     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
309 
310     params.function = BRC_UPDATE;
311 
312     auto brcFeature = dynamic_cast<Vp9EncodeBrc *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9BrcFeature));
313     ENCODE_CHK_NULL_RETURN(brcFeature);
314 
315     uint32_t statBufIdx = 0;
316     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeTile, Vp9FeatureIDs::encodeTile, GetStatisticsBufferIndex, statBufIdx);
317     MOS_RESOURCE *resTileBasedStatisticsBuffer = nullptr;
318     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeTile, Vp9FeatureIDs::encodeTile, GetTileBasedStatisticsBuffer, statBufIdx, resTileBasedStatisticsBuffer);
319     uint32_t offset = 0;
320 
321     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeBrc, Vp9FeatureIDs::vp9BrcFeature, InitConstantDataBuffer);
322     MOS_RESOURCE *resBrcDataBuffer = nullptr;
323     HucBrcBuffers *hucBrcBuffers = nullptr;
324     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeBrc, Vp9FeatureIDs::vp9BrcFeature, GetHucBrcBuffers, hucBrcBuffers);
325 
326     // Regions (in) : 0, 1, 2, 5, 7
327     // Regions (out): 0, 4
328     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeBrc, Vp9FeatureIDs::vp9BrcFeature, SetRegionsForBrcUpdate, params);
329 
330     // Regions (in) : 3
331     // Regions (out): 6
332     RUN_FEATURE_INTERFACE_RETURN(Vp9EncodePak, Vp9FeatureIDs::vp9PakFeature, SetRegionsForBrcUpdate, params, currentPass);
333 
334     if (m_pipeline->IsFirstPass())
335     {
336         if (m_basicFeature->m_lastFrameScalableMode)
337         {
338             // Regions (in): 1, 2, 7
339             RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeTile, Vp9FeatureIDs::encodeTile, SetRegionsForBrcUpdate, params);
340         }
341     }
342     else  // Second BRC Update Pass
343     {
344         if (m_basicFeature->m_scalableMode)
345         {
346             // Regions (in): 1, 2, 7
347             RUN_FEATURE_INTERFACE_RETURN(Vp9EncodeTile, Vp9FeatureIDs::encodeTile, SetRegionsForBrcUpdate, params);
348         }
349     }
350 
351     return MOS_STATUS_SUCCESS;
352 }
353 
354 }  // namespace encode
355