1 /*
2 * Copyright (c) 2017-2020, 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_kernel_hme_g12.cpp
24 //! \brief    Hme kernel implementation using MDF RT for Gen12 platform
25 //!
26 #include "codechal_kernel_hme_mdf_g12.h"
27 #include "Gen12LP_hme_genx.h"
28 
29 // clang-format off
30 const uint32_t CodechalKernelHmeMdfG12::Curbe::m_initCurbe[40] =
31 {
32     0x00000000, 0x00200010, 0x00003939, 0x77a43000, 0x00000000, 0x28300000, 0x00000000, 0x00000000,
33     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
34     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
35     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
36     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
37 };
38 // clang-format on
39 
CodechalKernelHmeMdfG12(CodechalEncoderState * encoder,bool me4xDistBufferSupported)40 CodechalKernelHmeMdfG12::CodechalKernelHmeMdfG12(
41     CodechalEncoderState *encoder,
42     bool     me4xDistBufferSupported)
43         : CodechalKernelHme(encoder, me4xDistBufferSupported)
44 {
45 }
46 
~CodechalKernelHmeMdfG12()47 CodechalKernelHmeMdfG12::~CodechalKernelHmeMdfG12()
48 {
49     ReleaseResources();
50 }
51 
ReleaseResources()52 MOS_STATUS CodechalKernelHmeMdfG12::ReleaseResources()
53 {
54     CODECHAL_ENCODE_FUNCTION_ENTER;
55 
56     CODECHAL_ENCODE_CHK_NULL_RETURN(m_encoder->m_cmDev);
57 
58     DestroyYUVSurfaces(m_HME4xYUVInfo);
59     DestroyYUVSurfaces(m_HME16xYUVInfo);
60     DestroyYUVSurfaces(m_HME32xYUVInfo);
61 
62     CmDevice* &cmDev = m_encoder->m_cmDev;
63 
64     if (m_HME4xDistortionSurface)
65     {
66         cmDev->DestroySurface(m_HME4xDistortionSurface);
67         m_HME4xDistortionSurface = nullptr;
68     }
69 
70     if (m_HME4xMVSurface)
71     {
72         cmDev->DestroySurface(m_HME4xMVSurface);
73         m_HME4xMVSurface = nullptr;
74     }
75 
76     if (m_HME16xMVSurface)
77     {
78         cmDev->DestroySurface(m_HME16xMVSurface);
79         m_HME16xMVSurface = nullptr;
80     }
81 
82     if (m_HME32xMVSurface)
83     {
84         cmDev->DestroySurface(m_HME32xMVSurface);
85         m_HME32xMVSurface = nullptr;
86     }
87 
88     if (m_VdencStreamInBuffer)
89     {
90         cmDev->DestroySurface(m_VdencStreamInBuffer);
91         m_VdencStreamInBuffer = nullptr;
92     }
93 
94     if (m_SumMvandDistortionBuffer)
95     {
96         cmDev->DestroySurface(m_SumMvandDistortionBuffer);
97         m_SumMvandDistortionBuffer = nullptr;
98     }
99 
100     if (m_threadSpace4x)
101     {
102         cmDev->DestroyThreadSpace(m_threadSpace4x);
103         m_threadSpace4x = nullptr;
104     }
105 
106     if (m_threadSpace16x)
107     {
108         cmDev->DestroyThreadSpace(m_threadSpace16x);
109         m_threadSpace16x = nullptr;
110     }
111 
112     if (m_threadSpace32x)
113     {
114         cmDev->DestroyThreadSpace(m_threadSpace32x);
115         m_threadSpace32x = nullptr;
116     }
117 
118     if (m_cmKrnME4xP)
119     {
120         (cmDev->DestroyKernel(m_cmKrnME4xP));
121         m_cmKrnME4xP = nullptr;
122     }
123 
124     if (m_cmKrnME16xP)
125     {
126         (cmDev->DestroyKernel(m_cmKrnME16xP));
127         m_cmKrnME16xP = nullptr;
128     }
129 
130     if (m_cmKrnME32xP)
131     {
132         (cmDev->DestroyKernel(m_cmKrnME32xP));
133         m_cmKrnME32xP = nullptr;
134     }
135 
136     if (m_cmKrnME4xB)
137     {
138         (cmDev->DestroyKernel(m_cmKrnME4xB));
139         m_cmKrnME4xB = nullptr;
140     }
141 
142     if (m_cmKrnME16xB)
143     {
144         (cmDev->DestroyKernel(m_cmKrnME16xB));
145         m_cmKrnME16xB = nullptr;
146     }
147 
148     if (m_cmKrnME32xB)
149     {
150         (cmDev->DestroyKernel(m_cmKrnME32xB));
151         m_cmKrnME32xB = nullptr;
152     }
153 
154     if (m_cmProgramME)
155     {
156         (cmDev->DestroyProgram(m_cmProgramME));
157         m_cmProgramME = nullptr;
158     }
159 
160     return MOS_STATUS_SUCCESS;
161 }
DestroyYUVSurfaces(HmeYUVInfo & YUVInfo)162 MOS_STATUS CodechalKernelHmeMdfG12::DestroyYUVSurfaces(HmeYUVInfo& YUVInfo)
163 {
164     CmDevice* &cmDev = m_encoder->m_cmDev;
165     if (YUVInfo.SrcSurface)
166     {
167         YUVInfo.SrcSurface->NotifyUmdResourceChanged(nullptr);
168         cmDev->DestroySurface(YUVInfo.SrcSurface);
169         YUVInfo.SrcSurface = nullptr;
170     }
171 
172     for (uint8_t i = 0; i < MAX_HME_BWD_REF; i++)
173     {
174         if (YUVInfo.BwdReference[i])
175         {
176             YUVInfo.BwdReference[i]->NotifyUmdResourceChanged(nullptr);
177             cmDev->DestroySurface(YUVInfo.BwdReference[i]);
178             YUVInfo.BwdReference[i] = nullptr;
179         }
180     }
181 
182     for (uint8_t i = 0; i < MAX_HME_FWD_REF; i++)
183     {
184         if (YUVInfo.FwdReference[i])
185         {
186             YUVInfo.FwdReference[i]->NotifyUmdResourceChanged(nullptr);
187             cmDev->DestroySurface(YUVInfo.FwdReference[i]);
188             YUVInfo.FwdReference[i] = nullptr;
189         }
190     }
191 
192     return MOS_STATUS_SUCCESS;
193 }
194 
195 
Execute(CurbeParam & curbeParam,SurfaceParams & surfaceParam,HmeLevel hmeLevel)196 MOS_STATUS CodechalKernelHmeMdfG12::Execute(CurbeParam &curbeParam, SurfaceParams &surfaceParam, HmeLevel hmeLevel)
197 {
198     CODECHAL_ENCODE_FUNCTION_ENTER;
199 
200     m_4xMeInUse = Is4xMeEnabled() ? (hmeLevel & HmeLevel::hmeLevel4x) != 0 : false;
201     m_16xMeInUse = Is16xMeEnabled() ? (hmeLevel & HmeLevel::hmeLevel16x) != 0 : false;
202     m_32xMeInUse = Is32xMeEnabled() ? (hmeLevel & HmeLevel::hmeLevel32x) != 0 : false;
203 
204     CmDevice* &cmDev = m_encoder->m_cmDev;
205 
206     MOS_SecureMemcpy(&m_curbeParam, sizeof(m_curbeParam), &curbeParam, sizeof(m_curbeParam));
207     MOS_SecureMemcpy(&m_surfaceParam, sizeof(m_surfaceParam), &surfaceParam, sizeof(m_surfaceParam));
208 
209     InitKernelState((void *)GEN12LP_HME_GENX, GEN12LP_HME_GENX_SIZE);
210 
211     SetupSurfaces();
212 
213     AddPerfTag();
214 
215     uint32_t scalingFactor = m_32xMeInUse ? scalingFactor32X : m_16xMeInUse ? scalingFactor16X : scalingFactor4X;
216     uint32_t xResolution = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / scalingFactor);
217     uint32_t yResolution = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / scalingFactor);
218 
219     CmThreadSpace          *threadSpace = nullptr;
220     CmKernel               *cmKrn = nullptr;
221 
222     uint32_t threadCount = xResolution * yResolution;
223 
224     if (m_16xMeInUse)
225     {
226         if(m_encoder->m_resolutionChanged && m_threadSpace16x != nullptr)
227         {
228             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->DestroyThreadSpace(m_threadSpace16x));
229             m_threadSpace16x = nullptr;
230         }
231         if (m_threadSpace16x == nullptr)
232         {
233             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateThreadSpace(
234                                                   xResolution,
235                                                   yResolution,
236                                                   m_threadSpace16x));
237         }
238         threadSpace = m_threadSpace16x;
239         cmKrn = m_cmKrnME16x;
240     }
241     else if (m_32xMeInUse)
242     {
243         if(m_encoder->m_resolutionChanged && m_threadSpace32x != nullptr)
244         {
245             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->DestroyThreadSpace(m_threadSpace32x));
246             m_threadSpace32x = nullptr;
247         }
248         if (m_threadSpace32x == nullptr)
249         {
250             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateThreadSpace(
251                                                   xResolution,
252                                                   yResolution,
253                                                   m_threadSpace32x));
254         }
255         threadSpace = m_threadSpace32x;
256         cmKrn = m_cmKrnME32x;
257     }
258     else
259     {
260         if(m_encoder->m_resolutionChanged && m_threadSpace4x != nullptr)
261         {
262             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->DestroyThreadSpace(m_threadSpace4x));
263             m_threadSpace4x = nullptr;
264         }
265         if (m_threadSpace4x == nullptr)
266         {
267             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateThreadSpace(
268                                                   xResolution,
269                                                   yResolution,
270                                                   m_threadSpace4x));
271         }
272         threadSpace = m_threadSpace4x;
273         cmKrn = m_cmKrnME4x;
274     }
275 
276     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKrn->SetThreadCount(threadCount));
277 
278     if (m_groupIdSelectSupported)
279     {
280         threadSpace->SetMediaWalkerGroupSelect((CM_MW_GROUP_SELECT)m_groupId);
281     }
282 
283     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKrn->AssociateThreadSpace(threadSpace));
284 
285     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgs(cmKrn));
286 
287     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->AddKernel(cmKrn));
288 
289     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
290     {
291         CmEvent * event = CM_NO_EVENT;
292         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmQueue->EnqueueFast(m_encoder->m_cmTask, event));
293 
294         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->Reset());
295 
296         m_lastTaskInPhase = false;
297     }
298     else
299     {
300         m_encoder->m_cmTask->AddSync();
301     }
302 
303     return MOS_STATUS_SUCCESS;
304 }
305 
GetCmSurface(uint32_t surfaceId)306 CmSurface2D* CodechalKernelHmeMdfG12::GetCmSurface(uint32_t surfaceId)
307 {
308     switch (surfaceId)
309     {
310         case SurfaceId::me4xMvDataBuffer:
311             return m_HME4xMVSurface;
312             break;
313         case SurfaceId::me16xMvDataBuffer:
314             return m_HME16xMVSurface;
315             break;
316         case SurfaceId::me32xMvDataBuffer:
317             return m_HME32xMVSurface;
318             break;
319         case SurfaceId::me4xDistortionBuffer:
320             return m_HME4xDistortionSurface;
321             break;
322      };
323     return nullptr;
324 }
325 
AllocateResources()326 MOS_STATUS CodechalKernelHmeMdfG12::AllocateResources()
327 {
328     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
329     PMOS_SURFACE allocSurface = nullptr;
330     CmDevice* &cmDev = m_encoder->m_cmDev;
331 
332     if (m_4xMeSupported)
333     {
334         if (!m_HME4xMVSurface)
335         {
336             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateSurface2D(
337                 MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64),  // MediaBlockRW requires pitch multiple of 64 bytes when linear.,
338                 (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER),
339                 CM_SURFACE_FORMAT_A8,
340                 m_HME4xMVSurface));
341         }
342 
343         if (m_4xMeDistortionBufferSupported)
344         {
345             uint32_t ajustedHeight =
346                 m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT * SCALE_FACTOR_4x;
347             uint32_t downscaledFieldHeightInMB4x =
348                 CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(((ajustedHeight + 1) >> 1) / 4);
349             if (!m_HME4xDistortionSurface)
350             {
351                 CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateSurface2D(
352                     MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64),
353                     (2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMB4x * 4 * 10), 8)),
354                     CM_SURFACE_FORMAT_A8,
355                     m_HME4xDistortionSurface));
356             }
357         }
358     }
359 
360     if (m_16xMeSupported)
361     {
362         if (!m_HME16xMVSurface)
363         {
364             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateSurface2D(
365                 MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64),  // MediaBlockRW requires pitch multiple of 64 bytes when linear,
366                 (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER),
367                 CM_SURFACE_FORMAT_A8,
368                 m_HME16xMVSurface));
369         }
370     }
371 
372     if (m_32xMeSupported)
373     {
374         if (!m_HME32xMVSurface)
375         {
376             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateSurface2D(
377                 MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64),  // MediaBlockRW requires pitch multiple of 64 bytes when linear
378                 (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER),
379                 CM_SURFACE_FORMAT_A8,
380                 m_HME32xMVSurface));
381         }
382     }
383     return MOS_STATUS_SUCCESS;
384 }
385 
386 
InitKernelState(void * kernelIsa,uint32_t kernelIsaSize)387 MOS_STATUS CodechalKernelHmeMdfG12::InitKernelState(void *kernelIsa, uint32_t kernelIsaSize)
388 {
389     CODECHAL_ENCODE_FUNCTION_ENTER;
390 
391     if (!m_cmProgramME)
392     {
393         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->LoadProgram(kernelIsa,
394             kernelIsaSize,
395             m_cmProgramME,
396             "-nojitter"));
397 
398         if (m_vdencEnabled)
399         {
400             if (m_standard == CODECHAL_AVC)
401             {
402                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_VDENC_STREAMIN", m_cmKrnME4xP));
403                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_VDENC_STREAMIN", m_cmKrnME4xB));
404             }
405             else
406             {
407                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_VDENC_STREAMIN_HEVC", m_cmKrnME4xP));
408                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_VDENC_STREAMIN_HEVC", m_cmKrnME4xB));
409             }
410         }
411         else
412         {
413             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_P", m_cmKrnME4xP));
414             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_B", m_cmKrnME4xB));
415         }
416 
417         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_B", m_cmKrnME16xB));
418         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_B", m_cmKrnME32xB));
419 
420         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_P", m_cmKrnME16xP));
421         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgramME, "HME_P", m_cmKrnME32xP));
422     }
423 
424     if ((m_pictureCodingType == B_TYPE) && (!m_noMEKernelForPFrame))
425     {
426         m_cmKrnME4x = m_cmKrnME4xB;
427         m_cmKrnME16x = m_cmKrnME16xB;
428         m_cmKrnME32x = m_cmKrnME32xB;
429     }
430     else
431     {
432         m_cmKrnME4x = m_cmKrnME4xP;
433         m_cmKrnME16x = m_cmKrnME16xP;
434         m_cmKrnME32x = m_cmKrnME32xP;
435     }
436 
437     return MOS_STATUS_SUCCESS;
438 }
439 
SetMECurbe(Curbe & curbe)440 MOS_STATUS CodechalKernelHmeMdfG12::SetMECurbe(Curbe&  curbe)
441 {
442 
443     uint32_t  mvShiftFactor       = 0;
444     uint32_t  prevMvReadPosFactor = 0;
445     uint32_t  scaleFactor;
446     bool      useMvFromPrevStep;
447     bool      writeDistortions;
448 
449     if (m_32xMeInUse)
450     {
451         useMvFromPrevStep   = false;
452         writeDistortions    = false;
453         scaleFactor         = scalingFactor32X;
454         mvShiftFactor       = 1;
455         prevMvReadPosFactor = 0;
456     }
457     else if (m_16xMeInUse)
458     {
459         useMvFromPrevStep   = Is32xMeEnabled() ? true : false;
460         writeDistortions    = false;
461         scaleFactor         = scalingFactor16X;
462         mvShiftFactor       = 2;
463         prevMvReadPosFactor = 1;
464     }
465     else if (m_4xMeInUse)
466     {
467         useMvFromPrevStep   = Is16xMeEnabled() ? true : false;
468         writeDistortions    = true;
469         scaleFactor         = scalingFactor4X;
470         mvShiftFactor       = 2;
471         prevMvReadPosFactor = 0;
472     }
473     else
474     {
475         return MOS_STATUS_INVALID_PARAMETER;
476     }
477 
478     curbe.m_data.DW3.SubPelMode = m_curbeParam.subPelMode;
479 
480     if (m_fieldScalingOutputInterleaved)
481     {
482         curbe.m_data.DW3.SrcAccess = curbe.m_data.DW3.RefAccess = CodecHal_PictureIsField(m_curbeParam.currOriginalPic);
483         curbe.m_data.DW7.SrcFieldPolarity                = CodecHal_PictureIsBottomField(m_curbeParam.currOriginalPic);
484     }
485     curbe.m_data.DW4.PictureHeightMinus1 = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight / scaleFactor) - 1;
486     curbe.m_data.DW4.PictureWidth        = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameWidth / scaleFactor);
487     curbe.m_data.DW5.QpPrimeY            = m_curbeParam.qpPrimeY;
488     curbe.m_data.DW6.WriteDistortions    = writeDistortions;
489     curbe.m_data.DW6.UseMvFromPrevStep   = useMvFromPrevStep;
490     curbe.m_data.DW6.SuperCombineDist    = SuperCombineDist[m_curbeParam.targetUsage];
491     curbe.m_data.DW6.MaxVmvR = CodecHal_PictureIsFrame(m_curbeParam.currOriginalPic) ? m_curbeParam.maxMvLen * 4 : (m_curbeParam.maxMvLen >> 1) * 4;
492 
493     if (m_pictureCodingType == B_TYPE)
494     {
495         curbe.m_data.DW1.BiWeight             = 32;
496         curbe.m_data.DW13.NumRefIdxL1MinusOne = m_curbeParam.numRefIdxL1Minus1;
497     }
498 
499     if (m_pictureCodingType == B_TYPE || m_pictureCodingType == P_TYPE)
500     {
501         if (m_vdencEnabled && Is16xMeEnabled())
502         {
503             curbe.m_data.DW30.ActualMBHeight = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight);
504             curbe.m_data.DW30.ActualMBWidth = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameWidth);
505         }
506         curbe.m_data.DW13.NumRefIdxL0MinusOne = m_curbeParam.numRefIdxL0Minus1;
507     }
508 
509     curbe.m_data.DW13.RefStreaminCost = 5;
510     // This flag is to indicate the ROI source type instead of indicating ROI is enabled or not
511     curbe.m_data.DW13.ROIEnable = 0;
512 
513     if (!CodecHal_PictureIsFrame(m_curbeParam.currOriginalPic))
514     {
515         if (m_pictureCodingType != I_TYPE)
516         {
517             curbe.m_data.DW14.List0RefID0FieldParity = m_curbeParam.list0RefID0FieldParity;
518             curbe.m_data.DW14.List0RefID1FieldParity = m_curbeParam.list0RefID1FieldParity;
519             curbe.m_data.DW14.List0RefID2FieldParity = m_curbeParam.list0RefID2FieldParity;
520             curbe.m_data.DW14.List0RefID3FieldParity = m_curbeParam.list0RefID3FieldParity;
521             curbe.m_data.DW14.List0RefID4FieldParity = m_curbeParam.list0RefID4FieldParity;
522             curbe.m_data.DW14.List0RefID5FieldParity = m_curbeParam.list0RefID5FieldParity;
523             curbe.m_data.DW14.List0RefID6FieldParity = m_curbeParam.list0RefID6FieldParity;
524             curbe.m_data.DW14.List0RefID7FieldParity = m_curbeParam.list0RefID7FieldParity;
525         }
526         if (m_pictureCodingType == B_TYPE)
527         {
528             curbe.m_data.DW14.List1RefID0FieldParity = m_curbeParam.list1RefID0FieldParity;
529             curbe.m_data.DW14.List1RefID1FieldParity = m_curbeParam.list1RefID1FieldParity;
530         }
531     }
532     curbe.m_data.DW15.MvShiftFactor       = mvShiftFactor;
533     curbe.m_data.DW15.PrevMvReadPosFactor = prevMvReadPosFactor;
534 
535     if (m_4xMeInUse && m_curbeParam.brcEnable) // HME kernel generates Sum MV and Distortion for Hevc dual pipe
536     {
537         curbe.m_data.DW5.SumMVThreshold = m_curbeParam.sumMVThreshold; // As per kernel requirement, used only when BRC is on/LTR is on
538         curbe.m_data.DW6.BRCEnable      = m_curbeParam.brcEnable;
539     }
540 
541     // r3 & r4
542     uint8_t methodIndex = 0; // kernel requirement
543     uint8_t tableIndex  = (m_pictureCodingType == B_TYPE) ? 1 : 0;
544 
545     MOS_SecureMemcpy(&curbe.m_data.SpDelta, 14 * sizeof(uint32_t), codechalEncodeSearchPath[tableIndex][methodIndex], 14 * sizeof(uint32_t));
546 
547     return MOS_STATUS_SUCCESS;
548 }
549 
SetupSurfaces()550 MOS_STATUS CodechalKernelHmeMdfG12::SetupSurfaces()
551 {
552     if (!(m_4xMeInUse || m_16xMeInUse || m_32xMeInUse))
553     {
554         return MOS_STATUS_INVALID_PARAMETER;
555     }
556 
557     if (m_surfaceParam.vdencStreamInEnabled)
558     {
559         CODECHAL_ENCODE_CHK_NULL_RETURN(m_surfaceParam.meVdencStreamInBuffer);
560     }
561     else
562     {
563         CODECHAL_ENCODE_CHK_NULL_RETURN(m_surfaceParam.meBrcDistortionBuffer);
564     }
565 
566     CmDevice* &cmDev = m_encoder->m_cmDev;
567 
568     PMOS_SURFACE currScaledSurface;
569 
570     uint32_t     refScaledBottomFieldOffset = 0;
571     bool         currFieldPicture = CodecHal_PictureIsField(*(m_surfaceParam.currOriginalPic)) ? true : false;
572     bool         currBottomField = CodecHal_PictureIsBottomField(*(m_surfaceParam.currOriginalPic)) ? true : false;
573     uint8_t      currVDirection = (!currFieldPicture) ? CODECHAL_VDIRECTION_FRAME : ((currBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD);
574 
575     HmeYUVInfo *YuvInfo = nullptr;
576 
577     if (m_32xMeInUse)
578     {
579         currScaledSurface = m_encoder->m_trackedBuf->Get32xDsSurface(CODEC_CURR_TRACKED_BUFFER);
580         YuvInfo = &m_HME32xYUVInfo;
581     }
582     else if (m_16xMeInUse)
583     {
584         currScaledSurface = m_encoder->m_trackedBuf->Get16xDsSurface(CODEC_CURR_TRACKED_BUFFER);
585         YuvInfo = &m_HME16xYUVInfo;
586     }
587     else
588     {
589         currScaledSurface = m_encoder->m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER);
590         YuvInfo = &m_HME4xYUVInfo;
591     }
592 
593     // Current Picture Y - VME
594     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->UpdateSurface2D(
595         &currScaledSurface->OsResource,
596         YuvInfo->SrcSurface));
597 
598     // Setup references 1...n
599     // LIST 0 references
600     CODEC_PICTURE refPic;
601     // NOTE; keeping some of the legacy comments below. This may help if MDF RT is extended to AVC
602 
603     // Reference height and width information should be taken from the current scaled surface rather
604     // than from the reference scaled surface in the case of PAFF.
605     MOS_SURFACE refScaledSurface = *currScaledSurface;
606     for (uint8_t refIdx = 0; refIdx <= m_surfaceParam.numRefIdxL0ActiveMinus1; refIdx++)
607     {
608         refPic = m_surfaceParam.refL0List[refIdx];
609 
610         if (!CodecHal_PictureIsInvalid(refPic) && m_surfaceParam.picIdx[refPic.FrameIdx].bValid)
611         {
612             bool    refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? 1 : 0;
613             uint8_t refPicIdx = m_surfaceParam.picIdx[refPic.FrameIdx].ucPicIdx;
614             uint8_t scaledIdx = m_surfaceParam.refList[refPicIdx]->ucScalingIdx;
615             if (m_32xMeInUse)
616             {
617                 MOS_SURFACE* p32xSurface = m_encoder->m_trackedBuf->Get32xDsSurface(scaledIdx);
618                 if (p32xSurface != nullptr)
619                 {
620                     refScaledSurface.OsResource = p32xSurface->OsResource;
621                 }
622                 else
623                 {
624                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
625                 }
626             }
627             else if (m_16xMeInUse)
628             {
629                 MOS_SURFACE* p16xSurface = m_encoder->m_trackedBuf->Get16xDsSurface(scaledIdx);
630                 if (p16xSurface != nullptr)
631                 {
632                     refScaledSurface.OsResource = p16xSurface->OsResource;
633                 }
634                 else
635                 {
636                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
637                 }
638             }
639             else
640             {
641                 MOS_SURFACE* p4xSurface = m_encoder->m_trackedBuf->Get4xDsSurface(scaledIdx);
642                 if (p4xSurface != nullptr)
643                 {
644                     refScaledSurface.OsResource = p4xSurface->OsResource;
645                 }
646                 else
647                 {
648                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
649                 }
650             }
651             // L0 Reference Picture Y - VME
652             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->UpdateSurface2D(
653                 &refScaledSurface.OsResource,
654                 YuvInfo->FwdReference[refIdx]));
655         }
656     }
657 
658     if (YuvInfo->VMEFwdIdx)
659     {
660         CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->DestroyVmeSurfaceG7_5(YuvInfo->VMEFwdIdx));
661         YuvInfo->VMEFwdIdx = nullptr;
662     }
663     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateVmeSurfaceG7_5(
664             YuvInfo->SrcSurface,
665             YuvInfo->FwdReference,
666             YuvInfo->FwdReference,
667             (m_surfaceParam.numRefIdxL0ActiveMinus1 + 1),
668             (m_surfaceParam.numRefIdxL0ActiveMinus1 + 1),
669             YuvInfo->VMEFwdIdx));
670     // Setup references 1...n
671     // LIST 1 references
672     for (uint8_t refIdx = 0; refIdx <= m_surfaceParam.numRefIdxL1ActiveMinus1; refIdx++)
673     {
674         refPic = m_surfaceParam.refL1List[refIdx];
675         if (!CodecHal_PictureIsInvalid(refPic) && m_surfaceParam.picIdx[refPic.FrameIdx].bValid)
676         {
677             bool    refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? true : false;
678             uint8_t refPicIdx = m_surfaceParam.picIdx[refPic.FrameIdx].ucPicIdx;
679             uint8_t scaledIdx = m_surfaceParam.refList[refPicIdx]->ucScalingIdx;
680             if (m_32xMeInUse)
681             {
682                 MOS_SURFACE* p32xSurface = m_encoder->m_trackedBuf->Get32xDsSurface(scaledIdx);
683                 if (p32xSurface != nullptr)
684                 {
685                     refScaledSurface.OsResource = p32xSurface->OsResource;
686                 }
687                 else
688                 {
689                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
690                 }
691             }
692             else if (m_16xMeInUse)
693             {
694                 MOS_SURFACE* p16xSurface = m_encoder->m_trackedBuf->Get16xDsSurface(scaledIdx);
695                 if (p16xSurface != nullptr)
696                 {
697                     refScaledSurface.OsResource = p16xSurface->OsResource;
698                 }
699                 else
700                 {
701                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
702                 }
703             }
704             else
705             {
706                 MOS_SURFACE* p4xSurface = m_encoder->m_trackedBuf->Get4xDsSurface(scaledIdx);
707                 if (p4xSurface != nullptr)
708                 {
709                     refScaledSurface.OsResource = p4xSurface->OsResource;
710                 }
711                 else
712                 {
713                     CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
714                 }
715             }
716             // L1 Reference Picture Y - VME
717             CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->UpdateSurface2D(
718                 &refScaledSurface.OsResource,
719                 YuvInfo->BwdReference[refIdx]));
720         }
721     }
722     if (YuvInfo->VMEBwdIdx)
723     {
724         CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->DestroyVmeSurfaceG7_5(YuvInfo->VMEBwdIdx));
725         YuvInfo->VMEBwdIdx = nullptr;
726     }
727     //  HME L1, L1 references are provided to kernel/VME as L0
728     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateVmeSurfaceG7_5(
729         YuvInfo->SrcSurface,
730         YuvInfo->BwdReference,
731         YuvInfo->BwdReference,
732         (m_surfaceParam.numRefIdxL1ActiveMinus1 + 1),
733         (m_surfaceParam.numRefIdxL1ActiveMinus1 + 1),
734         YuvInfo->VMEBwdIdx));
735 
736     CODECHAL_MEDIA_STATE_TYPE  mediaStateType = (m_32xMeInUse) ? CODECHAL_MEDIA_STATE_32X_ME :
737         m_16xMeInUse ? CODECHAL_MEDIA_STATE_16X_ME : CODECHAL_MEDIA_STATE_4X_ME;
738 
739     if ( m_surfaceParam.vdencStreamInEnabled && mediaStateType == CODECHAL_MEDIA_STATE_4X_ME)
740     {
741         mediaStateType = CODECHAL_MEDIA_STATE_ME_VDENC_STREAMIN;
742     }
743 
744     if (mediaStateType == CODECHAL_MEDIA_STATE_ME_VDENC_STREAMIN)
745     {
746         CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->UpdateBuffer(
747                 m_surfaceParam.meVdencStreamInBuffer,
748                 m_VdencStreamInBuffer));
749     }
750 
751     if (m_curbeParam.brcEnable && m_4xMeInUse)
752     {
753         if (!m_SumMvandDistortionBuffer)
754         {
755           CODECHAL_ENCODE_CHK_STATUS_RETURN(cmDev->CreateBuffer(
756               &m_surfaceParam.meSumMvandDistortionBuffer.sResource,
757               m_SumMvandDistortionBuffer));
758         }
759     }
760 
761     return MOS_STATUS_SUCCESS;
762 }
763 
SetupKernelArgs(CmKernel * cmKrn)764 MOS_STATUS CodechalKernelHmeMdfG12::SetupKernelArgs(CmKernel *cmKrn)
765 {
766     int idx = 0;
767     Curbe curbe;
768     if (!(m_4xMeInUse || m_16xMeInUse || m_32xMeInUse))
769     {
770         return MOS_STATUS_INVALID_PARAMETER;
771     }
772     SetMECurbe(curbe);
773     cmKrn->SetKernelArg(idx++, sizeof(Curbe), &curbe);
774     HmeYUVInfo *YuvInfo = nullptr;
775     SurfaceIndex * pSurfIndex = nullptr;
776 
777     CODECHAL_DEBUG_TOOL(
778         CODECHAL_MEDIA_STATE_TYPE  mediaStateType = (m_32xMeInUse) ? CODECHAL_MEDIA_STATE_32X_ME :
779             m_16xMeInUse ? CODECHAL_MEDIA_STATE_16X_ME : CODECHAL_MEDIA_STATE_4X_ME;
780         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpMDFCurbe(
781             mediaStateType,
782             (uint8_t *)&curbe,
783             sizeof(curbe)));)
784 
785     if (m_32xMeInUse)
786     {
787         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_HME32xMVSurface->GetIndex(pSurfIndex));
788         YuvInfo = &m_HME32xYUVInfo;
789     }
790     else if (m_16xMeInUse)
791     {
792         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_HME16xMVSurface->GetIndex(pSurfIndex));
793         YuvInfo = &m_HME16xYUVInfo;
794     }
795     else
796     {
797         m_HME4xMVSurface->GetIndex(pSurfIndex);
798         YuvInfo = &m_HME4xYUVInfo;
799     }
800     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
801 
802     if (m_16xMeInUse && Is32xMeEnabled())
803     {
804         // Pass 32x MV to 16x ME operation
805         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_HME32xMVSurface->GetIndex(pSurfIndex));
806 
807     }
808     else if (Is16xMeEnabled() && !m_32xMeInUse)
809     {
810         // Pass 16x MV to 4x ME
811         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_HME16xMVSurface->GetIndex(pSurfIndex));
812     }
813     // else pass same surface index as dummy
814     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
815 
816     // Insert Distortion buffers only for 4xMe case
817     if (m_4xMeInUse && m_4xMeDistortionBufferSupported)
818     {
819         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_HME4xDistortionSurface->GetIndex(pSurfIndex));
820     }
821     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
822 
823     if (m_4xMeInUse && !m_surfaceParam.vdencStreamInEnabled)
824     {
825         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_surfaceParam.meBrcDistortionSurface->GetIndex(pSurfIndex));
826     }
827     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
828 
829     CODECHAL_ENCODE_CHK_NULL_RETURN(YuvInfo->VMEFwdIdx)
830 
831     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), YuvInfo->VMEFwdIdx);
832 
833     if (m_pictureCodingType == B_TYPE)
834     {
835         cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), YuvInfo->VMEBwdIdx);
836     }
837     else
838     {
839         cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), (SurfaceIndex *)CM_NULL_SURFACE);
840     }
841 
842     if (m_surfaceParam.vdencStreamInEnabled && m_4xMeInUse)
843     {
844         m_VdencStreamInBuffer->GetIndex(pSurfIndex);
845     }
846     //set surface for vdenc streamin
847     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
848 
849     // hevc vdenc streamin. no separate buffer created for now
850     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
851 
852 
853     if (m_curbeParam.brcEnable && m_4xMeInUse)
854     {
855       CODECHAL_ENCODE_CHK_STATUS_RETURN(m_SumMvandDistortionBuffer->GetIndex(pSurfIndex));
856     }
857     //set surface for Sum MV distortion buffer
858     cmKrn->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex);
859 
860 
861     return MOS_STATUS_SUCCESS;
862 }
863