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