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