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             &param->ps16xMeMvDataBuffer->OsResource);
283     }
284 
285     if (param->ps32xMeMvDataBuffer != nullptr)
286     {
287         m_osInterface->pfnFreeResource(
288             m_osInterface,
289             &param->ps32xMeMvDataBuffer->OsResource);
290     }
291 
292     if (param->ps4xMeDistortionBuffer != nullptr)
293     {
294         m_osInterface->pfnFreeResource(
295             m_osInterface,
296             &param->ps4xMeDistortionBuffer->OsResource);
297     }
298 
299     if (param->ps4xMeMvDataBuffer != nullptr)
300     {
301         m_osInterface->pfnFreeResource(
302             m_osInterface,
303             &param->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         &param->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(&param->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             &param->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(&param->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             &param->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(&param->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             &param->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(&param->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(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
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(&copyMemMemParams , 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             &copyMemMemParams));
3569 
3570         // VCS_GPR0_Lo = ImageStatusCtrl
3571         MHW_MI_STORE_REGISTER_MEM_PARAMS registerMemParams;
3572         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
3589 
3590         // Reset GPR4_Lo
3591         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
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(&copyMemMemParams , 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             &copyMemMemParams));
3638 
3639         // GPR0_lo = n1_lo = 0
3640         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
3647 
3648         // Reset GPR4_Lo
3649         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
3701 
3702         // GPR0_Hi = n2_hi = 1
3703         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
3710 
3711         // Reset GPR4_Lo and GPR4_Hi
3712         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
3719         MOS_ZeroMemory(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
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(&registerMemParams, 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             &registerMemParams));
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