1 /*
2 * Copyright (c) 2017-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 codechal_encoder_base.cpp
24 //! \brief Implements the encode interface for CodecHal.
25 //! \details The encode interface is further sub-divided by standard, this file is for the base interface which is shared by all encode standards.
26 //!
27
28 #include "codechal_encoder_base.h"
29 #include "mos_solo_generic.h"
30 #include "hal_oca_interface.h"
31 #include "codechal_encode_csc_ds.h"
32 #include "mos_os_cp_interface_specific.h"
33 #if defined (_HEVC_ENCODE_VME_SUPPORTED) || defined (_HEVC_ENCODE_VDENC_SUPPORTED)
34 #include "codechal_encode_tracked_buffer_hevc.h"
35 #endif
36
PrepareNodes(MOS_GPU_NODE & videoGpuNode,bool & setVideoNode)37 void CodechalEncoderState::PrepareNodes(
38 MOS_GPU_NODE& videoGpuNode,
39 bool& setVideoNode)
40 {
41 if (MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface))
42 {
43 MOS_GPU_NODE node = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Decode);
44 if (node != MOS_GPU_NODE_MAX)
45 {
46 setVideoNode = true;
47 videoGpuNode = (node == MOS_GPU_NODE_VIDEO) ? MOS_GPU_NODE_VIDEO2 : MOS_GPU_NODE_VIDEO;
48 }
49 return;
50 }
51
52 if (m_vdboxOneDefaultUsed)
53 {
54 setVideoNode = true;
55 videoGpuNode = MOS_GPU_NODE_VIDEO;
56 }
57 else if (m_needCheckCpEnabled)
58 {
59 if (m_osInterface->osCpInterface->IsCpEnabled() ||
60 m_vdencEnabled)
61 {
62 setVideoNode = true;
63 videoGpuNode = MOS_GPU_NODE_VIDEO;
64 }
65 }
66 }
67
SetGpuCtxCreatOption()68 MOS_STATUS CodechalEncoderState::SetGpuCtxCreatOption()
69 {
70 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
71
72 m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS);
73 CODECHAL_ENCODE_CHK_NULL_RETURN(m_gpuCtxCreatOpt);
74
75 return eStatus;
76 }
77
CreateGpuContexts()78 MOS_STATUS CodechalEncoderState::CreateGpuContexts()
79 {
80 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
81
82 if (CodecHalUsesVideoEngine(m_codecFunction))
83 {
84 MOS_GPU_NODE videoGpuNode = MOS_GPU_NODE_VIDEO;
85 bool setVideoNode = false;
86
87 // Create Video Context
88 if (MEDIA_IS_SKU(m_skuTable, FtrVcs2) ||
89 (MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface) && m_numVdbox > 1)) // Eventually move this functionality to Mhw
90 {
91 setVideoNode = false;
92
93 PrepareNodes(videoGpuNode, setVideoNode);
94
95 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateVideoNodeAssociation(
96 m_osInterface,
97 setVideoNode,
98 &videoGpuNode));
99 m_videoNodeAssociationCreated = true;
100 }
101 m_videoGpuNode = videoGpuNode;
102
103 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetGpuCtxCreatOption());
104 CODECHAL_ENCODE_CHK_NULL_RETURN(m_gpuCtxCreatOpt);
105
106 MOS_GPU_CONTEXT gpuContext = (videoGpuNode == MOS_GPU_NODE_VIDEO2) && !MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface) ? MOS_GPU_CONTEXT_VDBOX2_VIDEO3 : MOS_GPU_CONTEXT_VIDEO3;
107
108 eStatus = (MOS_STATUS)m_osInterface->pfnCreateGpuContext(
109 m_osInterface,
110 gpuContext,
111 videoGpuNode,
112 m_gpuCtxCreatOpt);
113
114 if (eStatus != MOS_STATUS_SUCCESS)
115 {
116 // Failed to create new context. Try to reuse the existing one on the same VDBox.
117 if (videoGpuNode == MOS_GPU_NODE_VIDEO2)
118 {
119 // check other GPU contexts on VDBox2
120 gpuContext = MOS_GPU_CONTEXT_VDBOX2_VIDEO;
121 if (m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext) != MOS_STATUS_SUCCESS)
122 {
123 gpuContext = MOS_GPU_CONTEXT_VDBOX2_VIDEO2;
124 eStatus = (MOS_STATUS)m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext);
125 }
126 }
127 else // videoGpuNode == MOS_GPU_NODE_VIDEO
128 {
129 // check other GPU contexts on VDBox1
130 gpuContext = MOS_GPU_CONTEXT_VIDEO;
131 if (m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext) != MOS_STATUS_SUCCESS)
132 {
133 gpuContext = MOS_GPU_CONTEXT_VIDEO2;
134 eStatus = (MOS_STATUS)m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext);
135 }
136 }
137
138 if (eStatus != MOS_STATUS_SUCCESS)
139 {
140 // No valid GPU context on current VDBox, so destroy the video node association.
141 if (MEDIA_IS_SKU(m_skuTable, FtrVcs2))
142 {
143 m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, videoGpuNode);
144 m_videoNodeAssociationCreated = false;
145 }
146
147 if (videoGpuNode == MOS_GPU_NODE_VIDEO2)
148 {
149 // If no valid GPU context on VDBox2, check GPU contexts on VDBox1
150 gpuContext = MOS_GPU_CONTEXT_VIDEO3;
151 if (m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext) != MOS_STATUS_SUCCESS)
152 {
153 gpuContext = MOS_GPU_CONTEXT_VIDEO;
154 if (m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext) != MOS_STATUS_SUCCESS)
155 {
156 // If this context is also invalid, return an error as no context for the video engine
157 // is available, so PAK cannot occur
158 gpuContext = MOS_GPU_CONTEXT_VIDEO2;
159 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext));
160 }
161 }
162
163 // When using existing VDBOX1, UMD needs to notify KMD to increase the VDBOX1 counter
164 setVideoNode = true;
165 videoGpuNode = MOS_GPU_NODE_VIDEO;
166 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateVideoNodeAssociation(
167 m_osInterface,
168 setVideoNode,
169 &videoGpuNode));
170 m_videoNodeAssociationCreated = true;
171 }
172 else // videoGpuNode == MOS_GPU_NODE_VIDEO
173 {
174 // We won't check GPU contexts on VDBox2 if there is no valid GPU context on VDBox1
175 // since VDBox2 is not full featured.
176 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
177 }
178 }
179
180 // save the updated VDBox ordinal
181 m_videoGpuNode = videoGpuNode;
182 }
183
184 if (m_videoNodeAssociationCreated)
185 {
186 CODECHAL_UPDATE_VDBOX_USER_FEATURE(videoGpuNode, m_osInterface->pOsContext);
187 }
188
189 m_videoContext = gpuContext;
190
191 m_osInterface->pfnSetEncodePakContext(m_osInterface, m_videoContext);
192 }
193
194 if (m_hwInterface->UsesRenderEngine(m_codecFunction, m_standard))
195 {
196 MOS_GPU_CONTEXT gpuContext = MOS_GPU_CONTEXT_RENDER2;
197 MOS_GPU_NODE renderGpuNode = MOS_GPU_NODE_3D;
198 MOS_GPUCTX_CREATOPTIONS createOption;
199
200 if (!MEDIA_IS_SKU(m_skuTable, FtrCCSNode))
201 {
202 m_computeContextEnabled = false;
203 }
204
205 if (m_osInterface->osCpInterface->IsHMEnabled() &&
206 (MEDIA_IS_SKU(m_skuTable, FtrRAMode) || MEDIA_IS_SKU(m_skuTable, FtrProtectedEnableBitRequired)))
207 {
208 if (m_computeContextEnabled)
209 {
210 gpuContext = MOS_GPU_CONTEXT_COMPUTE_RA;
211 renderGpuNode = MOS_GPU_NODE_COMPUTE;
212 }
213 else
214 {
215 gpuContext = MOS_GPU_CONTEXT_RENDER_RA;
216 renderGpuNode = MOS_GPU_NODE_3D;
217 }
218 createOption.RAMode = MEDIA_IS_SKU(m_skuTable, FtrRAMode);
219 createOption.ProtectMode = MEDIA_IS_SKU(m_skuTable, FtrProtectedEnableBitRequired);
220 }
221 else
222 {
223 if (m_computeContextEnabled)
224 {
225 gpuContext = MOS_GPU_CONTEXT_COMPUTE;
226 renderGpuNode = MOS_GPU_NODE_COMPUTE;
227 }
228 else
229 {
230 gpuContext = MOS_GPU_CONTEXT_RENDER2;
231 renderGpuNode = MOS_GPU_NODE_3D;
232 }
233 createOption.RAMode = 0;
234 createOption.ProtectMode = 0;
235 }
236
237 if (m_hwInterface->m_slicePowerGate)
238 {
239 createOption.packed.SubSliceCount = (m_gtSystemInfo->SubSliceCount / m_gtSystemInfo->SliceCount);
240 // If there are multiply sub slices, disable half of sub slices.
241 if (createOption.packed.SubSliceCount > 1)
242 createOption.packed.SubSliceCount >>= 1;
243 createOption.packed.SliceCount = (uint8_t)m_gtSystemInfo->SliceCount;
244 createOption.packed.MaxEUcountPerSubSlice = (uint8_t)(m_gtSystemInfo->EUCount / m_gtSystemInfo->SubSliceCount);
245 createOption.packed.MinEUcountPerSubSlice = (uint8_t)(m_gtSystemInfo->EUCount / m_gtSystemInfo->SubSliceCount);
246 }
247
248 eStatus = (MOS_STATUS)m_osInterface->pfnCreateGpuContext(m_osInterface, gpuContext, renderGpuNode, &createOption);
249
250 if (eStatus != MOS_STATUS_SUCCESS)
251 {
252 // If this context is also invalid, return an error as no context for the 3D engine
253 // is available, so ENC cannot occur
254 gpuContext = MOS_GPU_CONTEXT_RENDER;
255 CODECHAL_ENCODE_ASSERTMESSAGE("create gpu context failure for Render Engine!");
256 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnIsGpuContextValid(m_osInterface, gpuContext));
257 }
258
259 m_renderContext = gpuContext;
260 m_osInterface->pfnSetEncodeEncContext(m_osInterface, m_renderContext);
261 }
262
263 // Set Vdbox index in use
264 m_vdboxIndex = (m_videoGpuNode == MOS_GPU_NODE_VIDEO2)? MHW_VDBOX_NODE_2 : MHW_VDBOX_NODE_1;
265
266 return eStatus;
267 }
268
DestroyMeResources(HmeParams * param)269 MOS_STATUS CodechalEncoderState::DestroyMeResources(
270 HmeParams* param)
271 {
272 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
273
274 CODECHAL_ENCODE_FUNCTION_ENTER;
275
276 CODECHAL_ENCODE_CHK_NULL_RETURN(param);
277
278 if (param->ps16xMeMvDataBuffer != nullptr)
279 {
280 m_osInterface->pfnFreeResource(
281 m_osInterface,
282 ¶m->ps16xMeMvDataBuffer->OsResource);
283 }
284
285 if (param->ps32xMeMvDataBuffer != nullptr)
286 {
287 m_osInterface->pfnFreeResource(
288 m_osInterface,
289 ¶m->ps32xMeMvDataBuffer->OsResource);
290 }
291
292 if (param->ps4xMeDistortionBuffer != nullptr)
293 {
294 m_osInterface->pfnFreeResource(
295 m_osInterface,
296 ¶m->ps4xMeDistortionBuffer->OsResource);
297 }
298
299 if (param->ps4xMeMvDataBuffer != nullptr)
300 {
301 m_osInterface->pfnFreeResource(
302 m_osInterface,
303 ¶m->ps4xMeMvDataBuffer->OsResource);
304 }
305
306 if (param->presMvAndDistortionSumSurface != nullptr)
307 {
308 m_osInterface->pfnFreeResource(
309 m_osInterface,
310 param->presMvAndDistortionSumSurface);
311 }
312
313 return eStatus;
314 }
315
CleanUpResource(PMOS_RESOURCE resource,PMOS_ALLOC_GFXRES_PARAMS allocParams)316 MOS_STATUS CodechalEncoderState::CleanUpResource(
317 PMOS_RESOURCE resource,
318 PMOS_ALLOC_GFXRES_PARAMS allocParams)
319 {
320 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
321
322 CODECHAL_ENCODE_FUNCTION_ENTER;
323
324 CODECHAL_ENCODE_CHK_NULL_RETURN(resource);
325 CODECHAL_ENCODE_CHK_NULL_RETURN(allocParams);
326
327 MOS_LOCK_PARAMS lockFlag;
328 MOS_ZeroMemory(&lockFlag, sizeof(lockFlag));
329 lockFlag.WriteOnly = true;
330 uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, resource, &lockFlag);
331 if(data == nullptr)
332 {
333 return MOS_STATUS_NULL_POINTER;
334 }
335
336 if(allocParams->Format == Format_Buffer)
337 {
338 MOS_ZeroMemory(data, allocParams->dwBytes);
339 }
340 else if(allocParams->Format == Format_Buffer_2D)
341 {
342 MOS_ZeroMemory(data, allocParams->dwHeight * allocParams->dwWidth);
343 }
344 else
345 {
346 eStatus = MOS_STATUS_INVALID_PARAMETER;
347 }
348
349 m_osInterface->pfnUnlockResource(m_osInterface, resource);
350
351 return eStatus;
352 }
353
AllocateResources4xMe(HmeParams * param)354 MOS_STATUS CodechalEncoderState::AllocateResources4xMe(
355 HmeParams* param)
356 {
357 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
358
359 CODECHAL_ENCODE_FUNCTION_ENTER;
360
361 CODECHAL_ENCODE_CHK_NULL_RETURN(param);
362
363 if(!m_encEnabled || !m_hmeSupported)
364 {
365 return eStatus;
366 }
367
368 MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
369 MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
370 allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
371 allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
372 allocParamsForBuffer2D.Format = Format_Buffer_2D;
373
374 MOS_ZeroMemory(param->ps4xMeMvDataBuffer, sizeof(MOS_SURFACE));
375 param->ps4xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
376 param->ps4xMeMvDataBuffer->bArraySpacing = true;
377 param->ps4xMeMvDataBuffer->Format = Format_Buffer_2D;
378 param->ps4xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear.
379 param->ps4xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
380 param->ps4xMeMvDataBuffer->dwPitch = param->ps4xMeMvDataBuffer->dwWidth;
381
382 allocParamsForBuffer2D.dwWidth = param->ps4xMeMvDataBuffer->dwWidth;
383 allocParamsForBuffer2D.dwHeight = param->ps4xMeMvDataBuffer->dwHeight;
384 allocParamsForBuffer2D.pBufName = "4xME MV Data Buffer";
385
386 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
387 m_osInterface,
388 &allocParamsForBuffer2D,
389 ¶m->ps4xMeMvDataBuffer->OsResource);
390
391 if (eStatus != MOS_STATUS_SUCCESS)
392 {
393 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME MV Data Buffer.");
394 return eStatus;
395 }
396
397 CleanUpResource(¶m->ps4xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
398
399 if (param->b4xMeDistortionBufferSupported)
400 {
401 uint32_t adjustedHeight =
402 m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT * SCALE_FACTOR_4x;
403 uint32_t downscaledFieldHeightInMb4x =
404 CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(((adjustedHeight + 1) >> 1)/4);
405
406 MOS_ZeroMemory(param->ps4xMeDistortionBuffer, sizeof(MOS_SURFACE));
407 param->ps4xMeDistortionBuffer->TileType = MOS_TILE_LINEAR;
408 param->ps4xMeDistortionBuffer->bArraySpacing = true;
409 param->ps4xMeDistortionBuffer->Format = Format_Buffer_2D;
410 param->ps4xMeDistortionBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
411 param->ps4xMeDistortionBuffer->dwHeight = 2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMb4x * 4 * 10), 8);
412 param->ps4xMeDistortionBuffer->dwPitch = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
413
414 allocParamsForBuffer2D.dwWidth = param->ps4xMeDistortionBuffer->dwWidth;
415 allocParamsForBuffer2D.dwHeight = param->ps4xMeDistortionBuffer->dwHeight;
416 allocParamsForBuffer2D.pBufName = "4xME Distortion Buffer";
417
418 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
419 m_osInterface,
420 &allocParamsForBuffer2D,
421 ¶m->ps4xMeDistortionBuffer->OsResource);
422
423 if (eStatus != MOS_STATUS_SUCCESS)
424 {
425 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME Distortion Buffer.");
426 return eStatus;
427 }
428 CleanUpResource(¶m->ps4xMeDistortionBuffer->OsResource, &allocParamsForBuffer2D);
429 }
430
431 return eStatus;
432 }
433
AllocateResources16xMe(HmeParams * param)434 MOS_STATUS CodechalEncoderState::AllocateResources16xMe(
435 HmeParams* param)
436 {
437 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
438
439 CODECHAL_ENCODE_FUNCTION_ENTER;
440
441 CODECHAL_ENCODE_CHK_NULL_RETURN(param);
442
443 if (!m_encEnabled || !m_hmeSupported)
444 {
445 return eStatus;
446 }
447
448 MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
449 MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
450 allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
451 allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
452 allocParamsForBuffer2D.Format = Format_Buffer_2D;
453
454 if (m_16xMeSupported)
455 {
456 MOS_ZeroMemory(param->ps16xMeMvDataBuffer, sizeof(MOS_SURFACE));
457 param->ps16xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
458 param->ps16xMeMvDataBuffer->bArraySpacing = true;
459 param->ps16xMeMvDataBuffer->Format = Format_Buffer_2D;
460 param->ps16xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
461 param->ps16xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
462 param->ps16xMeMvDataBuffer->dwPitch = param->ps16xMeMvDataBuffer->dwWidth;
463
464 allocParamsForBuffer2D.dwWidth = param->ps16xMeMvDataBuffer->dwWidth;
465 allocParamsForBuffer2D.dwHeight = param->ps16xMeMvDataBuffer->dwHeight;
466 allocParamsForBuffer2D.pBufName = "16xME MV Data Buffer";
467
468 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
469 m_osInterface,
470 &allocParamsForBuffer2D,
471 ¶m->ps16xMeMvDataBuffer->OsResource);
472
473 if (eStatus != MOS_STATUS_SUCCESS)
474 {
475 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 16xME MV Data Buffer.");
476 return eStatus;
477 }
478 CleanUpResource(¶m->ps16xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
479 }
480
481 return eStatus;
482 }
483
AllocateResources32xMe(HmeParams * param)484 MOS_STATUS CodechalEncoderState::AllocateResources32xMe(
485 HmeParams* param)
486 {
487 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
488
489 CODECHAL_ENCODE_FUNCTION_ENTER;
490
491 CODECHAL_ENCODE_CHK_NULL_RETURN(param);
492 if (!m_encEnabled || !m_hmeSupported)
493 {
494 return eStatus;
495 }
496
497 MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
498 MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
499 allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
500 allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
501 allocParamsForBuffer2D.Format = Format_Buffer_2D;
502
503 if (m_32xMeSupported)
504 {
505 MOS_ZeroMemory(param->ps32xMeMvDataBuffer, sizeof(MOS_SURFACE));
506 param->ps32xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
507 param->ps32xMeMvDataBuffer->bArraySpacing = true;
508 param->ps32xMeMvDataBuffer->Format = Format_Buffer_2D;
509 param->ps32xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
510 param->ps32xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
511 param->ps32xMeMvDataBuffer->dwPitch = param->ps32xMeMvDataBuffer->dwWidth;
512
513 allocParamsForBuffer2D.dwWidth = param->ps32xMeMvDataBuffer->dwWidth;
514 allocParamsForBuffer2D.dwHeight = param->ps32xMeMvDataBuffer->dwHeight;
515 allocParamsForBuffer2D.pBufName = "32xME MV Data Buffer";
516
517 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
518 m_osInterface,
519 &allocParamsForBuffer2D,
520 ¶m->ps32xMeMvDataBuffer->OsResource);
521
522 if (eStatus != MOS_STATUS_SUCCESS)
523 {
524 CODECHAL_ENCODE_ASSERTMESSAGE("%s: Failed to allocate 32xME MV Data Buffer\n", __FUNCTION__);
525 return eStatus;
526 }
527 CleanUpResource(¶m->ps32xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
528 }
529
530 return eStatus;
531 }
532
533 // Encode Public Interface Functions
Allocate(CodechalSetting * codecHalSettings)534 MOS_STATUS CodechalEncoderState::Allocate(CodechalSetting * codecHalSettings)
535 {
536 CODECHAL_ENCODE_FUNCTION_ENTER;
537
538 if (m_cscDsState)
539 {
540 // call before m_hwInterface->Initialize() to reserve ISH space for CscDs kernel
541 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cscDsState->Initialize());
542 }
543
544 {
545 CODECHAL_PUBLIC_FUNCTION_ENTER;
546
547 CODECHAL_PUBLIC_CHK_NULL_RETURN(codecHalSettings);
548 CODECHAL_PUBLIC_CHK_NULL_RETURN(m_hwInterface);
549 //CODECHAL_PUBLIC_CHK_NULL_RETURN(m_osInterface);
550
551 MOS_TraceEvent(EVENT_CODECHAL_CREATE,
552 EVENT_TYPE_INFO,
553 &codecHalSettings->codecFunction,
554 sizeof(uint32_t),
555 nullptr,
556 0);
557
558 CODECHAL_PUBLIC_CHK_STATUS_RETURN(m_hwInterface->Initialize(codecHalSettings));
559
560 MOS_NULL_RENDERING_FLAGS nullHWAccelerationEnable;
561 nullHWAccelerationEnable.Value = 0;
562
563 #if (_DEBUG || _RELEASE_INTERNAL)
564 if (!m_statusReportDebugInterface)
565 {
566 m_statusReportDebugInterface = MOS_New(CodechalDebugInterface);
567 CODECHAL_PUBLIC_CHK_NULL_RETURN(m_statusReportDebugInterface);
568 CODECHAL_PUBLIC_CHK_STATUS_RETURN(
569 m_statusReportDebugInterface->Initialize(m_hwInterface, codecHalSettings->codecFunction));
570 }
571
572 ReadUserSettingForDebug(
573 m_userSettingPtr,
574 nullHWAccelerationEnable.Value,
575 __MEDIA_USER_FEATURE_VALUE_NULL_HW_ACCELERATION_ENABLE,
576 MediaUserSetting::Group::Device);
577
578 m_useNullHw[MOS_GPU_CONTEXT_VIDEO] =
579 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVideo);
580 m_useNullHw[MOS_GPU_CONTEXT_VIDEO2] =
581 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVideo2);
582 m_useNullHw[MOS_GPU_CONTEXT_VIDEO3] =
583 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVideo3);
584 m_useNullHw[MOS_GPU_CONTEXT_VDBOX2_VIDEO] =
585 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVDBox2Video);
586 m_useNullHw[MOS_GPU_CONTEXT_VDBOX2_VIDEO2] =
587 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVDBox2Video2);
588 m_useNullHw[MOS_GPU_CONTEXT_VDBOX2_VIDEO3] =
589 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxVDBox2Video3);
590 m_useNullHw[MOS_GPU_CONTEXT_RENDER] =
591 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxRender);
592 m_useNullHw[MOS_GPU_CONTEXT_RENDER2] =
593 (nullHWAccelerationEnable.CodecGlobal || nullHWAccelerationEnable.CtxRender2);
594 #endif // _DEBUG || _RELEASE_INTERNAL
595
596 }
597
598 CODECHAL_ENCODE_CHK_STATUS_RETURN(Initialize(codecHalSettings));
599
600 // Create MMC state
601 if (m_mmcState == nullptr)
602 {
603 CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState = MOS_New(CodecHalMmcState, m_hwInterface));
604 }
605
606 // create resource allocator
607 CODECHAL_ENCODE_CHK_NULL_RETURN(m_allocator = MOS_New(CodechalEncodeAllocator, this));
608
609 // create tracked buffer state
610 #if defined (_HEVC_ENCODE_VME_SUPPORTED) || defined (_HEVC_ENCODE_VDENC_SUPPORTED)
611 if (m_standard == CODECHAL_HEVC)
612 {
613 CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf = MOS_New(CodechalEncodeTrackedBufferHevc, this));
614 }
615 else
616 #endif
617 {
618 CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf = MOS_New(CodechalEncodeTrackedBuffer, this));
619 }
620
621 MotionEstimationDisableCheck();
622
623 CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources());
624
625 CODECHAL_ENCODE_CHK_STATUS_RETURN(CreateGpuContexts());
626
627 if (m_hwInterface->UsesRenderEngine(codecHalSettings->codecFunction, codecHalSettings->standard))
628 {
629 m_renderContextUsesNullHw = m_useNullHw[m_renderContext];
630 }
631
632 if (CodecHalUsesVideoEngine(codecHalSettings->codecFunction))
633 {
634 m_videoContextUsesNullHw = m_useNullHw[m_videoContext];
635 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
636 m_osInterface,
637 m_videoContext));
638 }
639 else
640 {
641 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
642 m_osInterface,
643 m_renderContext));
644 }
645
646 if (!m_perfProfiler)
647 {
648 m_perfProfiler = MediaPerfProfiler::Instance();
649 CODECHAL_ENCODE_CHK_NULL_RETURN(m_perfProfiler);
650
651 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_perfProfiler->Initialize((void*)this, m_osInterface));
652 }
653 return MOS_STATUS_SUCCESS;
654 }
655
Execute(void * params)656 MOS_STATUS CodechalEncoderState::Execute(void *params)
657 {
658 CODECHAL_ENCODE_FUNCTION_ENTER;
659
660 PERF_UTILITY_AUTO(__FUNCTION__, PERF_ENCODE, PERF_LEVEL_HAL);
661
662 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_START,
663 &m_codecFunction, sizeof(m_codecFunction),
664 nullptr, 0);
665
666 CODECHAL_ENCODE_CHK_STATUS_RETURN(Codechal::Execute(params));
667
668 EncoderParams *encodeParams = (EncoderParams *)params;
669 // MSDK event handling
670 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mos_Solo_SetGpuAppTaskEvent(m_osInterface,encodeParams->gpuAppTaskEvent));
671
672 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->SetWatchdogTimerThreshold(m_frameWidth, m_frameHeight));
673
674 if (m_frameNum == 0)
675 {
676 m_osInterface->pfnSetLatestVirtualNode(m_osInterface, m_videoGpuNode);
677 }
678
679 if (m_codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
680 {
681 CODECHAL_ENCODE_CHK_STATUS_RETURN(ExecutePreEnc(encodeParams));
682 }
683 else
684 {
685 CODECHAL_ENCODE_CHK_STATUS_RETURN(ExecuteEnc(encodeParams));
686 }
687
688 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
689
690 return MOS_STATUS_SUCCESS;
691 }
692
693 // Encoder Public Interface Functions
Initialize(CodechalSetting * settings)694 MOS_STATUS CodechalEncoderState::Initialize(
695 CodechalSetting * settings)
696 {
697 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
698 MOS_STATUS statusKey = MOS_STATUS_SUCCESS;
699
700 CODECHAL_ENCODE_FUNCTION_ENTER;
701
702 CODECHAL_ENCODE_CHK_NULL_RETURN(settings);
703
704 m_storeData = 1;
705 m_firstFrame = true;
706 m_firstTwoFrames = true;
707 m_standard = settings->standard;
708 m_mode = settings->mode;
709 m_codecFunction = settings->codecFunction;
710
711 if (CodecHalUsesVideoEngine(m_codecFunction))
712 {
713 m_pakEnabled = true;
714 }
715
716 if (m_hwInterface->UsesRenderEngine(m_codecFunction, m_standard))
717 {
718 m_encEnabled = true;
719 }
720
721 MOS_USER_FEATURE_VALUE_DATA userFeatureData;
722 if (m_encEnabled)
723 {
724 m_brcPakStatisticsSize = CODECHAL_ENCODE_BRC_PAK_STATISTICS_SIZE;
725
726 m_hwScoreboardType = 1;
727
728 m_encodeVfeMaxThreads = 0;
729 #if (_DEBUG || _RELEASE_INTERNAL)
730 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
731 MOS_UserFeature_ReadValue_ID(
732 nullptr,
733 __MEDIA_USER_FEATURE_VALUE_ENCODE_VFE_MAX_THREADS_ID,
734 &userFeatureData,
735 m_osInterface->pOsContext);
736 m_encodeVfeMaxThreads = (uint32_t)userFeatureData.u32Data;
737 #endif // _DEBUG || _RELEASE_INTERNAL
738
739 m_encodeVfeMaxThreadsScaling = 0;
740 #if (_DEBUG || _RELEASE_INTERNAL)
741 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
742 MOS_UserFeature_ReadValue_ID(
743 nullptr,
744 __MEDIA_USER_FEATURE_VALUE_ENCODE_VFE_MAX_THREADS_SCALING_ID,
745 &userFeatureData,
746 m_osInterface->pOsContext);
747 m_encodeVfeMaxThreadsScaling = (uint32_t)userFeatureData.i32Data;
748 #endif // _DEBUG || _RELEASE_INTERNAL
749
750 {
751 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
752 MOS_UserFeature_ReadValue_ID(
753 nullptr,
754 __MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_ID,
755 &userFeatureData,
756 m_osInterface->pOsContext);
757
758 m_hwWalker = (userFeatureData.i32Data) ? true : false;
759
760 if (m_hwWalker)
761 {
762 m_walkerMode = (MHW_WALKER_MODE)0;
763 #if (_DEBUG || _RELEASE_INTERNAL)
764 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
765 MOS_UserFeature_ReadValue_ID(
766 nullptr,
767 __MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_MODE_ID,
768 &userFeatureData,
769 m_osInterface->pOsContext);
770 m_walkerMode = (MHW_WALKER_MODE)userFeatureData.u32Data;
771 #endif // _DEBUG || _RELEASE_INTERNAL
772
773 if (MEDIA_IS_SKU(m_skuTable, FtrSliceShutdownOverride))
774 {
775 //Default Slice State
776 m_sliceShutdownDefaultState = (uint32_t)0;
777 #if (_DEBUG || _RELEASE_INTERNAL)
778 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
779 MOS_UserFeature_ReadValue_ID(
780 nullptr,
781 __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_DEFAULT_STATE_ID,
782 &userFeatureData,
783 m_osInterface->pOsContext);
784 m_sliceShutdownDefaultState = (uint32_t)userFeatureData.u32Data;
785 #endif // _DEBUG || _RELEASE_INTERNAL
786
787 //Requested Slice State
788 m_sliceShutdownRequestState = (uint32_t)0;
789 #if (_DEBUG || _RELEASE_INTERNAL)
790 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
791 MOS_UserFeature_ReadValue_ID(
792 nullptr,
793 __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_REQUEST_STATE_ID,
794 &userFeatureData,
795 m_osInterface->pOsContext);
796 m_sliceShutdownRequestState = (uint32_t)userFeatureData.u32Data;
797 #endif // _DEBUG || _RELEASE_INTERNAL
798
799 //Slice Shutdown Resolution Threshold
800 m_ssdResolutionThreshold = (uint32_t)0;
801 #if (_DEBUG || _RELEASE_INTERNAL)
802 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
803 MOS_UserFeature_ReadValue_ID(
804 nullptr,
805 __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_RESOLUTION_THRESHOLD_ID,
806 &userFeatureData,
807 m_osInterface->pOsContext);
808 m_ssdResolutionThreshold = (uint32_t)userFeatureData.i32Data;
809 #endif // _DEBUG || _RELEASE_INTERNAL
810
811 //Slice Shutdown Target Usage Threshold
812 m_ssdTargetUsageThreshold = (uint32_t)0;
813 #if (_DEBUG || _RELEASE_INTERNAL)
814 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
815 MOS_UserFeature_ReadValue_ID(
816 nullptr,
817 __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_TARGET_USAGE_THRESHOLD_ID,
818 &userFeatureData,
819 m_osInterface->pOsContext);
820 m_ssdTargetUsageThreshold = (uint32_t)userFeatureData.i32Data;
821 #endif // _DEBUG || _RELEASE_INTERNAL
822
823 if (!m_sliceShutdownDefaultState &&
824 !m_sliceShutdownRequestState &&
825 !m_ssdTargetUsageThreshold &&
826 !m_ssdResolutionThreshold)
827 {
828 // slice shutdown used for power efficiency
829 // use it in case of ult and if hw has more than 2 slices
830 if (MEDIA_IS_SKU(m_skuTable, FtrULT))
831 {
832 if ((GFX_IS_GEN_10_OR_LATER(m_platform) && m_gtSystemInfo->SliceCount >= 2) ||
833 MEDIA_IS_SKU(m_skuTable, FtrGT3))
834 {
835 m_sliceShutdownDefaultState = CODECHAL_SLICE_SHUTDOWN_ONE_SLICE;
836 m_sliceShutdownRequestState = CODECHAL_SLICE_SHUTDOWN_TWO_SLICES;
837 m_ssdResolutionThreshold = m_hwInterface->m_ssdResolutionThreshold;
838 m_ssdTargetUsageThreshold = m_hwInterface->m_ssdTargetUsageThreshold;
839 }
840 }
841 else if (MEDIA_IS_SKU(m_skuTable, FtrGT4))
842 {
843 m_sliceShutdownDefaultState = CODECHAL_SLICE_SHUTDOWN_ONE_SLICE;
844 m_sliceShutdownRequestState = CODECHAL_SLICE_SHUTDOWN_TWO_SLICES;
845 m_ssdResolutionThreshold = m_hwInterface->m_ssdResolutionThreshold;
846 m_ssdTargetUsageThreshold = m_hwInterface->m_ssdTargetUsageThreshold;
847 }
848 }
849 }
850 }
851 }
852
853 #if (_DEBUG || _RELEASE_INTERNAL)
854 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
855 MOS_UserFeature_ReadValue_ID(
856 nullptr,
857 __MEDIA_USER_FEATURE_VALUE_ENCODE_BRC_SOFTWARE_ID,
858 &userFeatureData,
859 m_osInterface->pOsContext);
860
861 if (userFeatureData.i32Data)
862 {
863 char path_buffer[256];
864 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
865 MOS_ZeroMemory(path_buffer, 256);
866 userFeatureData.StringData.pStringData = path_buffer;
867
868 statusKey = MOS_UserFeature_ReadValue_ID(
869 nullptr,
870 __MEDIA_USER_FEATURE_VALUE_ENCODE_BRC_SOFTWARE_PATH_ID,
871 &userFeatureData,
872 m_osInterface->pOsContext);
873
874 if (statusKey == MOS_STATUS_SUCCESS && userFeatureData.StringData.uSize > 0)
875 {
876 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnLoadLibrary(m_osInterface, path_buffer, &m_swBrcMode));
877 }
878 }
879 // SW BRC DLL Reporting
880 CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_ENCODE_BRC_SOFTWARE_IN_USE_ID, ((m_swBrcMode == nullptr) ? false : true), m_osInterface->pOsContext);
881 #endif // _DEBUG || _RELEASE_INTERNAL
882
883 if (MEDIA_IS_SKU(m_skuTable, FtrSliceShutdown))
884 {
885 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
886 MOS_UserFeature_ReadValue_ID(
887 nullptr,
888 __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_ENABLE_ID,
889 &userFeatureData,
890 m_osInterface->pOsContext);
891 m_sliceShutdownEnable = (userFeatureData.i32Data) ? true : false;
892 }
893
894 m_targetUsageOverride = (uint8_t)0;
895 #if (_DEBUG || _RELEASE_INTERNAL)
896 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
897 MOS_UserFeature_ReadValue_ID(
898 nullptr,
899 __MEDIA_USER_FEATURE_VALUE_ENCODE_TARGET_USAGE_OVERRIDE_ID,
900 &userFeatureData,
901 m_osInterface->pOsContext);
902 m_targetUsageOverride = (uint8_t)userFeatureData.u32Data;
903 #endif // _DEBUG || _RELEASE_INTERNAL
904 }
905
906 if (m_pakEnabled)
907 {
908 //RCPanic settings
909 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
910 MOS_UserFeature_ReadValue_ID(
911 nullptr,
912 __MEDIA_USER_FEATURE_VALUE_RC_PANIC_ENABLE_ID,
913 &userFeatureData,
914 m_osInterface->pOsContext);
915 m_panicEnable = (userFeatureData.i32Data) ? true : false;
916
917 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
918 userFeatureData.i32Data = 1;
919 userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
920 MOS_UserFeature_ReadValue_ID(
921 nullptr,
922 __MEDIA_USER_FEATURE_VALUE_ENCODE_SUPPRESS_RECON_PIC_ENABLE_ID,
923 &userFeatureData,
924 m_osInterface->pOsContext);
925 m_suppressReconPicSupported = (userFeatureData.u32Data) ? true : false;
926 }
927
928 #if (_DEBUG || _RELEASE_INTERNAL)
929 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
930 statusKey = MOS_UserFeature_ReadValue_ID(
931 NULL,
932 __MEDIA_USER_FEATURE_VALUE_ENCODE_ENABLE_COMPUTE_CONTEXT_ID,
933 &userFeatureData,
934 m_osInterface->pOsContext);
935
936 if (statusKey == MOS_STATUS_SUCCESS)
937 {
938 // Change the default value only when CCS=on/off is set directly
939 m_computeContextEnabled = (userFeatureData.u32Data) ? true : false;
940 }
941 #endif
942
943 #if USE_CODECHAL_DEBUG_TOOL
944 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
945 MOS_UserFeature_ReadValue_ID(
946 nullptr,
947 __MEDIA_USER_FEATURE_VALUE_CODECHAL_ENABLE_FAKE_HEADER_SIZE_ID,
948 &userFeatureData,
949 m_osInterface->pOsContext);
950 m_enableFakeHrdSize = (uint32_t)userFeatureData.u32Data;
951
952 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
953 MOS_UserFeature_ReadValue_ID(
954 nullptr,
955 __MEDIA_USER_FEATURE_VALUE_CODECHAL_FAKE_IFRAME_HEADER_SIZE_ID,
956 &userFeatureData,
957 m_osInterface->pOsContext);
958 m_fakeIFrameHrdSize = (uint32_t)userFeatureData.u32Data;
959
960 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
961 MOS_UserFeature_ReadValue_ID(
962 nullptr,
963 __MEDIA_USER_FEATURE_VALUE_CODECHAL_FAKE_PBFRAME_HEADER_SIZE_ID,
964 &userFeatureData,
965 m_osInterface->pOsContext);
966 m_fakePBFrameHrdSize = (uint32_t)userFeatureData.u32Data;
967 #endif
968
969 m_oriFrameWidth = settings->width;
970 m_oriFrameHeight = settings->height;
971 m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth);
972 m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight);
973 m_frameWidth = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH;
974 m_frameHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT;
975 m_createWidth = m_frameWidth;
976 m_createHeight = m_frameHeight;
977
978 // HME Scaling WxH
979 m_downscaledWidthInMb4x =
980 CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x);
981 m_downscaledHeightInMb4x =
982 CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x);
983 m_downscaledWidth4x =
984 m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH;
985 m_downscaledHeight4x =
986 m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT;
987
988 // SuperHME Scaling WxH
989 m_downscaledWidthInMb16x =
990 CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_16x);
991 m_downscaledHeightInMb16x =
992 CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_16x);
993 m_downscaledWidth16x =
994 m_downscaledWidthInMb16x * CODECHAL_MACROBLOCK_WIDTH;
995 m_downscaledHeight16x =
996 m_downscaledHeightInMb16x * CODECHAL_MACROBLOCK_HEIGHT;
997
998 // UltraHME Scaling WxH
999 m_downscaledWidthInMb32x =
1000 CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_32x);
1001 m_downscaledHeightInMb32x =
1002 CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_32x);
1003 m_downscaledWidth32x =
1004 m_downscaledWidthInMb32x * CODECHAL_MACROBLOCK_WIDTH;
1005 m_downscaledHeight32x =
1006 m_downscaledHeightInMb32x * CODECHAL_MACROBLOCK_HEIGHT;
1007
1008 m_minScaledDimension = CODECHAL_ENCODE_MIN_SCALED_SURFACE_SIZE;
1009 m_minScaledDimensionInMb = (CODECHAL_ENCODE_MIN_SCALED_SURFACE_SIZE + 15) >> 4;
1010
1011 m_currOriginalPic.PicFlags = PICTURE_INVALID;
1012 m_currOriginalPic.FrameIdx = 0;
1013 m_currOriginalPic.PicEntry = 0;
1014
1015 m_hwInterface->GetCpInterface()->RegisterParams(settings->GetCpParams());
1016
1017 // flag to enable kmd for the frame tracking (so encoder driver doesn't need to send a separate command buffer
1018 // for frame tracking purpose). Currently this feature is disabled for HEVC.
1019 // For HEVC, this feature will be enabled later.
1020
1021 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
1022 statusKey = MOS_UserFeature_ReadValue_ID(
1023 nullptr,
1024 __MEDIA_USER_FEATURE_VALUE_ENCODE_ENABLE_FRAME_TRACKING_ID,
1025 &userFeatureData,
1026 m_osInterface->pOsContext);
1027 if (statusKey == MOS_STATUS_SUCCESS)
1028 {
1029 m_frameTrackingEnabled = userFeatureData.i32Data ? true : false;
1030 }
1031 else
1032 {
1033 m_frameTrackingEnabled = m_osInterface->bEnableKmdMediaFrameTracking ? true: false;
1034 }
1035
1036 if (m_standard == CODECHAL_AVC)
1037 {
1038 if (CodecHalUsesVideoEngine(m_codecFunction) && !(MEDIA_IS_WA(m_waTable, WaForceAllocateLML3)))
1039 {
1040 m_inlineEncodeStatusUpdate = m_osInterface->bInlineCodecStatusUpdate ? true: false;
1041 }
1042 }
1043
1044 if (m_standard == CODECHAL_AVC)
1045 {
1046 m_bRenderOcaEnabled = true;
1047 }
1048
1049 // Disable SHME and UHME if HME is disabled
1050 if(!m_hmeSupported)
1051 {
1052 m_16xMeSupported = false;
1053 m_32xMeSupported = false;
1054 }
1055 // Disable UHME if SHME is disabled
1056 else if(!m_16xMeSupported)
1057 {
1058 m_32xMeSupported = false;
1059 }
1060
1061 // Set Vdbox index in use
1062 m_vdboxIndex = (m_videoGpuNode == MOS_GPU_NODE_VIDEO2)? MHW_VDBOX_NODE_2 : MHW_VDBOX_NODE_1;
1063
1064 if (!m_feiEnable)
1065 {
1066 eStatus = AllocateMDFResources();
1067 }
1068
1069 if (eStatus != MOS_STATUS_SUCCESS)
1070 {
1071 Destroy();
1072 }
1073
1074 return eStatus;
1075 }
1076
AllocateMDFResources()1077 MOS_STATUS CodechalEncoderState::AllocateMDFResources()
1078 {
1079 uint32_t devOp;
1080
1081 if (CodecHalIsFeiEncode(m_codecFunction) && m_codecFunction != CODECHAL_FUNCTION_FEI_PAK)
1082 {
1083 devOp = CM_DEVICE_CREATE_OPTION_SCRATCH_SPACE_DISABLE;
1084
1085 if (m_cmDev == nullptr)
1086 {
1087 CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
1088 m_osInterface->pfnNotifyStreamIndexSharing(m_osInterface);
1089 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateCmDevice(m_osInterface->pOsContext, m_cmDev, devOp, CM_DEVICE_CREATE_PRIORITY_DEFAULT));
1090 }
1091 //just WA for issues in MDF null support
1092 if (!m_cmQueue)
1093 {
1094 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmDev->CreateQueue(m_cmQueue));
1095 }
1096 if (!m_cmTask)
1097 {
1098 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmDev->CreateTask(m_cmTask));
1099 }
1100 }
1101 return MOS_STATUS_SUCCESS;
1102 }
1103
DestroyMDFResources()1104 MOS_STATUS CodechalEncoderState::DestroyMDFResources()
1105 {
1106 uint32_t i;
1107
1108 if (m_cmDev && m_cmTask)
1109 {
1110 m_cmDev->DestroyTask(m_cmTask);
1111 m_cmTask = nullptr;
1112 }
1113 if (m_cmDev && m_osInterface)
1114 {
1115 m_osInterface->pfnDestroyCmDevice(m_cmDev);
1116 m_cmDev = nullptr;
1117 }
1118
1119 return MOS_STATUS_SUCCESS;
1120 }
1121
SetMfeSharedState(MfeSharedState * pMfeSharedState)1122 MOS_STATUS CodechalEncoderState::SetMfeSharedState(MfeSharedState *pMfeSharedState)
1123 {
1124 CODECHAL_ENCODE_FUNCTION_ENTER;
1125
1126 CODECHAL_ENCODE_CHK_NULL_RETURN(pMfeSharedState);
1127
1128 m_mfeEncodeSharedState = pMfeSharedState;
1129
1130 return MOS_STATUS_SUCCESS;
1131 }
1132
1133
AddKernelMdf(CmDevice * device,CmQueue * queue,CmKernel * kernel,CmTask * task,CmThreadSpace * threadspace,CmEvent * & event,bool isEnqueue)1134 MOS_STATUS CodechalEncoderState::AddKernelMdf(
1135 CmDevice * device,
1136 CmQueue * queue,
1137 CmKernel * kernel,
1138 CmTask * task,
1139 CmThreadSpace *threadspace,
1140 CmEvent *& event,
1141 bool isEnqueue)
1142 {
1143 CODECHAL_ENCODE_CHK_NULL_RETURN(device);
1144 CODECHAL_ENCODE_CHK_NULL_RETURN(kernel);
1145 CODECHAL_ENCODE_CHK_NULL_RETURN(queue);
1146 CODECHAL_ENCODE_CHK_NULL_RETURN(task);
1147 CODECHAL_ENCODE_CHK_NULL_RETURN(threadspace);
1148
1149 CODECHAL_ENCODE_CHK_STATUS_RETURN(kernel->AssociateThreadSpace(threadspace));
1150 CODECHAL_ENCODE_CHK_STATUS_RETURN(task->AddKernel(kernel));
1151 if (isEnqueue)
1152 {
1153 CODECHAL_ENCODE_CHK_STATUS_RETURN(queue->Enqueue(task, event));
1154 task->Reset();
1155 }
1156 else
1157 {
1158 CODECHAL_ENCODE_CHK_STATUS_RETURN(task->AddSync());
1159 }
1160
1161 return MOS_STATUS_SUCCESS;
1162 }
1163
CreateMDFKernelResource(CodechalEncodeMdfKernelResource * resource,uint8_t kernelNum,uint8_t bufNum,uint8_t surfNum,uint8_t vmeSurfNum,uint16_t curbeSize)1164 MOS_STATUS CodechalEncoderState::CreateMDFKernelResource(
1165 CodechalEncodeMdfKernelResource *resource,
1166 uint8_t kernelNum,
1167 uint8_t bufNum,
1168 uint8_t surfNum,
1169 uint8_t vmeSurfNum,
1170 uint16_t curbeSize)
1171 {
1172 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1173
1174 CODECHAL_ENCODE_CHK_NULL_RETURN(resource);
1175 if (kernelNum > 0)
1176 {
1177 resource->ppKernel = (CmKernel **)MOS_AllocAndZeroMemory(sizeof(CmKernel *) * kernelNum);
1178 resource->KernelNum = kernelNum;
1179 }
1180 if (bufNum > 0)
1181 {
1182 resource->ppCmBuf = (CmBuffer **)MOS_AllocAndZeroMemory(sizeof(CmBuffer *) * bufNum);
1183 resource->BufNum = bufNum;
1184 }
1185 if (surfNum > 0)
1186 {
1187 resource->ppCmSurf = (CmSurface2D **)MOS_AllocAndZeroMemory(sizeof(CmSurface2D *) * surfNum);
1188 resource->SurfNum = surfNum;
1189 }
1190 if (vmeSurfNum > 0)
1191 {
1192 resource->ppCmVmeSurf = (SurfaceIndex **)MOS_AllocAndZeroMemory(sizeof(SurfaceIndex *) * vmeSurfNum);
1193 resource->VmeSurfNum = vmeSurfNum;
1194 }
1195 if (curbeSize > 0)
1196 {
1197 resource->pCurbe = (uint8_t *)MOS_AllocAndZeroMemory(curbeSize);
1198 resource->wCurbeSize = curbeSize;
1199 }
1200
1201 resource->e = nullptr;
1202
1203 return MOS_STATUS_SUCCESS;
1204 }
1205
DestroyMDFKernelResource(CodechalEncodeMdfKernelResource * resource)1206 MOS_STATUS CodechalEncoderState::DestroyMDFKernelResource(
1207 CodechalEncodeMdfKernelResource *resource)
1208 {
1209 int i;
1210 CODECHAL_ENCODE_CHK_NULL_RETURN(resource);
1211
1212 CODECHAL_ENCODE_CHK_STATUS_RETURN(FreeMDFKernelSurfaces(resource));
1213
1214 if (resource->ppKernel && resource->KernelNum)
1215 {
1216 for (i = 0; i < resource->KernelNum; i++)
1217 {
1218 if (resource->ppKernel != nullptr)
1219 {
1220 m_cmDev->DestroyKernel(resource->ppKernel[i]);
1221 resource->ppKernel[i] = nullptr;
1222 }
1223 }
1224 MOS_FreeMemory(resource->ppKernel);
1225 resource->ppKernel = nullptr;
1226 }
1227 if (resource->pTS)
1228 {
1229 m_cmDev->DestroyThreadSpace(resource->pTS);
1230 resource->pTS = nullptr;
1231 }
1232 if (resource->ppCmBuf && resource->BufNum)
1233 {
1234 MOS_FreeMemory(resource->ppCmBuf);
1235 resource->ppCmBuf = nullptr;
1236 resource->BufNum = 0;
1237 }
1238 if (resource->ppCmSurf && resource->SurfNum)
1239 {
1240 MOS_FreeMemory(resource->ppCmSurf);
1241 resource->ppCmSurf = nullptr;
1242 resource->SurfNum = 0;
1243 }
1244 if (resource->ppCmVmeSurf && resource->VmeSurfNum)
1245 {
1246 MOS_FreeMemory(resource->ppCmVmeSurf);
1247 resource->ppCmVmeSurf = nullptr;
1248 resource->VmeSurfNum = 0;
1249 }
1250 if (resource->ppKernel && resource->KernelNum)
1251 {
1252 MOS_FreeMemory(resource->ppKernel);
1253 resource->ppKernel = nullptr;
1254 resource->KernelNum = 0;
1255 }
1256 if (resource->pCurbe && resource->wCurbeSize)
1257 {
1258 MOS_FreeMemory(resource->pCurbe);
1259 resource->pCurbe = nullptr;
1260 resource->wCurbeSize = 0;
1261 }
1262 if (resource->pCommonISA)
1263 {
1264 MOS_FreeMemory(resource->pCommonISA);
1265 resource->pCommonISA = nullptr;
1266 }
1267
1268 return MOS_STATUS_SUCCESS;
1269 }
1270
FreeMDFKernelSurfaces(CodechalEncodeMdfKernelResource * resource)1271 MOS_STATUS CodechalEncoderState::FreeMDFKernelSurfaces(
1272 CodechalEncodeMdfKernelResource* resource)
1273 {
1274 int i;
1275
1276 for (i = 0; i < resource->VmeSurfNum; i++)
1277 {
1278 if (resource->ppCmVmeSurf[i] != nullptr && resource->ppCmVmeSurf[i] != (SurfaceIndex *)CM_NULL_SURFACE)
1279 {
1280 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmDev->DestroyVmeSurfaceG7_5(resource->ppCmVmeSurf[i]));
1281 resource->ppCmVmeSurf[i] = nullptr;
1282 }
1283 }
1284 for (i = 0; i < resource->BufNum; i++)
1285 {
1286 if (resource->ppCmBuf[i] != nullptr)
1287 {
1288 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmDev->DestroySurface(resource->ppCmBuf[i]));
1289 resource->ppCmBuf[i] = nullptr;
1290 }
1291 }
1292 for (i = 0; i < resource->SurfNum; i++)
1293 {
1294 if (resource->ppCmSurf[i] != nullptr)
1295 {
1296 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmDev->DestroySurface(resource->ppCmSurf[i]));
1297 resource->ppCmSurf[i] = nullptr;
1298 }
1299 }
1300
1301 return MOS_STATUS_SUCCESS;
1302 }
1303
InitCommon()1304 MOS_STATUS CodechalEncoderState::InitCommon()
1305 {
1306 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1307
1308 CODECHAL_ENCODE_FUNCTION_ENTER;
1309
1310 EncoderParams* encodeParams = &m_encodeParams;
1311 m_newSeq = encodeParams->bNewSeq ? true: false; // used by all except JPEG
1312 m_mbDataBufferSize = encodeParams->dwMbDataBufferSize; // used by all except JPEG
1313 m_newVuiData = encodeParams->bNewVuiData ? true: false; // used by AVC and MPEG2
1314 m_picQuant = encodeParams->bPicQuant ? true: false; // used by AVC and MPEG2
1315 m_newQmatrixData = encodeParams->bNewQmatrixData ? true: false; // used by AVC and MPEG2
1316 m_numSlices = encodeParams->dwNumSlices; // used by all except VP9
1317 m_slcData =
1318 (PCODEC_ENCODER_SLCDATA)(encodeParams->pSlcHeaderData); // used by AVC, MPEG2, and HEVC
1319
1320 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeParams->presBitstreamBuffer);
1321 m_rawSurface = *(encodeParams->psRawSurface); // used by all
1322 m_resBitstreamBuffer = *(encodeParams->presBitstreamBuffer); // used by all
1323
1324 if(encodeParams->presMetadataBuffer)
1325 {
1326 m_presMetadataBuffer = encodeParams->presMetadataBuffer;
1327 m_metaDataOffset = encodeParams->metaDataOffset;
1328 }
1329
1330 CODECHAL_ENCODE_CHK_COND_RETURN(
1331 Mos_ResourceIsNull(&m_rawSurface.OsResource),
1332 "Raw surface is nullptr!");
1333
1334 m_rawSurfaceToEnc =
1335 m_rawSurfaceToPak = &m_rawSurface;
1336
1337 if(encodeParams->psReconSurface)
1338 {
1339 m_reconSurface = *(encodeParams->psReconSurface); // used by all except JPEG
1340 }
1341
1342 if(encodeParams->pBSBuffer)
1343 {
1344 m_bsBuffer = *(encodeParams->pBSBuffer); // used by all except VP9
1345 }
1346
1347 return eStatus;
1348 }
1349
ResizeOnResChange()1350 void CodechalEncoderState::ResizeOnResChange()
1351 {
1352 CODECHAL_ENCODE_FUNCTION_ENTER;
1353
1354 // if resolution changed, free existing tracked buffer resources
1355 m_trackedBuf->Resize();
1356 }
1357
CheckResChangeAndCsc()1358 MOS_STATUS CodechalEncoderState::CheckResChangeAndCsc()
1359 {
1360 CODECHAL_ENCODE_FUNCTION_ENTER;
1361
1362 if (m_resolutionChanged)
1363 {
1364 ResizeOnResChange();
1365 }
1366
1367 if (m_cscDsState)
1368 {
1369 // check recon surface's alignment meet HW requirement
1370 CODECHAL_ENCODE_CHK_STATUS_RETURN(
1371 m_cscDsState->CheckReconSurfaceAlignment(&m_reconSurface));
1372
1373 if (!m_cscDsState->IsEnabled() ||
1374 CodecHal_PictureIsField(m_currOriginalPic) ||
1375 CodecHal_PictureIsInterlacedFrame(m_currOriginalPic))
1376 {
1377 // CSC disabled for interlaced frame
1378 m_cscDsState->ResetCscFlag();
1379
1380 // check raw surface's alignment meet HW requirement
1381 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cscDsState->CheckRawSurfaceAlignment(m_rawSurfaceToEnc));
1382 }
1383 else
1384 {
1385 // check if we need to do CSC or copy non-aligned surface
1386 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cscDsState->CheckCondition());
1387 }
1388 }
1389
1390 return MOS_STATUS_SUCCESS;
1391 }
1392
1393 // Function to allocate all resources common to all encoders
AllocateResources()1394 MOS_STATUS CodechalEncoderState::AllocateResources()
1395 {
1396 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1397
1398 CODECHAL_ENCODE_FUNCTION_ENTER;
1399
1400 uint32_t numMbs = m_picWidthInMb * ((m_picHeightInMb+1)>>1)<<1;
1401
1402 // initiate allocation paramters and lock flags
1403 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
1404 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1405 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
1406 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
1407 allocParamsForBufferLinear.Format = Format_Buffer;
1408
1409 MOS_ALLOC_GFXRES_PARAMS allocParams2D;
1410 MOS_ZeroMemory(&allocParams2D, sizeof(allocParams2D));
1411 allocParams2D.Type = MOS_GFXRES_2D;
1412 allocParams2D.TileType = MOS_TILE_LINEAR;
1413 allocParams2D.Format = Format_Buffer_2D;
1414
1415 MOS_LOCK_PARAMS lockFlagsNoOverWrite;;
1416 MOS_ZeroMemory(&lockFlagsNoOverWrite, sizeof(MOS_LOCK_PARAMS));
1417 lockFlagsNoOverWrite.WriteOnly = 1;
1418 lockFlagsNoOverWrite.NoOverWrite = 1;
1419
1420 MOS_LOCK_PARAMS lockFlags;
1421 MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
1422 lockFlags.WriteOnly = 1;
1423
1424 // create VME and MFX sync objects
1425 if ((m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) ||
1426 (m_codecFunction == (CODECHAL_FUNCTION_ENC | CODECHAL_FUNCTION_ENC_PAK)) ||
1427 (m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) ||
1428 (m_codecFunction == (CODECHAL_FUNCTION_FEI_ENC | CODECHAL_FUNCTION_FEI_ENC_PAK)))
1429 {
1430 // Create OS synchronization object to sync between MFX => VME
1431 // if 3 is not good enough, need to increase MBCode buffer number
1432 m_semaphoreMaxCount = MOS_MAX_SEMAPHORE_COUNT;
1433 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObjectRenderContextInUse));
1434
1435 // Create OS synchronization object to sync between VME => MFX
1436 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse));
1437 }
1438
1439 // Create VME and VDENC/PAK sync objects
1440 if (m_codecFunction == CODECHAL_FUNCTION_ENC_VDENC_PAK)
1441 {
1442 m_semaphoreMaxCount = MOS_MAX_SEMAPHORE_COUNT;
1443 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObjectRenderContextInUse));
1444 }
1445
1446 //For HEVC, moved to standard specific as LCU size is not available here
1447 if (m_hwInterface->GetMfxInterface()->IsRowStoreCachingSupported() &&
1448 ((m_mode == CODECHAL_ENCODE_MODE_AVC) ||
1449 (m_mode == CODECHAL_ENCODE_MODE_VP9 && m_vdencEnabled)))
1450 {
1451 MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams = {};
1452 rowstoreParams.Mode = m_mode;
1453 rowstoreParams.dwPicWidth = m_frameWidth;
1454 rowstoreParams.bMbaff = false;
1455 m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams);
1456 }
1457
1458 // eStatus query reporting
1459 // HW requires the MI_CONDITIONAL_BATCH_BUFFER_END compare address aligned with cache line since TGL,
1460 // this change will guarantee the multi pak pass BRC works correctly
1461 m_encodeStatusBuf.dwReportSize = MOS_ALIGN_CEIL(sizeof(EncodeStatus), MHW_CACHELINE_SIZE);
1462 uint32_t size = m_encodeStatusBuf.dwReportSize * CODECHAL_ENCODE_STATUS_NUM + sizeof(uint32_t) * 2;
1463 allocParamsForBufferLinear.dwBytes = size;
1464 allocParamsForBufferLinear.pBufName = "StatusQueryBuffer";
1465 allocParamsForBufferLinear.bIsPersistent = true; // keeping status buffer persistent since its used in all command buffers
1466
1467 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1468 m_osInterface->pfnAllocateResource(
1469 m_osInterface,
1470 &allocParamsForBufferLinear,
1471 &m_encodeStatusBuf.resStatusBuffer),
1472 "Failed to allocate Encode eStatus Buffer.");
1473
1474 CODECHAL_ENCODE_CHK_STATUS_RETURN(
1475 m_osInterface->pfnSkipResourceSync(
1476 &m_encodeStatusBuf.resStatusBuffer));
1477
1478 uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
1479 m_osInterface,
1480 &(m_encodeStatusBuf.resStatusBuffer),
1481 &lockFlagsNoOverWrite);
1482
1483 MOS_ZeroMemory(data, size);
1484 m_encodeStatusBuf.pData = (uint32_t*)data;
1485 m_encodeStatusBuf.pEncodeStatus = (uint8_t*)(data + sizeof(uint32_t) * 2);
1486 m_encodeStatusBuf.dwSize = size;
1487
1488 // Addresses writen to by HW commands (MI_STORE_DATA_IMM, MI_FLUSH_DW, PIPE_CONTROL) must be QW aligned since these
1489 // commands are capable of writing QWs so the least significant 3 bits of the address field are not used for the
1490 // actual address
1491 m_encodeStatusBuf.dwStoreDataOffset = 0;
1492 m_encodeStatusBuf.dwBSByteCountOffset = CODECHAL_OFFSETOF(EncodeStatus, dwMFCBitstreamByteCountPerFrame);
1493 m_encodeStatusBuf.dwBSSEBitCountOffset = CODECHAL_OFFSETOF(EncodeStatus, dwMFCBitstreamSyntaxElementOnlyBitCount);
1494 m_encodeStatusBuf.dwImageStatusMaskOffset = CODECHAL_OFFSETOF(EncodeStatus, dwImageStatusMask);
1495 m_encodeStatusBuf.dwImageStatusCtrlOffset = CODECHAL_OFFSETOF(EncodeStatus, ImageStatusCtrl);
1496 m_encodeStatusBuf.dwNumSlicesOffset = CODECHAL_OFFSETOF(EncodeStatus, NumSlices);
1497 m_encodeStatusBuf.dwErrorFlagOffset = CODECHAL_OFFSETOF(EncodeStatus, dwErrorFlags);
1498 m_encodeStatusBuf.dwBRCQPReportOffset = CODECHAL_OFFSETOF(EncodeStatus, BrcQPReport);
1499 m_encodeStatusBuf.dwNumPassesOffset = CODECHAL_OFFSETOF(EncodeStatus, dwNumberPasses);
1500 m_encodeStatusBuf.dwQpStatusCountOffset = CODECHAL_OFFSETOF(EncodeStatus, QpStatusCount);
1501 m_encodeStatusBuf.dwImageStatusCtrlOfLastBRCPassOffset = CODECHAL_OFFSETOF(EncodeStatus, ImageStatusCtrlOfLastBRCPass);
1502 m_encodeStatusBuf.dwSceneChangedOffset = CODECHAL_OFFSETOF(EncodeStatus, dwSceneChangedFlag);
1503 m_encodeStatusBuf.dwSumSquareErrorOffset = CODECHAL_OFFSETOF(EncodeStatus, sumSquareError[0]);
1504 m_encodeStatusBuf.dwSliceReportOffset = CODECHAL_OFFSETOF(EncodeStatus, sliceReport);
1505 m_encodeStatusBuf.dwHuCStatusMaskOffset = CODECHAL_OFFSETOF(EncodeStatus, HuCStatusRegMask);
1506 m_encodeStatusBuf.dwHuCStatusRegOffset = CODECHAL_OFFSETOF(EncodeStatus, HuCStatusReg);
1507 m_encodeStatusBuf.dwHuCStatus2RegOffset = CODECHAL_OFFSETOF(EncodeStatus, HuCStatus2Reg);
1508 m_encodeStatusBuf.dwLookaheadStatusOffset = CODECHAL_OFFSETOF(EncodeStatus, lookaheadStatus);
1509 m_encodeStatusBuf.dwSADLumaOffset = CODECHAL_OFFSETOF(EncodeStatus, dwSADLuma);
1510 m_encodeStatusBuf.dwIntraBlockCountOffset = CODECHAL_OFFSETOF(EncodeStatus, dwIntraBlockCount);
1511 m_encodeStatusBuf.dwInterBlockCountOffset = CODECHAL_OFFSETOF(EncodeStatus, dwInterBlockCount);
1512 m_encodeStatusBuf.dwSkipBlockCountOffset = CODECHAL_OFFSETOF(EncodeStatus, dwSkipBlockCount);
1513
1514 m_encodeStatusBuf.wCurrIndex = 0;
1515 m_encodeStatusBuf.wFirstIndex = 0;
1516
1517 if (m_encEnabled)
1518 {
1519 m_encodeStatusBufRcs.dwReportSize = MOS_ALIGN_CEIL(sizeof(EncodeStatus), sizeof(uint64_t));
1520 size = m_encodeStatusBufRcs.dwReportSize * CODECHAL_ENCODE_STATUS_NUM + sizeof(uint32_t) * 2;
1521 allocParamsForBufferLinear.dwBytes = size;
1522 allocParamsForBufferLinear.pBufName = "StatusQueryBufferRcs";
1523 allocParamsForBufferLinear.bIsPersistent = true; // keeping status buffer persistent since its used in all command buffers
1524 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1525 m_osInterface,
1526 &allocParamsForBufferLinear,
1527 &m_encodeStatusBufRcs.resStatusBuffer);
1528
1529 if (eStatus != MOS_STATUS_SUCCESS)
1530 {
1531 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Encode eStatus Buffer.");
1532 return eStatus;
1533 }
1534
1535 data = (uint8_t*)m_osInterface->pfnLockResource(
1536 m_osInterface,
1537 &(m_encodeStatusBufRcs.resStatusBuffer),
1538 &lockFlagsNoOverWrite);
1539
1540 if (data == nullptr)
1541 {
1542 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to lock Encode eStatus Buffer RCS.");
1543 return eStatus;
1544 }
1545
1546 MOS_ZeroMemory(data, size);
1547 m_encodeStatusBufRcs.pData = (uint32_t*)data;
1548 m_encodeStatusBufRcs.pEncodeStatus = (uint8_t*)(data + sizeof(uint32_t) * 2);
1549 m_encodeStatusBufRcs.dwSize = size;
1550 m_encodeStatusBufRcs.dwStoreDataOffset = 0;
1551 m_encodeStatusBufRcs.wCurrIndex = 0;
1552 m_encodeStatusBufRcs.wFirstIndex = 0;
1553 }
1554
1555 if (m_pakEnabled)
1556 {
1557 m_stateHeapInterface->pfnSetCmdBufStatusPtr(m_stateHeapInterface, m_encodeStatusBuf.pData);
1558 }
1559 else
1560 {
1561 m_stateHeapInterface->pfnSetCmdBufStatusPtr(m_stateHeapInterface, m_encodeStatusBufRcs.pData);
1562 }
1563
1564 MOS_LOCK_PARAMS lockFlagsWriteOnly;
1565 MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
1566 lockFlagsWriteOnly.WriteOnly = 1;
1567
1568 if(m_inlineEncodeStatusUpdate)
1569 {
1570 m_atomicScratchBuf.dwSize = MOS_ALIGN_CEIL(sizeof(AtomicScratchBuffer), sizeof(uint64_t));
1571 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
1572 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
1573 allocParamsForBufferLinear.Format = Format_Buffer;
1574
1575 size = MHW_CACHELINE_SIZE * 4 * 2; // each set of scratch is 4 cacheline size, and allocate 2 set.
1576 allocParamsForBufferLinear.dwBytes = size;
1577 allocParamsForBufferLinear.pBufName = "atomic sratch buffer";
1578
1579 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1580 m_osInterface,
1581 &allocParamsForBufferLinear,
1582 &(m_atomicScratchBuf.resAtomicScratchBuffer));
1583
1584 if (eStatus != MOS_STATUS_SUCCESS)
1585 {
1586 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Finger Print Source Buffer.");
1587 return eStatus;
1588 }
1589
1590 data = (uint8_t*)m_osInterface->pfnLockResource(
1591 m_osInterface,
1592 &(m_atomicScratchBuf.resAtomicScratchBuffer),
1593 &lockFlagsWriteOnly);
1594
1595 if (data == nullptr)
1596 {
1597 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to lock Finger Print Source Buffer.");
1598 return eStatus;
1599 }
1600
1601 MOS_ZeroMemory(data, size);
1602 m_atomicScratchBuf.pData = (uint32_t*)data;
1603 m_atomicScratchBuf.dwSize = size;
1604 m_atomicScratchBuf.dwZeroValueOffset = 0;
1605 m_atomicScratchBuf.dwOperand1Offset = MHW_CACHELINE_SIZE;
1606 m_atomicScratchBuf.dwOperand2Offset = MHW_CACHELINE_SIZE * 2;
1607 m_atomicScratchBuf.dwOperand3Offset = MHW_CACHELINE_SIZE * 3;
1608 m_atomicScratchBuf.wEncodeUpdateIndex = 0;
1609 m_atomicScratchBuf.wTearDownIndex = 1;
1610 m_atomicScratchBuf.dwOperandSetSize = MHW_CACHELINE_SIZE * 4;
1611 }
1612
1613 if (m_pakEnabled)
1614 {
1615 if(m_hwInterface->GetMfxInterface()->IsDeblockingFilterRowstoreCacheEnabled() == false)
1616 {
1617 // Deblocking Filter Row Store Scratch buffer
1618 allocParamsForBufferLinear.dwBytes = m_picWidthInMb * 4 * CODECHAL_CACHELINE_SIZE; // 4 cachelines per MB
1619 allocParamsForBufferLinear.pBufName = "Deblocking Filter Row Store Scratch Buffer";
1620
1621 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1622 m_osInterface->pfnAllocateResource(
1623 m_osInterface,
1624 &allocParamsForBufferLinear,
1625 &m_resDeblockingFilterRowStoreScratchBuffer),
1626 "Failed to allocate Deblocking Filter Row Store Scratch Buffer.");
1627 }
1628
1629 if(m_hwInterface->GetMfxInterface()->IsBsdMpcRowstoreCacheEnabled() == false)
1630 {
1631 // MPC Row Store Scratch buffer
1632 allocParamsForBufferLinear.dwBytes = m_picWidthInMb * 2 * 64; // 2 cachelines per MB
1633 allocParamsForBufferLinear.pBufName = "MPC Row Store Scratch Buffer";
1634
1635 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1636 m_osInterface->pfnAllocateResource(
1637 m_osInterface,
1638 &allocParamsForBufferLinear,
1639 &m_resMPCRowStoreScratchBuffer),
1640 "Failed to allocate MPC Row Store Scratch Buffer.");
1641 }
1642
1643 if (!m_vdencEnabled && m_standard != CODECHAL_HEVC) // StreamOut is needed for HEVC VDEnc
1644 {
1645 // streamout data buffer
1646 allocParamsForBufferLinear.dwBytes = numMbs * MFX_PAK_STREAMOUT_DATA_BYTE_SIZE * sizeof(uint32_t);
1647 allocParamsForBufferLinear.pBufName = "Pak StreamOut Buffer";
1648
1649 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1650 {
1651 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1652 m_osInterface->pfnAllocateResource(
1653 m_osInterface,
1654 &allocParamsForBufferLinear,
1655 &m_resStreamOutBuffer[i]),
1656 "Failed to allocate Pak Stream Out Buffer.");
1657 }
1658 }
1659 }
1660
1661 if (m_encEnabled || m_vdencEnabled)
1662 {
1663 // Scaled surfaces are required to run both HME and IFrameDist
1664 CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateScalingResources());
1665 }
1666
1667 if(m_encEnabled && (!m_vdencEnabled))
1668 {
1669 for (auto i = 0; i < CODECHAL_ENCODE_MAX_NUM_MAD_BUFFERS; i++)
1670 {
1671 allocParamsForBufferLinear.dwBytes = CODECHAL_MAD_BUFFER_SIZE;
1672 allocParamsForBufferLinear.pBufName = "MAD Data Buffer";
1673
1674 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1675 m_osInterface->pfnAllocateResource(
1676 m_osInterface,
1677 &allocParamsForBufferLinear,
1678 &m_resMadDataBuffer[i]),
1679 "Failed to allocate MAD Data Buffer.");
1680 }
1681 }
1682
1683 if (m_vdencEnabled)
1684 {
1685 // VDENC BRC PAK MMIO buffer
1686 allocParamsForBufferLinear.dwBytes = sizeof(VdencBrcPakMmio);
1687 allocParamsForBufferLinear.pBufName = "VDENC BRC PAK MMIO Buffer";
1688
1689 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1690 m_osInterface->pfnAllocateResource(
1691 m_osInterface,
1692 &allocParamsForBufferLinear,
1693 &m_resPakMmioBuffer),
1694 "%s: Failed to allocate VDENC BRC PAK MMIO Buffer\n", __FUNCTION__);
1695
1696 // VDENC Huc Error Status Buffer
1697 allocParamsForBufferLinear.dwBytes = sizeof(VdencHucErrorStatus);
1698 allocParamsForBufferLinear.pBufName = "VDENC Huc Error Status Buffer";
1699
1700 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1701 m_osInterface->pfnAllocateResource(
1702 m_osInterface,
1703 &allocParamsForBufferLinear,
1704 &m_resHucErrorStatusBuffer),
1705 "%s: Failed to allocate VDENC Huc Error Status Buffer\n", __FUNCTION__);
1706
1707 // VDEnc StreamIn data buffers, shared between driver/ME kernel/VDEnc
1708 if ((m_mode == CODECHAL_ENCODE_MODE_HEVC) || (m_mode == CODECHAL_ENCODE_MODE_VP9))
1709 {
1710 allocParamsForBufferLinear.dwBytes = (MOS_ALIGN_CEIL(m_frameWidth, 64)/32) * (MOS_ALIGN_CEIL(m_frameHeight, 64)/32) * CODECHAL_CACHELINE_SIZE;
1711 }
1712 else
1713 {
1714 allocParamsForBufferLinear.dwBytes = m_picWidthInMb * m_picHeightInMb * CODECHAL_CACHELINE_SIZE;
1715 }
1716 allocParamsForBufferLinear.pBufName = "VDEnc StreamIn Data Buffer";
1717
1718 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1719 {
1720 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1721 m_osInterface->pfnAllocateResource(
1722 m_osInterface,
1723 &allocParamsForBufferLinear,
1724 &m_resVdencStreamInBuffer[i]),
1725 "Failed to allocate VDEnc StreamIn Data Buffer.");
1726
1727 data = (uint8_t*)m_osInterface->pfnLockResource(
1728 m_osInterface,
1729 &m_resVdencStreamInBuffer[i],
1730 &lockFlags);
1731
1732 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
1733
1734 MOS_ZeroMemory(
1735 data,
1736 allocParamsForBufferLinear.dwBytes);
1737
1738 m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencStreamInBuffer[i]);
1739 }
1740 }
1741
1742 if (m_vdencEnabled)
1743 {
1744 // HUC STATUS 2 Buffer for HuC status check in COND_BB_END
1745 allocParamsForBufferLinear.dwBytes = sizeof(uint64_t);
1746 allocParamsForBufferLinear.pBufName = "HUC STATUS 2 Buffer";
1747
1748 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1749 m_osInterface->pfnAllocateResource(
1750 m_osInterface,
1751 &allocParamsForBufferLinear,
1752 &m_resHucStatus2Buffer),
1753 "%s: Failed to allocate HUC STATUS 2 Buffer\n", __FUNCTION__);
1754 }
1755
1756 allocParamsForBufferLinear.dwBytes = sizeof(uint32_t);
1757 allocParamsForBufferLinear.pBufName = "PredicationBuffer";
1758
1759 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(
1760 m_osInterface->pfnAllocateResource(
1761 m_osInterface,
1762 &allocParamsForBufferLinear,
1763 &m_predicationBuffer),
1764 "%s: Failed to allocate predication buffer\n", __FUNCTION__);
1765
1766 return eStatus;
1767 }
1768
AllocateScalingResources()1769 MOS_STATUS CodechalEncoderState::AllocateScalingResources()
1770 {
1771 uint32_t numMBs, size;
1772 MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
1773 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
1774 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1775
1776 CODECHAL_ENCODE_FUNCTION_ENTER;
1777
1778 //Allocate the Batch Buffer for scaling Kernel.
1779 numMBs = m_picWidthInMb * ((m_picHeightInMb + 1) >> 1) << 1;
1780 size = m_hwInterface->GetMediaObjectBufferSize(
1781 numMBs,
1782 64);
1783
1784 for (int i = 0; i < CODECHAL_ENCODE_VME_BBUF_NUM; i++)
1785 {
1786 MOS_ZeroMemory(&m_scalingBBUF[i].BatchBuffer, sizeof(m_scalingBBUF[0].BatchBuffer));
1787
1788 /* For CM based Downscale kernel, unlike the old asm based downscale kernel,
1789 HW walker can be used as no inline data is required by the kernel. */
1790 if (!m_useCmScalingKernel && !m_useMwWlkrForAsmScalingKernel)
1791 {
1792 m_scalingBBUF[i].BatchBuffer.bSecondLevel = true;
1793 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
1794 m_osInterface,
1795 &m_scalingBBUF[i].BatchBuffer,
1796 NULL,
1797 size));
1798
1799 m_scalingBBUF[i].dwSize = size;
1800 m_scalingBBUF[i].dwNumMbsInBBuf = 0;
1801 m_scalingBBufIdx = CODECHAL_ENCODE_VME_BBUF_NUM - 1;
1802 }
1803 }
1804
1805 //MB stats buffer is supported by AVC kernels on g9+.
1806 if(m_mbStatsSupported)
1807 {
1808 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1809 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
1810 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
1811 allocParamsForBufferLinear.Format = Format_Buffer;
1812
1813 // Starting from g9 HVS kernel, MBEnc Curbe is decoupled from BRC kernel and a new MBEnc BRC surface is added.
1814 // new HVS-based BRC kernel requires size of MBStat surface be 1024-aligned
1815 m_hwInterface->m_avcMbStatBufferSize = MOS_ALIGN_CEIL(m_picWidthInMb * 16 * sizeof(uint32_t)* (4 * m_downscaledHeightInMb4x), 1024);
1816
1817 allocParamsForBufferLinear.dwBytes = m_hwInterface->m_avcMbStatBufferSize;
1818 allocParamsForBufferLinear.pBufName = "MB Statistics Buffer";
1819
1820 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
1821 m_osInterface,
1822 &allocParamsForBufferLinear,
1823 &m_resMbStatsBuffer), "Failed to allocate MB Statistics Buffer.");
1824
1825 m_mbStatsBottomFieldOffset = m_picWidthInMb * 16 * sizeof(uint32_t) * (2 * m_downscaledHeightInMb4x);
1826
1827 MOS_LOCK_PARAMS lockFlagsWriteOnly;
1828 MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
1829 lockFlagsWriteOnly.WriteOnly = 1;
1830
1831 uint8_t* pData = (uint8_t*)m_osInterface->pfnLockResource(
1832 m_osInterface,
1833 &m_resMbStatsBuffer,
1834 &lockFlagsWriteOnly);
1835
1836 if (pData == nullptr)
1837 {
1838 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock m_resMbStatsBuffer");
1839 eStatus = MOS_STATUS_UNKNOWN;
1840 return eStatus;
1841 }
1842
1843 MOS_ZeroMemory(pData, m_hwInterface->m_avcMbStatBufferSize);
1844 m_osInterface->pfnUnlockResource(
1845 m_osInterface, &m_resMbStatsBuffer);
1846 }
1847 else if(m_flatnessCheckSupported)
1848 {
1849 MOS_ZeroMemory(&m_flatnessCheckSurface, sizeof(MOS_SURFACE));
1850 m_flatnessCheckSurface.TileType = MOS_TILE_LINEAR;
1851 m_flatnessCheckSurface.bArraySpacing = true;
1852 m_flatnessCheckSurface.Format = Format_Buffer_2D;
1853
1854 MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1855 allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
1856 allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
1857 allocParamsForBuffer2D.Format = Format_Buffer_2D;
1858 // Data size for 1MB is 1DWORDs (4Bytes)
1859 allocParamsForBuffer2D.dwWidth = MOS_ALIGN_CEIL(m_picWidthInMb * 4, 64);
1860 // Because FlatnessCheckSurface was referenced and filled during 4xDownScaling operation,
1861 // the height should be fit to MediaWalker height setting for 4xDS Kernel.
1862 allocParamsForBuffer2D.dwHeight = MOS_ALIGN_CEIL(4 * m_downscaledHeightInMb4x, 64);
1863 allocParamsForBuffer2D.pBufName = "Flatness Check Surface";
1864
1865 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1866 m_osInterface,
1867 &allocParamsForBuffer2D,
1868 &m_flatnessCheckSurface.OsResource);
1869
1870 if (eStatus != MOS_STATUS_SUCCESS)
1871 {
1872 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate FlatnessCheck Surface.");
1873 return eStatus;
1874 }
1875
1876 CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
1877 m_osInterface,
1878 &m_flatnessCheckSurface));
1879
1880 m_flatnessCheckBottomFieldOffset = m_flatnessCheckSurface.dwPitch * m_flatnessCheckSurface.dwHeight >> 1;
1881 }
1882
1883 return eStatus;
1884 }
1885
ExecuteMeKernel(MeCurbeParams * meParams,MeSurfaceParams * meSurfaceParams,HmeLevel hmeLevel)1886 MOS_STATUS CodechalEncoderState::ExecuteMeKernel(
1887 MeCurbeParams *meParams,
1888 MeSurfaceParams *meSurfaceParams,
1889 HmeLevel hmeLevel)
1890 {
1891 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1892
1893 CODECHAL_ENCODE_FUNCTION_ENTER;
1894
1895 CODECHAL_ENCODE_CHK_NULL_RETURN(meParams);
1896 CODECHAL_ENCODE_CHK_NULL_RETURN(meSurfaceParams);
1897
1898 PerfTagSetting perfTag;
1899 perfTag.Value = 0;
1900 perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK;
1901 perfTag.CallType = m_singleTaskPhaseSupported ? CODECHAL_ENCODE_PERFTAG_CALL_SCALING_KERNEL : CODECHAL_ENCODE_PERFTAG_CALL_ME_KERNEL;
1902 perfTag.PictureCodingType = m_pictureCodingType;
1903 m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value);
1904 // Each ME kernel buffer counts as a separate perf task
1905 m_osInterface->pfnResetPerfBufferID(m_osInterface);
1906
1907 CODECHAL_MEDIA_STATE_TYPE encFunctionType = (hmeLevel == HME_LEVEL_32x) ? CODECHAL_MEDIA_STATE_32X_ME :
1908 (hmeLevel == HME_LEVEL_16x) ? CODECHAL_MEDIA_STATE_16X_ME : CODECHAL_MEDIA_STATE_4X_ME;
1909
1910 bool vdencMeInUse = false;
1911 if (m_vdencEnabled && (encFunctionType == CODECHAL_MEDIA_STATE_4X_ME))
1912 {
1913 vdencMeInUse = true;
1914 // Non legacy stream in is for hevc vp9 streamin kernel
1915 encFunctionType = m_useNonLegacyStreamin ? CODECHAL_MEDIA_STATE_4X_ME : CODECHAL_MEDIA_STATE_ME_VDENC_STREAMIN;
1916 }
1917
1918 uint32_t krnStateIdx = vdencMeInUse ?
1919 CODECHAL_ENCODE_ME_IDX_VDENC :
1920 ((m_pictureCodingType == P_TYPE) ? CODECHAL_ENCODE_ME_IDX_P : CODECHAL_ENCODE_ME_IDX_B);
1921
1922 PMHW_KERNEL_STATE kernelState = &m_meKernelStates[krnStateIdx];
1923
1924 // If Single Task Phase is not enabled, use BT count for the kernel state.
1925 if (m_firstTaskInPhase == true || !m_singleTaskPhaseSupported)
1926 {
1927 uint32_t maxBtCount = m_singleTaskPhaseSupported ?
1928 m_maxBtCount : kernelState->KernelParams.iBTCount;
1929 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf(
1930 m_stateHeapInterface,
1931 maxBtCount));
1932 m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount);
1933 CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
1934 }
1935
1936 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
1937 m_stateHeapInterface,
1938 kernelState,
1939 false,
1940 0,
1941 false,
1942 m_storeData));
1943 MHW_INTERFACE_DESCRIPTOR_PARAMS idParams;
1944 MOS_ZeroMemory(&idParams, sizeof(idParams));
1945 idParams.pKernelState = kernelState;
1946 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor(
1947 m_stateHeapInterface,
1948 1,
1949 &idParams));
1950
1951 // Setup Additional MeParams (Most of them set up in codec specific function, so don't zero out here)
1952 meParams->hmeLvl = hmeLevel;
1953 meParams->pKernelState = kernelState;
1954
1955 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoderGenState->SetCurbeMe(meParams));
1956
1957 CODECHAL_DEBUG_TOOL(
1958 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
1959 encFunctionType,
1960 MHW_DSH_TYPE,
1961 kernelState));
1962 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe(
1963 encFunctionType,
1964 kernelState));
1965 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
1966 encFunctionType,
1967 MHW_ISH_TYPE,
1968 kernelState));
1969 )
1970 MOS_COMMAND_BUFFER cmdBuffer;
1971 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
1972 SendKernelCmdsParams sendKernelCmdsParams;
1973 sendKernelCmdsParams = SendKernelCmdsParams();
1974 sendKernelCmdsParams.EncFunctionType = encFunctionType;
1975 sendKernelCmdsParams.pKernelState = kernelState;
1976
1977 CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams));
1978
1979 // Add binding table
1980 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable(
1981 m_stateHeapInterface,
1982 kernelState));
1983
1984 // Setup Additional ME surface params (Most of them set up in codec specific function, so don't zero out here)
1985 meSurfaceParams->dwDownscaledWidthInMb = (hmeLevel == HME_LEVEL_32x) ? m_downscaledWidthInMb32x :
1986 (hmeLevel == HME_LEVEL_16x) ? m_downscaledWidthInMb16x : m_downscaledWidthInMb4x;
1987 meSurfaceParams->dwDownscaledHeightInMb = (hmeLevel == HME_LEVEL_32x) ? m_downscaledFrameFieldHeightInMb32x :
1988 (hmeLevel == HME_LEVEL_16x) ? m_downscaledFrameFieldHeightInMb16x : m_downscaledFrameFieldHeightInMb4x;
1989 meSurfaceParams->b32xMeInUse = (hmeLevel == HME_LEVEL_32x) ? true : false;
1990 meSurfaceParams->b16xMeInUse = (hmeLevel == HME_LEVEL_16x) ? true : false;
1991 meSurfaceParams->pKernelState = kernelState;
1992
1993 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoderGenState->SendMeSurfaces(&cmdBuffer, meSurfaceParams));
1994
1995 // Dump SSH for ME kernel
1996 CODECHAL_DEBUG_TOOL(
1997 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
1998 encFunctionType,
1999 MHW_SSH_TYPE,
2000 kernelState)));
2001
2002 /* zero out the mv data memory and me distortion buffer for the driver ULT
2003 kernel only writes out this data used for current frame, in some cases the the data used for
2004 previous frames would be left in the buffer (for example, the L1 mv for B frame would still show
2005 in the P frame mv data buffer */
2006
2007 // Zeroing out the buffers has perf impact, so zero it out only when dumps are actually enabled
2008 CODECHAL_DEBUG_TOOL(
2009 CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface);
2010 uint8_t* data = NULL;
2011 uint32_t size = 0;
2012 bool driverMeDumpEnabled = m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrOutput, encFunctionType);
2013
2014 if (driverMeDumpEnabled)
2015 {
2016 MOS_LOCK_PARAMS lockFlags;
2017 MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
2018 lockFlags.WriteOnly = 1;
2019
2020 switch (hmeLevel)
2021 {
2022 case HME_LEVEL_32x:
2023 data = (uint8_t*)m_osInterface->pfnLockResource(
2024 m_osInterface,
2025 &meSurfaceParams->ps32xMeMvDataBuffer->OsResource,
2026 &lockFlags);
2027 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
2028 size = MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) *
2029 (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
2030 MOS_ZeroMemory(data, size);
2031 m_osInterface->pfnUnlockResource(
2032 m_osInterface,
2033 &meSurfaceParams->ps32xMeMvDataBuffer->OsResource);
2034 break;
2035 case HME_LEVEL_16x:
2036 data = (uint8_t*)m_osInterface->pfnLockResource(
2037 m_osInterface,
2038 &meSurfaceParams->ps16xMeMvDataBuffer->OsResource,
2039 &lockFlags);
2040 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
2041 size = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) *
2042 (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
2043 MOS_ZeroMemory(data, size);
2044 m_osInterface->pfnUnlockResource(
2045 m_osInterface,
2046 &meSurfaceParams->ps16xMeMvDataBuffer->OsResource);
2047 break;
2048 case HME_LEVEL_4x:
2049 if (!m_vdencEnabled)
2050 {
2051 data = (uint8_t*)m_osInterface->pfnLockResource(
2052 m_osInterface,
2053 &meSurfaceParams->ps4xMeMvDataBuffer->OsResource,
2054 &lockFlags);
2055 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
2056 size = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) *
2057 (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
2058 MOS_ZeroMemory(data, size);
2059 m_osInterface->pfnUnlockResource(
2060 m_osInterface,
2061 &meSurfaceParams->ps4xMeMvDataBuffer->OsResource);
2062 }
2063 break;
2064 default:
2065 return MOS_STATUS_INVALID_PARAMETER;
2066 }
2067
2068 // zeroing out ME dist buffer
2069 if (meSurfaceParams->b4xMeDistortionBufferSupported)
2070 {
2071 data = (uint8_t*)m_osInterface->pfnLockResource(
2072 m_osInterface, &meSurfaceParams->psMeDistortionBuffer->OsResource, &lockFlags);
2073 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
2074 size = meSurfaceParams->psMeDistortionBuffer->dwHeight * meSurfaceParams->psMeDistortionBuffer->dwPitch;
2075 MOS_ZeroMemory(data, size);
2076 m_osInterface->pfnUnlockResource(
2077 m_osInterface,
2078 &meSurfaceParams->psMeDistortionBuffer->OsResource);
2079 }
2080 }
2081 );
2082
2083 uint32_t scalingFactor = (hmeLevel == HME_LEVEL_32x) ? SCALE_FACTOR_32x :
2084 (hmeLevel == HME_LEVEL_16x) ? SCALE_FACTOR_16x : SCALE_FACTOR_4x;
2085
2086 uint32_t resolutionX = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / scalingFactor);
2087 uint32_t resolutionY = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight / scalingFactor);
2088
2089 CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams;
2090 MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams));
2091 walkerCodecParams.WalkerMode = m_walkerMode;
2092 walkerCodecParams.dwResolutionX = resolutionX;
2093 walkerCodecParams.dwResolutionY = resolutionY;
2094 walkerCodecParams.bNoDependency = true;
2095 walkerCodecParams.bMbaff = meSurfaceParams->bMbaff;
2096 walkerCodecParams.bGroupIdSelectSupported = m_groupIdSelectSupported;
2097 walkerCodecParams.ucGroupId = m_groupId;
2098
2099 MHW_WALKER_PARAMS walkerParams;
2100 CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams(
2101 m_hwInterface,
2102 &walkerParams,
2103 &walkerCodecParams));
2104
2105 HalOcaInterface::TraceMessage(cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, __FUNCTION__, sizeof(__FUNCTION__));
2106 HalOcaInterface::OnDispatch(cmdBuffer, *m_osInterface, *m_miInterface, *m_renderEngineInterface->GetMmioRegisters());
2107
2108 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaObjectWalkerCmd(
2109 &cmdBuffer,
2110 &walkerParams));
2111
2112 CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType));
2113
2114 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks(
2115 m_stateHeapInterface,
2116 kernelState));
2117 if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
2118 {
2119 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId(
2120 m_stateHeapInterface));
2121 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
2122 }
2123
2124 CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
2125 &cmdBuffer,
2126 encFunctionType,
2127 nullptr)));
2128
2129 m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase);
2130
2131 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
2132
2133 if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
2134 {
2135 HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
2136 m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw);
2137 m_lastTaskInPhase = false;
2138 }
2139
2140 return eStatus;
2141 }
2142
CheckSupportedFormat(PMOS_SURFACE surface)2143 bool CodechalEncoderState::CheckSupportedFormat(
2144 PMOS_SURFACE surface)
2145 {
2146 bool isColorFormatSupported = true;
2147
2148 if (!surface)
2149 {
2150 CODECHAL_ENCODE_ASSERTMESSAGE("Invalid (NULL) Pointer.");
2151 return isColorFormatSupported;
2152 }
2153
2154 // if input is not Tile-Y, or color format not NV12, invoke Ds+Copy kernel
2155 if (!IS_Y_MAJOR_TILE_FORMAT(surface->TileType) ||
2156 surface->Format != Format_NV12)
2157 {
2158 isColorFormatSupported = false;
2159 }
2160
2161 return isColorFormatSupported;
2162 }
2163
FreeResources()2164 void CodechalEncoderState::FreeResources()
2165 {
2166 CODECHAL_ENCODE_FUNCTION_ENTER;
2167
2168 // destroy sync objects
2169 if (!Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
2170 {
2171 m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectRenderContextInUse);
2172 }
2173 if (!Mos_ResourceIsNull(&m_resSyncObjectVideoContextInUse))
2174 {
2175 m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse);
2176 }
2177
2178 // Release eStatus buffer
2179 if (!Mos_ResourceIsNull(&m_encodeStatusBuf.resStatusBuffer))
2180 {
2181 if(m_encodeStatusBuf.pEncodeStatus != nullptr)
2182 {
2183 EncodeStatus* tmpEncodeStatus = nullptr;
2184 for(int i = 0; i < CODECHAL_ENCODE_STATUS_NUM; i++)
2185 {
2186 tmpEncodeStatus = (EncodeStatus*)(m_encodeStatusBuf.pEncodeStatus + i * m_encodeStatusBuf.dwReportSize);
2187 if(tmpEncodeStatus != nullptr && tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo != nullptr)
2188 {
2189 MOS_FreeMemory(tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo);
2190 tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo = nullptr;
2191 }
2192 }
2193 }
2194
2195 m_osInterface->pfnUnlockResource(
2196 m_osInterface,
2197 &(m_encodeStatusBuf.resStatusBuffer));
2198
2199 m_osInterface->pfnFreeResource(
2200 m_osInterface,
2201 &m_encodeStatusBuf.resStatusBuffer);
2202
2203 m_encodeStatusBuf.pData = nullptr;
2204 m_encodeStatusBuf.pEncodeStatus = nullptr;
2205 }
2206
2207 // Release HW Counter buffer
2208 if (m_osInterface->osCpInterface->IsCpEnabled() && m_hwInterface->GetCpInterface()->IsHwCounterIncrement(m_osInterface) && m_skipFrameBasedHWCounterRead == false)
2209 {
2210 if (!Mos_ResourceIsNull(&m_resHwCount))
2211 {
2212 m_osInterface->pfnUnlockResource(
2213 m_osInterface,
2214 &(m_resHwCount));
2215
2216 m_osInterface->pfnFreeResource(
2217 m_osInterface,
2218 &m_resHwCount);
2219 }
2220 }
2221
2222 if (!Mos_ResourceIsNull(&m_encodeStatusBufRcs.resStatusBuffer))
2223 {
2224 if(m_encodeStatusBufRcs.pEncodeStatus != nullptr)
2225 {
2226 EncodeStatus* tmpEncodeStatus = nullptr;
2227 for(int i = 0; i < CODECHAL_ENCODE_STATUS_NUM; i++)
2228 {
2229 tmpEncodeStatus = (EncodeStatus*)(m_encodeStatusBufRcs.pEncodeStatus + i * m_encodeStatusBufRcs.dwReportSize);
2230 if(tmpEncodeStatus != nullptr && tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo != nullptr)
2231 {
2232 MOS_FreeMemory(tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo);
2233 tmpEncodeStatus->encodeStatusReport.pHEVCTileinfo = nullptr;
2234 }
2235 }
2236 }
2237
2238 m_osInterface->pfnUnlockResource(
2239 m_osInterface,
2240 &(m_encodeStatusBufRcs.resStatusBuffer));
2241
2242 m_osInterface->pfnFreeResource(
2243 m_osInterface,
2244 &m_encodeStatusBufRcs.resStatusBuffer);
2245
2246 m_encodeStatusBufRcs.pData = nullptr;
2247 m_encodeStatusBufRcs.pEncodeStatus = nullptr;
2248 }
2249
2250 if (m_pakEnabled)
2251 {
2252 if (!Mos_ResourceIsNull(&m_resDeblockingFilterRowStoreScratchBuffer))
2253 {
2254 m_osInterface->pfnFreeResource(
2255 m_osInterface,
2256 &m_resDeblockingFilterRowStoreScratchBuffer);
2257 }
2258 if (!Mos_ResourceIsNull(&m_resMPCRowStoreScratchBuffer))
2259 {
2260 m_osInterface->pfnFreeResource(
2261 m_osInterface,
2262 &m_resMPCRowStoreScratchBuffer);
2263 }
2264
2265 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
2266 {
2267 if (!Mos_ResourceIsNull(&m_resStreamOutBuffer[i]))
2268 {
2269 m_osInterface->pfnFreeResource(
2270 m_osInterface,
2271 &m_resStreamOutBuffer[i]);
2272 }
2273
2274 if (!Mos_ResourceIsNull(&m_sliceMapSurface[i].OsResource))
2275 {
2276 m_osInterface->pfnFreeResource(
2277 m_osInterface,
2278 &m_sliceMapSurface[i].OsResource);
2279 }
2280 }
2281 }
2282
2283 // release CSC Downscaling kernel resources
2284 if (m_cscDsState)
2285 {
2286 MOS_Delete(m_cscDsState);
2287 m_cscDsState = nullptr;
2288 }
2289
2290 if (m_encoderGenState)
2291 {
2292 MOS_Delete(m_encoderGenState);
2293 m_encoderGenState = nullptr;
2294 }
2295
2296 if(m_inlineEncodeStatusUpdate)
2297 {
2298 if (!Mos_ResourceIsNull(&m_atomicScratchBuf.resAtomicScratchBuffer))
2299 {
2300 m_osInterface->pfnUnlockResource(
2301 m_osInterface,
2302 &(m_atomicScratchBuf.resAtomicScratchBuffer));
2303
2304 m_osInterface->pfnFreeResource(
2305 m_osInterface,
2306 &m_atomicScratchBuf.resAtomicScratchBuffer);
2307 }
2308 }
2309
2310 if (m_encEnabled)
2311 {
2312 for (auto i = 0; i < CODECHAL_ENCODE_VME_BBUF_NUM; i++)
2313 {
2314 if (!Mos_ResourceIsNull(&m_scalingBBUF[i].BatchBuffer.OsResource))
2315 {
2316 Mhw_FreeBb(m_osInterface, &m_scalingBBUF[i].BatchBuffer, nullptr);
2317 }
2318 }
2319
2320 if(!Mos_ResourceIsNull(&m_flatnessCheckSurface.OsResource))
2321 {
2322 m_osInterface->pfnFreeResource(
2323 m_osInterface,
2324 &m_flatnessCheckSurface.OsResource);
2325 }
2326
2327 if(!Mos_ResourceIsNull(&m_resMbStatsBuffer))
2328 {
2329 m_osInterface->pfnFreeResource(
2330 m_osInterface,
2331 &m_resMbStatsBuffer);
2332 }
2333
2334 for (auto i = 0; i < CODECHAL_ENCODE_MAX_NUM_MAD_BUFFERS; i++)
2335 {
2336 if (!Mos_ResourceIsNull(&m_resMadDataBuffer[i]))
2337 {
2338 m_osInterface->pfnFreeResource(
2339 m_osInterface,
2340 &m_resMadDataBuffer[i]);
2341 }
2342 }
2343 }
2344
2345 if (m_vdencEnabled)
2346 {
2347 m_osInterface->pfnFreeResource(
2348 m_osInterface,
2349 &m_resPakMmioBuffer);
2350
2351 m_osInterface->pfnFreeResource(
2352 m_osInterface,
2353 &m_resHucErrorStatusBuffer);
2354
2355 m_osInterface->pfnFreeResource(m_osInterface, &m_resHucFwBuffer);
2356
2357 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
2358 {
2359 m_osInterface->pfnFreeResource(
2360 m_osInterface,
2361 &m_resVdencStreamInBuffer[i]);
2362 }
2363 }
2364
2365 if (m_vdencEnabled)
2366 {
2367 m_osInterface->pfnFreeResource(m_osInterface, &m_resHucStatus2Buffer);
2368 }
2369
2370 m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencCmdInitializerDmemBuffer);
2371 for (auto i = 0; i < 2; i++)
2372 {
2373 m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencCmdInitializerDataBuffer[i]);
2374 }
2375
2376 m_osInterface->pfnFreeResource(m_osInterface, &m_predicationBuffer);
2377
2378 return;
2379 }
2380
Destroy()2381 void CodechalEncoderState::Destroy()
2382 {
2383 CODECHAL_ENCODE_FUNCTION_ENTER;
2384
2385 if (m_videoNodeAssociationCreated &&
2386 MEDIA_IS_SKU(m_skuTable, FtrVcs2) &&
2387 (m_videoGpuNode < MOS_GPU_NODE_MAX))
2388 {
2389 // Destroy encode video node associations
2390 m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, m_videoGpuNode);
2391 m_osInterface->pfnSetLatestVirtualNode(m_osInterface, MOS_GPU_NODE_MAX);
2392 }
2393
2394 if (m_mmcState != nullptr)
2395 {
2396 MOS_Delete(m_mmcState);
2397 m_mmcState = nullptr;
2398 }
2399
2400 MOS_Delete(m_allocator);
2401 m_allocator = nullptr;
2402
2403 MOS_Delete(m_trackedBuf);
2404 m_trackedBuf = nullptr;
2405
2406 // Release encoder resources
2407 FreeResources();
2408 return;
2409 }
2410
CalculateCommandBufferSize()2411 uint32_t CodechalEncoderState::CalculateCommandBufferSize()
2412 {
2413 uint32_t commandBufferSize =
2414 m_pictureStatesSize +
2415 m_extraPictureStatesSize +
2416 (m_sliceStatesSize * m_numSlices);
2417
2418 if (m_singleTaskPhaseSupported)
2419 {
2420 commandBufferSize *= (m_numPasses + 1);
2421 }
2422
2423 // 4K align since allocation is in chunks of 4K bytes.
2424 commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, 0x1000);
2425
2426 return commandBufferSize;
2427 }
2428
VerifySpaceAvailable()2429 MOS_STATUS CodechalEncoderState::VerifySpaceAvailable()
2430 {
2431 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2432
2433 CODECHAL_ENCODE_FUNCTION_ENTER;
2434
2435 uint32_t requestedSize = 0;
2436 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_renderContext)
2437 {
2438 requestedSize = m_vmeStatesSize;
2439
2440 eStatus = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
2441 m_osInterface,
2442 requestedSize,
2443 0);
2444
2445 return eStatus;
2446 }
2447
2448 uint32_t requestedPatchListSize = 0;
2449 MOS_STATUS statusPatchList = MOS_STATUS_SUCCESS, statusCmdBuf;
2450
2451 bool m_usePatchList = m_osInterface->bUsesPatchList || MEDIA_IS_SKU(m_skuTable, FtrMediaPatchless);
2452 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_videoContext)
2453 {
2454 if (m_usePatchList)
2455 {
2456 requestedPatchListSize =
2457 m_picturePatchListSize +
2458 m_extraPicturePatchListSize +
2459 (m_slicePatchListSize * m_numSlices);
2460
2461 if (m_singleTaskPhaseSupported)
2462 {
2463 requestedPatchListSize *= (m_numPasses + 1);
2464 }
2465 }
2466
2467 requestedSize = CalculateCommandBufferSize();
2468
2469 // Try a maximum of 3 attempts to request the required sizes from OS
2470 // OS could reset the sizes if necessary, therefore, requires to re-verify
2471 for (auto i = 0; i < 3; i++)
2472 {
2473 //Experiment shows resizing CmdBuf size and PatchList size in two calls one after the other would cause previously
2474 //successfully requested size to fallback to wrong value, hence never satisfying the requirement. So we call pfnResize()
2475 //only once depending on whether CmdBuf size not enough, or PatchList size not enough, or both.
2476 if (m_usePatchList)
2477 {
2478 statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
2479 m_osInterface,
2480 requestedPatchListSize);
2481 }
2482
2483 statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
2484 m_osInterface,
2485 requestedSize,
2486 0);
2487
2488 if (statusPatchList != MOS_STATUS_SUCCESS && statusCmdBuf != MOS_STATUS_SUCCESS)
2489 {
2490 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(requestedSize + COMMAND_BUFFER_RESERVED_SPACE, requestedPatchListSize));
2491 }
2492 else if (statusPatchList != MOS_STATUS_SUCCESS)
2493 {
2494 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(0, requestedPatchListSize));
2495 }
2496 else if (statusCmdBuf != MOS_STATUS_SUCCESS)
2497 {
2498 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(requestedSize + COMMAND_BUFFER_RESERVED_SPACE, 0));
2499 }
2500 else
2501 {
2502 m_singleTaskPhaseSupportedInPak = m_singleTaskPhaseSupported;
2503 return eStatus;
2504 }
2505 }
2506 }
2507
2508 if (m_usePatchList)
2509 {
2510 statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
2511 m_osInterface,
2512 requestedPatchListSize);
2513 }
2514
2515 statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
2516 m_osInterface,
2517 requestedSize,
2518 0);
2519
2520 if ((statusCmdBuf == MOS_STATUS_SUCCESS) && (statusPatchList == MOS_STATUS_SUCCESS))
2521 {
2522 m_singleTaskPhaseSupportedInPak = m_singleTaskPhaseSupported;
2523 return eStatus;
2524 }
2525
2526 if (m_singleTaskPhaseSupported)
2527 {
2528 uint32_t requestedSizeOriginal = 0, requestedPatchListSizeOriginal = 0;
2529 for (auto i = 0; i < 3; i++)
2530 {
2531 //Experiment shows resizing CmdBuf size and PatchList size in two calls one after the other would cause previously
2532 //successfully requested size to fallback to wrong value, hence never satisfying the requirement. So we call pfnResize()
2533 //only once depending on whether CmdBuf size not enough, or PatchList size not enough, or both.
2534 if (m_usePatchList)
2535 {
2536 statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
2537 m_osInterface,
2538 requestedPatchListSizeOriginal);
2539 }
2540
2541 statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
2542 m_osInterface,
2543 requestedSizeOriginal,
2544 0);
2545
2546 if (statusPatchList != MOS_STATUS_SUCCESS && statusCmdBuf != MOS_STATUS_SUCCESS)
2547 {
2548 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(requestedSizeOriginal + COMMAND_BUFFER_RESERVED_SPACE, requestedPatchListSizeOriginal));
2549 }
2550 else if (statusPatchList != MOS_STATUS_SUCCESS)
2551 {
2552 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(0, requestedPatchListSizeOriginal));
2553 }
2554 else if (statusCmdBuf != MOS_STATUS_SUCCESS)
2555 {
2556 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(requestedSizeOriginal + COMMAND_BUFFER_RESERVED_SPACE, 0));
2557 }
2558 else
2559 {
2560 m_singleTaskPhaseSupportedInPak = false;
2561 return eStatus;
2562 }
2563 }
2564 if (m_usePatchList)
2565 {
2566 statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
2567 m_osInterface,
2568 requestedPatchListSizeOriginal);
2569 }
2570
2571 statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
2572 m_osInterface,
2573 requestedSizeOriginal,
2574 0);
2575
2576 if (statusPatchList == MOS_STATUS_SUCCESS && statusCmdBuf == MOS_STATUS_SUCCESS)
2577 {
2578 m_singleTaskPhaseSupportedInPak = false;
2579 }
2580 else
2581 {
2582 eStatus = MOS_STATUS_NO_SPACE;
2583 }
2584 }
2585 else
2586 {
2587 eStatus = MOS_STATUS_NO_SPACE;
2588 }
2589
2590 return eStatus;
2591 }
2592
AddMediaVfeCmd(PMOS_COMMAND_BUFFER cmdBuffer,SendKernelCmdsParams * params)2593 MOS_STATUS CodechalEncoderState::AddMediaVfeCmd(
2594 PMOS_COMMAND_BUFFER cmdBuffer,
2595 SendKernelCmdsParams *params)
2596 {
2597 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2598
2599 MHW_VFE_PARAMS vfeParams = {};
2600 vfeParams.pKernelState = params->pKernelState;
2601 vfeParams.eVfeSliceDisable = MHW_VFE_SLICE_ALL;
2602 vfeParams.Scoreboard.ScoreboardEnable = m_useHwScoreboard;
2603 vfeParams.Scoreboard.ScoreboardType = m_hwScoreboardType;
2604 vfeParams.dwMaximumNumberofThreads = m_encodeVfeMaxThreads;
2605
2606 if (!m_useHwScoreboard)
2607 {
2608 vfeParams.Scoreboard.ScoreboardMask = 0;
2609 }
2610 else if (params->bEnableCustomScoreBoard == true)
2611 {
2612 MOS_SecureMemcpy(&vfeParams.Scoreboard, sizeof(vfeParams.Scoreboard),
2613 params->pCustomScoreBoard, sizeof(*params->pCustomScoreBoard));
2614 }
2615 else if (params->bEnable45ZWalkingPattern == true)
2616 {
2617 vfeParams.Scoreboard.ScoreboardMask = 0x0F;
2618 vfeParams.Scoreboard.ScoreboardType = 1;
2619
2620 // Scoreboard 0
2621 vfeParams.Scoreboard.ScoreboardDelta[0].x = 0;
2622 vfeParams.Scoreboard.ScoreboardDelta[0].y = 0xF;
2623 // Scoreboard 1
2624 vfeParams.Scoreboard.ScoreboardDelta[1].x = 0;
2625 vfeParams.Scoreboard.ScoreboardDelta[1].y = 0xE;
2626 // Scoreboard 2
2627 vfeParams.Scoreboard.ScoreboardDelta[2].x = 0xF;
2628 vfeParams.Scoreboard.ScoreboardDelta[2].y = 3;
2629 // Scoreboard 3
2630 vfeParams.Scoreboard.ScoreboardDelta[3].x = 0xF;
2631 vfeParams.Scoreboard.ScoreboardDelta[3].y = 1;
2632 }
2633 else
2634 {
2635 vfeParams.Scoreboard.ScoreboardMask = 0xFF;
2636
2637 // Scoreboard 0
2638 vfeParams.Scoreboard.ScoreboardDelta[0].x = 0xF;
2639 vfeParams.Scoreboard.ScoreboardDelta[0].y = 0;
2640
2641 // Scoreboard 1
2642 vfeParams.Scoreboard.ScoreboardDelta[1].x = 0;
2643 vfeParams.Scoreboard.ScoreboardDelta[1].y = 0xF;
2644
2645 // Scoreboard 2
2646 vfeParams.Scoreboard.ScoreboardDelta[2].x = 1;
2647 vfeParams.Scoreboard.ScoreboardDelta[2].y = 0xF;
2648 // Scoreboard 3
2649 vfeParams.Scoreboard.ScoreboardDelta[3].x = 0xF;
2650 vfeParams.Scoreboard.ScoreboardDelta[3].y = 0xF;
2651 // Scoreboard 4
2652 vfeParams.Scoreboard.ScoreboardDelta[4].x = 0xF;
2653 vfeParams.Scoreboard.ScoreboardDelta[4].y = 1;
2654 // Scoreboard 5
2655 vfeParams.Scoreboard.ScoreboardDelta[5].x = 0;
2656 vfeParams.Scoreboard.ScoreboardDelta[5].y = 0xE;
2657 // Scoreboard 6
2658 vfeParams.Scoreboard.ScoreboardDelta[6].x = 1;
2659 vfeParams.Scoreboard.ScoreboardDelta[6].y = 0xE;
2660 // Scoreboard 7
2661 vfeParams.Scoreboard.ScoreboardDelta[7].x = 0xF;
2662 vfeParams.Scoreboard.ScoreboardDelta[7].y = 0xE;
2663 }
2664
2665 if (MEDIA_IS_WA(m_waTable, WaUseStallingScoreBoard))
2666 vfeParams.Scoreboard.ScoreboardType = 0;
2667
2668 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaVfeCmd(cmdBuffer, &vfeParams));
2669
2670 return MOS_STATUS_SUCCESS;
2671 }
2672
SendGenericKernelCmds(PMOS_COMMAND_BUFFER cmdBuffer,SendKernelCmdsParams * params)2673 MOS_STATUS CodechalEncoderState::SendGenericKernelCmds(
2674 PMOS_COMMAND_BUFFER cmdBuffer,
2675 SendKernelCmdsParams *params)
2676 {
2677 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2678
2679 CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);
2680
2681 if(MEDIA_IS_SKU(m_skuTable, FtrSSEUPowerGating))
2682 {
2683 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetDefaultSSEuSetting(params->EncFunctionType, m_setRequestedEUSlices, m_setRequestedSubSlices, m_setRequestedEUs));
2684 }
2685
2686 if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
2687 {
2688 bool requestFrameTracking = false;
2689
2690 if (CodecHalUsesOnlyRenderEngine(m_codecFunction) && m_lastEncPhase)
2691 {
2692 // frame tracking tag is only added in the last command buffer header
2693 requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : m_lastTaskInPhase;
2694 }
2695
2696 // Send command buffer header at the beginning (OS dependent)
2697 CODECHAL_ENCODE_CHK_STATUS_RETURN(
2698 SendPrologWithFrameTracking(cmdBuffer, requestFrameTracking, m_bRenderOcaEnabled ? m_renderEngineInterface->GetMmioRegisters() : nullptr));
2699
2700 m_firstTaskInPhase = false;
2701 }
2702
2703 CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(cmdBuffer, params->EncFunctionType));
2704
2705 if (m_renderEngineInterface->GetL3CacheConfig()->bL3CachingEnabled)
2706 {
2707 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->SetL3Cache(cmdBuffer));
2708 }
2709
2710 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->EnablePreemption(cmdBuffer));
2711
2712 // Add Pipeline select command
2713 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddPipelineSelectCmd(cmdBuffer, m_computeContextEnabled));
2714
2715 // Add State Base Addr command
2716 MHW_STATE_BASE_ADDR_PARAMS stateBaseAddrParams;
2717 MOS_ZeroMemory(&stateBaseAddrParams, sizeof(stateBaseAddrParams));
2718 // This bit will not be used in Driver ID but it will be used to determine if Render Target Flag has to be Clear or Set
2719 // Read this bit in pfnAddStateBaseAddrCmd and propagate it using ResourceParams via bRenderTarget
2720 stateBaseAddrParams.bDynamicStateRenderTarget = params->bDshInUse;
2721
2722 MOS_RESOURCE* dsh = params->pKernelState->m_dshRegion.GetResource();
2723 CODECHAL_ENCODE_CHK_NULL_RETURN(dsh);
2724 MOS_RESOURCE* ish = params->pKernelState->m_ishRegion.GetResource();
2725 CODECHAL_ENCODE_CHK_NULL_RETURN(ish);
2726 stateBaseAddrParams.presDynamicState = dsh;
2727 stateBaseAddrParams.dwDynamicStateSize = params->pKernelState->m_dshRegion.GetHeapSize();
2728 stateBaseAddrParams.presInstructionBuffer = ish;
2729 stateBaseAddrParams.dwInstructionBufferSize = params->pKernelState->m_ishRegion.GetHeapSize();
2730
2731 if (m_computeContextEnabled)
2732 {
2733 stateBaseAddrParams.presGeneralState = dsh;
2734 stateBaseAddrParams.dwGeneralStateSize = params->pKernelState->m_dshRegion.GetHeapSize();
2735 stateBaseAddrParams.presIndirectObjectBuffer = dsh;
2736 stateBaseAddrParams.dwIndirectObjectBufferSize = params->pKernelState->m_dshRegion.GetHeapSize();
2737 stateBaseAddrParams.bDynamicStateRenderTarget = false;
2738 }
2739
2740 if (m_standard == CODECHAL_HEVC)
2741 {
2742 stateBaseAddrParams.mocs4InstructionCache = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_ELLC_LLC_L3].Value;
2743 }
2744
2745 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddStateBaseAddrCmd(cmdBuffer, &stateBaseAddrParams));
2746
2747 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupWalkerContext(cmdBuffer, params));
2748
2749 return eStatus;
2750 }
2751
2752 // Refer to layout of EncodeBRCPAKStatistics_g7
ReadBrcPakStatistics(PMOS_COMMAND_BUFFER cmdBuffer,EncodeReadBrcPakStatsParams * params)2753 MOS_STATUS CodechalEncoderState::ReadBrcPakStatistics(
2754 PMOS_COMMAND_BUFFER cmdBuffer,
2755 EncodeReadBrcPakStatsParams* params)
2756 {
2757 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2758
2759 CODECHAL_ENCODE_FUNCTION_ENTER;
2760
2761 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2762 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2763 CODECHAL_ENCODE_CHK_NULL_RETURN(params->presBrcPakStatisticBuffer);
2764 CODECHAL_ENCODE_CHK_NULL_RETURN(params->presStatusBuffer);
2765
2766 CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");
2767 MmioRegistersMfx* mmioRegisters = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
2768
2769 MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2770 MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2771
2772 miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2773 miStoreRegMemParams.dwOffset = 0;
2774 miStoreRegMemParams.dwRegister = mmioRegisters->mfcBitstreamBytecountFrameRegOffset;
2775 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2776
2777 miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2778 miStoreRegMemParams.dwOffset = sizeof(uint32_t);
2779 miStoreRegMemParams.dwRegister = mmioRegisters->mfcBitstreamBytecountSliceRegOffset;
2780 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2781
2782 MHW_MI_STORE_DATA_PARAMS storeDataParams;
2783 storeDataParams.pOsResource = params->presBrcPakStatisticBuffer;
2784 storeDataParams.dwResourceOffset = sizeof(uint32_t) * 2;
2785 storeDataParams.dwValue = params->ucPass + 1;
2786 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));
2787
2788 storeDataParams.pOsResource = params->presStatusBuffer;
2789 storeDataParams.dwResourceOffset = params->dwStatusBufNumPassesOffset;
2790 storeDataParams.dwValue = params->ucPass + 1;
2791 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));
2792
2793 miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2794 miStoreRegMemParams.dwOffset = sizeof(uint32_t) * (4 + params->ucPass);
2795 miStoreRegMemParams.dwRegister = mmioRegisters->mfcImageStatusCtrlRegOffset;
2796 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2797
2798 return eStatus;
2799 }
2800
2801 //------------------------------------------------------------------------------
2802 //| Purpose: Retrieves the MFC image eStatus information
2803 //| Return: N/A
2804 //------------------------------------------------------------------------------
ReadImageStatus(PMOS_COMMAND_BUFFER cmdBuffer)2805 MOS_STATUS CodechalEncoderState::ReadImageStatus(
2806 PMOS_COMMAND_BUFFER cmdBuffer)
2807 {
2808 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2809
2810 CODECHAL_ENCODE_FUNCTION_ENTER;
2811
2812 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2813
2814 CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");
2815 MmioRegistersMfx* mmioRegisters = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
2816
2817 EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
2818
2819 uint32_t baseOffset =
2820 (encodeStatusBuf->wCurrIndex * m_encodeStatusBuf.dwReportSize) +
2821 sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource
2822
2823 MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2824 MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2825
2826 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2827 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusMaskOffset;
2828 miStoreRegMemParams.dwRegister = mmioRegisters->mfcImageStatusMaskRegOffset;
2829 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2830
2831 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2832 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusCtrlOffset;
2833 miStoreRegMemParams.dwRegister = mmioRegisters->mfcImageStatusCtrlRegOffset;
2834 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2835
2836 // VDEnc dynamic slice overflow semaphore, DW0 is SW programmed mask(MFX_IMAGE_MASK does not support), DW1 is MFX_IMAGE_STATUS_CONTROL
2837 if (m_vdencBrcEnabled)
2838 {
2839 MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
2840
2841 // Added for VDEnc slice overflow bit in MFC_IMAGE_STATUS_CONTROL
2842 // The bit is connected on the non-AVC encoder side of MMIO register.
2843 // Need a dummy MFX_PIPE_MODE_SELECT to decoder and read this register.
2844 if (m_waReadVDEncOverflowStatus)
2845 {
2846 pipeModeSelectParams = {};
2847 pipeModeSelectParams.Mode = CODECHAL_DECODE_MODE_AVCVLD;
2848 m_hwInterface->GetMfxInterface()->SetDecodeInUse(true);
2849 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxInterface()->AddMfxPipeModeSelectCmd(cmdBuffer, &pipeModeSelectParams));
2850 }
2851
2852 // Store MFC_IMAGE_STATUS_CONTROL MMIO to DMEM for HuC next BRC pass of current frame and first pass of next frame.
2853 for (int i = 0; i < 2; i++)
2854 {
2855 if (m_resVdencBrcUpdateDmemBufferPtr[i])
2856 {
2857 miStoreRegMemParams.presStoreBuffer = m_resVdencBrcUpdateDmemBufferPtr[i];
2858 miStoreRegMemParams.dwOffset = 7 * sizeof(uint32_t); // offset of SliceSizeViolation in HUC_BRC_UPDATE_DMEM
2859 miStoreRegMemParams.dwRegister = mmioRegisters->mfcImageStatusCtrlRegOffset;
2860 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2861 }
2862 }
2863
2864 // Restore MFX_PIPE_MODE_SELECT to encode mode
2865 if (m_waReadVDEncOverflowStatus)
2866 {
2867 pipeModeSelectParams = {};
2868 pipeModeSelectParams.Mode = m_mode;
2869 pipeModeSelectParams.bVdencEnabled = true;
2870 m_hwInterface->GetMfxInterface()->SetDecodeInUse(false);
2871 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxInterface()->AddMfxPipeModeSelectCmd(cmdBuffer, &pipeModeSelectParams));
2872 }
2873 }
2874
2875 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
2876 MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
2877 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
2878
2879 return eStatus;
2880 }
2881
2882 //------------------------------------------------------------------------------
2883 //| Purpose: Retrieves the MFC registers and stores them in the eStatus report
2884 //| Return: N/A
2885 //------------------------------------------------------------------------------
ReadMfcStatus(PMOS_COMMAND_BUFFER cmdBuffer)2886 MOS_STATUS CodechalEncoderState::ReadMfcStatus(
2887 PMOS_COMMAND_BUFFER cmdBuffer)
2888 {
2889 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2890
2891 CODECHAL_ENCODE_FUNCTION_ENTER;
2892
2893 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2894
2895 CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");
2896 MmioRegistersMfx* mmioRegisters = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
2897
2898 EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
2899
2900 uint32_t baseOffset =
2901 (encodeStatusBuf->wCurrIndex * m_encodeStatusBuf.dwReportSize) +
2902 sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource
2903
2904 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
2905 MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
2906 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
2907
2908 MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2909 MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2910
2911 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2912 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
2913 miStoreRegMemParams.dwRegister = mmioRegisters->mfcBitstreamBytecountFrameRegOffset;
2914 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2915
2916 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2917 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSSEBitCountOffset;
2918 miStoreRegMemParams.dwRegister = mmioRegisters->mfcBitstreamSeBitcountFrameRegOffset;
2919 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2920
2921 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2922 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwQpStatusCountOffset;
2923 miStoreRegMemParams.dwRegister = mmioRegisters->mfcQPStatusCountOffset;
2924 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2925
2926 if (mmioRegisters->mfcAvcNumSlicesRegOffset > 0)
2927 {
2928 //read MFC_AVC_NUM_SLICES register to status report
2929 miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2930 miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwNumSlicesOffset;
2931 miStoreRegMemParams.dwRegister = mmioRegisters->mfcAvcNumSlicesRegOffset;
2932 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2933 }
2934
2935 if (m_vdencBrcEnabled)
2936 {
2937 // Store PAK FrameSize MMIO to DMEM for HuC next BRC pass of current frame and first pass of next frame.
2938 for (int i = 0; i < 2; i++)
2939 {
2940 if (m_resVdencBrcUpdateDmemBufferPtr[i])
2941 {
2942 miStoreRegMemParams.presStoreBuffer = m_resVdencBrcUpdateDmemBufferPtr[i];
2943 miStoreRegMemParams.dwOffset = 5 * sizeof(uint32_t);
2944 miStoreRegMemParams.dwRegister = mmioRegisters->mfcBitstreamBytecountFrameRegOffset;
2945 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2946
2947 if (m_vdencBrcNumOfSliceOffset)
2948 {
2949 miStoreRegMemParams.presStoreBuffer = m_resVdencBrcUpdateDmemBufferPtr[i];
2950 miStoreRegMemParams.dwOffset = m_vdencBrcNumOfSliceOffset;
2951 miStoreRegMemParams.dwRegister = mmioRegisters->mfcAvcNumSlicesRegOffset;
2952 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2953 }
2954 }
2955 }
2956 }
2957
2958 CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadImageStatus(cmdBuffer));
2959
2960 return eStatus;
2961 }
2962
2963 //------------------------------------------------------------------------------
2964 //| Purpose: Retrieves the MFC registers and stores them in the eStatus report
2965 //| Return: N/A
2966 //------------------------------------------------------------------------------
SetStatusReportParams(PCODEC_REF_LIST currRefList)2967 MOS_STATUS CodechalEncoderState::SetStatusReportParams(
2968 PCODEC_REF_LIST currRefList)
2969 {
2970 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2971
2972 CODECHAL_ENCODE_FUNCTION_ENTER;
2973
2974 EncodeStatusBuffer* encodeStatusBuf = nullptr;
2975 if ((m_codecFunction == CODECHAL_FUNCTION_ENC) ||
2976 (m_codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC) ||
2977 (m_codecFunction == CODECHAL_FUNCTION_FEI_ENC) ||
2978 (m_codecFunction == CODECHAL_FUNCTION_HYBRIDPAK))
2979 {
2980 encodeStatusBuf = &m_encodeStatusBufRcs;
2981 }
2982 else
2983 {
2984 encodeStatusBuf = &m_encodeStatusBuf;
2985 }
2986
2987 EncodeStatus* encodeStatus =
2988 (EncodeStatus*)(encodeStatusBuf->pEncodeStatus +
2989 encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize);
2990
2991 EncodeStatusReport* encodeStatusReport = &encodeStatus->encodeStatusReport;
2992
2993 encodeStatus->dwStoredData = m_storeData;
2994 encodeStatusReport->StatusReportNumber = m_statusReportFeedbackNumber;
2995 encodeStatusReport->CurrOriginalPic = m_currOriginalPic;
2996 encodeStatus->wPictureCodingType = m_pictureCodingType;
2997 switch (m_codecFunction)
2998 {
2999 case CODECHAL_FUNCTION_ENC:
3000 encodeStatusReport->Func = CODECHAL_ENCODE_ENC_ID;
3001 break;
3002 case CODECHAL_FUNCTION_PAK:
3003 encodeStatusReport->Func = CODECHAL_ENCODE_PAK_ID;
3004 break;
3005 case CODECHAL_FUNCTION_ENC_PAK:
3006 case CODECHAL_FUNCTION_ENC_VDENC_PAK:
3007 encodeStatusReport->Func = CODECHAL_ENCODE_ENC_PAK_ID;
3008 break;
3009 case CODECHAL_FUNCTION_FEI_PRE_ENC:
3010 encodeStatusReport->Func = CODECHAL_ENCODE_FEI_PRE_ENC_ID;
3011 break;
3012 case CODECHAL_FUNCTION_FEI_ENC:
3013 encodeStatusReport->Func = CODECHAL_ENCODE_FEI_ENC_ID;
3014 break;
3015 case CODECHAL_FUNCTION_FEI_PAK:
3016 encodeStatusReport->Func = CODECHAL_ENCODE_FEI_PAK_ID;
3017 break;
3018 case CODECHAL_FUNCTION_FEI_ENC_PAK:
3019 encodeStatusReport->Func = CODECHAL_ENCODE_FEI_ENC_PAK_ID;
3020 break;
3021 case CODECHAL_FUNCTION_HYBRIDPAK:
3022 encodeStatusReport->Func = CODECHAL_ENCODE_ENC_ID; /* Only the render engine(EU) is used, MFX is not used */
3023 break;
3024 default:
3025 break;
3026 }
3027 encodeStatusReport->pCurrRefList = m_currRefList;
3028 encodeStatusReport->NumberTilesInFrame = m_numberTilesInFrame;
3029 encodeStatusReport->UsedVdBoxNumber = m_numUsedVdbox;
3030
3031 if (m_lookaheadDepth > 0)
3032 {
3033 uint32_t laStatusIndex = (encodeStatusBuf->wCurrIndex + m_lookaheadDepth - 1) % CODECHAL_ENCODE_STATUS_NUM;
3034 EncodeStatus* encodeStatus =
3035 (EncodeStatus*)(encodeStatusBuf->pEncodeStatus + laStatusIndex * encodeStatusBuf->dwReportSize);
3036 encodeStatus->lookaheadStatus.StatusReportNumber = m_statusReportFeedbackNumber;
3037 }
3038
3039 return eStatus;
3040 }
3041
3042 //------------------------------------------------------------------------------
3043 //| Purpose: Set each of status report buffer to completed status (only render context)
3044 //| Return: N/A
3045 //------------------------------------------------------------------------------
InitStatusReport()3046 MOS_STATUS CodechalEncoderState::InitStatusReport()
3047 {
3048 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3049
3050 CODECHAL_ENCODE_FUNCTION_ENTER;
3051
3052 EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
3053 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusBuf);
3054
3055 EncodeStatus* encodeStatus = (EncodeStatus*)(encodeStatusBuf->pEncodeStatus + encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize);
3056 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
3057
3058 for (auto i = 0; i < CODECHAL_NUM_MEDIA_STATES; i += 1)
3059 {
3060 encodeStatus->qwStoredDataEnc[i].dwStoredData = CODECHAL_STATUS_QUERY_END_FLAG;
3061 }
3062
3063 if (m_encEnabled)
3064 {
3065 EncodeStatusBuffer* encodeStatusBufRcs = &m_encodeStatusBufRcs;
3066 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusBufRcs);
3067
3068 encodeStatus = (EncodeStatus*)(encodeStatusBufRcs->pEncodeStatus + encodeStatusBufRcs->wCurrIndex * encodeStatusBufRcs->dwReportSize);
3069 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
3070
3071 for (auto i = 0; i < CODECHAL_NUM_MEDIA_STATES; i += 1)
3072 {
3073 encodeStatus->qwStoredDataEnc[i].dwStoredData = CODECHAL_STATUS_QUERY_END_FLAG;
3074 }
3075 }
3076
3077 return eStatus;
3078 }
3079
3080 //------------------------------------------------------------------------------
3081 //| Purpose: Indicates to the driver that the batch buffer has started processing
3082 //| Return: N/A
3083 //------------------------------------------------------------------------------
StartStatusReport(PMOS_COMMAND_BUFFER cmdBuffer,CODECHAL_MEDIA_STATE_TYPE encFunctionType)3084 MOS_STATUS CodechalEncoderState::StartStatusReport(
3085 PMOS_COMMAND_BUFFER cmdBuffer,
3086 CODECHAL_MEDIA_STATE_TYPE encFunctionType)
3087 {
3088 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3089
3090 CODECHAL_ENCODE_FUNCTION_ENTER;
3091
3092 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
3093
3094 EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
3095 EncodeStatusBuffer* encodeStatusBufRcs = &m_encodeStatusBufRcs;
3096
3097 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_renderContext)
3098 {
3099 uint32_t offset =
3100 (encodeStatusBufRcs->wCurrIndex * m_encodeStatusBufRcs.dwReportSize) +
3101 encodeStatusBufRcs->dwStoreDataOffset + 8 + // VME stored data offset is 2nd
3102 sizeof(uint32_t) * 2 * encFunctionType + // Each VME stored data is 1 QW
3103 sizeof(uint32_t) * 2; // encodeStatus is offset by 2 DWs in the resource
3104
3105 MHW_PIPE_CONTROL_PARAMS pipeControlParams;
3106 MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
3107 pipeControlParams.presDest = &encodeStatusBufRcs->resStatusBuffer;
3108 pipeControlParams.dwPostSyncOp = MHW_FLUSH_WRITE_IMMEDIATE_DATA;
3109 pipeControlParams.dwResourceOffset = offset;
3110 pipeControlParams.dwDataDW1 = CODECHAL_STATUS_QUERY_START_FLAG;
3111 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(
3112 cmdBuffer,
3113 nullptr,
3114 &pipeControlParams));
3115 }
3116
3117 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_videoContext)
3118 {
3119 uint32_t offset =
3120 (encodeStatusBuf->wCurrIndex * m_encodeStatusBuf.dwReportSize) +
3121 encodeStatusBuf->dwStoreDataOffset + // MFX stored data offset is 1st, so no additional offset is needed
3122 sizeof(uint32_t) * 2; // encodeStatus is offset by 2 DWs in the resource
3123
3124 MHW_MI_STORE_DATA_PARAMS storeDataParams;
3125 storeDataParams.pOsResource = &encodeStatusBuf->resStatusBuffer;
3126 storeDataParams.dwResourceOffset = offset;
3127 storeDataParams.dwValue = CODECHAL_STATUS_QUERY_START_FLAG;
3128
3129 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3130 cmdBuffer,
3131 &storeDataParams));
3132
3133 if (m_osInterface->osCpInterface->IsCpEnabled() && m_hwInterface->GetCpInterface()->IsHwCounterIncrement(m_osInterface) && m_skipFrameBasedHWCounterRead == false )
3134 {
3135 uint32_t writeOffset = sizeof(HwCounter) * CODECHAL_ENCODE_STATUS_NUM;
3136
3137 CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface->GetCpInterface());
3138
3139 // Lazy allocation
3140 if (Mos_ResourceIsNull(&m_resHwCount))
3141 {
3142 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
3143 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
3144 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
3145 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
3146 allocParamsForBufferLinear.Format = Format_Buffer;
3147
3148 MOS_LOCK_PARAMS lockFlagsNoOverWrite;;
3149 MOS_ZeroMemory(&lockFlagsNoOverWrite, sizeof(MOS_LOCK_PARAMS));
3150 lockFlagsNoOverWrite.WriteOnly = 1;
3151 lockFlagsNoOverWrite.NoOverWrite = 1;
3152
3153 // eStatus query reporting
3154 m_encodeStatusBuf.dwReportSize = MOS_ALIGN_CEIL(sizeof(EncodeStatus), MHW_CACHELINE_SIZE);
3155 uint32_t size = sizeof(HwCounter) * CODECHAL_ENCODE_STATUS_NUM + sizeof(HwCounter);
3156 allocParamsForBufferLinear.dwBytes = size;
3157 allocParamsForBufferLinear.pBufName = "HWCounterQueryBuffer";
3158 allocParamsForBufferLinear.bIsPersistent = true; // keeping status buffer persistent since its used in all command buffers
3159
3160 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
3161 m_osInterface,
3162 &allocParamsForBufferLinear,
3163 &m_resHwCount);
3164
3165 if (eStatus != MOS_STATUS_SUCCESS)
3166 {
3167 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Encode eStatus Buffer.");
3168 return eStatus;
3169 }
3170
3171 CODECHAL_ENCODE_CHK_STATUS_RETURN(
3172 m_osInterface->pfnSkipResourceSync(
3173 &m_resHwCount));
3174
3175 uint8_t *dataHwCount = (uint8_t *)m_osInterface->pfnLockResource(
3176 m_osInterface,
3177 &(m_resHwCount),
3178 &lockFlagsNoOverWrite);
3179
3180 if (!dataHwCount)
3181 {
3182 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Local Resource for MbEnc Adv Count Query Buffer.");
3183 return eStatus;
3184 }
3185
3186 MOS_ZeroMemory(dataHwCount, size);
3187 m_dataHwCount = (uint32_t*)dataHwCount;
3188 }
3189
3190 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetCpInterface()->ReadEncodeCounterFromHW(
3191 m_osInterface,
3192 cmdBuffer,
3193 &m_resHwCount,
3194 encodeStatusBuf->wCurrIndex));
3195 }
3196 }
3197
3198 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_perfProfiler->AddPerfCollectStartCmd((void*)this, m_osInterface, m_miInterface, cmdBuffer));
3199 CODECHAL_ENCODE_CHK_STATUS_RETURN(NullHW::StartPredicate(m_osInterface, m_miInterface, cmdBuffer));
3200
3201 return eStatus;
3202 }
3203
3204 //------------------------------------------------------------------------------
3205 //| Purpose: Indicates to the driver that the batch buffer has completed processing
3206 //| Return: N/A
3207 //------------------------------------------------------------------------------
EndStatusReport(PMOS_COMMAND_BUFFER cmdBuffer,CODECHAL_MEDIA_STATE_TYPE encFunctionType)3208 MOS_STATUS CodechalEncoderState::EndStatusReport(
3209 PMOS_COMMAND_BUFFER cmdBuffer,
3210 CODECHAL_MEDIA_STATE_TYPE encFunctionType)
3211 {
3212 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3213
3214 CODECHAL_ENCODE_FUNCTION_ENTER;
3215
3216 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
3217 CODECHAL_ENCODE_CHK_STATUS_RETURN(NullHW::StopPredicate(m_osInterface, m_miInterface, cmdBuffer));
3218
3219 // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if applicable
3220 if (m_frameTrackingEnabled && m_osInterface->bTagResourceSync)
3221 {
3222 MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
3223 bool writeResourceSyncTag = false;
3224
3225 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_renderContext)
3226 {
3227 syncParams.GpuContext = m_renderContext;
3228
3229 // Enc only and VDEnc SHME requires render engine GPU tag
3230 if (CodecHalUsesOnlyRenderEngine(m_codecFunction) ||
3231 (m_vdencEnabled && m_16xMeSupported))
3232 {
3233 writeResourceSyncTag = m_lastEncPhase && m_lastTaskInPhase;
3234 }
3235 }
3236 else if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_videoContext)
3237 {
3238 syncParams.GpuContext = m_videoContext;
3239 writeResourceSyncTag = m_lastTaskInPhase;
3240 }
3241
3242 if (writeResourceSyncTag)
3243 {
3244 if (!m_firstField || CodecHal_PictureIsFrame(m_currOriginalPic))
3245 {
3246 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(cmdBuffer, &syncParams));
3247 }
3248 }
3249 }
3250
3251 MHW_MI_STORE_DATA_PARAMS storeDataParams = {};
3252 uint32_t offset = 0;
3253 if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_renderContext)
3254 {
3255 // Flush the write cache for ENC output
3256 MHW_PIPE_CONTROL_PARAMS pipeControlParams;
3257 MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
3258 pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
3259 pipeControlParams.bGenericMediaStateClear = true;
3260 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(cmdBuffer, nullptr, &pipeControlParams));
3261
3262 if (MEDIA_IS_WA(m_waTable, WaSendDummyVFEafterPipelineSelect))
3263 {
3264 MHW_VFE_PARAMS vfeStateParams = {};
3265 vfeStateParams.dwNumberofURBEntries = 1;
3266 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaVfeCmd(cmdBuffer, &vfeStateParams));
3267 }
3268
3269 offset =
3270 (m_encodeStatusBufRcs.wCurrIndex * m_encodeStatusBufRcs.dwReportSize) +
3271 m_encodeStatusBufRcs.dwStoreDataOffset + 8 + // VME stored data offset is 2nd
3272 sizeof(uint32_t) * 2 * encFunctionType + // Each VME stored data is 1 QW
3273 sizeof(uint32_t) * 2; // encodeStatus is offset by 2 DWs in the resource
3274 storeDataParams.pOsResource = &m_encodeStatusBufRcs.resStatusBuffer;
3275 }
3276 else if (m_osInterface->pfnGetGpuContext(m_osInterface) == m_videoContext)
3277 {
3278 offset =
3279 m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize +
3280 m_encodeStatusBuf.dwStoreDataOffset + // MFX stored data offset is 1st, so no additional offset is needed
3281 sizeof(uint32_t) * 2; // encodeStatus is offset by 2 DWs in the resource
3282 storeDataParams.pOsResource = &m_encodeStatusBuf.resStatusBuffer;
3283 }
3284
3285 storeDataParams.dwResourceOffset = offset;
3286 storeDataParams.dwValue = CODECHAL_STATUS_QUERY_END_FLAG;
3287 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3288 cmdBuffer,
3289 &storeDataParams));
3290
3291 if (encFunctionType == CODECHAL_NUM_MEDIA_STATES && m_inlineEncodeStatusUpdate)
3292 {
3293 if (m_currPass < m_numPasses)
3294 {
3295 if(m_vdencBrcEnabled)
3296 {
3297 //delay to check at the beginning of next pass util huc status updated;
3298 }
3299 else
3300 {
3301 // inc m_storeData conditionaly
3302 UpdateEncodeStatus(cmdBuffer, false);
3303 }
3304 }
3305 else
3306 {
3307 // inc m_storeData forcely
3308 UpdateEncodeStatus(cmdBuffer, true);
3309 }
3310 }
3311
3312 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_perfProfiler->AddPerfCollectEndCmd((void*)this, m_osInterface, m_miInterface, cmdBuffer));
3313
3314 return eStatus;
3315 }
3316
3317 //!
3318 //! \brief Update m_storeData in offset 0 of statusReport.
3319 //! \details Add conditonal encode status report to avoid of extra small batch buffer
3320 //! to avoid of extra context switch interrupt. if ImageStatusRegister show
3321 //! encoding completion, update the m_storeData, otherwise continue.
3322 //! n0 n1 n2 n3
3323 //! +-------+--------+--------+--------+--------+--------+--------+--------+
3324 //! | 0 0 | 0 | val/0 1/0 | 0 1 |
3325 //! +-------+--------+--------+--------+--------+--------+--------+--------+
3326 //! low high low high low high low high
3327 //!
3328 //! if(m_forceOperation==true)
3329 //! step-1: m_storeData = m_storeData + 1 // ADD directly
3330 //! else
3331 //! step-1: n2_lo = ImageStatusCtrl & dwImageStatusMask // AND
3332 //! step-2: n2_lo = (n2_lo == 0) ? 0 : n2_lo // uint32_t CMP
3333 //! step-3: n2_lo:n2_hi = (n2_lo:n2_hi == 0:1) ? 0:0 : n2_lo:n2_hi // uint64_t CMP
3334 //! step-4: n2_hi = n2_hi ^ n3_hi // XOR
3335 //! step-5: m_storeData = m_storeData + n2_hi // ADD conditionaly
3336 //!
3337 //! \param [in] cmdBuffer
3338 //! Command buffer
3339 //! \param [in] forceOperation
3340 //! whether add m_storeData directly
3341 //! \return MOS_STATUS
3342 //! MOS_STATUS_SUCCESS if success, else fail reason
3343 //!
UpdateEncodeStatus(PMOS_COMMAND_BUFFER cmdBuffer,bool forceOperation)3344 MOS_STATUS CodechalEncoderState::UpdateEncodeStatus(
3345 PMOS_COMMAND_BUFFER cmdBuffer,
3346 bool forceOperation)
3347 {
3348 MmioRegistersMfx *mmioRegisters;
3349 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3350
3351 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
3352
3353 CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");
3354 mmioRegisters = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
3355
3356 // Get the right offset of EncodeStatusUpdate Operand scratch buffer
3357 uint32_t baseOffset = m_atomicScratchBuf.dwOperandSetSize * m_atomicScratchBuf.wEncodeUpdateIndex;
3358 uint32_t zeroValueOffset = baseOffset;
3359 uint32_t operand1Offset = baseOffset + m_atomicScratchBuf.dwOperand1Offset;
3360 uint32_t operand2Offset = baseOffset + m_atomicScratchBuf.dwOperand2Offset;
3361 uint32_t operand3Offset = baseOffset + m_atomicScratchBuf.dwOperand3Offset;
3362
3363 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
3364 MOS_ZeroMemory(&flushDwParams , sizeof(flushDwParams));
3365 flushDwParams.bVideoPipelineCacheInvalidate = true;
3366 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3367 cmdBuffer,
3368 &flushDwParams));
3369
3370 MHW_MI_LOAD_REGISTER_MEM_PARAMS miLoadRegMemParams;
3371 miLoadRegMemParams.presStoreBuffer = &m_encodeStatusBuf.resStatusBuffer;
3372 miLoadRegMemParams.dwOffset = 0;
3373 miLoadRegMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset;
3374 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(cmdBuffer, &miLoadRegMemParams));
3375
3376 MHW_MI_LOAD_REGISTER_IMM_PARAMS miLoadRegImmParams;
3377 miLoadRegImmParams.dwData = 0;
3378 miLoadRegImmParams.dwRegister = mmioRegisters->generalPurposeRegister0HiOffset;
3379 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(cmdBuffer, &miLoadRegImmParams));
3380
3381 miLoadRegImmParams.dwData = 0xFFFFFFFF;
3382 miLoadRegImmParams.dwRegister = mmioRegisters->generalPurposeRegister4LoOffset;
3383 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(cmdBuffer, &miLoadRegImmParams));
3384 miLoadRegImmParams.dwData = 0;
3385 miLoadRegImmParams.dwRegister = mmioRegisters->generalPurposeRegister4HiOffset;
3386 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(cmdBuffer, &miLoadRegImmParams));
3387 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3388 cmdBuffer,
3389 &flushDwParams));
3390
3391 MHW_MI_ALU_PARAMS aluParams[20];
3392 int aluCount = 0;
3393
3394 aluCount = 0;
3395
3396 //load1 srca, reg1
3397 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
3398 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCA;
3399 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG0;
3400 ++aluCount;
3401 //load srcb, reg2
3402 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
3403 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCB;
3404 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG4;
3405 ++aluCount;
3406 //add
3407 aluParams[aluCount].AluOpcode = MHW_MI_ALU_SUB;
3408 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCB;
3409 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG4;
3410 ++aluCount;
3411 //store reg1, accu
3412 aluParams[aluCount].AluOpcode = MHW_MI_ALU_STORE;
3413 aluParams[aluCount].Operand1 = MHW_MI_ALU_GPREG0;
3414 aluParams[aluCount].Operand2 = MHW_MI_ALU_ZF;
3415 ++aluCount;
3416
3417 MHW_MI_MATH_PARAMS miMathParams;
3418 miMathParams.dwNumAluParams = aluCount;
3419 miMathParams.pAluPayload = aluParams;
3420 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(cmdBuffer, &miMathParams));
3421
3422 miLoadRegImmParams.dwData = 1;
3423 miLoadRegImmParams.dwRegister = mmioRegisters->generalPurposeRegister4LoOffset;
3424 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(cmdBuffer, &miLoadRegImmParams));
3425 miLoadRegImmParams.dwData = 0;
3426 miLoadRegImmParams.dwRegister = mmioRegisters->generalPurposeRegister4HiOffset;
3427 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(cmdBuffer, &miLoadRegImmParams));
3428 aluCount = 0;
3429
3430 //load1 srca, reg1
3431 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
3432 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCA;
3433 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG0;
3434 ++aluCount;
3435 //load srcb, reg2
3436 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
3437 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCB;
3438 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG4;
3439 ++aluCount;
3440 //add
3441 aluParams[aluCount].AluOpcode = MHW_MI_ALU_AND;
3442 ++aluCount;
3443 //store reg1, accu
3444 aluParams[aluCount].AluOpcode = MHW_MI_ALU_STORE;
3445 aluParams[aluCount].Operand1 = MHW_MI_ALU_GPREG0;
3446 aluParams[aluCount].Operand2 = MHW_MI_ALU_ACCU;
3447 ++aluCount;
3448
3449 miMathParams.dwNumAluParams = aluCount;
3450 miMathParams.pAluPayload = aluParams;
3451 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(cmdBuffer, &miMathParams));
3452
3453 MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
3454 MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
3455 miStoreRegMemParams.presStoreBuffer = &m_atomicScratchBuf.resAtomicScratchBuffer;
3456 miStoreRegMemParams.dwOffset = operand1Offset;
3457 miStoreRegMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset;
3458 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
3459
3460 // Make Flush DW call to make sure all previous work is done
3461 MOS_ZeroMemory(&flushDwParams , sizeof(flushDwParams));
3462 flushDwParams.bVideoPipelineCacheInvalidate = true;
3463 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3464 cmdBuffer,
3465 &flushDwParams));
3466
3467 // Forcely ADD m_storeData, always happened in last pass.
3468 if(forceOperation)
3469 {
3470 // Make Flush DW call to make sure all previous work is done
3471 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
3472 MOS_ZeroMemory(&flushDwParams , sizeof(flushDwParams));
3473 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3474 cmdBuffer,
3475 &flushDwParams));
3476
3477 // n2_hi = 0x1
3478 MHW_MI_STORE_DATA_PARAMS storeDataParams;
3479 MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
3480 storeDataParams.pOsResource = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3481 storeDataParams.dwResourceOffset = operand2Offset + sizeof(uint32_t) ;
3482 storeDataParams.dwValue = 0x1;
3483 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3484 cmdBuffer,
3485 &storeDataParams));
3486
3487 // VCS_GPR0_Lo = n2_hi = 0x1
3488 MHW_MI_STORE_REGISTER_MEM_PARAMS registerMemParams;
3489 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3490 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3491 registerMemParams.dwOffset = operand2Offset + sizeof(uint32_t) ;
3492 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo
3493 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3494 cmdBuffer,
3495 ®isterMemParams));
3496
3497 // Make Flush DW call to make sure all previous work is done
3498 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3499 cmdBuffer,
3500 &flushDwParams));
3501
3502 // m_storeData = m_storeData + VCS_GPR0_Lo = m_storeData + 1
3503 MHW_MI_ATOMIC_PARAMS atomicParams;
3504 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3505 atomicParams.pOsResource =&m_encodeStatusBuf.resStatusBuffer;
3506 atomicParams.dwResourceOffset = 0;
3507 atomicParams.dwDataSize = sizeof(uint32_t);
3508 atomicParams.Operation = MHW_MI_ATOMIC_ADD;
3509 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3510 cmdBuffer,
3511 &atomicParams));
3512
3513 // Make Flush DW call to make sure all previous work is done
3514 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3515 cmdBuffer,
3516 &flushDwParams));
3517
3518 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3519 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3520 registerMemParams.dwOffset = operand1Offset;
3521 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset;
3522 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3523 cmdBuffer,
3524 ®isterMemParams));
3525
3526 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3527 atomicParams.pOsResource =&m_encodeStatusBuf.resStatusBuffer;
3528 atomicParams.dwResourceOffset = 0;
3529 atomicParams.dwDataSize = sizeof(uint32_t);
3530 atomicParams.Operation = MHW_MI_ATOMIC_ADD;
3531 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3532 cmdBuffer,
3533 &atomicParams));
3534
3535 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3536 cmdBuffer,
3537 &flushDwParams));
3538 return MOS_STATUS_SUCCESS;
3539 }
3540 else
3541 {
3542 // Make Flush DW call to make sure all previous work is done
3543 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
3544 MOS_ZeroMemory(&flushDwParams , sizeof(flushDwParams));
3545 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3546 cmdBuffer,
3547 &flushDwParams));
3548
3549 // n2_lo = dwImageStatusMask
3550 MHW_MI_COPY_MEM_MEM_PARAMS copyMemMemParams;
3551 MOS_ZeroMemory(©MemMemParams , sizeof(copyMemMemParams));
3552 if(!m_vdencBrcEnabled)
3553 {
3554 copyMemMemParams.presSrc = &m_encodeStatusBuf.resStatusBuffer;
3555 copyMemMemParams.dwSrcOffset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
3556 m_encodeStatusBuf.dwImageStatusMaskOffset +
3557 (sizeof(uint32_t) * 2);
3558 }
3559 else
3560 {
3561 copyMemMemParams.presSrc = &m_resPakMmioBuffer;
3562 copyMemMemParams.dwSrcOffset = (sizeof(uint32_t) * 1);
3563 }
3564 copyMemMemParams.presDst = &m_atomicScratchBuf.resAtomicScratchBuffer;
3565 copyMemMemParams.dwDstOffset = operand2Offset;
3566 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
3567 cmdBuffer,
3568 ©MemMemParams));
3569
3570 // VCS_GPR0_Lo = ImageStatusCtrl
3571 MHW_MI_STORE_REGISTER_MEM_PARAMS registerMemParams;
3572 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3573 if(!m_vdencBrcEnabled)
3574 {
3575 registerMemParams.presStoreBuffer = &m_encodeStatusBuf.resStatusBuffer;
3576 registerMemParams.dwOffset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
3577 m_encodeStatusBuf.dwImageStatusMaskOffset +
3578 (sizeof(uint32_t) * 2) + sizeof(uint32_t);
3579 }
3580 else
3581 {
3582 registerMemParams.presStoreBuffer = &m_resPakMmioBuffer;
3583 registerMemParams.dwOffset = (sizeof(uint32_t) * 0);
3584 }
3585 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo
3586 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3587 cmdBuffer,
3588 ®isterMemParams));
3589
3590 // Reset GPR4_Lo
3591 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3592 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3593 registerMemParams.dwOffset = zeroValueOffset; //Offset 0, has value of 0.
3594 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister4LoOffset; // VCS_GPR4
3595 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3596 cmdBuffer,
3597 ®isterMemParams));
3598
3599 // Make Flush DW call to make sure all previous work is done
3600 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3601 cmdBuffer,
3602 &flushDwParams));
3603
3604 // step-1: n2_lo = n2_lo & VCS_GPR0_Lo = dwImageStatusMask & ImageStatusCtrl
3605 MHW_MI_ATOMIC_PARAMS atomicParams;
3606 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3607 atomicParams.pOsResource = &m_atomicScratchBuf.resAtomicScratchBuffer;
3608 atomicParams.dwResourceOffset = operand2Offset;
3609 atomicParams.dwDataSize = sizeof(uint32_t);
3610 atomicParams.Operation = MHW_MI_ATOMIC_AND;
3611 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3612 cmdBuffer,
3613 &atomicParams));
3614
3615 // n3_lo = 0
3616 MHW_MI_STORE_DATA_PARAMS storeDataParams;
3617 MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
3618 storeDataParams.pOsResource = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3619 storeDataParams.dwResourceOffset = operand3Offset;
3620 storeDataParams.dwValue = 0;
3621 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3622 cmdBuffer,
3623 &storeDataParams));
3624
3625 // Make Flush DW call to make sure all previous work is done
3626 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3627 cmdBuffer,
3628 &flushDwParams));
3629
3630 MOS_ZeroMemory(©MemMemParams , sizeof(copyMemMemParams));
3631 copyMemMemParams.presSrc = &m_atomicScratchBuf.resAtomicScratchBuffer;
3632 copyMemMemParams.dwSrcOffset = operand2Offset;
3633 copyMemMemParams.presDst = &m_atomicScratchBuf.resAtomicScratchBuffer;
3634 copyMemMemParams.dwDstOffset = operand1Offset + sizeof(uint32_t);
3635 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
3636 cmdBuffer,
3637 ©MemMemParams));
3638
3639 // GPR0_lo = n1_lo = 0
3640 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3641 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3642 registerMemParams.dwOffset = zeroValueOffset;
3643 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0
3644 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3645 cmdBuffer,
3646 ®isterMemParams));
3647
3648 // Reset GPR4_Lo
3649 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3650 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3651 registerMemParams.dwOffset = zeroValueOffset; //Offset 0, has value of 0.
3652 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister4LoOffset; // VCS_GPR4
3653 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3654 cmdBuffer,
3655 ®isterMemParams));
3656
3657 // Make Flush DW call to make sure all previous work is done
3658 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3659 cmdBuffer,
3660 &flushDwParams));
3661
3662 // step-2: n2_lo == n1_lo ? 0 : n2_lo
3663 // compare n1 vs n2. i.e. GRP0 vs. memory of operand2
3664 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3665 atomicParams.pOsResource = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3666 atomicParams.dwResourceOffset = operand2Offset;
3667 atomicParams.dwDataSize = sizeof(uint32_t);
3668 atomicParams.Operation = MHW_MI_ATOMIC_CMP;
3669 atomicParams.bReturnData = true;
3670
3671 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3672 cmdBuffer,
3673 &atomicParams));
3674
3675 // n2_hi = 1
3676 MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
3677 storeDataParams.pOsResource =&(m_atomicScratchBuf.resAtomicScratchBuffer);
3678 storeDataParams.dwResourceOffset = operand2Offset + sizeof(uint32_t);
3679 storeDataParams.dwValue = 1;
3680 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3681 cmdBuffer,
3682 &storeDataParams));
3683
3684 // n3_hi = 1
3685 MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
3686 storeDataParams.pOsResource =&(m_atomicScratchBuf.resAtomicScratchBuffer);
3687 storeDataParams.dwResourceOffset = operand3Offset + sizeof(uint32_t);
3688 storeDataParams.dwValue = 1;
3689 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
3690 cmdBuffer,
3691 &storeDataParams));
3692
3693 // VCS_GPR0_Lo = n3_lo = 0
3694 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3695 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3696 registerMemParams.dwOffset = operand3Offset;
3697 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo
3698 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3699 cmdBuffer,
3700 ®isterMemParams));
3701
3702 // GPR0_Hi = n2_hi = 1
3703 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3704 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3705 registerMemParams.dwOffset = operand2Offset + sizeof(uint32_t) ; // update 1
3706 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0HiOffset; // VCS_GPR0_Hi
3707 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3708 cmdBuffer,
3709 ®isterMemParams));
3710
3711 // Reset GPR4_Lo and GPR4_Hi
3712 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3713 registerMemParams.presStoreBuffer =&(m_atomicScratchBuf.resAtomicScratchBuffer);
3714 registerMemParams.dwOffset = zeroValueOffset ;
3715 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister4LoOffset; // VCS_GPR4_Hi
3716 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3717 cmdBuffer,
3718 ®isterMemParams));
3719 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3720 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3721 registerMemParams.dwOffset = zeroValueOffset ;
3722 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister4HiOffset; // VCS_GPR4_Hi
3723 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3724 cmdBuffer,
3725 ®isterMemParams));
3726
3727 // Make Flush DW call to make sure all previous work is done
3728 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3729 cmdBuffer,
3730 &flushDwParams));
3731
3732 // steop-3: n2 = (n2 == 0:1) ? 0:0 : n2 // uint64_t CMP
3733 // If n2==0 (Lo) and 1 (Hi), covert n2 to 0 (Lo)and 0 (Hi), else no change.
3734 // n2 == 0:1 means encoding completsion. the n2 memory will be updated with 0:0, otherwise, no change.
3735 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3736 atomicParams.pOsResource = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3737 atomicParams.dwResourceOffset = operand2Offset;
3738 atomicParams.dwDataSize = sizeof(uint64_t);
3739 atomicParams.Operation = MHW_MI_ATOMIC_CMP;
3740 atomicParams.bReturnData = true;
3741 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3742 cmdBuffer,
3743 &atomicParams));
3744
3745 // Make Flush DW call to make sure all previous work is done
3746 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3747 cmdBuffer,
3748 &flushDwParams));
3749
3750 // VCS_GPR0_Lo = n3_hi = 1
3751 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3752 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3753 registerMemParams.dwOffset = operand3Offset + sizeof(uint32_t);
3754 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo
3755 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3756 cmdBuffer,
3757 ®isterMemParams));
3758
3759 // Make Flush DW call to make sure all previous work is done
3760 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3761 cmdBuffer,
3762 &flushDwParams));
3763
3764 // step-4: n2_hi = n2_hi ^ VCS_GPR0_Lo = n2_hi ^ n3_hi
3765 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3766 atomicParams.pOsResource =&(m_atomicScratchBuf.resAtomicScratchBuffer);
3767 atomicParams.dwResourceOffset = operand2Offset + sizeof(uint32_t);
3768 atomicParams.dwDataSize = sizeof(uint32_t);
3769 atomicParams.Operation = MHW_MI_ATOMIC_XOR;
3770 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3771 cmdBuffer,
3772 &atomicParams));
3773
3774 // VCS_GPR0_Lo = n2_hi
3775 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3776 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3777 registerMemParams.dwOffset = operand2Offset + sizeof(uint32_t) ;
3778 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo
3779 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3780 cmdBuffer,
3781 ®isterMemParams));
3782
3783 // step-5: m_storeData = m_storeData + VCS_GPR0_Lo = m_storeData + n2_hi
3784 // if not completed n2_hi should be 0, then m_storeData = m_storeData + 0
3785 // if completed, n2_hi should be 1, then m_storeData = m_storeData + 1
3786 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3787 atomicParams.pOsResource =&m_encodeStatusBuf.resStatusBuffer;
3788 atomicParams.dwResourceOffset = 0;
3789 atomicParams.dwDataSize = sizeof(uint32_t);
3790 atomicParams.Operation = MHW_MI_ATOMIC_ADD;
3791 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3792 cmdBuffer,
3793 &atomicParams));
3794
3795 // Make Flush DW call to make sure all previous work is done
3796 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3797 cmdBuffer,
3798 &flushDwParams));
3799
3800 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3801 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3802 registerMemParams.dwOffset = operand1Offset + sizeof(uint32_t);
3803 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset;
3804 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3805 cmdBuffer,
3806 ®isterMemParams));
3807
3808 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3809 atomicParams.pOsResource = &m_atomicScratchBuf.resAtomicScratchBuffer;
3810 atomicParams.dwResourceOffset = operand1Offset;
3811 atomicParams.dwDataSize = sizeof(uint32_t);
3812 atomicParams.Operation = MHW_MI_ATOMIC_AND;
3813 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3814 cmdBuffer,
3815 &atomicParams));
3816
3817 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3818 cmdBuffer,
3819 &flushDwParams));
3820
3821 MOS_ZeroMemory(®isterMemParams, sizeof(registerMemParams));
3822 registerMemParams.presStoreBuffer = &(m_atomicScratchBuf.resAtomicScratchBuffer);
3823 registerMemParams.dwOffset = operand1Offset;
3824 registerMemParams.dwRegister = mmioRegisters->generalPurposeRegister0LoOffset;
3825 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
3826 cmdBuffer,
3827 ®isterMemParams));
3828
3829 MOS_ZeroMemory(&atomicParams, sizeof(atomicParams));
3830 atomicParams.pOsResource =&m_encodeStatusBuf.resStatusBuffer;
3831 atomicParams.dwResourceOffset = 0;
3832 atomicParams.dwDataSize = sizeof(uint32_t);
3833 atomicParams.Operation = MHW_MI_ATOMIC_ADD;
3834 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(
3835 cmdBuffer,
3836 &atomicParams));
3837
3838 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
3839 cmdBuffer,
3840 &flushDwParams));
3841 }
3842
3843 return eStatus;
3844 }
3845
3846 //------------------------------------------------------------------------------
3847 //| Purpose: Sets up the eStatus reporting values for the next frame
3848 //| Return: N/A
3849 //------------------------------------------------------------------------------
ResetStatusReport()3850 MOS_STATUS CodechalEncoderState::ResetStatusReport()
3851 {
3852 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3853
3854 CODECHAL_ENCODE_FUNCTION_ENTER;
3855
3856 CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeStatusBuf.pEncodeStatus);
3857
3858 EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
3859 EncodeStatusBuffer* encodeStatusBufRcs = &m_encodeStatusBufRcs;
3860
3861 EncodeStatus* encodeStatus =
3862 (EncodeStatus*)(encodeStatusBuf->pEncodeStatus +
3863 encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize);
3864
3865 if (!m_frameTrackingEnabled && !m_inlineEncodeStatusUpdate)
3866 {
3867 bool renderEngineInUse = m_osInterface->pfnGetGpuContext(m_osInterface) == m_renderContext;
3868 bool nullRendering = false;
3869
3870 MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
3871 if (renderEngineInUse)
3872 {
3873 syncParams.GpuContext = m_renderContext;
3874 nullRendering = m_renderContextUsesNullHw;
3875 }
3876 else
3877 {
3878 syncParams.GpuContext = m_videoContext;
3879 nullRendering = m_videoContextUsesNullHw;
3880 }
3881
3882 m_osInterface->pfnResetOsStates(m_osInterface);
3883 MOS_COMMAND_BUFFER cmdBuffer;
3884 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
3885
3886 cmdBuffer.Attributes.bTurboMode = m_hwInterface->m_turboMode;
3887 cmdBuffer.Attributes.dwNumRequestedEUSlices = m_hwInterface->m_numRequestedEuSlices;
3888
3889 CODECHAL_ENCODE_CHK_STATUS_RETURN(UpdateCmdBufAttribute(&cmdBuffer, renderEngineInUse));
3890
3891 MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
3892 MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
3893 genericPrologParams.pOsInterface = m_osInterface;
3894 genericPrologParams.pvMiInterface = m_miInterface;
3895 genericPrologParams.bMmcEnabled = m_mmcState ? m_mmcState->IsMmcEnabled() : false;
3896 genericPrologParams.presStoreData = (renderEngineInUse) ?
3897 &encodeStatusBufRcs->resStatusBuffer : &encodeStatusBuf->resStatusBuffer;
3898 genericPrologParams.dwStoreDataValue = m_storeData;
3899 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmd(&cmdBuffer, &genericPrologParams));
3900
3901 // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
3902 if (m_osInterface->bTagResourceSync)
3903 {
3904 if (!m_firstField || CodecHal_PictureIsFrame(m_currOriginalPic))
3905 {
3906 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
3907 }
3908 }
3909
3910 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
3911 &cmdBuffer,
3912 nullptr));
3913 CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
3914 &cmdBuffer,
3915 CODECHAL_NUM_MEDIA_STATES,
3916 "_RESET_STATUS")));
3917
3918 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
3919
3920 HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
3921 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, nullRendering));
3922 }
3923
3924 if (m_videoContextUsesNullHw ||
3925 m_renderContextUsesNullHw)
3926 {
3927 if (CodecHalUsesOnlyRenderEngine(m_codecFunction))
3928 {
3929 *(encodeStatusBufRcs->pData) = m_storeData;
3930 }
3931 else
3932 {
3933 *(encodeStatusBuf->pData) = m_storeData;
3934 }
3935 }
3936
3937 encodeStatus->dwHeaderBytesInserted = m_headerBytesInserted;
3938 m_headerBytesInserted = 0;
3939
3940 if (!m_disableStatusReport)
3941 {
3942 m_storeData = m_storeData + 1 ? m_storeData + 1 : 1;
3943 encodeStatusBuf->wCurrIndex = (encodeStatusBuf->wCurrIndex + 1) % CODECHAL_ENCODE_STATUS_NUM;
3944 encodeStatusBufRcs->wCurrIndex = (encodeStatusBufRcs->wCurrIndex + 1) % CODECHAL_ENCODE_STATUS_NUM;
3945 }
3946
3947 // clean up the Status for next frame
3948 encodeStatus =
3949 (EncodeStatus*)(encodeStatusBuf->pEncodeStatus +
3950 encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize);
3951 uint32_t statusReportNumber = encodeStatus->lookaheadStatus.StatusReportNumber;
3952 MOS_ZeroMemory((uint8_t*)encodeStatus, sizeof(EncodeStatus));
3953 encodeStatus->lookaheadStatus.StatusReportNumber = statusReportNumber;
3954
3955 if (m_encEnabled)
3956 {
3957 EncodeStatus* pEncodeStatusRcs =
3958 (EncodeStatus*)(encodeStatusBufRcs->pEncodeStatus +
3959 encodeStatusBufRcs->wCurrIndex * encodeStatusBufRcs->dwReportSize);
3960 MOS_ZeroMemory((uint8_t*)pEncodeStatusRcs, sizeof(EncodeStatus));
3961 }
3962
3963 return eStatus;
3964 }
3965
ReadCounterValue(uint16_t index,EncodeStatusReport * encodeStatusReport)3966 MOS_STATUS CodechalEncoderState::ReadCounterValue(uint16_t index, EncodeStatusReport* encodeStatusReport)
3967 {
3968 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3969 CODECHAL_ENCODE_FUNCTION_ENTER;
3970 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);
3971 uint64_t *address2Counter = nullptr;
3972 uint32_t ctr[4] = { 0 };
3973
3974 if (m_hwInterface->GetCpInterface()->IsHwCounterIncrement(m_osInterface))
3975 {
3976 if (Mos_ResourceIsNull(&m_resHwCount))
3977 {
3978 CODECHAL_ENCODE_ASSERTMESSAGE("m_resHwCount is not allocated");
3979 return MOS_STATUS_NULL_POINTER;
3980 }
3981
3982 //Report HW counter by command output resource
3983 address2Counter = (uint64_t *)(((char *)(m_dataHwCount)) + (index * sizeof(HwCounter)));
3984 }
3985 else
3986 {
3987 //Report driver generated counter which was submitted to HW by command
3988 eStatus = m_hwInterface->GetCpInterface()->GetCounterValue(ctr);
3989 if (MOS_STATUS_SUCCESS == eStatus)
3990 {
3991 address2Counter = (uint64_t *)ctr;
3992 }
3993 else
3994 {
3995 return eStatus;
3996 }
3997 }
3998 encodeStatusReport->HWCounterValue.Count = *address2Counter;
3999 //Report back in Big endian
4000 encodeStatusReport->HWCounterValue.Count = SwapEndianness(encodeStatusReport->HWCounterValue.Count);
4001 //IV value computation
4002 encodeStatusReport->HWCounterValue.IV = *(++address2Counter);
4003 encodeStatusReport->HWCounterValue.IV = SwapEndianness(encodeStatusReport->HWCounterValue.IV);
4004 CODECHAL_ENCODE_NORMALMESSAGE(
4005 "encodeStatusReport->HWCounterValue.Count = 0x%llx, encodeStatusReport->HWCounterValue.IV = 0x%llx",
4006 encodeStatusReport->HWCounterValue.Count,
4007 encodeStatusReport->HWCounterValue.IV);
4008 return eStatus;
4009 }
4010
4011 //------------------------------------------------------------------------------
4012 //| Purpose: Gets available eStatus report data
4013 //| Return: N/A
4014 //------------------------------------------------------------------------------
GetStatusReport(void * status,uint16_t numStatus)4015 MOS_STATUS CodechalEncoderState::GetStatusReport(
4016 void *status,
4017 uint16_t numStatus)
4018 {
4019 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4020
4021 CODECHAL_ENCODE_FUNCTION_ENTER;
4022
4023 CODECHAL_ENCODE_CHK_NULL_RETURN(status);
4024 EncodeStatusReport *codecStatus = (EncodeStatusReport *)status;
4025
4026 EncodeStatusBuffer* encodeStatusBuf = nullptr;
4027 if (m_pakEnabled)
4028 {
4029 encodeStatusBuf = &m_encodeStatusBuf;
4030 }
4031 else
4032 {
4033 encodeStatusBuf = &m_encodeStatusBufRcs;
4034 }
4035
4036 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusBuf->pEncodeStatus);
4037
4038 uint16_t numReportsAvailable =
4039 (encodeStatusBuf->wCurrIndex - encodeStatusBuf->wFirstIndex) &
4040 (CODECHAL_ENCODE_STATUS_NUM - 1); // max is (CODECHAL_ENCODE_STATUS_NUM - 1)
4041
4042 uint32_t globalHWStoredData = 0;
4043 if (m_pakEnabled)
4044 {
4045 globalHWStoredData = *(m_encodeStatusBuf.pData); // HW stored Data
4046 }
4047 else
4048 {
4049 globalHWStoredData = *(m_encodeStatusBufRcs.pData); // HW stored Data
4050 }
4051 uint32_t globalCount = m_storeData - globalHWStoredData;
4052
4053 uint16_t reportsGenerated = 0;
4054 if (m_videoContextUsesNullHw ||
4055 m_renderContextUsesNullHw)
4056 {
4057 for (auto i = 0; i < numReportsAvailable; i++)
4058 {
4059 codecStatus[i].CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
4060 // Set fake bitstream size to avoid DDI report error
4061 codecStatus[i].bitstreamSize = 1024;
4062 reportsGenerated++;
4063 }
4064
4065 encodeStatusBuf->wFirstIndex =
4066 (encodeStatusBuf->wFirstIndex + reportsGenerated) % CODECHAL_ENCODE_STATUS_NUM;
4067
4068 return eStatus;
4069 }
4070
4071 CODECHAL_ENCODE_VERBOSEMESSAGE(" numStatus = %d, dwNumReportsAvailable = %d.", numStatus, numReportsAvailable);
4072 CODECHAL_ENCODE_VERBOSEMESSAGE(" hwstoreData = %d, globalCount = %d", globalHWStoredData, globalCount);
4073
4074 if (numReportsAvailable < numStatus && numStatus < CODECHAL_ENCODE_STATUS_NUM)
4075 {
4076 for (auto i = numReportsAvailable; i < numStatus; i++)
4077 {
4078 codecStatus[i].CodecStatus = CODECHAL_STATUS_UNAVAILABLE;
4079 }
4080 numStatus = numReportsAvailable;
4081 }
4082
4083 if (numReportsAvailable == 0)
4084 {
4085 CODECHAL_ENCODE_ASSERTMESSAGE("No reports available, wCurrIndex = %d, wFirstIndex = %d", encodeStatusBuf->wCurrIndex, encodeStatusBuf->wFirstIndex);
4086 return MOS_STATUS_SUCCESS;
4087 }
4088
4089 uint16_t index = 0;
4090
4091 for (auto i = 0; i < numStatus; i++)
4092 {
4093 if(codecStatus->bSequential)
4094 {
4095 index = (encodeStatusBuf->wFirstIndex + i) & (CODECHAL_ENCODE_STATUS_NUM - 1);
4096 }
4097 else
4098 {
4099 index = (encodeStatusBuf->wFirstIndex + numStatus - i - 1) & (CODECHAL_ENCODE_STATUS_NUM - 1);
4100 }
4101
4102 EncodeStatus* encodeStatus =
4103 (EncodeStatus*)(encodeStatusBuf->pEncodeStatus +
4104 index * encodeStatusBuf->dwReportSize);
4105 EncodeStatusReport* encodeStatusReport = &encodeStatus->encodeStatusReport;
4106 PCODEC_REF_LIST refList = encodeStatusReport->pCurrRefList;
4107 uint32_t localCount = encodeStatus->dwStoredData - globalHWStoredData;
4108
4109 encodeStatusReport->pFrmStatsInfo = codecStatus[i].pFrmStatsInfo;
4110 encodeStatusReport->pBlkStatsInfo = codecStatus[i].pBlkStatsInfo;
4111
4112 if (localCount == 0 || localCount > globalCount)
4113 {
4114 CODECHAL_DEBUG_TOOL(
4115 m_statusReportDebugInterface->m_bufferDumpFrameNum = encodeStatus->dwStoredData;
4116 )
4117
4118 // to be discussed, how to identify whether huc involved in pipeline
4119 if (!m_swBrcMode && m_vdencEnabled && m_vdencBrcEnabled && (m_standard == CODECHAL_HEVC || m_standard == CODECHAL_AVC || m_standard == CODECHAL_VP9))
4120 {
4121 MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
4122 MOS_ZeroMemory(&userFeatureWriteData, sizeof(MOS_USER_FEATURE_VALUE_WRITE_DATA));
4123
4124 if (!MEDIA_IS_SKU(m_hwInterface->GetSkuTable(), FtrEnableMediaKernels))
4125 {
4126 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to load HuC firmware!");
4127
4128 // Reporting
4129 MOS_ZeroMemory(&userFeatureWriteData, sizeof(MOS_USER_FEATURE_VALUE_WRITE_DATA));
4130 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4131 userFeatureWriteData.Value.i32Data = 1;
4132 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_HUC_FIRMWARE_LOAD_FAILED_ID;
4133 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4134
4135 return MOS_STATUS_HUC_KERNEL_FAILED;
4136 }
4137 else if (!(encodeStatus->HuCStatus2Reg & m_hucInterface->GetHucStatus2ImemLoadedMask()))
4138 {
4139 CODECHAL_ENCODE_ASSERTMESSAGE("HuC status2 indicates Valid Imem Load failed!");
4140
4141 // Reporting
4142 MOS_ZeroMemory(&userFeatureWriteData, sizeof(MOS_USER_FEATURE_VALUE_WRITE_DATA));
4143 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4144 userFeatureWriteData.Value.i32Data = 1;
4145 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_HUC_IMEM_LOAD_FALIED_ID;
4146 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4147
4148 #if (_DEBUG || _RELEASE_INTERNAL)
4149 MOS_ZeroMemory(&userFeatureWriteData, sizeof(MOS_USER_FEATURE_VALUE_WRITE_DATA));
4150 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4151 userFeatureWriteData.Value.u32Data = encodeStatus->HuCStatus2Reg;
4152 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_HUC_STATUS2_VALUE;
4153 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4154 #endif
4155 return MOS_STATUS_HUC_KERNEL_FAILED;
4156 }
4157 }
4158
4159 if ((m_standard == CODECHAL_HEVC && m_vdencEnabled && (encodeStatus->HuCStatusReg & m_hucInterface->GetHevcVdencHucErrorFlagMask())) ||
4160 (m_standard == CODECHAL_AVC && m_vdencEnabled && (encodeStatus->HuCStatusReg & m_hucInterface->GetAvcVdencHucErrorFlagMask())) ||
4161 (m_standard == CODECHAL_VP9 && m_vdencEnabled && (encodeStatus->HuCStatusReg & m_hucInterface->GetVp9VdencHucErrorFlagMask())) )
4162 {
4163 CODECHAL_ENCODE_ASSERTMESSAGE("HuC status indicates error");
4164 CODECHAL_DEBUG_TOOL(
4165 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpData(
4166 &encodeStatus->HuCStatusReg,
4167 sizeof(encodeStatus->HuCStatusReg),
4168 CodechalDbgAttr::attrStatusReport,
4169 "HuC_StatusRegister"));)
4170 }
4171
4172 // Current command is executed
4173 if (m_osInterface->pfnIsGPUHung(m_osInterface))
4174 {
4175 encodeStatusReport->CodecStatus = CODECHAL_STATUS_ERROR;
4176 *(encodeStatusBuf->pData) += 1;
4177 }
4178 else if (encodeStatusReport->Func != CODECHAL_ENCODE_ENC_ID &&
4179 encodeStatusReport->Func != CODECHAL_ENCODE_FEI_ENC_ID &&
4180 encodeStatus->dwStoredDataMfx != CODECHAL_STATUS_QUERY_END_FLAG)
4181 {
4182 if(encodeStatusReport->Func == CODECHAL_ENCODE_FEI_PRE_ENC_ID)
4183 {
4184 CODECHAL_DEBUG_TOOL(
4185 m_statusReportDebugInterface->m_scaledBottomFieldOffset = m_scaledBottomFieldOffset;
4186 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4187 m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER),
4188 CodechalDbgAttr::attrReconstructedSurface,
4189 "4xScaledSurf"));
4190
4191 /*CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgDumpEncode1Dbuffer(
4192 m_debugInterface,
4193 pEncoder));*/
4194
4195 // dump EncodeFeiPreproc
4196 FeiPreEncParams PreEncParams;
4197 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpBuffer(
4198 CodecHal_PictureIsBottomField(m_currOriginalPic) ? &PreEncParams.resStatsBotFieldBuffer
4199 : &PreEncParams.resStatsBotFieldBuffer,
4200 CodechalDbgAttr::attrOutput,
4201 "MbStats",
4202 m_picWidthInMb * m_frameFieldHeightInMb * 64,
4203 CodecHal_PictureIsBottomField(m_currOriginalPic) ? m_mbvProcStatsBottomFieldOffset : 0,
4204 CODECHAL_MEDIA_STATE_PREPROC));)
4205 encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
4206 }
4207 else
4208 {
4209 CODECHAL_ENCODE_NORMALMESSAGE("Media reset may have occured.");
4210 encodeStatusReport->CodecStatus = CODECHAL_STATUS_ERROR;
4211 }
4212 }
4213 else if (m_hwWalker && encodeStatusReport->Func == CODECHAL_ENCODE_ENC_ID)
4214 {
4215 // iterate over all media states and check that all of them completed
4216 for (auto j = 0; j < CODECHAL_NUM_MEDIA_STATES; j += 1)
4217 {
4218 if (encodeStatus->qwStoredDataEnc[j].dwStoredData != CODECHAL_STATUS_QUERY_END_FLAG)
4219 {
4220 // some media state failed to complete
4221 CODECHAL_ENCODE_ASSERTMESSAGE("Error: Unable to finish encoding");
4222 encodeStatusReport->CodecStatus = CODECHAL_STATUS_ERROR;
4223 break;
4224 }
4225 }
4226
4227 encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
4228
4229 if (m_codecFunction == CODECHAL_FUNCTION_HYBRIDPAK && m_mode == CODECHAL_ENCODE_MODE_VP9 &&
4230 encodeStatusReport->CodecStatus != CODECHAL_STATUS_ERROR)
4231 {
4232 unsigned int size = ((m_frameWidth + 63) >> 6) * ((m_frameHeight + 63) >> 6) + 1;
4233 encodeStatusReport->bitstreamSize = CODECHAL_VP9_MB_CODE_SIZE * sizeof(uint32_t) * size;
4234 }
4235 }
4236 else
4237 {
4238 if (m_codecGetStatusReportDefined)
4239 {
4240 // Call corresponding CODEC's status report function if existing
4241 eStatus = GetStatusReport(encodeStatus, encodeStatusReport);
4242 }
4243 else
4244 {
4245 eStatus = GetStatusReportCommon(encodeStatus, encodeStatusReport);
4246 }
4247
4248 if (MOS_STATUS_SUCCESS != eStatus)
4249 {
4250 return eStatus;
4251 }
4252
4253 CODECHAL_ENCODE_CHK_STATUS_RETURN(GetStatusReportExt(encodeStatus, encodeStatusReport, index));
4254
4255 if (m_osInterface->osCpInterface->IsCpEnabled() && m_skipFrameBasedHWCounterRead == false)
4256 {
4257 eStatus = ReadCounterValue(index, encodeStatusReport);
4258 if (MOS_STATUS_SUCCESS != eStatus)
4259 {
4260 return eStatus;
4261 }
4262 }
4263
4264 if (encodeStatusReport->bitstreamSize > m_bitstreamUpperBound)
4265 {
4266 encodeStatusReport->CodecStatus = CODECHAL_STATUS_ERROR;
4267 encodeStatusReport->bitstreamSize = 0;
4268 CODECHAL_ENCODE_ASSERTMESSAGE("Bit-stream size exceeds upper bound!");
4269 return MOS_STATUS_NOT_ENOUGH_BUFFER;
4270 }
4271
4272 if(refList && refList->bMADEnabled)
4273 {
4274 // set lock flag to READ_ONLY
4275 MOS_LOCK_PARAMS lockFlags;
4276 MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
4277 lockFlags.ReadOnly = 1;
4278
4279 uint8_t* data = (uint8_t* )m_osInterface->pfnLockResource(
4280 m_osInterface,
4281 &m_resMadDataBuffer[refList->ucMADBufferIdx],
4282 &lockFlags);
4283
4284 CODECHAL_ENCODE_CHK_NULL_RETURN(data);
4285
4286 eStatus = MOS_SecureMemcpy(
4287 &encodeStatusReport->MAD,
4288 CODECHAL_MAD_BUFFER_SIZE,
4289 data,
4290 CODECHAL_MAD_BUFFER_SIZE);
4291 if(eStatus != MOS_STATUS_SUCCESS)
4292 {
4293 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
4294 return eStatus;
4295 }
4296
4297 m_osInterface->pfnUnlockResource(
4298 m_osInterface,
4299 &m_resMadDataBuffer[refList->ucMADBufferIdx]);
4300
4301 // The driver needs to divide the output distortion by 4 before sending to the app
4302 encodeStatusReport->MAD /= 4;
4303 }
4304 else
4305 {
4306 encodeStatusReport->MAD = 0;
4307 }
4308
4309 CODECHAL_DEBUG_TOOL(
4310 CODEC_REF_LIST currRefList = *refList;
4311 currRefList.RefPic = encodeStatusReport->CurrOriginalPic;
4312
4313 m_statusReportDebugInterface->m_currPic = encodeStatusReport->CurrOriginalPic;
4314 m_statusReportDebugInterface->m_bufferDumpFrameNum = encodeStatus->dwStoredData;
4315 m_statusReportDebugInterface->m_frameType = encodeStatus->wPictureCodingType;
4316
4317 if (!m_vdencEnabled) {
4318 if (currRefList.bMADEnabled)
4319 {
4320 CODECHAL_ENCODE_CHK_STATUS_RETURN(
4321 m_statusReportDebugInterface->DumpBuffer(
4322 &m_resMadDataBuffer[currRefList.ucMADBufferIdx],
4323 CodechalDbgAttr::attrInput,
4324 "MADWrite",
4325 CODECHAL_MAD_BUFFER_SIZE,
4326 0,
4327 CODECHAL_MEDIA_STATE_ENC_NORMAL));
4328 }
4329
4330 DumpMbEncPakOutput(refList, m_statusReportDebugInterface);
4331 }
4332
4333 if (CodecHalUsesVideoEngine(m_codecFunction)) {
4334 /* Only where the MFX engine is used the bitstream surface will be available */
4335 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpBuffer(
4336 &currRefList.resBitstreamBuffer,
4337 CodechalDbgAttr::attrBitstream,
4338 "_PAK",
4339 encodeStatusReport->bitstreamSize,
4340 0,
4341 CODECHAL_NUM_MEDIA_STATES));
4342
4343 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpData(
4344 encodeStatusReport,
4345 sizeof(EncodeStatusReport),
4346 CodechalDbgAttr::attrStatusReport,
4347 "EncodeStatusReport_Buffer"));
4348
4349 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpEncodeStatusReport(
4350 encodeStatusReport));
4351
4352 CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpFrameStatsBuffer(m_statusReportDebugInterface));
4353
4354 if (m_vdencEnabled)
4355 {
4356 /*CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgDumpEncodeVdencOutputs(
4357 m_debugInterface, pEncoder));
4358
4359 if (m_cmdGenHucUsed)
4360 {
4361 CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgDumpEncodeHucCmdGen(
4362 m_debugInterface, pEncoder));
4363 }*/
4364 }
4365 }
4366
4367 if (currRefList.b32xScalingUsed) {
4368 m_statusReportDebugInterface->m_scaledBottomFieldOffset = m_scaled32xBottomFieldOffset;
4369 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4370 m_trackedBuf->Get32xDsSurface(currRefList.ucScalingIdx),
4371 CodechalDbgAttr::attrReconstructedSurface,
4372 "32xScaledSurf"))
4373 }
4374
4375 if (currRefList.b2xScalingUsed) // Currently only used for Gen10 Hevc Encode
4376 {
4377 m_statusReportDebugInterface->m_scaledBottomFieldOffset = 0; // No bottom field offset for Hevc
4378 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4379 m_trackedBuf->Get2xDsSurface(currRefList.ucScalingIdx),
4380 CodechalDbgAttr::attrReconstructedSurface,
4381 "2xScaledSurf"))
4382 }
4383
4384 if (currRefList.b16xScalingUsed) {
4385 m_statusReportDebugInterface->m_scaledBottomFieldOffset = m_scaled16xBottomFieldOffset;
4386 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4387 m_trackedBuf->Get16xDsSurface(currRefList.ucScalingIdx),
4388 CodechalDbgAttr::attrReconstructedSurface,
4389 "16xScaledSurf"))
4390 }
4391
4392 if (currRefList.b4xScalingUsed) {
4393 m_statusReportDebugInterface->m_scaledBottomFieldOffset = m_scaledBottomFieldOffset;
4394 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4395 m_trackedBuf->Get4xDsSurface(currRefList.ucScalingIdx),
4396 CodechalDbgAttr::attrReconstructedSurface,
4397 "4xScaledSurf"))
4398 }
4399
4400 if (!(m_codecFunction == CODECHAL_FUNCTION_ENC || m_codecFunction == CODECHAL_FUNCTION_FEI_ENC)) {
4401 if (m_codecFunction == CODECHAL_FUNCTION_HYBRIDPAK)
4402 {
4403 m_statusReportDebugInterface->m_hybridPakP1 = false;
4404 }
4405
4406 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpYUVSurface(
4407 &currRefList.sRefReconBuffer,
4408 CodechalDbgAttr::attrReconstructedSurface,
4409 "ReconSurf"))
4410 }
4411
4412 if (currRefList.bUsedAsRef && m_vdencMvTemporalBufferSize) {
4413 uint8_t coloc_idx = (m_currRefList->bIsIntra) ? CODEC_CURR_TRACKED_BUFFER : currRefList.ucScalingIdx;
4414 auto coloc_buffer = m_trackedBuf->GetMvTemporalBuffer(coloc_idx);
4415 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_statusReportDebugInterface->DumpBuffer(
4416 coloc_buffer,
4417 CodechalDbgAttr::attrMvData,
4418 "_CoLocated_Out",
4419 m_vdencMvTemporalBufferSize,
4420 0,
4421 CODECHAL_NUM_MEDIA_STATES));
4422 })
4423 }
4424 CODECHAL_ENCODE_VERBOSEMESSAGE("Incrementing reports generated to %d.", (reportsGenerated + 1));
4425 reportsGenerated++;
4426 }
4427 else
4428 {
4429 //update GPU status, and skip the hang frame
4430 if(m_osInterface->pfnIsGPUHung(m_osInterface))
4431 {
4432 *(encodeStatusBuf->pData) += 1;
4433 reportsGenerated++;
4434 }
4435
4436 CODECHAL_ENCODE_VERBOSEMESSAGE("Status buffer %d is INCOMPLETE.", i);
4437 encodeStatusReport->CodecStatus = CODECHAL_STATUS_INCOMPLETE;
4438 }
4439 codecStatus[i] = *encodeStatusReport;
4440
4441 NullHW::StatusReport(m_osInterface, (uint32_t &)codecStatus[i].CodecStatus,
4442 codecStatus[i].bitstreamSize);
4443 }
4444
4445 encodeStatusBuf->wFirstIndex =
4446 (encodeStatusBuf->wFirstIndex + reportsGenerated) % CODECHAL_ENCODE_STATUS_NUM;
4447 CODECHAL_ENCODE_VERBOSEMESSAGE("wFirstIndex now becomes %d.", encodeStatusBuf->wFirstIndex);
4448
4449 return eStatus;
4450 }
4451
GetStatusReportCommon(EncodeStatus * encodeStatus,EncodeStatusReport * encodeStatusReport)4452 MOS_STATUS CodechalEncoderState::GetStatusReportCommon(
4453 EncodeStatus* encodeStatus,
4454 EncodeStatusReport* encodeStatusReport)
4455 {
4456 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4457
4458 encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
4459 encodeStatusReport->bitstreamSize =
4460 encodeStatus->dwMFCBitstreamByteCountPerFrame + encodeStatus->dwHeaderBytesInserted;
4461
4462 // dwHeaderBytesInserted is for WAAVCSWHeaderInsertion
4463 // and is 0 otherwise
4464 encodeStatusReport->QpY = encodeStatus->BrcQPReport.DW0.QPPrimeY;
4465 encodeStatusReport->SuggestedQpYDelta =
4466 encodeStatus->ImageStatusCtrl.CumulativeSliceDeltaQP;
4467 encodeStatusReport->NumberPasses = (uint8_t)(encodeStatus->ImageStatusCtrl.TotalNumPass + 1);
4468 encodeStatusReport->SceneChangeDetected =
4469 (encodeStatus->dwSceneChangedFlag & CODECHAL_ENCODE_SCENE_CHANGE_DETECTED_MASK) ? 1 : 0;
4470
4471 CODECHAL_ENCODE_CHK_NULL_RETURN(m_skuTable);
4472
4473 if (m_picWidthInMb != 0 && m_frameFieldHeightInMb != 0)
4474 {
4475 encodeStatusReport->AverageQp = (unsigned char)(((uint32_t)encodeStatus->QpStatusCount.cumulativeQP)
4476 / (m_picWidthInMb * m_frameFieldHeightInMb));
4477 }
4478 encodeStatusReport->PanicMode = encodeStatus->ImageStatusCtrl.Panic;
4479
4480 // If Num slices is greater than spec limit set NumSlicesNonCompliant to 1 and report error
4481 PMHW_VDBOX_PAK_NUM_OF_SLICES numSlices = &encodeStatus->NumSlices;
4482 if (numSlices->NumberOfSlices > m_maxNumSlicesAllowed)
4483 {
4484 encodeStatusReport->NumSlicesNonCompliant = 1;
4485 }
4486 encodeStatusReport->NumberSlices = numSlices->NumberOfSlices;
4487
4488 return eStatus;
4489 }
4490
4491 //------------------------------------------------------------------------------
4492 //| Purpose: Reports user feature keys used for encoding
4493 //| Return: N/A
4494 //------------------------------------------------------------------------------
UserFeatureKeyReport()4495 MOS_STATUS CodechalEncoderState::UserFeatureKeyReport()
4496 {
4497 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4498
4499 CODECHAL_ENCODE_FUNCTION_ENTER;
4500
4501 MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
4502
4503 // Encode HW Walker Reporting
4504 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4505 userFeatureWriteData.Value.i32Data = m_hwWalker;
4506 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_ID;
4507 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4508
4509 if (m_hwWalker)
4510 {
4511 // Encode HW Walker m_mode Reporting
4512 #if (_DEBUG || _RELEASE_INTERNAL)
4513 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4514 userFeatureWriteData.Value.i32Data = m_walkerMode;
4515 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_MODE_ID;
4516 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4517 #endif // _DEBUG || _RELEASE_INTERNAL
4518 }
4519
4520 if (MEDIA_IS_SKU(m_skuTable, FtrSliceShutdown))
4521 {
4522 // SliceShutdownEnable Reporting
4523 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4524 userFeatureWriteData.Value.i32Data = m_sliceShutdownEnable;
4525 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_ENABLE_ID;
4526 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4527 }
4528
4529 #if (_DEBUG || _RELEASE_INTERNAL)
4530 // report encode CSC method
4531 if (m_cscDsState)
4532 {
4533 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4534 userFeatureWriteData.Value.i32Data = m_cscDsState->CscMethod();
4535 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_CSC_METHOD_ID;
4536 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4537
4538 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4539 userFeatureWriteData.Value.u32Data = (uint32_t)m_rawSurface.TileType;
4540 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_RAW_TILE_ID;
4541 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4542
4543 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4544 userFeatureWriteData.Value.u32Data = (uint32_t)m_rawSurface.Format;
4545 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_RAW_FORMAT_ID;
4546 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4547 }
4548
4549 // Encode compute context Reporting
4550 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4551 userFeatureWriteData.Value.i32Data = m_computeContextEnabled;
4552 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENCODE_ENABLE_COMPUTE_CONTEXT_ID;
4553 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4554
4555 // Single Task Phase support reporting
4556 userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
4557 userFeatureWriteData.Value.i32Data = m_singleTaskPhaseSupported;
4558 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_SINGLE_TASK_PHASE_ENABLE_ID;
4559 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
4560 #endif
4561
4562 return eStatus;
4563 }
4564
SubmitCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer,bool bNullRendering)4565 MOS_STATUS CodechalEncoderState::SubmitCommandBuffer(
4566 PMOS_COMMAND_BUFFER cmdBuffer,
4567 bool bNullRendering)
4568 {
4569 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4570
4571 CODECHAL_ENCODE_FUNCTION_ENTER;
4572
4573 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
4574
4575 HalOcaInterface::On1stLevelBBEnd(*cmdBuffer, *m_osInterface);
4576 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, cmdBuffer, bNullRendering));
4577 return eStatus;
4578 }
4579
MotionEstimationDisableCheck()4580 void CodechalEncoderState::MotionEstimationDisableCheck()
4581 {
4582 CODECHAL_ENCODE_FUNCTION_ENTER;
4583
4584 if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb ||
4585 m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
4586 {
4587 m_32xMeSupported = false;
4588 m_16xMeSupported = false;
4589 if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb)
4590 {
4591 m_downscaledWidth4x = m_minScaledDimension;
4592 m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth4x);
4593 }
4594 if (m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
4595 {
4596 m_downscaledHeight4x = m_minScaledDimension;
4597 m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight4x);
4598 }
4599 }
4600 else if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb ||
4601 m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
4602 {
4603 m_32xMeSupported = false;
4604 if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb)
4605 {
4606 m_downscaledWidth16x = m_minScaledDimension;
4607 m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth16x);
4608 }
4609 if (m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
4610 {
4611 m_downscaledHeight16x = m_minScaledDimension;
4612 m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight16x);
4613 }
4614 }
4615 else
4616 {
4617 if (m_downscaledWidth32x < m_minScaledDimension || m_downscaledWidthInMb32x < m_minScaledDimensionInMb)
4618 {
4619 m_downscaledWidth32x = m_minScaledDimension;
4620 m_downscaledWidthInMb32x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth32x);
4621 }
4622 if (m_downscaledHeight32x < m_minScaledDimension || m_downscaledHeightInMb32x < m_minScaledDimensionInMb)
4623 {
4624 m_downscaledHeight32x = m_minScaledDimension;
4625 m_downscaledHeightInMb32x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight32x);
4626 }
4627 }
4628 }
4629
SendPrologWithFrameTracking(PMOS_COMMAND_BUFFER cmdBuffer,bool frameTrackingRequested,MHW_MI_MMIOREGISTERS * mmioRegister)4630 MOS_STATUS CodechalEncoderState::SendPrologWithFrameTracking(
4631 PMOS_COMMAND_BUFFER cmdBuffer,
4632 bool frameTrackingRequested,
4633 MHW_MI_MMIOREGISTERS* mmioRegister)
4634 {
4635 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4636
4637 CODECHAL_ENCODE_FUNCTION_ENTER;
4638
4639 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
4640
4641 MOS_GPU_CONTEXT gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
4642
4643 // Send Start Marker command
4644 if (m_encodeParams.m_setMarkerEnabled)
4645 {
4646 CODECHAL_ENCODE_CHK_STATUS_RETURN(SendMarkerCommand(cmdBuffer, MOS_RCS_ENGINE_USED(gpuContext)));
4647 }
4648
4649 // initialize command buffer attributes
4650 cmdBuffer->Attributes.bTurboMode = m_hwInterface->m_turboMode;
4651 cmdBuffer->Attributes.bMediaPreemptionEnabled = MOS_RCS_ENGINE_USED(gpuContext) ?
4652 m_renderEngineInterface->IsPreemptionEnabled() : 0;
4653 cmdBuffer->Attributes.dwNumRequestedEUSlices = m_hwInterface->m_numRequestedEuSlices;
4654 cmdBuffer->Attributes.dwNumRequestedSubSlices = m_hwInterface->m_numRequestedSubSlices;
4655 cmdBuffer->Attributes.dwNumRequestedEUs = m_hwInterface->m_numRequestedEus;
4656 cmdBuffer->Attributes.bValidPowerGatingRequest = true;
4657
4658 if (frameTrackingRequested && m_frameTrackingEnabled)
4659 {
4660 cmdBuffer->Attributes.bEnableMediaFrameTracking = true;
4661 cmdBuffer->Attributes.resMediaFrameTrackingSurface =
4662 &m_encodeStatusBuf.resStatusBuffer;
4663 cmdBuffer->Attributes.dwMediaFrameTrackingTag = m_storeData;
4664 // Set media frame tracking address offset(the offset from the encoder status buffer page)
4665 cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset = 0;
4666 }
4667
4668 #ifdef _MMC_SUPPORTED
4669 CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
4670 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SendPrologCmd(m_miInterface, cmdBuffer, gpuContext));
4671 #endif
4672
4673 MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
4674 MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
4675 genericPrologParams.pOsInterface = m_osInterface;
4676 genericPrologParams.pvMiInterface = m_miInterface;
4677 genericPrologParams.bMmcEnabled = m_mmcState ? m_mmcState->IsMmcEnabled() : false;
4678 genericPrologParams.dwStoreDataValue = m_storeData - 1;
4679 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmd(cmdBuffer, &genericPrologParams, mmioRegister));
4680
4681 // Send predication command
4682 if (m_encodeParams.m_predicationEnabled)
4683 {
4684 CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPredicationCommand(cmdBuffer));
4685 }
4686
4687 return eStatus;
4688 }
4689
SendPredicationCommand(PMOS_COMMAND_BUFFER cmdBuffer)4690 MOS_STATUS CodechalEncoderState::SendPredicationCommand(
4691 PMOS_COMMAND_BUFFER cmdBuffer)
4692 {
4693 CODECHAL_ENCODE_FUNCTION_ENTER;
4694
4695 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
4696 CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface);
4697
4698 // Predication can be set based on the value of 64-bits within a buffer
4699 auto PreparePredicationBuf = [&](bool predicationNotEqualZero) {
4700 auto mmioRegistersMfx = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
4701 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
4702 MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
4703 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
4704
4705 // load presPredication to general purpose register0
4706 MHW_MI_LOAD_REGISTER_MEM_PARAMS loadRegisterMemParams;
4707 MOS_ZeroMemory(&loadRegisterMemParams, sizeof(loadRegisterMemParams));
4708 loadRegisterMemParams.presStoreBuffer = m_encodeParams.m_presPredication;
4709 loadRegisterMemParams.dwOffset = (uint32_t)m_encodeParams.m_predicationResOffset;
4710 loadRegisterMemParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0LoOffset;
4711 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
4712 cmdBuffer,
4713 &loadRegisterMemParams));
4714 MHW_MI_LOAD_REGISTER_IMM_PARAMS loadRegisterImmParams;
4715 MOS_ZeroMemory(&loadRegisterImmParams, sizeof(loadRegisterImmParams));
4716 loadRegisterImmParams.dwData = 0;
4717 loadRegisterImmParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0HiOffset;
4718 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
4719 cmdBuffer,
4720 &loadRegisterImmParams));
4721
4722 MOS_ZeroMemory(&loadRegisterMemParams, sizeof(loadRegisterMemParams));
4723 loadRegisterMemParams.presStoreBuffer = m_encodeParams.m_presPredication;
4724 loadRegisterMemParams.dwOffset = (uint32_t)m_encodeParams.m_predicationResOffset + sizeof(uint32_t);
4725 loadRegisterMemParams.dwRegister = mmioRegistersMfx->generalPurposeRegister4LoOffset;
4726 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
4727 cmdBuffer,
4728 &loadRegisterMemParams));
4729 MOS_ZeroMemory(&loadRegisterImmParams, sizeof(loadRegisterImmParams));
4730 loadRegisterImmParams.dwData = 0;
4731 loadRegisterImmParams.dwRegister = mmioRegistersMfx->generalPurposeRegister4HiOffset;
4732 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
4733 cmdBuffer,
4734 &loadRegisterImmParams));
4735
4736 //perform operation
4737 MHW_MI_MATH_PARAMS miMathParams;
4738 MHW_MI_ALU_PARAMS miAluParams[4];
4739 MOS_ZeroMemory(&miMathParams, sizeof(miMathParams));
4740 MOS_ZeroMemory(&miAluParams, sizeof(miAluParams));
4741 // load srcA, reg0
4742 miAluParams[0].AluOpcode = MHW_MI_ALU_LOAD;
4743 miAluParams[0].Operand1 = MHW_MI_ALU_SRCA;
4744 miAluParams[0].Operand2 = MHW_MI_ALU_GPREG0;
4745 // load srcB, reg4
4746 miAluParams[1].AluOpcode = MHW_MI_ALU_LOAD;
4747 miAluParams[1].Operand1 = MHW_MI_ALU_SRCB;
4748 miAluParams[1].Operand2 = MHW_MI_ALU_GPREG4;
4749 // add srcA, srcB
4750 miAluParams[2].AluOpcode = predicationNotEqualZero ? MHW_MI_ALU_ADD : MHW_MI_ALU_OR;
4751 miAluParams[2].Operand1 = MHW_MI_ALU_SRCB;
4752 miAluParams[2].Operand2 = MHW_MI_ALU_GPREG4;
4753 // store reg0, ZF
4754 miAluParams[3].AluOpcode = MHW_MI_ALU_STORE;
4755 miAluParams[3].Operand1 = MHW_MI_ALU_GPREG0;
4756 miAluParams[3].Operand2 = predicationNotEqualZero ? MHW_MI_ALU_ZF : MHW_MI_ALU_ACCU;
4757 miMathParams.pAluPayload = miAluParams;
4758 miMathParams.dwNumAluParams = 4; // four ALU commands needed for this substract opertaion. see following ALU commands.
4759 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(
4760 cmdBuffer,
4761 &miMathParams));
4762
4763 // if MHW_MI_ALU_ZF, the zero flag will be 0xFFFFFFFF, else zero flag will be 0x0.
4764 // if MHW_MI_ALU_ACCU, the OR result directly copied
4765 MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
4766 MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
4767 storeRegParams.presStoreBuffer = &m_predicationBuffer;
4768 storeRegParams.dwOffset = 0;
4769 storeRegParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0LoOffset;
4770 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
4771 cmdBuffer,
4772 &storeRegParams));
4773
4774 CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeParams.m_tempPredicationBuffer);
4775 *m_encodeParams.m_tempPredicationBuffer = &m_predicationBuffer;
4776
4777 return MOS_STATUS_SUCCESS;
4778 };
4779
4780 CODECHAL_ENCODE_CHK_STATUS_RETURN(PreparePredicationBuf(m_encodeParams.m_predicationNotEqualZero));
4781
4782 MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS condBBEndParams;
4783 MOS_ZeroMemory(&condBBEndParams, sizeof(condBBEndParams));
4784 condBBEndParams.presSemaphoreBuffer = &m_predicationBuffer;
4785 condBBEndParams.dwOffset = 0;
4786 condBBEndParams.dwValue = 0;
4787 condBBEndParams.bDisableCompareMask = true;
4788 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd(
4789 cmdBuffer,
4790 &condBBEndParams));
4791
4792 return MOS_STATUS_SUCCESS;
4793 }
4794
SendMarkerCommand(PMOS_COMMAND_BUFFER cmdBuffer,bool isRender)4795 MOS_STATUS CodechalEncoderState::SendMarkerCommand(
4796 PMOS_COMMAND_BUFFER cmdBuffer,
4797 bool isRender)
4798 {
4799 CODECHAL_ENCODE_FUNCTION_ENTER;
4800
4801 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
4802 CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface);
4803
4804 PMOS_RESOURCE presSetMarker = (PMOS_RESOURCE) m_encodeParams.m_presSetMarker;
4805
4806 if (Mos_ResourceIsNull(presSetMarker))
4807 {
4808 return MOS_STATUS_SUCCESS;
4809 }
4810
4811 if (isRender)
4812 {
4813 // Send pipe_control to get the timestamp
4814 MHW_PIPE_CONTROL_PARAMS pipeControlParams;
4815 MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
4816 pipeControlParams.presDest = presSetMarker;
4817 pipeControlParams.dwResourceOffset = 0;
4818 pipeControlParams.dwPostSyncOp = MHW_FLUSH_WRITE_TIMESTAMP_REG;
4819 pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
4820
4821 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(cmdBuffer, NULL, &pipeControlParams));
4822 }
4823 else
4824 {
4825 // Send flush_dw to get the timestamp
4826 MHW_MI_FLUSH_DW_PARAMS flushDwParams;
4827 MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
4828 flushDwParams.pOsResource = presSetMarker;
4829 flushDwParams.dwResourceOffset = 0;
4830 flushDwParams.postSyncOperation = MHW_FLUSH_WRITE_TIMESTAMP_REG;
4831 flushDwParams.bQWordEnable = 1;
4832
4833 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
4834 }
4835
4836 return MOS_STATUS_SUCCESS;
4837 }
4838
UpdateCmdBufAttribute(PMOS_COMMAND_BUFFER cmdBuffer,bool renderEngineInUse)4839 MOS_STATUS CodechalEncoderState::UpdateCmdBufAttribute(
4840 PMOS_COMMAND_BUFFER cmdBuffer,
4841 bool renderEngineInUse)
4842 {
4843 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4844
4845 return eStatus;
4846 }
4847
ExecuteEnc(EncoderParams * encodeParams)4848 MOS_STATUS CodechalEncoderState::ExecuteEnc(
4849 EncoderParams* encodeParams)
4850 {
4851 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
4852
4853 CODECHAL_ENCODE_FUNCTION_ENTER;
4854
4855 CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface->GetCpInterface());
4856
4857 if (m_mfeEnabled == false || encodeParams->ExecCodecFunction == CODECHAL_FUNCTION_ENC
4858 || encodeParams->ExecCodecFunction == CODECHAL_FUNCTION_FEI_ENC)
4859 {
4860 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_START,
4861 &encodeParams->ExecCodecFunction, sizeof(encodeParams->ExecCodecFunction),
4862 nullptr, 0);
4863 // No need to wait if the driver is executing on a simulator
4864 EncodeStatusBuffer* pencodeStatusBuf = CodecHalUsesOnlyRenderEngine(m_codecFunction) ? &m_encodeStatusBufRcs : &m_encodeStatusBuf;
4865 if (!m_osInterface->bSimIsActive &&
4866 m_recycledBufStatusNum[m_currRecycledBufIdx] >
4867 *(pencodeStatusBuf->pData))
4868 {
4869 uint32_t waitMs;
4870
4871 // Wait for Batch Buffer complete event OR timeout
4872 for (waitMs = MHW_TIMEOUT_MS_DEFAULT; waitMs > 0; waitMs -= MHW_EVENT_TIMEOUT_MS)
4873 {
4874 if (m_recycledBufStatusNum[m_currRecycledBufIdx] <= *(pencodeStatusBuf->pData))
4875 {
4876 break;
4877 }
4878
4879 MosUtilities::MosSleep(MHW_EVENT_TIMEOUT_MS);
4880 }
4881
4882 CODECHAL_ENCODE_VERBOSEMESSAGE("Waited for %d ms", (MHW_TIMEOUT_MS_DEFAULT - waitMs));
4883
4884 if (m_recycledBufStatusNum[m_currRecycledBufIdx] >
4885 *(pencodeStatusBuf->pData))
4886 {
4887 CODECHAL_ENCODE_ASSERTMESSAGE("No recycled buffers available, wait timed out at %d ms!", MHW_TIMEOUT_MS_DEFAULT);
4888 CODECHAL_ENCODE_ASSERTMESSAGE("m_storeData = %d, m_recycledBufStatusNum[%d] = %d, data = %d", m_storeData, m_currRecycledBufIdx, m_recycledBufStatusNum[m_currRecycledBufIdx], *(pencodeStatusBuf->pData));
4889 return MOS_STATUS_CLIENT_AR_NO_SPACE;
4890 }
4891 }
4892
4893 m_recycledBufStatusNum[m_currRecycledBufIdx] = m_storeData;
4894
4895 // These parameters are updated at the DDI level
4896 if (encodeParams->bMbDisableSkipMapEnabled)
4897 {
4898 CodecHalGetResourceInfo(m_osInterface, encodeParams->psMbDisableSkipMapSurface);
4899 }
4900
4901 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeParams->psRawSurface);
4902 CodecHalGetResourceInfo(m_osInterface, encodeParams->psRawSurface);
4903 if (encodeParams->bMbQpDataEnabled)
4904 {
4905 CodecHalGetResourceInfo(m_osInterface, encodeParams->psMbQpDataSurface);
4906 }
4907
4908 if (m_standard != CODECHAL_JPEG)
4909 {
4910 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeParams->psReconSurface);
4911 CodecHalGetResourceInfo(m_osInterface, encodeParams->psReconSurface);
4912 }
4913
4914 m_encodeParams = *encodeParams;
4915
4916 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetCpInterface()->UpdateParams(true));
4917
4918 if (CodecHalUsesVideoEngine(m_codecFunction))
4919 {
4920 // Get resource details of the bitstream resource
4921 MOS_SURFACE details;
4922 MOS_ZeroMemory(&details, sizeof(details));
4923 details.Format = Format_Invalid;
4924 CODECHAL_ENCODE_CHK_NULL_RETURN(encodeParams->presBitstreamBuffer);
4925 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(m_osInterface, encodeParams->presBitstreamBuffer, &details));
4926
4927 m_encodeParams.dwBitstreamSize = details.dwHeight * details.dwWidth;
4928 }
4929
4930 m_osInterface->pfnIncPerfFrameID(m_osInterface);
4931
4932 // init function common to all codecs, before encode each frame
4933 CODECHAL_ENCODE_CHK_STATUS_RETURN(InitCommon());
4934
4935 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(InitializePicture(m_encodeParams),
4936 "Encoding initialization failed.");
4937
4938 if (m_newSeq)
4939 {
4940 CODECHAL_ENCODE_CHK_STATUS_RETURN(CheckResChangeAndCsc());
4941 }
4942
4943 if (FRAME_SKIP_NORMAL == m_skipFrameFlag)
4944 {
4945 if (m_standard == CODECHAL_MPEG2)
4946 {
4947 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(EncodeCopySkipFrame(), "Skip-frame failed.\n");
4948 m_skipFrameFlag = FRAME_NO_SKIP;
4949 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(ResetStatusReport(), "Flushing encode status buffer for skipped frame failed.\n");
4950 m_firstFrame = false;
4951 return eStatus;
4952 }
4953 }
4954
4955 MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
4956 syncParams.bReadOnly = true;
4957
4958 // Synchronize MB QP data surface resource if any.
4959 if (encodeParams->bMbQpDataEnabled)
4960 {
4961 syncParams.presSyncResource = &encodeParams->psMbQpDataSurface->OsResource;
4962 syncParams.GpuContext = m_renderContext;
4963 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
4964 }
4965
4966 // Check if source surface needs to be synchronized and should wait for decode or VPP or any other context
4967 syncParams.presSyncResource = &m_rawSurface.OsResource;
4968
4969 if (m_hwInterface->UsesRenderEngine(m_codecFunction, m_standard) &&
4970 m_firstField)
4971 {
4972 syncParams.GpuContext = m_renderContext;
4973 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
4974
4975 if (CodecHalUsesVideoEngine(m_codecFunction))
4976 {
4977 // Perform Sync on PAK context if it is not ENC only case.
4978 // This is done to set the read mask for PAK context for on demand sync
4979 syncParams.GpuContext = m_videoContext;
4980 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
4981 }
4982 // Update the resource tag (s/w tag) for On-Demand Sync
4983 // set the tag on render context for ENC case only, else set it on video context for ENC+PAK case
4984 m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
4985 }
4986 else if (CodecHalUsesVideoEngine(m_codecFunction))
4987 {
4988 // Perform resource sync for encode uses only video engine
4989 syncParams.GpuContext = m_videoContext;
4990 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
4991 m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
4992 }
4993
4994 CODECHAL_ENCODE_CHK_NULL_RETURN(m_currRefList);
4995
4996 if (CODECHAL_JPEG != m_standard && m_firstField)
4997 {
4998 for (int i = 0; i < m_currRefList->ucNumRef; i++)
4999 {
5000 CODECHAL_ENCODE_CHK_COND_RETURN(
5001 m_currReconstructedPic.FrameIdx == m_currRefList->RefList[i].FrameIdx,
5002 "the same frame (FrameIdx = %d) cannot be used as both Recon surface and ref frame",
5003 m_currReconstructedPic.FrameIdx);
5004 }
5005
5006 // clear flags
5007 m_currRefList->b2xScalingUsed =
5008 m_currRefList->b4xScalingUsed =
5009 m_currRefList->b16xScalingUsed =
5010 m_currRefList->b32xScalingUsed = false;
5011
5012 // allocate tracked buffer for current frame
5013 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_trackedBuf->AllocateForCurrFrame());
5014 m_currRefList->ucScalingIdx = m_trackedBuf->GetCurrIndex();
5015
5016 if (m_trackedBuf->IsMbCodeAllocationNeeded())
5017 {
5018 // MbCode/MvData buffer can be tracked using the same index as DS surface
5019 m_currRefList->ucMbCodeIdx = m_currMbCodeIdx = m_trackedBuf->GetCurrIndexMbCode();
5020
5021 m_resMbCodeSurface = m_currRefList->resRefMbCodeBuffer = *m_trackedBuf->GetCurrMbCodeBuffer();
5022 if (m_trackedBuf->GetCurrMvDataBuffer())
5023 {
5024 m_resMvDataSurface = m_currRefList->resRefMvDataBuffer = *m_trackedBuf->GetCurrMvDataBuffer();
5025 }
5026 }
5027 else
5028 {
5029 CODECHAL_ENCODE_NORMALMESSAGE("App provides MbCode and MvData buffer!");
5030 if(CODECHAL_AVC == m_standard)
5031 {
5032 m_currRefList->resRefMbCodeBuffer = m_resMbCodeSurface;
5033 m_currRefList->resRefMvDataBuffer = m_resMvDataSurface;
5034 }
5035 }
5036
5037 m_trackedBuf->SetAllocationFlag(false);
5038 }
5039
5040 if (m_hwInterface->UsesRenderEngine(m_codecFunction, m_standard))
5041 {
5042 // set render engine context
5043 m_osInterface->pfnSetGpuContext(m_osInterface, m_renderContext);
5044 m_osInterface->pfnResetOsStates(m_osInterface);
5045
5046 // set all status reports to completed state
5047 InitStatusReport();
5048
5049 // on-demand sync for tracked buffer
5050 syncParams = g_cInitSyncParams;
5051 syncParams.GpuContext = m_renderContext;
5052 syncParams.bReadOnly = false;
5053 if (m_trackedBuf->GetWait() && !Mos_ResourceIsNull(&m_resMbCodeSurface))
5054 {
5055 syncParams.presSyncResource = &m_resMbCodeSurface;
5056 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
5057 m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
5058 }
5059
5060 // Call ENC Kernels
5061 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(ExecuteKernelFunctions(),
5062 "ENC failed.");
5063 }
5064 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
5065 }
5066
5067 if (m_mfeEnabled == false || encodeParams->ExecCodecFunction == CODECHAL_FUNCTION_PAK
5068 || encodeParams->ExecCodecFunction == CODECHAL_FUNCTION_FEI_PAK)
5069 {
5070 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_START,
5071 &encodeParams->ExecCodecFunction, sizeof(encodeParams->ExecCodecFunction),
5072 nullptr, 0);
5073 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mos_Solo_PreProcessEncode(m_osInterface, &m_resBitstreamBuffer, &m_reconSurface));
5074
5075 if (CodecHalUsesVideoEngine(m_codecFunction))
5076 {
5077 // Set to video context
5078 m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext);
5079 m_osInterface->pfnResetOsStates(m_osInterface);
5080 m_currPass = 0;
5081
5082 for (m_currPass = 0; m_currPass <= m_numPasses; m_currPass++)
5083 {
5084 m_firstTaskInPhase = (m_currPass == 0);
5085 m_lastTaskInPhase = (m_currPass == m_numPasses);
5086
5087 if (m_firstTaskInPhase || !m_singleTaskPhaseSupported)
5088 CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
5089
5090 // Setup picture level PAK commands
5091 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(ExecutePictureLevel(),
5092 "Picture level encoding failed.");
5093
5094 // Setup slice level PAK commands
5095 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(ExecuteSliceLevel(),
5096 "Slice level encoding failed.");
5097
5098 m_lastTaskInPhase = false;
5099 }
5100 }
5101
5102 m_prevRawSurface = *m_rawSurfaceToPak;
5103
5104 // User Feature Key Reporting - only happens after first frame
5105 if (m_firstFrame == true)
5106 {
5107 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(UserFeatureKeyReport(),
5108 "Reporting user feature keys failed.");
5109 }
5110
5111 m_currRecycledBufIdx =
5112 (m_currRecycledBufIdx + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
5113
5114 if (m_currRecycledBufIdx == 0)
5115 {
5116 MOS_ZeroMemory(m_recycledBufStatusNum, sizeof(m_recycledBufStatusNum));
5117 }
5118
5119 m_currLaDataIdx = (m_currLaDataIdx + 1) % m_numLaDataEntry;
5120
5121 // Flush encode eStatus buffer
5122 CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(ResetStatusReport(),
5123 "Flushing encode eStatus buffer failed.");
5124
5125 if (m_firstFrame == false && m_firstTwoFrames == true)
5126 {
5127 m_firstTwoFrames = false;
5128 }
5129 m_firstFrame = false;
5130
5131 CODECHAL_ENCODE_CHK_STATUS_RETURN(Mos_Solo_PostProcessEncode(m_osInterface, &m_resBitstreamBuffer, &m_reconSurface));
5132 MOS_TraceEventExt(EVENT_CODECHAL_EXECUTE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
5133 }
5134 return eStatus;
5135 }
5136
GetNumBrcPakPasses(uint16_t usBRCPrecision)5137 uint8_t CodechalEncoderState::GetNumBrcPakPasses(uint16_t usBRCPrecision)
5138 {
5139 uint8_t numBRCPAKPasses = CODECHAL_ENCODE_BRC_DEFAULT_NUM_PASSES;
5140
5141 switch (usBRCPrecision)
5142 {
5143 case 0:
5144 case 2: numBRCPAKPasses = CODECHAL_ENCODE_BRC_DEFAULT_NUM_PASSES;
5145 break;
5146
5147 case 1: numBRCPAKPasses = CODECHAL_ENCODE_BRC_MINIMUM_NUM_PASSES;
5148 break;
5149
5150 case 3: numBRCPAKPasses = CODECHAL_ENCODE_BRC_MAXIMUM_NUM_PASSES;
5151 break;
5152
5153 default: CODECHAL_ENCODE_ASSERT("Invalid BRC Precision value in Pic Params.");
5154 numBRCPAKPasses = CODECHAL_ENCODE_BRC_DEFAULT_NUM_PASSES;
5155 break;
5156 }
5157
5158 return numBRCPAKPasses;
5159 }
5160
CodechalEncoderGenState(CodechalEncoderState * encoder)5161 CodechalEncoderGenState::CodechalEncoderGenState(CodechalEncoderState* encoder)
5162 {
5163 CODECHAL_ENCODE_ASSERT(encoder);
5164 m_encoder = encoder;
5165 m_hwInterface = encoder->GetHwInterface();
5166 m_osInterface = encoder->GetOsInterface();
5167 m_miInterface = encoder->m_miInterface;
5168 m_renderEngineInterface = encoder->m_renderEngineInterface;
5169 m_stateHeapInterface = encoder->m_stateHeapInterface;
5170 }
5171
CodechalEncoderState(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)5172 CodechalEncoderState::CodechalEncoderState(
5173 CodechalHwInterface* hwInterface,
5174 CodechalDebugInterface* debugInterface,
5175 PCODECHAL_STANDARD_INFO standardInfo):
5176 Codechal((hwInterface==nullptr) ?nullptr:hwInterface->m_hwInterfaceNext, debugInterface)
5177 {
5178 m_hwInterface = hwInterface;
5179 pfnGetKernelHeaderAndSize = nullptr;
5180 // Add Null checks here for all interfaces.
5181 CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
5182 m_mfxInterface = m_hwInterface->GetMfxInterface();
5183 m_hcpInterface = m_hwInterface->GetHcpInterface();
5184 m_hucInterface = m_hwInterface->GetHucInterface();
5185 m_vdencInterface = m_hwInterface->GetVdencInterface();
5186 m_miInterface = hwInterface->GetMiInterface();
5187 m_renderEngineInterface = hwInterface->GetRenderInterface();
5188 CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(m_renderEngineInterface);
5189 m_stateHeapInterface = m_renderEngineInterface->m_stateHeapInterface;
5190 CODECHAL_ENCODE_ASSERT(m_renderEngineInterface->GetHwCaps());
5191
5192 m_osInterface = hwInterface->GetOsInterface();
5193 CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
5194 m_userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
5195 m_osInterface->pfnGetPlatform(m_osInterface, &m_platform);
5196 m_skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
5197 m_waTable = m_osInterface->pfnGetWaTable(m_osInterface);
5198 m_gtSystemInfo = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
5199 m_videoGpuNode = MOS_GPU_NODE_MAX;
5200 m_renderContext = MOS_GPU_CONTEXT_INVALID_HANDLE;
5201 m_videoContext = MOS_GPU_CONTEXT_INVALID_HANDLE;
5202
5203 m_vdencEnabled = CodecHalUsesVdencEngine(standardInfo->CodecFunction);
5204 m_codecFunction = standardInfo->CodecFunction;
5205
5206 m_vdencMeKernelState = MHW_KERNEL_STATE();
5207 m_vdencStreaminKernelState = MHW_KERNEL_STATE();
5208 m_vdencMeKernelStateRAB = MHW_KERNEL_STATE();
5209 m_vdencStreaminKernelStateRAB = MHW_KERNEL_STATE();
5210
5211 for (auto i = 0; i < CODEC_NUM_FIELDS_PER_FRAME; i++)
5212 {
5213 m_scaling2xKernelStates[i] = MHW_KERNEL_STATE();
5214 m_scaling4xKernelStates[i] = MHW_KERNEL_STATE();
5215 }
5216 for (auto i = 0; i < CODECHAL_ENCODE_ME_IDX_NUM; i++)
5217 {
5218 m_meKernelStates[i] = MHW_KERNEL_STATE();
5219 }
5220
5221 MOS_ZeroMemory(&m_encodeParams, sizeof(m_encodeParams));
5222 MOS_ZeroMemory(&m_resHwCount, sizeof(m_resHwCount));
5223 MOS_ZeroMemory(&m_rawSurface, sizeof(m_rawSurface)); // Pointer to MOS_SURFACE of raw surface
5224 MOS_ZeroMemory(&m_reconSurface, sizeof(m_reconSurface)); // Pointer to MOS_SURFACE of reconstructed surface
5225 MOS_ZeroMemory(&m_resBitstreamBuffer, sizeof(m_resBitstreamBuffer)); // Pointer to MOS_SURFACE of bitstream surface
5226 MOS_ZeroMemory(&m_resMbCodeSurface, sizeof(m_resMbCodeSurface)); // Pointer to MOS_SURFACE of MbCode surface
5227 MOS_ZeroMemory(&m_resMvDataSurface, sizeof(m_resMvDataSurface)); // Pointer to MOS_SURFACE of MvData surface
5228
5229 MOS_ZeroMemory(&m_resSyncObjectRenderContextInUse, sizeof(m_resSyncObjectRenderContextInUse));
5230 MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse));
5231 MOS_ZeroMemory(&m_encodeStatusBuf, sizeof(m_encodeStatusBuf)); // Stores all the status_query related data for PAK engine
5232 MOS_ZeroMemory(&m_encodeStatusBufRcs, sizeof(m_encodeStatusBufRcs)); // Stores all the status_query related data for render ring (RCS)
5233 MOS_ZeroMemory(&m_imgStatusControlBuffer, sizeof(m_imgStatusControlBuffer)); // Stores image eStatus control data
5234 MOS_ZeroMemory(&m_atomicScratchBuf, sizeof(m_atomicScratchBuf)); // Stores atomic operands and result
5235 MOS_ZeroMemory(&m_bsBuffer, sizeof(m_bsBuffer));
5236
5237 MOS_ZeroMemory(&m_resVdencCmdInitializerDmemBuffer, sizeof(m_resVdencCmdInitializerDmemBuffer));
5238 MOS_ZeroMemory(&m_resVdencCmdInitializerDataBuffer, sizeof(m_resVdencCmdInitializerDataBuffer));
5239
5240 MOS_ZeroMemory(&m_resDistortionBuffer, sizeof(m_resDistortionBuffer)); // MBEnc Distortion Buffer
5241 for (auto i = 0; i < CODECHAL_ENCODE_MAX_NUM_MAD_BUFFERS; i++)
5242 {
5243 MOS_ZeroMemory(&m_resMadDataBuffer[i], sizeof(m_resMadDataBuffer[i])); // Buffers to store Mean of Absolute Differences
5244 }
5245 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
5246 {
5247 MOS_ZeroMemory(&m_sliceMapSurface[i], sizeof(m_sliceMapSurface[i]));
5248 }
5249
5250 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
5251 {
5252 MOS_ZeroMemory(&m_resVdencStreamInBuffer[i], sizeof(m_resVdencStreamInBuffer[i]));
5253 }
5254 MOS_ZeroMemory(&m_resPakMmioBuffer, sizeof(m_resPakMmioBuffer));
5255 MOS_ZeroMemory(&m_resHucErrorStatusBuffer, sizeof(m_resHucErrorStatusBuffer));
5256 MOS_ZeroMemory(&m_resHucStatus2Buffer, sizeof(m_resHucStatus2Buffer));
5257 MOS_ZeroMemory(&m_resHucFwBuffer, sizeof(m_resHucFwBuffer));
5258
5259 MOS_ZeroMemory(&m_resDeblockingFilterRowStoreScratchBuffer, sizeof(m_resDeblockingFilterRowStoreScratchBuffer)); // Handle of deblock row store surface
5260 MOS_ZeroMemory(&m_resMPCRowStoreScratchBuffer, sizeof(m_resMPCRowStoreScratchBuffer)); // Handle of mpc row store surface
5261 for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
5262 {
5263 MOS_ZeroMemory(&m_resStreamOutBuffer[i], sizeof(m_resStreamOutBuffer[i])); // Handle of streamout data surface
5264 }
5265
5266 MOS_ZeroMemory(&m_scaling4xBindingTable, sizeof(m_scaling4xBindingTable));
5267 MOS_ZeroMemory(&m_scaling2xBindingTable, sizeof(m_scaling2xBindingTable));
5268 for (auto i = 0; i < CODECHAL_ENCODE_VME_BBUF_NUM; i++)
5269 {
5270 MOS_ZeroMemory(&m_scalingBBUF[i], sizeof(m_scalingBBUF[i])); // This Batch Buffer is used for scaling kernel.
5271 }
5272 MOS_ZeroMemory(&m_flatnessCheckSurface, sizeof(m_flatnessCheckSurface));
5273 MOS_ZeroMemory(&m_resMbStatisticsSurface, sizeof(m_resMbStatisticsSurface));
5274 MOS_ZeroMemory(&m_resMbStatsBuffer, sizeof(m_resMbStatsBuffer));
5275
5276 MOS_ZeroMemory(&m_meBindingTable, sizeof(m_meBindingTable));
5277
5278 MOS_ZeroMemory(&m_vdencMeKernelBindingTable, sizeof(m_vdencMeKernelBindingTable));
5279
5280 MOS_ZeroMemory(&m_vdencStreaminKernelBindingTable, sizeof(m_vdencStreaminKernelBindingTable));
5281 }
5282
~CodechalEncoderState()5283 CodechalEncoderState::~CodechalEncoderState()
5284 {
5285 if (m_gpuCtxCreatOpt)
5286 {
5287 MOS_Delete(m_gpuCtxCreatOpt);
5288 m_gpuCtxCreatOpt = nullptr;
5289 }
5290
5291 DestroyMDFResources();
5292
5293 if (m_perfProfiler)
5294 {
5295 MediaPerfProfiler::Destroy(m_perfProfiler, (void*)this, m_osInterface);
5296 m_perfProfiler = nullptr;
5297 }
5298
5299 // Destroy HW interface objects (GSH, SSH, etc)
5300 if (m_hwInterface != nullptr)
5301 {
5302 MOS_Delete(m_hwInterface);
5303 m_hwInterface = nullptr;
5304 Codechal::m_hwInterface = nullptr;
5305 }
5306 }
5307
SetupWalkerContext(MOS_COMMAND_BUFFER * cmdBuffer,SendKernelCmdsParams * params)5308 MOS_STATUS CodechalEncoderState::SetupWalkerContext(
5309 MOS_COMMAND_BUFFER* cmdBuffer,
5310 SendKernelCmdsParams* params)
5311 {
5312 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
5313
5314 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
5315 CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);
5316
5317 MOS_RESOURCE* dsh = params->pKernelState->m_dshRegion.GetResource();
5318 CODECHAL_ENCODE_CHK_NULL_RETURN(dsh);
5319
5320 // Add Media VFE command
5321 CODECHAL_ENCODE_CHK_STATUS_RETURN(AddMediaVfeCmd(cmdBuffer, params));
5322
5323 // Add Media Curbe Load command
5324 if (params->pKernelState->KernelParams.iCurbeLength)
5325 {
5326 MHW_CURBE_LOAD_PARAMS curbeLoadParams;
5327 MOS_ZeroMemory(&curbeLoadParams, sizeof(curbeLoadParams));
5328 curbeLoadParams.pKernelState = params->pKernelState;
5329 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaCurbeLoadCmd(cmdBuffer, &curbeLoadParams));
5330
5331 HalOcaInterface::OnIndirectState(
5332 *cmdBuffer,
5333 (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext,
5334 dsh,
5335 params->pKernelState->m_dshRegion.GetOffset() + params->pKernelState->dwCurbeOffset,
5336 false,
5337 params->pKernelState->KernelParams.iCurbeLength);
5338 }
5339
5340 uint32_t InterfaceDescriptorTotalLength = m_stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData();
5341 uint32_t InterfaceDescriptorDataStartOffset = MOS_ALIGN_CEIL(
5342 params->pKernelState->m_dshRegion.GetOffset() + params->pKernelState->dwIdOffset,
5343 m_stateHeapInterface->pStateHeapInterface->GetIdAlignment());
5344
5345 // Media_State_Flush should be used before MEDIA_INTERFACE_DESCRIPTOR_LOAD to ensure that the temporary Interface Descriptor storage is cleared
5346 MHW_MEDIA_STATE_FLUSH_PARAM mediaStateFlushParams;
5347 MOS_ZeroMemory(&mediaStateFlushParams, sizeof(mediaStateFlushParams));
5348 mediaStateFlushParams.bFlushToGo = true;
5349 mediaStateFlushParams.ui8InterfaceDescriptorOffset = (uint8_t)InterfaceDescriptorDataStartOffset;
5350 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMediaStateFlush(cmdBuffer, nullptr, &mediaStateFlushParams));
5351
5352 MHW_ID_LOAD_PARAMS idLoadParams;
5353 MOS_ZeroMemory(&idLoadParams, sizeof(idLoadParams));
5354 idLoadParams.pKernelState = params->pKernelState;
5355 idLoadParams.dwNumKernelsLoaded = 1;
5356 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaIDLoadCmd(cmdBuffer, &idLoadParams));
5357
5358 HalOcaInterface::OnIndirectState(
5359 *cmdBuffer,
5360 (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext,
5361 dsh,
5362 InterfaceDescriptorDataStartOffset,
5363 false,
5364 InterfaceDescriptorTotalLength);
5365
5366 return eStatus;
5367 }
5368
ResolveMetaData(PMOS_RESOURCE pHwLayoutMetaData,PMOS_RESOURCE pResolvedLayoutMetadata)5369 MOS_STATUS CodechalEncoderState::ResolveMetaData(
5370 PMOS_RESOURCE pHwLayoutMetaData,
5371 PMOS_RESOURCE pResolvedLayoutMetadata)
5372 {
5373 CODECHAL_ENCODE_FUNCTION_ENTER;
5374 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
5375
5376 MOS_COMMAND_BUFFER cmdBuffer;
5377 MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
5378 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
5379
5380 MHW_MI_COPY_MEM_MEM_PARAMS CpyParams;
5381 CpyParams.presSrc = pHwLayoutMetaData;
5382 CpyParams.presDst = pResolvedLayoutMetadata;
5383
5384 int bufSize = m_metaDataOffset.dwMetaDataSize + m_numSlices * m_metaDataOffset.dwMetaDataSubRegionSize;
5385 for (int i = 0; i < bufSize; i = i + 4)
5386 {
5387 CpyParams.dwSrcOffset = i;
5388 CpyParams.dwDstOffset = i;
5389 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(&cmdBuffer, &CpyParams));
5390 }
5391
5392 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
5393 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
5394 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, false));
5395
5396 return eStatus;
5397 }
5398
ReportErrorFlag(PMOS_RESOURCE pMetadataBuffer,uint32_t size,uint32_t offset,uint32_t flag)5399 MOS_STATUS CodechalEncoderState::ReportErrorFlag(
5400 PMOS_RESOURCE pMetadataBuffer,
5401 uint32_t size,
5402 uint32_t offset,
5403 uint32_t flag)
5404 {
5405 CODECHAL_ENCODE_FUNCTION_ENTER;
5406
5407 m_metaDataOffset.dwMetaDataSize = size; // init common
5408
5409 MOS_COMMAND_BUFFER cmdBuffer;
5410 MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
5411 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
5412
5413 MHW_MI_STORE_DATA_PARAMS storeDataParams;
5414 MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
5415
5416 // Report error flags to metadata buffer
5417 storeDataParams.pOsResource = pMetadataBuffer;
5418 storeDataParams.dwResourceOffset = offset;
5419 storeDataParams.dwValue = flag;
5420 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams));
5421
5422 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
5423 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
5424 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, false));
5425
5426 return MOS_STATUS_SUCCESS;
5427 }
5428
StoreHuCStatus2Report(PMOS_COMMAND_BUFFER cmdBuffer)5429 MOS_STATUS CodechalEncoderState::StoreHuCStatus2Report(PMOS_COMMAND_BUFFER cmdBuffer)
5430 {
5431 CODECHAL_ENCODE_FUNCTION_ENTER;
5432
5433 #if (_DEBUG || _RELEASE_INTERNAL)
5434 if (m_swBrcMode != nullptr)
5435 {
5436 // Skip check if SW BRC DLL path
5437 return MOS_STATUS_SUCCESS;
5438 }
5439 #endif // _DEBUG || _RELEASE_INTERNAL
5440
5441 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
5442
5443 EncodeStatusBuffer encodeStatusBuf = m_encodeStatusBuf;
5444
5445 uint32_t baseOffset =
5446 (encodeStatusBuf.wCurrIndex * encodeStatusBuf.dwReportSize) + sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource
5447
5448 // store HUC_STATUS2 register
5449 MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
5450 MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
5451 storeRegParams.presStoreBuffer = &encodeStatusBuf.resStatusBuffer;
5452 storeRegParams.dwOffset = baseOffset + encodeStatusBuf.dwHuCStatus2RegOffset;
5453 storeRegParams.dwRegister = m_hucInterface->GetMmioRegisters(m_vdboxIndex)->hucStatus2RegOffset;
5454 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &storeRegParams));
5455
5456 return MOS_STATUS_SUCCESS;
5457 }
5458
5459 #if USE_CODECHAL_DEBUG_TOOL
DumpMbEncPakOutput(PCODEC_REF_LIST currRefList,CodechalDebugInterface * debugInterface)5460 MOS_STATUS CodechalEncoderState::DumpMbEncPakOutput(PCODEC_REF_LIST currRefList, CodechalDebugInterface* debugInterface)
5461 {
5462 CODECHAL_ENCODE_FUNCTION_ENTER;
5463 CODECHAL_ENCODE_CHK_NULL_RETURN(currRefList);
5464 CODECHAL_ENCODE_CHK_NULL_RETURN(debugInterface);
5465
5466 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
5467 &currRefList->resRefMbCodeBuffer,
5468 CodechalDbgAttr::attrOutput,
5469 "MbCode",
5470 m_picWidthInMb * m_frameFieldHeightInMb * 64,
5471 CodecHal_PictureIsBottomField(currRefList->RefPic) ? m_frameFieldHeightInMb * m_picWidthInMb * 64 : 0,
5472 (m_codecFunction != CODECHAL_FUNCTION_HYBRIDPAK) ?
5473 CODECHAL_MEDIA_STATE_ENC_NORMAL : CODECHAL_MEDIA_STATE_HYBRID_PAK_P2));
5474
5475 if (m_mvDataSize)
5476 {
5477 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
5478 &currRefList->resRefMvDataBuffer,
5479 CodechalDbgAttr::attrOutput,
5480 "MbData",
5481 m_picWidthInMb * m_frameFieldHeightInMb * (32 * 4),
5482 CodecHal_PictureIsBottomField(currRefList->RefPic) ? MOS_ALIGN_CEIL(m_frameFieldHeightInMb * m_picWidthInMb * (32 * 4), 0x1000) : 0,
5483 (m_codecFunction != CODECHAL_FUNCTION_HYBRIDPAK) ?
5484 CODECHAL_MEDIA_STATE_ENC_NORMAL : CODECHAL_MEDIA_STATE_HYBRID_PAK_P2));
5485 }
5486 if (CodecHalIsFeiEncode(m_codecFunction))
5487 {
5488 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
5489 &m_resDistortionBuffer,
5490 CodechalDbgAttr::attrOutput,
5491 "DistortionSurf",
5492 m_picWidthInMb * m_frameFieldHeightInMb * 48,
5493 CodecHal_PictureIsBottomField(currRefList->RefPic) ? MOS_ALIGN_CEIL(m_frameFieldHeightInMb * m_picWidthInMb * 48, 0x1000) : 0,
5494 (m_codecFunction != CODECHAL_FUNCTION_HYBRIDPAK) ?
5495 CODECHAL_MEDIA_STATE_ENC_NORMAL : CODECHAL_MEDIA_STATE_HYBRID_PAK_P2));
5496 }
5497 return MOS_STATUS_SUCCESS;
5498 }
5499
AddBufferWithIMMValue(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_RESOURCE presStoreBuffer,uint32_t offset,uint32_t value,bool bAdd)5500 MOS_STATUS CodechalEncoderState::AddBufferWithIMMValue(
5501 PMOS_COMMAND_BUFFER cmdBuffer,
5502 PMOS_RESOURCE presStoreBuffer,
5503 uint32_t offset,
5504 uint32_t value,
5505 bool bAdd)
5506 {
5507 MHW_MI_STORE_REGISTER_MEM_PARAMS StoreRegParams;
5508 MHW_MI_LOAD_REGISTER_REG_PARAMS LoadRegRegParams;
5509 MHW_MI_LOAD_REGISTER_IMM_PARAMS LoadRegisterImmParams;
5510 MHW_MI_FLUSH_DW_PARAMS FlushDwParams;
5511 MHW_MI_MATH_PARAMS MiMathParams;
5512 MHW_MI_ALU_PARAMS MiAluParams[4];
5513 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
5514
5515 CODECHAL_ENCODE_FUNCTION_ENTER;
5516
5517 if (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex())
5518 {
5519 CODECHAL_ENCODE_ASSERTMESSAGE("ERROR - vdbox index exceed the maximum");
5520 eStatus = MOS_STATUS_INVALID_PARAMETER;
5521 return eStatus;
5522 }
5523
5524 auto pMmioRegistersMfx = m_mfxInterface->GetMmioRegisters(m_vdboxIndex);
5525 auto pMmioRegistersHcp = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
5526
5527 MOS_ZeroMemory(&FlushDwParams, sizeof(FlushDwParams));
5528 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &FlushDwParams));
5529
5530 MOS_ZeroMemory(&LoadRegRegParams, sizeof(LoadRegRegParams));
5531
5532 MHW_MI_LOAD_REGISTER_MEM_PARAMS miLoadRegMemParams;
5533 MOS_ZeroMemory(&miLoadRegMemParams, sizeof(miLoadRegMemParams));
5534
5535 miLoadRegMemParams.presStoreBuffer = presStoreBuffer;
5536 miLoadRegMemParams.dwOffset = offset;
5537 miLoadRegMemParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0LoOffset;
5538 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(cmdBuffer, &miLoadRegMemParams));
5539
5540 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5541 LoadRegisterImmParams.dwData = 0;
5542 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0HiOffset;
5543 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5544 cmdBuffer,
5545 &LoadRegisterImmParams));
5546
5547 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5548 LoadRegisterImmParams.dwData = value;
5549 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4LoOffset;
5550 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5551 cmdBuffer,
5552 &LoadRegisterImmParams));
5553 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5554 LoadRegisterImmParams.dwData = 0;
5555 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4HiOffset;
5556 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5557 cmdBuffer,
5558 &LoadRegisterImmParams));
5559
5560 MOS_ZeroMemory(&MiMathParams, sizeof(MiMathParams));
5561 MOS_ZeroMemory(&MiAluParams, sizeof(MiAluParams));
5562 // load srcA, reg0
5563 MiAluParams[0].AluOpcode = MHW_MI_ALU_LOAD;
5564 MiAluParams[0].Operand1 = MHW_MI_ALU_SRCA;
5565 MiAluParams[0].Operand2 = MHW_MI_ALU_GPREG0;
5566 // load srcB, reg4
5567 MiAluParams[1].AluOpcode = MHW_MI_ALU_LOAD;
5568 MiAluParams[1].Operand1 = MHW_MI_ALU_SRCB;
5569 MiAluParams[1].Operand2 = MHW_MI_ALU_GPREG4;
5570
5571 if (bAdd)
5572 {
5573 // add srcA, srcB
5574 MiAluParams[2].AluOpcode = MHW_MI_ALU_ADD;
5575 }
5576 else
5577 {
5578 // sub srcA, srcB
5579 MiAluParams[2].AluOpcode = MHW_MI_ALU_SUB;
5580 }
5581
5582 // store reg0, ACCU
5583 MiAluParams[3].AluOpcode = MHW_MI_ALU_STORE;
5584 MiAluParams[3].Operand1 = MHW_MI_ALU_GPREG0;
5585 MiAluParams[3].Operand2 = MHW_MI_ALU_ACCU;
5586
5587 MiMathParams.pAluPayload = MiAluParams;
5588 MiMathParams.dwNumAluParams = 4; // four ALU commands needed for this substract opertaion. see following ALU commands.
5589 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(
5590 cmdBuffer,
5591 &MiMathParams));
5592
5593 // update the value
5594 MOS_ZeroMemory(&StoreRegParams, sizeof(StoreRegParams));
5595 StoreRegParams.presStoreBuffer = presStoreBuffer;
5596 StoreRegParams.dwOffset = offset;
5597 StoreRegParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0LoOffset;
5598 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &StoreRegParams));
5599
5600 return eStatus;
5601 }
5602
SetBufferWithIMMValueU16(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_RESOURCE presStoreBuffer,uint32_t offset,uint32_t value,bool bSecond)5603 MOS_STATUS CodechalEncoderState::SetBufferWithIMMValueU16(
5604 PMOS_COMMAND_BUFFER cmdBuffer,
5605 PMOS_RESOURCE presStoreBuffer,
5606 uint32_t offset,
5607 uint32_t value,
5608 bool bSecond)
5609 {
5610 MHW_MI_STORE_REGISTER_MEM_PARAMS StoreRegParams;
5611 MHW_MI_LOAD_REGISTER_REG_PARAMS LoadRegRegParams;
5612 MHW_MI_LOAD_REGISTER_IMM_PARAMS LoadRegisterImmParams;
5613 MHW_MI_FLUSH_DW_PARAMS FlushDwParams;
5614 MHW_MI_MATH_PARAMS MiMathParams;
5615 MHW_MI_ALU_PARAMS MiAluParams[4]; // is used twice
5616 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
5617
5618 CODECHAL_ENCODE_FUNCTION_ENTER;
5619
5620 if (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex())
5621 {
5622 CODECHAL_ENCODE_ASSERTMESSAGE("ERROR - vdbox index exceed the maximum");
5623 eStatus = MOS_STATUS_INVALID_PARAMETER;
5624 return eStatus;
5625 }
5626
5627 auto pMmioRegistersMfx = m_mfxInterface->GetMmioRegisters(m_vdboxIndex);
5628 auto pMmioRegistersHcp = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
5629
5630 MOS_ZeroMemory(&FlushDwParams, sizeof(FlushDwParams));
5631 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &FlushDwParams));
5632
5633 MOS_ZeroMemory(&LoadRegRegParams, sizeof(LoadRegRegParams));
5634
5635 MHW_MI_LOAD_REGISTER_MEM_PARAMS miLoadRegMemParams;
5636 MOS_ZeroMemory(&miLoadRegMemParams, sizeof(miLoadRegMemParams));
5637
5638 miLoadRegMemParams.presStoreBuffer = presStoreBuffer;
5639 miLoadRegMemParams.dwOffset = offset;
5640 miLoadRegMemParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0LoOffset;
5641 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(cmdBuffer, &miLoadRegMemParams));
5642
5643 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5644 LoadRegisterImmParams.dwData = 0;
5645 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0HiOffset;
5646 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5647 cmdBuffer,
5648 &LoadRegisterImmParams));
5649
5650 uint32_t mask = bSecond ? 0xffff : 0xffff0000;
5651 value = bSecond ? value << 16 : value;
5652
5653 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5654 LoadRegisterImmParams.dwData = mask;
5655 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4LoOffset;
5656 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5657 cmdBuffer,
5658 &LoadRegisterImmParams));
5659 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5660 LoadRegisterImmParams.dwData = 0;
5661 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4HiOffset;
5662 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5663 cmdBuffer,
5664 &LoadRegisterImmParams));
5665
5666 MOS_ZeroMemory(&MiMathParams, sizeof(MiMathParams));
5667 MOS_ZeroMemory(&MiAluParams, sizeof(MiAluParams));
5668 // load srcA, reg0
5669 MiAluParams[0].AluOpcode = MHW_MI_ALU_LOAD;
5670 MiAluParams[0].Operand1 = MHW_MI_ALU_SRCA;
5671 MiAluParams[0].Operand2 = MHW_MI_ALU_GPREG0;
5672 // load srcB, reg4
5673 MiAluParams[1].AluOpcode = MHW_MI_ALU_LOAD;
5674 MiAluParams[1].Operand1 = MHW_MI_ALU_SRCB;
5675 MiAluParams[1].Operand2 = MHW_MI_ALU_GPREG4;
5676
5677 // and srcA, srcB
5678 MiAluParams[2].AluOpcode = MHW_MI_ALU_AND;
5679
5680 // store reg0, ACCU
5681 MiAluParams[3].AluOpcode = MHW_MI_ALU_STORE;
5682 MiAluParams[3].Operand1 = MHW_MI_ALU_GPREG0;
5683 MiAluParams[3].Operand2 = MHW_MI_ALU_ACCU;
5684
5685 MiMathParams.pAluPayload = MiAluParams;
5686 MiMathParams.dwNumAluParams = 4;
5687 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(
5688 cmdBuffer,
5689 &MiMathParams));
5690
5691 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5692 LoadRegisterImmParams.dwData = value;
5693 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4LoOffset;
5694 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5695 cmdBuffer,
5696 &LoadRegisterImmParams));
5697 MOS_ZeroMemory(&LoadRegisterImmParams, sizeof(LoadRegisterImmParams));
5698 LoadRegisterImmParams.dwData = 0;
5699 LoadRegisterImmParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister4HiOffset;
5700 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
5701 cmdBuffer,
5702 &LoadRegisterImmParams));
5703
5704 // load srcA, reg0
5705 MiAluParams[0].AluOpcode = MHW_MI_ALU_LOAD;
5706 MiAluParams[0].Operand1 = MHW_MI_ALU_SRCA;
5707 MiAluParams[0].Operand2 = MHW_MI_ALU_GPREG0;
5708 // load srcB, reg4
5709 MiAluParams[1].AluOpcode = MHW_MI_ALU_LOAD;
5710 MiAluParams[1].Operand1 = MHW_MI_ALU_SRCB;
5711 MiAluParams[1].Operand2 = MHW_MI_ALU_GPREG4;
5712
5713 // or srcA, srcB
5714 MiAluParams[2].AluOpcode = MHW_MI_ALU_OR;
5715
5716 // store reg0, ACCU
5717 MiAluParams[3].AluOpcode = MHW_MI_ALU_STORE;
5718 MiAluParams[3].Operand1 = MHW_MI_ALU_GPREG0;
5719 MiAluParams[3].Operand2 = MHW_MI_ALU_ACCU;
5720
5721 MiMathParams.pAluPayload = MiAluParams;
5722 MiMathParams.dwNumAluParams = 4; // 4 ALU commands needed for this opertaion. see following ALU commands.
5723 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(
5724 cmdBuffer,
5725 &MiMathParams));
5726
5727 // update the value
5728 MOS_ZeroMemory(&StoreRegParams, sizeof(StoreRegParams));
5729 StoreRegParams.presStoreBuffer = presStoreBuffer;
5730 StoreRegParams.dwOffset = offset;
5731 StoreRegParams.dwRegister = pMmioRegistersMfx->generalPurposeRegister0LoOffset;
5732 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &StoreRegParams));
5733
5734 return eStatus;
5735 }
5736 #endif
5737