1 /*
2 * Copyright (c) 2018-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 //!
24 //! \file     media_context.cpp
25 //! \brief    Defines the common interface for media context
26 //! \details  The media context interface is further sub-divided by component,
27 //!           this file is for the base interface which is shared by all components.
28 //!
29 
30 #include "media_context.h"
31 #include "mos_interface.h"
32 #include "mos_os_virtualengine_next.h"
33 #if !EMUL
34 #include "codec_hw_next.h"
35 #include "decode_scalability_defs.h"
36 #endif
37 #include "mos_os_cp_interface_specific.h"
MediaContext(uint8_t componentType,void * hwInterface,PMOS_INTERFACE osInterface)38 MediaContext::MediaContext(uint8_t componentType, void *hwInterface, PMOS_INTERFACE osInterface)
39 {
40     if (!hwInterface)
41     {
42         MOS_OS_ASSERTMESSAGE("null HW interface, failed to create Media Context");
43         return;
44     }
45 
46     if (!osInterface)
47     {
48         MOS_OS_ASSERTMESSAGE("null OS interface, failed to create Media Context");
49         return;
50     }
51 
52     if (componentType >= scalabilityTotal)
53     {
54         MOS_OS_ASSERTMESSAGE("Invalid component type, failed to create Media Context");
55         return;
56     }
57 
58     m_hwInterface = hwInterface;
59     m_osInterface = osInterface;
60     m_userSettingPtr = osInterface->pfnGetUserSettingInstance(osInterface);
61     m_componentType = componentType;
62 
63     m_streamId = m_osInterface->streamIndex;
64     m_gpuContextAttributeTable.clear();
65 }
66 
~MediaContext()67 MediaContext::~MediaContext()
68 {
69     if (m_osInterface && m_osInterface->pfnWaitAllCmdCompletion)
70     {
71         m_osInterface->pfnWaitAllCmdCompletion(m_osInterface);
72     }
73 
74     if ((MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface)) &&
75        (m_curNodeOrdinal == MOS_GPU_NODE_VIDEO || m_curNodeOrdinal == MOS_GPU_NODE_VIDEO2))
76     {
77         m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, m_curNodeOrdinal);
78         if (m_osInterface->osStreamState && m_osInterface->osStreamState->component == COMPONENT_Encode)
79         {
80             m_osInterface->pfnSetLatestVirtualNode(m_osInterface, MOS_GPU_NODE_MAX);
81         }
82     }
83 
84     for (auto& curAttribute : m_gpuContextAttributeTable)
85     {
86         if (curAttribute.scalabilityState)
87         {
88             MOS_STATUS status = curAttribute.scalabilityState->Destroy();
89             if (MOS_FAILED(status))
90             {
91                 MOS_OS_ASSERTMESSAGE("scalabilityState destroy fail.");
92             }
93             MOS_Delete(curAttribute.scalabilityState);
94             // set legacy MOS ve interface to null to be compatible to legacy MOS
95             if (m_osInterface)
96             {
97                 m_osInterface->pVEInterf = nullptr;
98             }
99         }
100         else
101         {
102             MOS_OS_ASSERTMESSAGE("scalabilityState is nullptr, something must be wrong");
103             return;
104         }
105 
106         if (!m_osInterface || !m_osInterface->pOsContext)
107         {
108             MOS_OS_ASSERTMESSAGE("m_osInterface and OsContext cannot be nullptr");
109             return;
110         }
111 
112         if (curAttribute.gpuContext != MOS_GPU_CONTEXT_INVALID_HANDLE)
113         {
114             if (m_osInterface->apoMosEnabled || m_osInterface->modularizedGpuCtxEnabled)
115             {
116                 auto status = m_osInterface->pfnDestroyGpuContextByHandle(m_osInterface, curAttribute.gpuContext);
117 
118                 if (status != MOS_STATUS_SUCCESS)
119                 {
120                     MOS_OS_NORMALMESSAGE("Gpu Context destory failed, something must be wrong");
121                     return;
122                 }
123             }
124             else
125             {
126                 auto status = m_osInterface->pfnDestroyGpuContext(
127                     m_osInterface,
128                     curAttribute.ctxForLegacyMos);
129                 if (status != MOS_STATUS_SUCCESS)
130                 {
131                     MOS_OS_NORMALMESSAGE("Gpu Context destory failed, something must be wrong");
132                     return;
133                 }
134             }
135         }
136         else
137         {
138             MOS_OS_ASSERTMESSAGE("Invalid gpu Context handle in entry, something must be wrong");
139             return;
140         }
141 #if !EMUL
142         // Be compatible to legacy MOS
143         m_osInterface->pfnSetGpuContextHandle(m_osInterface, MOS_GPU_CONTEXT_INVALID_HANDLE, curAttribute.ctxForLegacyMos);
144 #endif
145     }
146 
147     m_gpuContextAttributeTable.clear();
148 }
149 
SwitchContext(MediaFunction func,ContextRequirement * requirement,MediaScalability ** scalabilityState)150 MOS_STATUS MediaContext::SwitchContext(MediaFunction func, ContextRequirement *requirement, MediaScalability **scalabilityState)
151 {
152     MOS_OS_FUNCTION_ENTER;
153     MOS_STATUS status = MOS_STATUS_SUCCESS;
154 
155     MOS_OS_CHK_NULL_RETURN(m_osInterface);
156     MOS_OS_CHK_NULL_RETURN(m_osInterface->pOsContext);
157     MOS_OS_CHK_NULL_RETURN(scalabilityState);
158     MOS_OS_CHK_NULL_RETURN(requirement);
159 
160     if (func >= INVALID_MEDIA_FUNCTION)
161     {
162         MOS_OS_ASSERTMESSAGE("Func required is invalid");
163         return MOS_STATUS_INVALID_PARAMETER;
164     }
165 
166     MediaScalability * veStateProvided = nullptr;
167 
168     if (IS_RENDER_ENGINE_FUNCTION(func))
169     {
170         auto scalPars = (ScalabilityPars *)requirement;
171         MOS_OS_CHK_NULL_RETURN(scalPars);
172         MOS_OS_CHK_NULL_RETURN(m_osInterface->osCpInterface);
173         scalPars->raMode = m_osInterface->osCpInterface->IsHMEnabled() ? MEDIA_IS_SKU(m_osInterface->pfnGetSkuTable(m_osInterface), FtrRAMode) : 0;
174         scalPars->protectMode = m_osInterface->osCpInterface->IsHMEnabled() ? MEDIA_IS_SKU(m_osInterface->pfnGetSkuTable(m_osInterface), FtrProtectedEnableBitRequired) : 0;
175         if (scalPars->raMode)
176         {
177             MOS_OS_NORMALMESSAGE("request RA mode context for protected render workload");
178             ReportUserSetting(m_userSettingPtr,
179                               __MEDIA_USER_FEATURE_VALUE_RA_MODE_ENABLE,
180                               uint32_t(1),
181                               MediaUserSetting::Group::Device);
182         }
183         if (scalPars->protectMode)
184         {
185             MOS_OS_NORMALMESSAGE("request protect mode context for protected render workload");
186             ReportUserSetting(m_userSettingPtr,
187                               __MEDIA_USER_FEATURE_VALUE_PROTECT_MODE_ENABLE,
188                               uint32_t(1),
189                               MediaUserSetting::Group::Device);
190         }
191     }
192 
193     uint32_t index = m_invalidContextAttribute;
194 #if !EMUL
195     MOS_OS_CHK_STATUS_RETURN(SearchContext<ScalabilityPars*>(func, (ScalabilityPars*)requirement, index));
196 #endif
197     if (index == m_invalidContextAttribute)
198     {
199         MOS_OS_CHK_STATUS_RETURN(CreateContext<ScalabilityPars*>(func, (ScalabilityPars*)requirement, index));
200     }
201     if (index == m_invalidContextAttribute || index >= m_gpuContextAttributeTable.size())
202     {
203         MOS_OS_ASSERTMESSAGE("Incorrect index get from Context attribute table");
204         return MOS_STATUS_UNKNOWN;
205     }
206 
207     // Be compatible to legacy MOS
208     MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos));
209     veStateProvided = m_gpuContextAttributeTable[index].scalabilityState;
210     MOS_OS_NORMALMESSAGE("Switched to GpuContext %d, index %d", m_gpuContextAttributeTable[index].ctxForLegacyMos, index);
211 
212     if (requirement->IsEnc)
213     {
214         m_osInterface->pfnSetEncodeEncContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos);
215     }
216     if (requirement->IsPak)
217     {
218         m_osInterface->pfnSetEncodePakContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos);
219     }
220 
221     if (!requirement->IsContextSwitchBack)
222     {
223         m_osInterface->pfnResetOsStates(m_osInterface);
224     }
225 
226     *scalabilityState = veStateProvided;
227 
228     return status;
229 }
230 
231 template<typename T>
SearchContext(MediaFunction func,T params,uint32_t & indexFound)232 MOS_STATUS MediaContext::SearchContext(MediaFunction func, T params, uint32_t& indexFound)
233 {
234     MOS_OS_FUNCTION_ENTER;
235 
236     MOS_OS_CHK_NULL_RETURN(m_osInterface);
237 
238     indexFound = m_invalidContextAttribute;
239     uint32_t index = 0;
240 
241     for (auto& curAttribute : m_gpuContextAttributeTable)
242     {
243         if (curAttribute.func == func)
244         {
245             MOS_OS_CHK_NULL_RETURN(curAttribute.scalabilityState);
246 
247             if (curAttribute.scalabilityState->IsScalabilityModeMatched(params))
248             {
249                 // Found the matching GPU context and scalability state
250                 indexFound = index;
251 
252                 // Be compatible to legacy MOS
253                 MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContextHandle(m_osInterface, curAttribute.gpuContext, curAttribute.ctxForLegacyMos));
254                 // set legacy MOS ve interface to current reused scalability state's ve interface
255                 m_osInterface->pVEInterf = curAttribute.scalabilityState->m_veInterface;
256                 if (m_osInterface->apoMosEnabled)
257                 {
258                     if (curAttribute.scalabilityState->m_veState)
259                     {
260                         MOS_OS_CHK_NULL_RETURN(m_osInterface->osStreamState);
261                         m_osInterface->osStreamState->virtualEngineInterface = curAttribute.scalabilityState->m_veState;
262                     }
263                 }
264                 break;
265             }
266         }
267 
268         index++;
269     }
270 
271     return MOS_STATUS_SUCCESS;
272 }
273 
274 template<typename T>
CreateContext(MediaFunction func,T params,uint32_t & indexReturn)275 MOS_STATUS MediaContext::CreateContext(MediaFunction func, T params, uint32_t& indexReturn)
276 {
277     MOS_OS_FUNCTION_ENTER;
278 
279     MOS_OS_CHK_NULL_RETURN(m_osInterface);
280 
281     // Reach the max number of Gpu Context attr entries in current Media Context
282     if (m_gpuContextAttributeTable.size() == m_maxContextAttribute)
283     {
284         MOS_OS_ASSERTMESSAGE("Reached max num of entries of gpuContextAttributeTable: 4096. Cannot create more Gpu Contexts");
285         return MOS_STATUS_NOT_ENOUGH_BUFFER;
286     }
287 
288     GpuContextAttribute newAttr;
289 
290     // Setup func
291     newAttr.func = func;
292     if (newAttr.func >= INVALID_MEDIA_FUNCTION)
293     {
294         MOS_OS_ASSERTMESSAGE("Func required is invalid");
295         return MOS_STATUS_INVALID_PARAMETER;
296     }
297 
298     // Create scalabilityState
299     MOS_GPUCTX_CREATOPTIONS_ENHANCED option;
300     MediaScalabilityFactory<T> scalabilityFactory;
301     newAttr.scalabilityState = scalabilityFactory.CreateScalability(
302         m_componentType, params, m_hwInterface, this, &option);
303     if (newAttr.scalabilityState == nullptr)
304     {
305         MOS_OS_ASSERTMESSAGE("Failed to create scalability state");
306         return MOS_STATUS_NO_SPACE;
307     }
308 
309     // request to create or reuse gpuContext
310     MOS_GPU_NODE node = MOS_GPU_NODE_MAX;
311     MOS_OS_CHK_STATUS_RETURN(FunctionToNode(func, option, node));
312 
313     // WA for legacy MOS
314     MOS_OS_CHK_STATUS_RETURN(FunctionToGpuContext(func, option, node, newAttr.ctxForLegacyMos));
315 
316     if(m_osInterface->bSetHandleInvalid)
317     {
318         MOS_OS_NORMALMESSAGE("Force set INVALID_HANDLE for GpuContext %d", newAttr.ctxForLegacyMos);
319         MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContextHandle(m_osInterface, MOS_GPU_CONTEXT_INVALID_HANDLE, newAttr.ctxForLegacyMos));
320     }
321 
322     MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(m_osInterface, newAttr.ctxForLegacyMos, node, &option));
323     m_osInterface->pfnSetGpuContext(m_osInterface, newAttr.ctxForLegacyMos);
324     newAttr.gpuContext = m_osInterface->CurrentGpuContextHandle;
325     MOS_OS_NORMALMESSAGE("Create GpuContext %d, node %d, handle 0x%x, protectMode %d, raMode %d",
326         newAttr.ctxForLegacyMos, node, newAttr.gpuContext, option.ProtectMode, option.RAMode);
327 
328     // Add entry to the table
329     indexReturn = m_gpuContextAttributeTable.size();
330     m_gpuContextAttributeTable.push_back(newAttr);
331 
332     if (func == VeboxVppFunc || func == ComputeVppFunc)
333     {
334          m_osInterface->pfnRegisterBBCompleteNotifyEvent(
335             m_osInterface,
336             newAttr.ctxForLegacyMos);
337     }
338 
339     return MOS_STATUS_SUCCESS;
340 }
341 
SwitchContext(MediaFunction func,MediaScalabilityOption & scalabilityOption,MediaScalability ** scalabilityState,bool isEnc,bool isPak)342 MOS_STATUS MediaContext::SwitchContext(
343     MediaFunction func,
344     MediaScalabilityOption &scalabilityOption,
345     MediaScalability **scalabilityState,
346     bool isEnc,
347     bool isPak)
348 {
349     MOS_OS_FUNCTION_ENTER;
350 
351     MOS_OS_CHK_NULL_RETURN(m_osInterface);
352     MOS_OS_CHK_NULL_RETURN(m_osInterface->pOsContext);
353     MOS_OS_CHK_NULL_RETURN(scalabilityState);
354 
355     if (func >= INVALID_MEDIA_FUNCTION)
356     {
357         MOS_OS_ASSERTMESSAGE("Func required is invalid");
358         return MOS_STATUS_INVALID_PARAMETER;
359     }
360 
361     MediaScalability * veStateProvided = nullptr;
362 
363     uint32_t index = m_invalidContextAttribute;
364 #if !EMUL
365     MOS_OS_CHK_STATUS_RETURN(SearchContext<MediaScalabilityOption&>(func, scalabilityOption, index));
366 #endif
367     if (index == m_invalidContextAttribute)
368     {
369         MOS_OS_CHK_STATUS_RETURN(CreateContext<MediaScalabilityOption *>(func, &scalabilityOption, index));
370     }
371     if (index == m_invalidContextAttribute || index >= m_gpuContextAttributeTable.size())
372     {
373         MOS_OS_ASSERTMESSAGE("Incorrect index get from Context attribute table");
374         return MOS_STATUS_UNKNOWN;
375     }
376 
377     // Be compatible to legacy MOS
378     MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos));
379     veStateProvided = m_gpuContextAttributeTable[index].scalabilityState;
380 
381     if (isEnc)
382     {
383         m_osInterface->pfnSetEncodeEncContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos);
384     }
385     if (isPak)
386     {
387         m_osInterface->pfnSetEncodePakContext(m_osInterface, m_gpuContextAttributeTable[index].ctxForLegacyMos);
388     }
389 
390     m_osInterface->pfnResetOsStates(m_osInterface);
391 
392     *scalabilityState = veStateProvided;
393 
394     return MOS_STATUS_SUCCESS;
395 }
396 
FunctionToNode(MediaFunction func,const MOS_GPUCTX_CREATOPTIONS_ENHANCED & option,MOS_GPU_NODE & node)397 MOS_STATUS MediaContext::FunctionToNode(MediaFunction func, const MOS_GPUCTX_CREATOPTIONS_ENHANCED &option, MOS_GPU_NODE& node)
398 {
399     MOS_OS_FUNCTION_ENTER;
400     MOS_STATUS status = MOS_STATUS_SUCCESS;
401 
402     if (func >= INVALID_MEDIA_FUNCTION)
403     {
404         MOS_OS_ASSERTMESSAGE("Func required is invalid");
405         return MOS_STATUS_INVALID_PARAMETER;
406     }
407 
408     switch (func)
409     {
410     case RenderGenericFunc:
411         node = MOS_GPU_NODE_3D;
412         break;
413     case VdboxEncodeFunc:
414     case VdboxDecodeFunc:
415     case VdboxDecodeVirtualNode0Func:
416     case VdboxDecodeVirtualNode1Func:
417         if (option.LRCACount >= 2)
418         {
419             node = MOS_GPU_NODE_VIDEO; // multiple pipe decode or encode always using VIDEO node
420             if (MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface))
421             {
422                 if (m_curNodeOrdinal == MOS_GPU_NODE_VIDEO || m_curNodeOrdinal == MOS_GPU_NODE_VIDEO2)
423                 {
424                     m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, m_curNodeOrdinal);
425                     if (func == VdboxEncodeFunc)
426                     {
427                         m_osInterface->pfnSetLatestVirtualNode(m_osInterface, MOS_GPU_NODE_MAX);
428                     }
429                 }
430                 MOS_OS_CHK_STATUS_RETURN(m_osInterface->pfnCreateVideoNodeAssociation(
431                     m_osInterface,
432                     true,
433                     &node));
434                 if (func == VdboxDecodeFunc || func == VdboxDecodeVirtualNode0Func || func == VdboxDecodeVirtualNode1Func)
435                 {
436                     m_osInterface->pfnSetDecoderVirtualNodePerStream(m_osInterface, node);
437                 }
438                 else if (func == VdboxEncodeFunc)
439                 {
440                     m_osInterface->pfnSetLatestVirtualNode(m_osInterface, node);
441                 }
442             }
443             m_curNodeOrdinal = node;
444         }
445 #if !EMUL
446         else
447         {
448             MOS_OS_CHK_STATUS_RETURN(FunctionToNodeCodec(func, node));
449         }
450 #endif
451         break;
452     case VdboxDecodeWaFunc:
453     case VdboxDecrpytFunc:
454     case VdboxCpFunc:
455         node = MOS_GPU_NODE_VIDEO;
456         break;
457     case VeboxVppFunc:
458         node = MOS_GPU_NODE_VE;
459         break;
460     case ComputeMdfFunc:
461     case ComputeVppFunc:
462         node = MOS_GPU_NODE_COMPUTE;
463         break;
464     default:
465         MOS_OS_ASSERTMESSAGE("Cannot find the GPU node by the func");
466         status = MOS_STATUS_INVALID_PARAMETER;
467         node = MOS_GPU_NODE_MAX;
468         break;
469     }
470 
471     return status;
472 }
473 #if !EMUL
FunctionToNodeCodec(MediaFunction func,MOS_GPU_NODE & node)474 MOS_STATUS MediaContext::FunctionToNodeCodec(MediaFunction func, MOS_GPU_NODE& node)
475 {
476     MHW_VDBOX_GPUNODE_LIMIT gpuNodeLimit = {0};
477 
478     MOS_OS_CHK_STATUS_RETURN(FindGpuNodeToUse(func , &gpuNodeLimit));
479 
480     node = (MOS_GPU_NODE)(gpuNodeLimit.dwGpuNodeToUse);
481 
482     return MOS_STATUS_SUCCESS;
483 }
484 
485 #if (_DEBUG || _RELEASE_INTERNAL)
CheckScalabilityOverrideValidity()486 MOS_STATUS MediaContext::CheckScalabilityOverrideValidity()
487 {
488     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
489 
490     MEDIA_SYSTEM_INFO *gtSystemInfo = nullptr;
491     uint32_t           forceVdbox   = 0;
492     bool               scalableDecMode = false;
493     bool               useVD1          = false;
494     bool               useVD2          = false;
495 
496     MHW_MI_CHK_NULL(m_osInterface);
497     scalableDecMode = m_osInterface->bHcpDecScalabilityMode ? true : false;
498     forceVdbox      = m_osInterface->eForceVdbox;
499     gtSystemInfo    = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
500     MHW_MI_CHK_NULL(gtSystemInfo);
501 
502     if (forceVdbox != MOS_FORCE_VDBOX_NONE &&
503         forceVdbox != MOS_FORCE_VDBOX_1 &&
504         forceVdbox != MOS_FORCE_VDBOX_2 &&
505         // 2 pipes, VDBOX1-BE1, VDBOX2-BE2
506         forceVdbox != MOS_FORCE_VDBOX_1_1_2 &&
507         forceVdbox != MOS_FORCE_VDBOX_2_1_2)
508     {
509         eStatus = MOS_STATUS_INVALID_PARAMETER;
510         MHW_ASSERTMESSAGE("user feature forceVdbox value is invalid.");
511         return eStatus;
512     }
513     if (!scalableDecMode &&
514         (forceVdbox == MOS_FORCE_VDBOX_1_1_2 ||
515             forceVdbox == MOS_FORCE_VDBOX_2_1_2))
516     {
517         eStatus = MOS_STATUS_INVALID_PARAMETER;
518         MHW_ASSERTMESSAGE("user feature forceVdbox valude does not consistent with regkey scalability mode.");
519         return eStatus;
520     }
521 
522     if (scalableDecMode && !m_scalabilitySupported)
523     {
524         eStatus = MOS_STATUS_INVALID_PARAMETER;
525         MHW_ASSERTMESSAGE("user feature scalability mode is not allowed on current platform!");
526         return eStatus;
527     }
528 
529     if (forceVdbox == 0)
530     {
531         useVD1 = true;
532     }
533     else
534     {
535         MHW_VDBOX_IS_VDBOX_SPECIFIED(forceVdbox, MOS_FORCE_VDBOX_1, MOS_FORCEVDBOX_VDBOXID_BITSNUM, MOS_FORCEVDBOX_MASK, useVD1);
536         MHW_VDBOX_IS_VDBOX_SPECIFIED(forceVdbox, MOS_FORCE_VDBOX_2, MOS_FORCEVDBOX_VDBOXID_BITSNUM, MOS_FORCEVDBOX_MASK, useVD2);
537     }
538     if (!gtSystemInfo->VDBoxInfo.IsValid ||
539         (useVD1 && !gtSystemInfo->VDBoxInfo.Instances.Bits.VDBox0Enabled) ||
540         (useVD2 && !gtSystemInfo->VDBoxInfo.Instances.Bits.VDBox1Enabled))
541     {
542         eStatus = MOS_STATUS_INVALID_PARAMETER;
543         MHW_ASSERTMESSAGE("the forced VDBOX is not enabled in current platform.");
544         return eStatus;
545     }
546 
547     return eStatus;
548 }
549 #endif
550 
FindGpuNodeToUse(MediaFunction func,PMHW_VDBOX_GPUNODE_LIMIT gpuNodeLimit)551 MOS_STATUS MediaContext::FindGpuNodeToUse(MediaFunction func, PMHW_VDBOX_GPUNODE_LIMIT gpuNodeLimit)
552 {
553     bool       setVideoNode = false;
554     MOS_STATUS eStatus      = MOS_STATUS_SUCCESS;
555 
556     MOS_GPU_NODE videoGpuNode = MOS_GPU_NODE_VIDEO;
557 
558     if (MOS_VE_MULTINODESCALING_SUPPORTED(m_osInterface))
559     {
560         if (GetNumVdbox() == 1)
561         {
562             videoGpuNode = MOS_GPU_NODE_VIDEO;
563         }
564         else
565         {
566             if (m_curNodeOrdinal == MOS_GPU_NODE_VIDEO || m_curNodeOrdinal == MOS_GPU_NODE_VIDEO2)
567             {
568                 m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, m_curNodeOrdinal);
569                 if (func == VdboxEncodeFunc)
570                 {
571                     m_osInterface->pfnSetLatestVirtualNode(m_osInterface, MOS_GPU_NODE_MAX);
572                 }
573             }
574             if (func == VdboxDecodeVirtualNode0Func)
575             {
576                 setVideoNode = true;
577                 videoGpuNode = MOS_GPU_NODE_VIDEO;
578             }
579             else if (func == VdboxDecodeVirtualNode1Func)
580             {
581                 setVideoNode = true;
582                 videoGpuNode = MOS_GPU_NODE_VIDEO2;
583             }
584             else if (func == VdboxEncodeFunc)
585             {
586                 MOS_GPU_NODE node = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Decode);
587                 if (node != MOS_GPU_NODE_MAX)
588                 {
589                     setVideoNode = true;
590                     videoGpuNode = (node == MOS_GPU_NODE_VIDEO) ? MOS_GPU_NODE_VIDEO2 : MOS_GPU_NODE_VIDEO;
591                 }
592             }
593             MHW_MI_CHK_STATUS(m_osInterface->pfnCreateVideoNodeAssociation(
594                 m_osInterface,
595                 setVideoNode,
596                 &videoGpuNode));
597             m_curNodeOrdinal = videoGpuNode;
598             if (func == VdboxDecodeFunc || func == VdboxDecodeVirtualNode0Func || func == VdboxDecodeVirtualNode1Func)
599             {
600                 m_osInterface->pfnSetDecoderVirtualNodePerStream(m_osInterface, m_curNodeOrdinal);
601             }
602             else if (func == VdboxEncodeFunc)
603             {
604                 m_osInterface->pfnSetLatestVirtualNode(m_osInterface, m_curNodeOrdinal);
605             }
606         }
607     }
608 #if (_DEBUG || _RELEASE_INTERNAL)
609     if (m_osInterface != nullptr && m_osInterface->bEnableDbgOvrdInVE &&
610         (!m_osInterface->bSupportVirtualEngine || !m_scalabilitySupported))
611     {
612         eStatus = MOS_STATUS_INVALID_PARAMETER;
613         MHW_ASSERTMESSAGE("not support DebugOverrid on current OS or Platform.");
614         return eStatus;
615     }
616 
617     if (m_osInterface != nullptr && m_osInterface->bEnableDbgOvrdInVE)
618     {
619         MHW_MI_CHK_STATUS(CheckScalabilityOverrideValidity());
620     }
621 #endif
622     gpuNodeLimit->dwGpuNodeToUse = videoGpuNode;
623 
624     return eStatus;
625 }
626 #endif
627 
FunctionToGpuContext(MediaFunction func,const MOS_GPUCTX_CREATOPTIONS_ENHANCED & option,const MOS_GPU_NODE & node,MOS_GPU_CONTEXT & ctx)628 MOS_STATUS MediaContext::FunctionToGpuContext(MediaFunction func, const MOS_GPUCTX_CREATOPTIONS_ENHANCED &option, const MOS_GPU_NODE &node, MOS_GPU_CONTEXT &ctx)
629 {
630     MOS_OS_FUNCTION_ENTER;
631 
632     if (func >= INVALID_MEDIA_FUNCTION)
633     {
634         MOS_OS_ASSERTMESSAGE("Func is invalid");
635         return MOS_STATUS_INVALID_PARAMETER;
636     }
637 
638     switch (func)
639     {
640     case VdboxEncodeFunc:
641         MOS_OS_CHK_STATUS_RETURN(FunctionToGpuContextEncode(option, ctx));
642         break;
643     case VdboxDecodeFunc:
644     case VdboxDecodeVirtualNode0Func:
645     case VdboxDecodeVirtualNode1Func:
646         MOS_OS_CHK_STATUS_RETURN(FunctionToGpuContextDecode(option, node, ctx));
647         break;
648     case VdboxDecodeWaFunc:
649         ctx = MOS_GPU_CONTEXT_VIDEO2;
650         break;
651     case VdboxDecrpytFunc:
652         ctx = MOS_GPU_CONTEXT_VDBOX2_VIDEO2;
653         break;
654     case VeboxVppFunc:
655         ctx = MOS_GPU_CONTEXT_VEBOX;
656         break;
657     case RenderGenericFunc:
658         ctx = option.RAMode ? MOS_GPU_CONTEXT_RENDER_RA : MOS_GPU_CONTEXT_RENDER;
659         break;
660     case ComputeVppFunc:
661         ctx = option.RAMode ? MOS_GPU_CONTEXT_COMPUTE_RA : MOS_GPU_CONTEXT_COMPUTE;
662         break;
663     case ComputeMdfFunc:
664         ctx = MOS_GPU_CONTEXT_CM_COMPUTE;
665         break;
666     case VdboxCpFunc:
667         ctx = MOS_GPU_CONTEXT_VIDEO;
668         break;
669     default:
670         ctx = MOS_GPU_CONTEXT_MAX;
671         MOS_OS_ASSERTMESSAGE("Func is invalid");
672         return MOS_STATUS_INVALID_PARAMETER;
673     }
674 
675     return MOS_STATUS_SUCCESS;
676 }
677 
FunctionToGpuContextDecode(const MOS_GPUCTX_CREATOPTIONS_ENHANCED & option,const MOS_GPU_NODE & node,MOS_GPU_CONTEXT & ctx)678 MOS_STATUS MediaContext::FunctionToGpuContextDecode(const MOS_GPUCTX_CREATOPTIONS_ENHANCED &option, const MOS_GPU_NODE &node, MOS_GPU_CONTEXT &ctx)
679 {
680     if (option.UsingSFC)
681     {
682         ctx = MOS_GPU_CONTEXT_VIDEO4;
683     }
684     else
685     {
686         switch (option.LRCACount)
687         {
688         case 0:
689         case 1:
690             ctx = (node == MOS_GPU_NODE_VIDEO) ? MOS_GPU_CONTEXT_VIDEO : MOS_GPU_CONTEXT_VDBOX2_VIDEO;
691             break;
692         case 2:
693             ctx = MOS_GPU_CONTEXT_VIDEO5;
694             break;
695         case 3:
696             ctx = MOS_GPU_CONTEXT_VIDEO7;
697             break;
698         default:
699             ctx = MOS_GPU_CONTEXT_VIDEO;
700             break;
701         }
702     }
703 
704     return MOS_STATUS_SUCCESS;
705 }
706 
FunctionToGpuContextEncode(const MOS_GPUCTX_CREATOPTIONS_ENHANCED & option,MOS_GPU_CONTEXT & ctx)707 MOS_STATUS MediaContext::FunctionToGpuContextEncode(const MOS_GPUCTX_CREATOPTIONS_ENHANCED &option, MOS_GPU_CONTEXT &ctx)
708 {
709     switch (option.LRCACount)
710     {
711     case 0:
712     case 1:
713         ctx = MOS_GPU_CONTEXT_VIDEO3;
714         break;
715     case 2:
716         ctx = MOS_GPU_CONTEXT_VIDEO6;
717         break;
718     case 4:
719         ctx = MOS_GPU_CONTEXT_VIDEO6;  //Change to proper slot when MOS_GPU_CONTEXT num extended
720         break;
721     default:
722         ctx = MOS_GPU_CONTEXT_VIDEO3;
723         break;
724     }
725 
726     return MOS_STATUS_SUCCESS;
727 }
728 
SetLatestDecoderVirtualNode()729 void MediaContext::SetLatestDecoderVirtualNode()
730 {
731     if (m_curNodeOrdinal == MOS_GPU_NODE_VIDEO || m_curNodeOrdinal == MOS_GPU_NODE_VIDEO2)
732     {
733         m_osInterface->pfnSetLatestVirtualNode(m_osInterface, m_curNodeOrdinal);
734     }
735 }
736 
ReassignContextForDecoder(uint32_t frameNum,ContextRequirement * requirement,MediaScalability ** scalabilityState)737 MOS_STATUS MediaContext::ReassignContextForDecoder(uint32_t frameNum, ContextRequirement *requirement, MediaScalability **scalabilityState)
738 {
739     if (frameNum == 0)
740     {
741         // if encoder is working, always reassign decoder to different virtual node
742         MOS_GPU_NODE encoderNode = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Encode);
743         if (encoderNode == MOS_GPU_NODE_VIDEO)
744         {
745             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, requirement, scalabilityState));
746         }
747         else if (encoderNode == MOS_GPU_NODE_VIDEO2)
748         {
749             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, requirement, scalabilityState));
750         }
751         else
752         {
753             // if only decoders are working, reassign decoder to different virtual node compared to latest used virtual node
754             MOS_GPU_NODE decoderNode = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Decode);
755             if (decoderNode == MOS_GPU_NODE_VIDEO)
756             {
757                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, requirement, scalabilityState));
758             }
759             else if (decoderNode == MOS_GPU_NODE_VIDEO2)
760             {
761                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, requirement, scalabilityState));
762             }
763             else
764             {
765                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeFunc, requirement, scalabilityState));
766             }
767         }
768     }
769     else
770     {
771         // for remaining frames, don't change virtual node assignment
772         MOS_GPU_NODE decoderNode = m_osInterface->pfnGetDecoderVirtualNodePerStream(m_osInterface);
773         if (decoderNode == MOS_GPU_NODE_VIDEO)
774         {
775             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, requirement, scalabilityState));
776         }
777         else if (decoderNode == MOS_GPU_NODE_VIDEO2)
778         {
779             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, requirement, scalabilityState));
780         }
781         else
782         {
783             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeFunc, requirement, scalabilityState));
784         }
785     }
786 
787     return MOS_STATUS_SUCCESS;
788 }
789 
ReassignContextForDecoder(uint32_t frameNum,MediaScalabilityOption & scalabilityOption,MediaScalability ** scalabilityState)790 MOS_STATUS MediaContext::ReassignContextForDecoder(uint32_t frameNum, MediaScalabilityOption &scalabilityOption, MediaScalability **scalabilityState)
791 {
792     if (frameNum == 0)
793     {
794         // if encoder is working, always reassign decoder to different virtual node
795         MOS_GPU_NODE encoderNode = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Encode);
796         if (encoderNode == MOS_GPU_NODE_VIDEO)
797         {
798             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, scalabilityOption, scalabilityState));
799         }
800         else if (encoderNode == MOS_GPU_NODE_VIDEO2)
801         {
802             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, scalabilityOption, scalabilityState));
803         }
804         else
805         {
806             // if only decoders are working, reassign decoder to different virtual node compared to latest used virtual node
807             MOS_GPU_NODE decoderNode = m_osInterface->pfnGetLatestVirtualNode(m_osInterface, COMPONENT_Decode);
808             if (decoderNode == MOS_GPU_NODE_VIDEO)
809             {
810                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, scalabilityOption, scalabilityState));
811             }
812             else if (decoderNode == MOS_GPU_NODE_VIDEO2)
813             {
814                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, scalabilityOption, scalabilityState));
815             }
816             else
817             {
818                 MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeFunc, scalabilityOption, scalabilityState));
819             }
820         }
821     }
822     else
823     {
824         // for remaining frames, don't change virtual node assignment
825         MOS_GPU_NODE decoderNode = m_osInterface->pfnGetDecoderVirtualNodePerStream(m_osInterface);
826         if (decoderNode == MOS_GPU_NODE_VIDEO)
827         {
828             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode0Func, scalabilityOption, scalabilityState));
829         }
830         else if (decoderNode == MOS_GPU_NODE_VIDEO2)
831         {
832             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeVirtualNode1Func, scalabilityOption, scalabilityState));
833         }
834         else
835         {
836             MOS_OS_CHK_STATUS_RETURN(SwitchContext(VdboxDecodeFunc, scalabilityOption, scalabilityState));
837         }
838     }
839 
840     return MOS_STATUS_SUCCESS;
841 }
842