1 /*
2 * Copyright (c) 2022, 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     decode_scalability_multipipe_next.cpp
25 //! \brief    Defines the common interface for decode scalability multipipe mode.
26 //!
27 
28 #include "decode_scalability_multipipe_next.h"
29 
30 #include "media_context.h"
31 #include "media_status_report.h"
32 #include "mhw_utilities.h"
33 #include "decode_status_report_defs.h"
34 #include "mos_interface.h"
35 #include "mos_os_virtualengine_next.h"
36 
37 namespace decode
38 {
DecodeScalabilityMultiPipeNext(void * hwInterface,MediaContext * mediaContext,uint8_t componentType)39 DecodeScalabilityMultiPipeNext::DecodeScalabilityMultiPipeNext(void *hwInterface, MediaContext *mediaContext, uint8_t componentType)
40     : MediaScalabilityMultiPipe(mediaContext)
41 {
42     m_hwInterface   = (CodechalHwInterfaceNext *)hwInterface;
43     m_componentType = componentType;
44     m_secondaryCmdBuffers.clear();
45     m_resSemaphoreAllPipes.clear();
46     m_resSemaphoreOnePipeWait.clear();
47 }
48 
~DecodeScalabilityMultiPipeNext()49 DecodeScalabilityMultiPipeNext::~DecodeScalabilityMultiPipeNext()
50 {
51 }
52 
AllocateSemaphore()53 MOS_STATUS DecodeScalabilityMultiPipeNext::AllocateSemaphore()
54 {
55     SCALABILITY_FUNCTION_ENTER;
56     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
57 
58     m_secondaryCmdBuffers.resize(m_initSecondaryCmdBufNum);
59 
60     MOS_LOCK_PARAMS lockFlagsWriteOnly;
61     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
62     lockFlagsWriteOnly.WriteOnly = 1;
63     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
64     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
65     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
66     allocParamsForBufferLinear.Format   = Format_Buffer;
67     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
68     allocParamsForBufferLinear.dwBytes  = sizeof(uint32_t);
69     allocParamsForBufferLinear.pBufName = "Sync All Pipes SemaphoreMemory";
70 
71     m_resSemaphoreAllPipes.resize(m_maxCmdBufferSetsNum);
72     for (auto &semaphoreBufferVec : m_resSemaphoreAllPipes)
73     {
74         semaphoreBufferVec.resize(m_scalabilityOption->GetNumPipe());
75         for (auto &semaphoreBuffer : semaphoreBufferVec)
76         {
77             memset(&semaphoreBuffer, 0, sizeof(MOS_RESOURCE));
78             SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
79                                                       m_osInterface,
80                                                       &allocParamsForBufferLinear,
81                                                       &semaphoreBuffer),
82                 "Cannot create HW semaphore for scalability all pipes sync.");
83             uint32_t *data = (uint32_t *)m_osInterface->pfnLockResource(
84                 m_osInterface,
85                 &semaphoreBuffer,
86                 &lockFlagsWriteOnly);
87             SCALABILITY_CHK_NULL_RETURN(data);
88             *data = 0;
89             SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
90                 m_osInterface,
91                 &semaphoreBuffer));
92         }
93     }
94 
95     allocParamsForBufferLinear.pBufName = "Sync One Pipe Wait SemaphoreMemory";
96     m_resSemaphoreOnePipeWait.resize(m_maxCmdBufferSetsNum);
97     for (auto &semaphoreBufferVec : m_resSemaphoreOnePipeWait)
98     {
99         semaphoreBufferVec.resize(m_scalabilityOption->GetNumPipe());
100         for (auto &semaphoreBuffer : semaphoreBufferVec)
101         {
102             memset(&semaphoreBuffer, 0, sizeof(MOS_RESOURCE));
103             SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
104                                                       m_osInterface,
105                                                       &allocParamsForBufferLinear,
106                                                       &semaphoreBuffer),
107                 "Cannot create HW semaphore for scalability one pipe sync.");
108             uint32_t *data = (uint32_t *)m_osInterface->pfnLockResource(
109                 m_osInterface,
110                 &semaphoreBuffer,
111                 &lockFlagsWriteOnly);
112             SCALABILITY_CHK_NULL_RETURN(data);
113             *data = 0;
114             SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
115                 m_osInterface,
116                 &semaphoreBuffer));
117         }
118     }
119 
120     m_semaphoreIndex = 0;
121 
122     return MOS_STATUS_SUCCESS;
123 }
124 
Initialize(const MediaScalabilityOption & option)125 MOS_STATUS DecodeScalabilityMultiPipeNext::Initialize(const MediaScalabilityOption &option)
126 {
127     SCALABILITY_FUNCTION_ENTER;
128 
129     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
130     m_osInterface = m_hwInterface->GetOsInterface();
131     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
132     m_miItf = m_hwInterface->GetMiInterfaceNext();
133     SCALABILITY_CHK_NULL_RETURN(m_miItf);
134 
135     DecodeScalabilityOption *decodeScalabilityOption = MOS_New(DecodeScalabilityOption, (const DecodeScalabilityOption &)option);
136     SCALABILITY_CHK_NULL_RETURN(decodeScalabilityOption);
137     m_scalabilityOption = decodeScalabilityOption;
138 
139     m_frameTrackingEnabled = m_osInterface->bEnableKmdMediaFrameTracking ? true : false;
140     //virtual engine init with scalability
141     MOS_VIRTUALENGINE_INIT_PARAMS veInitParms;
142     MOS_ZeroMemory(&veInitParms, sizeof(veInitParms));
143     veInitParms.bScalabilitySupported          = true;
144     veInitParms.bFESeparateSubmit              = decodeScalabilityOption->IsFESeparateSubmission();
145     veInitParms.ucMaxNumPipesInUse             = decodeScalabilityOption->GetMaxMultiPipeNum();
146     veInitParms.ucNumOfSdryCmdBufSets          = m_maxCmdBufferSetsNum;
147     veInitParms.ucMaxNumOfSdryCmdBufInOneFrame = decodeScalabilityOption->IsFESeparateSubmission() ?
148                                                  veInitParms.ucMaxNumPipesInUse : (veInitParms.ucMaxNumPipesInUse + 1);
149     if (MOS_VE_SUPPORTED(m_osInterface))
150     {
151         MOS_STATUS status = m_osInterface->pfnVirtualEngineInit(m_osInterface, &m_veHitParams, veInitParms);
152         SCALABILITY_CHK_STATUS_MESSAGE_RETURN(status, "Virtual Engine Init failed");
153         m_veInterface = m_osInterface->pVEInterf;
154         if (m_osInterface->osStreamState && m_osInterface->osStreamState->virtualEngineInterface)
155         {
156             // we set m_veState here when pOsInterface->apoMosEnabled is true
157             m_veState = m_osInterface->osStreamState->virtualEngineInterface;
158         }
159     }
160 
161     m_pipeNum = m_scalabilityOption->GetNumPipe();
162     m_pipeIndexForSubmit = m_pipeNum;
163 
164     PMOS_GPUCTX_CREATOPTIONS_ENHANCED gpuCtxCreateOption = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
165     SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
166     gpuCtxCreateOption->LRCACount = decodeScalabilityOption->GetLRCACount();
167     gpuCtxCreateOption->UsingSFC  = decodeScalabilityOption->IsUsingSFC();
168     if (decodeScalabilityOption->IsUsingSlimVdbox())
169     {
170         gpuCtxCreateOption->Flags |=  (1 << 2);
171     }
172 #if (_DEBUG || _RELEASE_INTERNAL)
173     if (m_osInterface->bEnableDbgOvrdInVE)
174     {
175         gpuCtxCreateOption->DebugOverride = true;
176         uint8_t engineLogicId             = 0;
177         if (m_osInterface->pfnGetEngineLogicId(m_osInterface, engineLogicId) == MOS_STATUS_SUCCESS)
178         {
179             gpuCtxCreateOption->EngineInstance[0] = engineLogicId;
180         }
181     }
182 #endif
183     m_gpuCtxCreateOption = (PMOS_GPUCTX_CREATOPTIONS)(gpuCtxCreateOption);
184 
185     //Allocate and init for semaphores
186     SCALABILITY_CHK_STATUS_RETURN(AllocateSemaphore());
187     return MOS_STATUS_SUCCESS;
188 }
189 
GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS * gpuCtxCreateOption)190 MOS_STATUS DecodeScalabilityMultiPipeNext::GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS *gpuCtxCreateOption)
191 {
192     SCALABILITY_FUNCTION_ENTER;
193     SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
194     SCALABILITY_CHK_NULL_RETURN(m_gpuCtxCreateOption);
195 
196     MOS_GPUCTX_CREATOPTIONS_ENHANCED *dest = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(gpuCtxCreateOption);
197     MOS_GPUCTX_CREATOPTIONS_ENHANCED *source = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(m_gpuCtxCreateOption);
198 
199     SCALABILITY_CHK_NULL_RETURN(dest);
200     SCALABILITY_CHK_NULL_RETURN(source);
201 
202     *dest = *source;
203     return MOS_STATUS_SUCCESS;
204 }
205 
Destroy()206 MOS_STATUS DecodeScalabilityMultiPipeNext::Destroy()
207 {
208     SCALABILITY_FUNCTION_ENTER;
209 
210     SCALABILITY_CHK_STATUS_RETURN(MediaScalability::Destroy());
211 
212     if (m_gpuCtxCreateOption)
213     {
214         MOS_Delete(m_gpuCtxCreateOption);
215     }
216     if (m_scalabilityOption)
217     {
218         MOS_Delete(m_scalabilityOption);
219     }
220 
221     m_osInterface->pfnDestroyVeInterface(&m_veInterface);
222 
223     for (auto &semaphoreBufferVec : m_resSemaphoreAllPipes)
224     {
225         for (auto &semaphoreBuffer : semaphoreBufferVec)
226         {
227             m_osInterface->pfnFreeResource(m_osInterface, &semaphoreBuffer);
228         }
229     }
230     for (auto &semaphoreBufferVec : m_resSemaphoreOnePipeWait)
231     {
232         for (auto &semaphoreBuffer : semaphoreBufferVec)
233         {
234             m_osInterface->pfnFreeResource(m_osInterface, &semaphoreBuffer);
235         }
236     }
237 
238     return MOS_STATUS_SUCCESS;
239 }
240 
ResizeCommandBufferAndPatchList(uint32_t requestedCommandBufferSize,uint32_t requestedPatchListSize)241 MOS_STATUS DecodeScalabilityMultiPipeNext::ResizeCommandBufferAndPatchList(
242     uint32_t                    requestedCommandBufferSize,
243     uint32_t                    requestedPatchListSize)
244 {
245     SCALABILITY_FUNCTION_ENTER;
246     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
247 
248     return m_hwInterface->ResizeCommandBufferAndPatchList(requestedCommandBufferSize, requestedPatchListSize);
249 }
250 
VerifySpaceAvailable(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)251 MOS_STATUS DecodeScalabilityMultiPipeNext::VerifySpaceAvailable(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
252 {
253     SCALABILITY_FUNCTION_ENTER;
254     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
255     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
256 
257     uint8_t looptimes = 3;
258     for(auto i = 0 ; i < looptimes ; i++)
259     {
260         bool bothPatchListAndCmdBufChkSuccess = false;
261         SCALABILITY_CHK_STATUS_RETURN(MediaScalability::VerifySpaceAvailable(
262             requestedSize, requestedPatchListSize, bothPatchListAndCmdBufChkSuccess));
263         if (bothPatchListAndCmdBufChkSuccess)
264         {
265             return MOS_STATUS_SUCCESS;
266         }
267 
268         MOS_STATUS statusPatchList = MOS_STATUS_SUCCESS;
269         if (requestedPatchListSize)
270         {
271             statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
272                 m_osInterface,
273                 requestedPatchListSize);
274         }
275 
276         MOS_STATUS statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
277             m_osInterface,
278             requestedSize,
279             0);
280 
281         if (statusCmdBuf == MOS_STATUS_SUCCESS && statusPatchList == MOS_STATUS_SUCCESS)
282         {
283             return MOS_STATUS_SUCCESS;
284         }
285     }
286 
287     SCALABILITY_ASSERTMESSAGE("Resize Command buffer failed with no space!");
288     return MOS_STATUS_NO_SPACE;
289 }
290 
VerifyCmdBuffer(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)291 MOS_STATUS DecodeScalabilityMultiPipeNext::VerifyCmdBuffer(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
292 {
293     SCALABILITY_FUNCTION_ENTER;
294     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
295     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
296 
297     // Verify Primary Cmd buffer.
298     SCALABILITY_CHK_STATUS_RETURN(VerifySpaceAvailable(
299         requestedSize, requestedPatchListSize, singleTaskPhaseSupportedInPak));
300 
301     uint8_t looptimes = 3;
302     for (auto i = 0; i < looptimes; i++)
303     {
304         // Verify secondary cmd buffer
305         if (m_osInterface->pfnVerifyCommandBufferSize(
306                 m_osInterface,
307                 requestedSize,
308                 MOS_VE_HAVE_SECONDARY_CMDBUFFER) == MOS_STATUS_SUCCESS)
309         {
310             return MOS_STATUS_SUCCESS;
311         }
312 
313         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnResizeCommandBufferAndPatchList(
314             m_osInterface,
315             requestedSize,
316             0,
317             MOS_VE_HAVE_SECONDARY_CMDBUFFER));
318     }
319 
320     SCALABILITY_ASSERTMESSAGE("Verify secondary command buffer failed with no space!");
321     return MOS_STATUS_NO_SPACE;
322 }
323 
GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer,bool frameTrackingRequested)324 MOS_STATUS DecodeScalabilityMultiPipeNext::GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer, bool frameTrackingRequested)
325 {
326     SCALABILITY_FUNCTION_ENTER;
327     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
328     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
329     SCALABILITY_CHK_NULL_RETURN(m_phase);
330 
331     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0));
332 
333     uint32_t bufIdx = m_phase->GetCmdBufIndex();
334     SCALABILITY_ASSERT(bufIdx >= DecodePhase::m_secondaryCmdBufIdxBase);
335     uint32_t secondaryIdx = bufIdx - DecodePhase::m_secondaryCmdBufIdxBase;
336     if (secondaryIdx >= m_secondaryCmdBuffers.size())
337     {
338         m_secondaryCmdBuffers.resize(secondaryIdx + 1);
339     }
340     auto &scdryCmdBuffer = m_secondaryCmdBuffers[secondaryIdx];
341     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &scdryCmdBuffer, bufIdx));
342 
343     if (m_osInterface->apoMosEnabled)
344     {
345         SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState);
346         SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState->virtualEngineInterface);
347         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->osStreamState->virtualEngineInterface->SetSubmissionType(&scdryCmdBuffer, m_phase->GetSubmissionType()));
348     }
349     else
350     {
351         scdryCmdBuffer.iSubmissionType = m_phase->GetSubmissionType();
352     }
353     *cmdBuffer = scdryCmdBuffer;
354 
355     if (!m_attrReady)
356     {
357         SCALABILITY_CHK_STATUS_RETURN(SendAttrWithFrameTracking(m_primaryCmdBuffer, frameTrackingRequested));
358         // Insert noop to primary command buffer, avoid zero length command buffer
359         SCALABILITY_CHK_STATUS_RETURN(m_miItf->ADDCMD_MI_NOOP(&m_primaryCmdBuffer, nullptr));
360         m_attrReady = true;
361     }
362     return MOS_STATUS_SUCCESS;
363 }
364 
ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)365 MOS_STATUS DecodeScalabilityMultiPipeNext::ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
366 {
367     SCALABILITY_FUNCTION_ENTER;
368     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
369     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
370     SCALABILITY_CHK_NULL_RETURN(m_phase);
371 
372     uint32_t bufIdx = m_phase->GetCmdBufIndex();
373     SCALABILITY_ASSERT(bufIdx >= DecodePhase::m_secondaryCmdBufIdxBase);
374     uint32_t secondaryIdx = bufIdx - DecodePhase::m_secondaryCmdBufIdxBase;
375     SCALABILITY_ASSERT(secondaryIdx < m_secondaryCmdBuffers.size());
376 
377     m_secondaryCmdBuffers[secondaryIdx] = *cmdBuffer;  //Need to record the iOffset, ptr and other data of CMD buffer, it's not maintain in the mos.
378     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_secondaryCmdBuffers[secondaryIdx], bufIdx);
379     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0);
380     return MOS_STATUS_SUCCESS;
381 }
382 
SetHintParams()383 MOS_STATUS DecodeScalabilityMultiPipeNext::SetHintParams()
384 {
385     SCALABILITY_FUNCTION_ENTER;
386     MOS_STATUS               eStatus                 = MOS_STATUS_SUCCESS;
387     DecodeScalabilityOption *decodeScalabilityOption = dynamic_cast<DecodeScalabilityOption *>(m_scalabilityOption);
388     SCALABILITY_CHK_NULL_RETURN(decodeScalabilityOption);
389     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
390 
391     MOS_VIRTUALENGINE_SET_PARAMS veParams;
392     MOS_ZeroMemory(&veParams, sizeof(veParams));
393 
394     veParams.ucScalablePipeNum = m_pipeNum;
395     veParams.bHaveFrontEndCmds = (decodeScalabilityOption->GetMode() == scalabilityVirtualTileMode) &&
396                                  (!decodeScalabilityOption->IsFESeparateSubmission());
397     veParams.bScalableMode     = true;
398 
399     m_osInterface->pVEInterf = m_veInterface;
400     eStatus = m_osInterface->pfnSetHintParams(m_osInterface, &veParams);
401 
402     return eStatus;
403 }
404 
PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)405 MOS_STATUS DecodeScalabilityMultiPipeNext::PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)
406 {
407     SCALABILITY_FUNCTION_ENTER;
408     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
409     SCALABILITY_CHK_NULL_RETURN(m_veHitParams);
410     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
411 
412     PMOS_CMD_BUF_ATTRI_VE attriVe  = m_osInterface->pfnGetAttributeVeBuffer(cmdBuffer);
413     if (attriVe)
414     {
415         attriVe->VEngineHintParams     = *(m_veHitParams);
416         attriVe->bUseVirtualEngineHint = true;
417     }
418     return MOS_STATUS_SUCCESS;
419 }
420 
SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)421 MOS_STATUS DecodeScalabilityMultiPipeNext::SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
422 {
423     SCALABILITY_FUNCTION_ENTER;
424     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
425 
426     // Hold the actual command buffer submission till pipes are ready
427     if (!IsPipeReadyToSubmit())
428     {
429         return MOS_STATUS_SUCCESS;
430     }
431 
432     // Add BB end for every secondary cmd buf when ready for submit
433     for (uint32_t secondaryIdx = 0; secondaryIdx < m_pipeNum; secondaryIdx++)
434     {
435         MOS_COMMAND_BUFFER& scdryCmdBuffer = m_secondaryCmdBuffers[secondaryIdx];
436         uint32_t bufIdx = secondaryIdx + DecodePhase::m_secondaryCmdBufIdxBase;
437         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &scdryCmdBuffer, bufIdx));
438         SCALABILITY_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(&scdryCmdBuffer, nullptr));
439         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &scdryCmdBuffer, bufIdx);
440     }
441 
442     m_attrReady = false;
443 
444     SCALABILITY_CHK_STATUS_RETURN(SetHintParams());
445     SCALABILITY_CHK_STATUS_RETURN(PopulateHintParams(&m_primaryCmdBuffer));
446 
447     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &m_primaryCmdBuffer, false));
448 
449     m_semaphoreIndex++;
450     if (m_semaphoreIndex >= m_maxCmdBufferSetsNum)
451     {
452         m_semaphoreIndex = 0;
453     }
454 
455     return MOS_STATUS_SUCCESS;
456 }
457 
SyncAllPipes(PMOS_COMMAND_BUFFER cmdBuffer)458 MOS_STATUS DecodeScalabilityMultiPipeNext::SyncAllPipes(PMOS_COMMAND_BUFFER cmdBuffer)
459 {
460     SCALABILITY_FUNCTION_ENTER;
461     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
462     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
463 
464     SCALABILITY_ASSERT(m_semaphoreIndex < m_resSemaphoreAllPipes.size());
465     auto &semaphoreBufs = m_resSemaphoreAllPipes[m_semaphoreIndex];
466     SCALABILITY_ASSERT(semaphoreBufs.size() >= m_scalabilityOption->GetNumPipe());
467 
468     //Not stop watch dog here, expect to stop it in the packet when needed.
469     //HW Semaphore cmd to make sure all pipes start encode at the same time
470 
471     // Increment all pipe flags
472     for (uint32_t i = 0; i < m_pipeNum; i++)
473     {
474         if (!Mos_ResourceIsNull(&semaphoreBufs[i]))
475         {
476             SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(
477                 &semaphoreBufs[i], 1, MHW_MI_ATOMIC_INC, cmdBuffer));
478         }
479     }
480 
481     if (!Mos_ResourceIsNull(&semaphoreBufs[m_currentPipe]))
482     {
483         // Waiting current pipe flag euqal to pipe number which means other pipes are executing
484         SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendHwSemaphoreWaitCmd(
485             &semaphoreBufs[m_currentPipe], m_pipeNum, MHW_MI_SAD_EQUAL_SDD, cmdBuffer));
486 
487         // Reset current pipe flag for next frame
488         auto &params            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
489         params                  = {};
490         params.pOsResource      = &semaphoreBufs[m_currentPipe];
491         params.dwResourceOffset = 0;
492         params.dwValue          = 0;
493         SCALABILITY_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(cmdBuffer));
494     }
495 
496     return MOS_STATUS_SUCCESS;
497 }
498 
SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer,uint32_t pipeIdx)499 MOS_STATUS DecodeScalabilityMultiPipeNext::SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer, uint32_t pipeIdx)
500 {
501     SCALABILITY_FUNCTION_ENTER;
502     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
503 
504     SCALABILITY_ASSERT(m_semaphoreIndex < m_resSemaphoreOnePipeWait.size());
505     auto &semaphoreBufs = m_resSemaphoreOnePipeWait[m_semaphoreIndex];
506     SCALABILITY_ASSERT(semaphoreBufs.size() >= m_scalabilityOption->GetNumPipe());
507 
508     // Send MI_FLUSH command
509     auto &parFlush                         = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
510     parFlush                               = {};
511     parFlush.bVideoPipelineCacheInvalidate = true;
512     if (!Mos_ResourceIsNull(&semaphoreBufs[m_currentPipe]))
513     {
514         parFlush.pOsResource = &semaphoreBufs[m_currentPipe];
515         parFlush.dwDataDW1   = m_currentPass + 1;
516     }
517     SCALABILITY_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer));
518 
519     if (m_currentPipe == pipeIdx)
520     {
521         // this pipe needs to ensure all other pipes are ready
522         for (uint32_t i = 0; i < m_pipeNum; i++)
523         {
524             if (!Mos_ResourceIsNull(&semaphoreBufs[i]))
525             {
526                 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendHwSemaphoreWaitCmd(
527                         &semaphoreBufs[i], m_currentPass + 1, MHW_MI_SAD_EQUAL_SDD, cmdBuffer));
528             }
529         }
530 
531         // Reset all pipe flags for next frame
532         for (uint32_t i = 0; i < m_pipeNum; i++)
533         {
534             if (!Mos_ResourceIsNull(&semaphoreBufs[i]))
535             {
536                 auto &params            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
537                 params                  = {};
538                 params.pOsResource      = &semaphoreBufs[i];
539                 params.dwResourceOffset = 0;
540                 params.dwValue          = 0;
541                 SCALABILITY_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(cmdBuffer));
542             }
543         }
544     }
545 
546     return MOS_STATUS_SUCCESS;
547 }
548 
SyncPipe(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)549 MOS_STATUS DecodeScalabilityMultiPipeNext::SyncPipe(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
550 {
551     SCALABILITY_FUNCTION_ENTER;
552     if (syncType == syncAllPipes)
553     {
554         return SyncAllPipes(cmdBuffer);
555     }
556     else if (syncType == syncOnePipeWaitOthers)
557     {
558         return SyncOnePipeWaitOthers(cmdBuffer, semaphoreId);
559     }
560     else
561     {
562         return MOS_STATUS_INVALID_PARAMETER;
563     }
564 }
565 
ResetSemaphore(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)566 MOS_STATUS DecodeScalabilityMultiPipeNext::ResetSemaphore(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
567 {
568     SCALABILITY_FUNCTION_ENTER;
569     // Don't need to reset semaphore
570     return MOS_STATUS_SUCCESS;
571 }
572 
UpdateState(void * statePars)573 MOS_STATUS DecodeScalabilityMultiPipeNext::UpdateState(void *statePars)
574 {
575     SCALABILITY_FUNCTION_ENTER;
576 
577     StateParams *decodeStatePars = (StateParams *)statePars;
578     if (decodeStatePars->currentPipe >= m_pipeNum)
579     {
580         SCALABILITY_ASSERTMESSAGE("UpdateState failed with invalid parameter: currentPipe %d!",
581                                   decodeStatePars->currentPipe);
582         return MOS_STATUS_INVALID_PARAMETER;
583     }
584     m_currentPipe              = decodeStatePars->currentPipe;
585     m_currentPass              = decodeStatePars->currentPass;
586     m_pipeIndexForSubmit       = decodeStatePars->pipeIndexForSubmit;
587     m_singleTaskPhaseSupported = decodeStatePars->singleTaskPhaseSupported;
588     m_statusReport             = decodeStatePars->statusReport;
589     m_currentRow               = decodeStatePars->currentRow;
590     m_currentSubPass           = decodeStatePars->currentSubPass;
591     m_componentState           = decodeStatePars->componentState;
592 
593     m_phase                    = static_cast<DecodePhase *>(m_componentState);
594     SCALABILITY_CHK_NULL_RETURN(m_phase);
595 
596     return MOS_STATUS_SUCCESS;
597 }
598 
SendAttrWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)599 MOS_STATUS DecodeScalabilityMultiPipeNext::SendAttrWithFrameTracking(
600     MOS_COMMAND_BUFFER &cmdBuffer,
601     bool                frameTrackingRequested)
602 {
603     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
604 
605     SCALABILITY_FUNCTION_ENTER;
606 
607     bool renderEngineUsed = m_mediaContext->IsRenderEngineUsed();
608 
609     // initialize command buffer attributes
610     cmdBuffer.Attributes.bTurboMode               = m_hwInterface->m_turboMode;
611     cmdBuffer.Attributes.bMediaPreemptionEnabled  = renderEngineUsed ? m_hwInterface->GetRenderInterfaceNext()->IsPreemptionEnabled() : 0;
612 
613     if (frameTrackingRequested && m_frameTrackingEnabled)
614     {
615         PMOS_RESOURCE resource = nullptr;
616         uint32_t      offset   = 0;
617         m_statusReport->GetAddress(decode::statusReportGlobalCount, resource, offset);
618 
619         cmdBuffer.Attributes.bEnableMediaFrameTracking    = true;
620         cmdBuffer.Attributes.resMediaFrameTrackingSurface = resource;
621         cmdBuffer.Attributes.dwMediaFrameTrackingTag      = m_statusReport->GetSubmittedCount() + 1;
622         // Set media frame tracking address offset(the offset from the decode status buffer page)
623         cmdBuffer.Attributes.dwMediaFrameTrackingAddrOffset = offset;
624     }
625 
626     return eStatus;
627 }
628 
CreateDecodeMultiPipe(void * hwInterface,MediaContext * mediaContext,uint8_t componentType)629 MOS_STATUS DecodeScalabilityMultiPipeNext::CreateDecodeMultiPipe(void *hwInterface, MediaContext *mediaContext, uint8_t componentType)
630 {
631     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
632 
633     SCALABILITY_FUNCTION_ENTER;
634     SCALABILITY_CHK_NULL_RETURN(hwInterface);
635     SCALABILITY_CHK_NULL_RETURN(mediaContext);
636 
637     ((CodechalHwInterfaceNext *)hwInterface)->m_multiPipeScalability = MOS_New(DecodeScalabilityMultiPipeNext, hwInterface, mediaContext, scalabilityDecoder);
638     SCALABILITY_CHK_NULL_RETURN(((CodechalHwInterfaceNext *)hwInterface)->m_multiPipeScalability);
639     return eStatus;
640 }
641 
642 }
643