1 /*
2 * Copyright (c) 2020-2024, 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     vp_scalability_multipipe_next.cpp
25 //! \brief    Defines the common interface for vp scalability multipipe mode.
26 //!
27 
28 #include "vp_scalability_multipipe_next.h"
29 
30 #include "media_context.h"
31 #include "media_status_report.h"
32 #include "mhw_utilities.h"
33 #include "mhw_mi_cmdpar.h"
34 
35 #define VP_SEMAPHORE_COUNT 1024
36 
37 namespace vp
38 {
VpScalabilityMultiPipeNext(void * hwInterface,MediaContext * mediaContext,uint8_t componentType)39 VpScalabilityMultiPipeNext::VpScalabilityMultiPipeNext(void *hwInterface, MediaContext *mediaContext, uint8_t componentType)
40     : MediaScalabilityMultiPipe(mediaContext)
41 {
42     m_hwInterface   = (PVP_MHWINTERFACE)hwInterface;
43     m_componentType = componentType;
44 }
45 
~VpScalabilityMultiPipeNext()46 VpScalabilityMultiPipeNext::~VpScalabilityMultiPipeNext()
47 {
48 
49 }
50 
AllocateSemaphore()51 MOS_STATUS VpScalabilityMultiPipeNext::AllocateSemaphore()
52 {
53     VP_FUNC_CALL();
54 
55     SCALABILITY_FUNCTION_ENTER;
56     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
57 
58     m_secondaryCmdBuffers.resize(m_initSecondaryCmdBufNum);
59     m_secondaryCmdBuffersReturned.resize(m_initSecondaryCmdBufNum);
60 
61     for (uint32_t idx = 0; idx < m_initSecondaryCmdBufNum; idx++)
62     {
63         m_secondaryCmdBuffersReturned[idx] = false;
64     }
65 
66     MOS_LOCK_PARAMS lockFlagsWriteOnly;
67     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
68     lockFlagsWriteOnly.WriteOnly = 1;
69 
70     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
71     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
72     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
73     allocParamsForBufferLinear.Format   = Format_Buffer;
74     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
75     allocParamsForBufferLinear.dwBytes  = VP_SEMAPHORE_COUNT * sizeof(uint32_t);
76     allocParamsForBufferLinear.pBufName = "Sync All Pipes SemaphoreMemory";
77 
78     for (uint32_t i = 0; i < 2; i++)
79     {
80         memset(&m_resSemaphoreAllPipes[i], 0, sizeof(MOS_RESOURCE));
81         SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
82                                                   m_osInterface,
83                                                   &allocParamsForBufferLinear,
84                                                   &m_resSemaphoreAllPipes[i]),
85             "Cannot create HW semaphore for scalability all pipes sync.");
86 
87         MOS_LOCK_PARAMS lockFlagsWriteOnly;
88         MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
89         lockFlagsWriteOnly.WriteOnly = 1;
90 
91         uint32_t *data = (uint32_t *)m_osInterface->pfnLockResource(
92             m_osInterface,
93             &m_resSemaphoreAllPipes[i],
94             &lockFlagsWriteOnly);
95         SCALABILITY_CHK_NULL_RETURN(data);
96         MOS_ZeroMemory(data, VP_SEMAPHORE_COUNT * sizeof(uint32_t));
97         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
98             m_osInterface,
99             &m_resSemaphoreAllPipes[i]));
100     }
101     memset(&m_resSemaphoreOnePipeWait, 0, sizeof(MOS_RESOURCE));
102     SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
103                                               m_osInterface,
104                                               &allocParamsForBufferLinear,
105                                               &m_resSemaphoreOnePipeWait),
106         "Cannot create HW semaphore for scalability one pipe sync.");
107 
108     m_semaphoreAllPipesIndex = 0;
109     m_semaphoreAllPipesPhase = 0;
110 
111     return MOS_STATUS_SUCCESS;
112 }
113 
Initialize(const MediaScalabilityOption & option)114 MOS_STATUS VpScalabilityMultiPipeNext::Initialize(const MediaScalabilityOption &option)
115 {
116     VP_FUNC_CALL();
117 
118     SCALABILITY_FUNCTION_ENTER;
119 
120     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
121     m_osInterface = m_hwInterface->m_osInterface;
122     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
123     SCALABILITY_CHK_NULL_RETURN(m_hwInterface->m_vpPlatformInterface);
124     m_miItf = m_hwInterface->m_vpPlatformInterface->GetMhwMiItf();
125 
126     VpScalabilityOption *vpScalabilityOption = MOS_New(VpScalabilityOption, (const VpScalabilityOption &)option);
127     SCALABILITY_CHK_NULL_RETURN(vpScalabilityOption);
128     m_scalabilityOption = vpScalabilityOption;
129 
130     if (m_hwInterface->m_bIsMediaSfcInterfaceInUse)
131     {
132         m_frameTrackingEnabled = false;
133         VP_PUBLIC_NORMALMESSAGE("Media Frame Tracking is disabled for Media Sfc Interface enalbed.");
134     }
135     else
136     {
137         m_frameTrackingEnabled = m_osInterface->bEnableKmdMediaFrameTracking ? true : false;
138         VP_PUBLIC_NORMALMESSAGE("Media Frame Tracking flag is %d. Not using Meida Sfc Interface.", m_frameTrackingEnabled);
139     }
140 
141     //virtual engine init with scalability
142     MOS_VIRTUALENGINE_INIT_PARAMS veInitParms;
143     MOS_ZeroMemory(&veInitParms, sizeof(veInitParms));
144     veInitParms.bScalabilitySupported          = true;
145     veInitParms.ucNumOfSdryCmdBufSets          = m_maxCmdBufferSetsNum;
146     veInitParms.ucMaxNumPipesInUse             = vpScalabilityOption->GetMaxMultiPipeNum();
147     veInitParms.ucMaxNumOfSdryCmdBufInOneFrame = veInitParms.ucMaxNumPipesInUse;
148 
149     if (m_osInterface->apoMosEnabled)
150     {
151         SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState);
152         m_osInterface->osStreamState->component = COMPONENT_VPCommon;
153         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnVirtualEngineInit(m_osInterface, &m_veHitParams, veInitParms));
154         m_veState = m_osInterface->osStreamState->virtualEngineInterface;
155         SCALABILITY_CHK_NULL_RETURN(m_veState);
156         SCALABILITY_CHK_NULL_RETURN(m_veHitParams);
157     }
158 
159     m_pipeNum = m_scalabilityOption->GetNumPipe();
160     m_pipeIndexForSubmit = m_pipeNum;
161 
162     PMOS_GPUCTX_CREATOPTIONS_ENHANCED gpuCtxCreateOption = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
163     SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
164     gpuCtxCreateOption->LRCACount = vpScalabilityOption->GetLRCACount();
165     gpuCtxCreateOption->UsingSFC  = vpScalabilityOption->IsUsingSFC();
166     gpuCtxCreateOption->RAMode    = vpScalabilityOption->GetRAMode();
167     gpuCtxCreateOption->ProtectMode = vpScalabilityOption->GetProtectMode();
168 
169 #if (_DEBUG || _RELEASE_INTERNAL)
170     if (m_osInterface->bEnableDbgOvrdInVE)
171     {
172         for (uint32_t i = 0; i < m_osInterface->pfnGetVeEngineCount(m_osInterface->osStreamState); i++)
173         {
174             gpuCtxCreateOption->EngineInstance[i] =
175                 m_osInterface->pfnGetEngineLogicIdByIdx(m_osInterface->osStreamState, i);
176         }
177     }
178 #endif
179     m_gpuCtxCreateOption = (PMOS_GPUCTX_CREATOPTIONS)(gpuCtxCreateOption);
180 
181     //Allocate and init for semaphores
182     SCALABILITY_CHK_STATUS_RETURN(AllocateSemaphore());
183     return MOS_STATUS_SUCCESS;
184 }
185 
GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS * gpuCtxCreateOption)186 MOS_STATUS VpScalabilityMultiPipeNext::GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS *gpuCtxCreateOption)
187 {
188     VP_FUNC_CALL();
189 
190     SCALABILITY_FUNCTION_ENTER;
191     SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
192     SCALABILITY_CHK_NULL_RETURN(m_gpuCtxCreateOption);
193 
194     MOS_GPUCTX_CREATOPTIONS_ENHANCED *dest = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(gpuCtxCreateOption);
195     MOS_GPUCTX_CREATOPTIONS_ENHANCED *source = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(m_gpuCtxCreateOption);
196 
197     SCALABILITY_CHK_NULL_RETURN(dest);
198     SCALABILITY_CHK_NULL_RETURN(source);
199 
200     *dest = *source;
201     return MOS_STATUS_SUCCESS;
202 }
203 
Destroy()204 MOS_STATUS VpScalabilityMultiPipeNext::Destroy()
205 {
206     VP_FUNC_CALL();
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->pfnFreeResource(m_osInterface, &m_resSemaphoreAllPipes[0]);
222     m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreAllPipes[1]);
223     m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreOnePipeWait);
224 
225     return MOS_STATUS_SUCCESS;
226 }
227 
ResizeCommandBufferAndPatchList(uint32_t requestedCommandBufferSize,uint32_t requestedPatchListSize)228 MOS_STATUS VpScalabilityMultiPipeNext::ResizeCommandBufferAndPatchList(
229     uint32_t requestedCommandBufferSize,
230     uint32_t requestedPatchListSize)
231 {
232     VP_FUNC_CALL();
233 
234     MOS_UNUSED(requestedCommandBufferSize);
235     MOS_UNUSED(requestedPatchListSize);
236 
237     return MOS_STATUS_SUCCESS;
238 }
239 
VerifySpaceAvailable(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)240 MOS_STATUS VpScalabilityMultiPipeNext::VerifySpaceAvailable(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
241 {
242     VP_FUNC_CALL();
243 
244     SCALABILITY_FUNCTION_ENTER;
245     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
246     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
247 
248     uint8_t looptimes = 3;
249     for (auto i = 0; i < looptimes; i++)
250     {
251         bool bothPatchListAndCmdBufChkSuccess = false;
252         SCALABILITY_CHK_STATUS_RETURN(MediaScalability::VerifySpaceAvailable(
253             requestedSize, requestedPatchListSize, bothPatchListAndCmdBufChkSuccess));
254         if (bothPatchListAndCmdBufChkSuccess)
255         {
256             return MOS_STATUS_SUCCESS;
257         }
258 
259         MOS_STATUS statusPatchList = MOS_STATUS_SUCCESS;
260         if (requestedPatchListSize)
261         {
262             statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
263                 m_osInterface,
264                 requestedPatchListSize);
265         }
266 
267         MOS_STATUS statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
268             m_osInterface,
269             requestedSize,
270             0);
271 
272         if (statusCmdBuf == MOS_STATUS_SUCCESS && statusPatchList == MOS_STATUS_SUCCESS)
273         {
274             return MOS_STATUS_SUCCESS;
275         }
276     }
277 
278     SCALABILITY_ASSERTMESSAGE("Resize Command buffer failed with no space!");
279     return MOS_STATUS_NO_SPACE;
280 }
281 
VerifyCmdBuffer(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)282 MOS_STATUS VpScalabilityMultiPipeNext::VerifyCmdBuffer(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
283 {
284     VP_FUNC_CALL();
285 
286     SCALABILITY_FUNCTION_ENTER;
287     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
288     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
289 
290     requestedSize = MOS_MAX(requestedSize, m_CmdBufferSize);
291 
292     // Verify Primary Cmd buffer.
293     SCALABILITY_CHK_STATUS_RETURN(VerifySpaceAvailable(
294         requestedSize, requestedPatchListSize, singleTaskPhaseSupportedInPak));
295 
296     uint8_t looptimes = 3;
297     for (auto i = 0; i < looptimes; i++)
298     {
299         // Verify secondary cmd buffer
300         if (m_osInterface->pfnVerifyCommandBufferSize(
301                 m_osInterface,
302                 requestedSize,
303                 MOS_VE_HAVE_SECONDARY_CMDBUFFER) == MOS_STATUS_SUCCESS)
304         {
305             return MOS_STATUS_SUCCESS;
306         }
307 
308         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnResizeCommandBufferAndPatchList(
309             m_osInterface,
310             requestedSize,
311             0,
312             MOS_VE_HAVE_SECONDARY_CMDBUFFER));
313     }
314 
315     SCALABILITY_ASSERTMESSAGE("Verify secondary command buffer failed with no space!");
316     return MOS_STATUS_NO_SPACE;
317 }
318 
GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer,bool frameTrackingRequested)319 MOS_STATUS VpScalabilityMultiPipeNext::GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer, bool frameTrackingRequested)
320 {
321     VP_FUNC_CALL();
322 
323     MOS_STATUS          eStatus = MOS_STATUS_SUCCESS;
324     PMOS_COMMAND_BUFFER scdryCmdBuffer;
325 
326     SCALABILITY_FUNCTION_ENTER;
327     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
328     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
329 
330     if (m_currentPipe >= m_pipeNum)
331     {
332         eStatus = MOS_STATUS_INVALID_PARAMETER;
333         SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPipe!");
334         return eStatus;
335     }
336 
337     // Get primary cmd buffer
338     if (Mos_ResourceIsNull(&m_primaryCmdBuffer.OsResource))
339     {
340         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0));
341     }
342 
343     // Get Secondary cmd buffer
344     uint32_t bufIdx = m_currentPipe;  //Make CMD buffer one next to one.
345     uint32_t bufIdxPlus1 = bufIdx + 1;
346 
347     if (Mos_ResourceIsNull(&m_secondaryCmdBuffers[bufIdx].OsResource))
348     {
349         m_osInterface->pfnGetCommandBuffer(m_osInterface, &m_secondaryCmdBuffers[bufIdx], bufIdxPlus1);
350     }
351 
352     int32_t submissionType = IsFirstPipe() ? SUBMISSION_TYPE_MULTI_PIPE_MASTER : SUBMISSION_TYPE_MULTI_PIPE_SLAVE;
353     if (IsLastPipe())
354     {
355         submissionType |= SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE;
356     }
357     SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState);
358     SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState->virtualEngineInterface);
359     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->osStreamState->virtualEngineInterface->SetSubmissionType(&(m_secondaryCmdBuffers[bufIdx]), submissionType));
360 
361     *cmdBuffer = m_secondaryCmdBuffers[bufIdx];
362     m_secondaryCmdBuffersReturned[bufIdx] = false;
363 
364     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
365 
366     if (!m_attrReady)
367     {
368         SCALABILITY_CHK_STATUS_RETURN(SendAttrWithFrameTracking(m_primaryCmdBuffer, frameTrackingRequested));
369         m_attrReady = true;
370     }
371 
372     return eStatus;
373 }
374 
ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)375 MOS_STATUS VpScalabilityMultiPipeNext::ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
376 {
377     VP_FUNC_CALL();
378 
379     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
380 
381     SCALABILITY_FUNCTION_ENTER;
382     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
383     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
384 
385     if (m_currentPipe >= m_pipeNum)
386     {
387         eStatus = MOS_STATUS_INVALID_PARAMETER;
388         SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPipe!");
389         return eStatus;
390     }
391 
392     uint32_t bufIdx = m_currentPipe;  //Make CMD buffer one next to one.
393     uint32_t bufIdxPlus1 = bufIdx + 1;
394     if (m_secondaryCmdBuffersReturned[bufIdx] == false)
395     {
396         m_secondaryCmdBuffers[bufIdx] = *cmdBuffer;  //Need to record the iOffset, ptr and other data of CMD buffer, it's not maintain in the mos.
397         m_secondaryCmdBuffersReturned[bufIdx] = true;
398         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_secondaryCmdBuffers[bufIdx], bufIdxPlus1);
399     }
400     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0);
401 
402     return eStatus;
403 }
404 
SetHintParams()405 MOS_STATUS VpScalabilityMultiPipeNext::SetHintParams()
406 {
407     VP_FUNC_CALL();
408 
409     SCALABILITY_FUNCTION_ENTER;
410 
411     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
412 
413     VpScalabilityOption *vpScalabilityOption = dynamic_cast<VpScalabilityOption *>(m_scalabilityOption);
414     SCALABILITY_CHK_NULL_RETURN(vpScalabilityOption);
415 
416     MOS_VIRTUALENGINE_SET_PARAMS veParams;
417     MOS_ZeroMemory(&veParams, sizeof(veParams));
418 
419     veParams.ucScalablePipeNum = m_pipeNum;
420     veParams.bScalableMode     = true;
421 
422     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSetHintParams(m_osInterface, &veParams));
423 
424     return MOS_STATUS_SUCCESS;
425 }
426 
PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)427 MOS_STATUS VpScalabilityMultiPipeNext::PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)
428 {
429     VP_FUNC_CALL();
430 
431     SCALABILITY_FUNCTION_ENTER;
432     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
433     SCALABILITY_CHK_NULL_RETURN(m_veHitParams);
434     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
435 
436     PMOS_CMD_BUF_ATTRI_VE attriVe  = m_osInterface->pfnGetAttributeVeBuffer(cmdBuffer);
437     if (attriVe)
438     {
439         attriVe->VEngineHintParams     = *(m_veHitParams);
440         attriVe->bUseVirtualEngineHint = true;
441     }
442     return MOS_STATUS_SUCCESS;
443 }
444 
SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)445 MOS_STATUS VpScalabilityMultiPipeNext::SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
446 {
447     VP_FUNC_CALL();
448 
449     MOS_STATUS status = MOS_STATUS_SUCCESS;
450 
451     SCALABILITY_FUNCTION_ENTER;
452     SCALABILITY_CHK_NULL_RETURN(m_osInterface);
453 
454     m_attrReady = false;
455 
456     SCALABILITY_CHK_STATUS_RETURN(SetHintParams());
457     SCALABILITY_CHK_STATUS_RETURN(PopulateHintParams(&m_primaryCmdBuffer));
458 
459 #if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
460     if (m_osInterface->bDumpCommandBuffer)
461     {
462         for (uint32_t i = 0; i < m_pipeNum; i++)
463         {
464             status = m_osInterface->pfnDumpCommandBuffer(m_osInterface, &m_secondaryCmdBuffers[i]);
465             if (MOS_FAILED(status))
466             {
467                 SCALABILITY_ASSERTMESSAGE("DumpCommandBuffer failed with status=%d", status);
468             }
469         }
470     }
471 #endif  // MOS_COMMAND_BUFFER_DUMP_SUPPORTED
472 
473     SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &m_primaryCmdBuffer, false));
474 
475     MOS_ZeroMemory(&m_primaryCmdBuffer.OsResource, sizeof(m_primaryCmdBuffer.OsResource));
476     for (uint32_t i = 0; i < m_pipeNum; i++)
477     {
478         MOS_ZeroMemory(&m_secondaryCmdBuffers[i].OsResource, sizeof(m_secondaryCmdBuffers[i].OsResource));
479     }
480 
481     return MOS_STATUS_SUCCESS;
482 }
483 
SyncAllPipes(PMOS_COMMAND_BUFFER cmdBuffer)484 MOS_STATUS VpScalabilityMultiPipeNext::SyncAllPipes(PMOS_COMMAND_BUFFER cmdBuffer)
485 {
486     VP_FUNC_CALL();
487 
488     SCALABILITY_FUNCTION_ENTER;
489     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
490     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
491     SCALABILITY_ASSERT(m_semaphoreAllPipesIndex < VP_SEMAPHORE_COUNT * 2);
492     SCALABILITY_ASSERT(!Mos_ResourceIsNull(&m_resSemaphoreAllPipes[0]));
493     SCALABILITY_ASSERT(!Mos_ResourceIsNull(&m_resSemaphoreAllPipes[1]));
494 
495     // use two Semaphore Buffer repeatly to avoid waiting for lock, use the first Semaphore Buffer when m_semaphoreAllPipesIndex < VP_SEMAPHORE_COUNT.
496     // when the m_semaphoreAllPipesIndex >= VP_SEMAPHORE_COUNT, switch to the second Semaphore Buffer
497     uint32_t semaphoreIndex = (m_semaphoreAllPipesIndex >= VP_SEMAPHORE_COUNT) ? 1 : 0;
498 
499     if (m_semaphoreAllPipesPhase == 0)
500     {
501         if (m_currentPipe == 0)
502         {
503             std::stringstream ss;
504             ss << "VEBOX0 SCALABILITY. semaphoreIndex 0x" << std::hex << semaphoreIndex << " m_semaphoreAllPipesIndex 0x"
505                 << std::hex  << m_semaphoreAllPipesIndex ;
506             std::string ocaMsg = ss.str();
507             HalOcaInterfaceNext::TraceMessage(*cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, ocaMsg.c_str(), ocaMsg.length());
508         }
509         else
510         {
511             std::stringstream ss;
512             ss << "VEBOX1 SCALABILITY. semaphoreIndex 0x" << std::hex << semaphoreIndex << " m_semaphoreAllPipesIndex 0x"
513                 << std::hex  << m_semaphoreAllPipesIndex ;
514             std::string ocaMsg = ss.str();
515             HalOcaInterfaceNext::TraceMessage(*cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, ocaMsg.c_str(), ocaMsg.length());
516         }
517 
518         for (int32_t i = 0; i < 2 * m_pipeNum; i++)
519         {
520             HalOcaInterfaceNext::OnIndirectState(*cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, &m_resSemaphoreAllPipes[semaphoreIndex], (m_semaphoreAllPipesIndex % VP_SEMAPHORE_COUNT + i) * sizeof(uint32_t), false, sizeof(uint32_t));
521         }
522     }
523 
524     // memset the semaphore to avoid the semaphore was not clear during media reset
525     if ((m_semaphoreAllPipesPhase == 0) && (m_currentPipe == 0) && (m_semaphoreAllPipesIndex % VP_SEMAPHORE_COUNT == 0))
526     {
527         MOS_LOCK_PARAMS lockFlagsWriteOnly;
528         MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
529         lockFlagsWriteOnly.WriteOnly = 1;
530 
531         uint32_t *data = (uint32_t *)m_osInterface->pfnLockResource(
532             m_osInterface,
533             &m_resSemaphoreAllPipes[semaphoreIndex],
534             &lockFlagsWriteOnly);
535         SCALABILITY_CHK_NULL_RETURN(data);
536         MOS_ZeroMemory(data, VP_SEMAPHORE_COUNT * sizeof(uint32_t));
537         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
538             m_osInterface,
539             &m_resSemaphoreAllPipes[semaphoreIndex]));
540     }
541 
542     // Increment all pipe flags
543     for (uint32_t i = 0; i < m_pipeNum; i++)
544     {
545         if (!Mos_ResourceIsNull(&m_resSemaphoreAllPipes[semaphoreIndex]))
546         {
547             SCALABILITY_CHK_STATUS_RETURN(SendMiAtomicDwordCmd(
548                 &m_resSemaphoreAllPipes[semaphoreIndex], (m_semaphoreAllPipesIndex % VP_SEMAPHORE_COUNT + m_semaphoreAllPipesPhase * m_pipeNum + i) * sizeof(uint32_t), 1, MHW_MI_ATOMIC_INC, cmdBuffer));
549         }
550     }
551 
552     if (!Mos_ResourceIsNull(&m_resSemaphoreAllPipes[semaphoreIndex]))
553     {
554         // Waiting current pipe flag euqal to pipe number which means other pipes are executing
555         SCALABILITY_CHK_STATUS_RETURN(SendHwSemaphoreWaitCmd(
556             &m_resSemaphoreAllPipes[semaphoreIndex], (m_semaphoreAllPipesIndex % VP_SEMAPHORE_COUNT + m_semaphoreAllPipesPhase * m_pipeNum + m_currentPipe) * sizeof(uint32_t), m_pipeNum, MHW_MI_SAD_EQUAL_SDD, cmdBuffer));
557 
558         // Reset current pipe semaphore
559         SCALABILITY_CHK_STATUS_RETURN(AddMiStoreDataImmCmd(
560             &m_resSemaphoreAllPipes[semaphoreIndex], (m_semaphoreAllPipesIndex % VP_SEMAPHORE_COUNT + m_semaphoreAllPipesPhase * m_pipeNum + m_currentPipe) * sizeof(uint32_t), cmdBuffer));
561     }
562 
563     m_semaphoreAllPipesPhase = 1 - m_semaphoreAllPipesPhase;
564     if ((m_semaphoreAllPipesPhase == 0) && (m_currentPipe == 1))
565     {
566         m_semaphoreAllPipesIndex = (m_semaphoreAllPipesIndex + 2 * m_pipeNum) % (VP_SEMAPHORE_COUNT * 2);
567     }
568 
569     return MOS_STATUS_SUCCESS;
570 }
571 
SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer,uint32_t pipeIdx)572 MOS_STATUS VpScalabilityMultiPipeNext::SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer, uint32_t pipeIdx)
573 {
574     VP_FUNC_CALL();
575 
576     SCALABILITY_FUNCTION_ENTER;
577     SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
578     SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
579     SCALABILITY_ASSERT(!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait));
580 
581     // Send MI_FLUSH command
582     SCALABILITY_CHK_STATUS_RETURN(AddMiFlushDwCmd(
583             &m_resSemaphoreOnePipeWait, 0, cmdBuffer));
584 
585     if (m_currentPipe == pipeIdx)
586     {
587         // this pipe needs to ensure all other pipes are ready
588         for (uint32_t i = 0; i < m_pipeNum; i++)
589         {
590             if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait))
591             {
592                 SCALABILITY_CHK_STATUS_RETURN(SendHwSemaphoreWaitCmd(
593                     &m_resSemaphoreOnePipeWait, i, m_currentPass + 1, MHW_MI_SAD_EQUAL_SDD, cmdBuffer));
594             }
595         }
596 
597         // Reset all pipe flags for next frame
598         for (uint32_t i = 0; i < m_pipeNum; i++)
599         {
600             if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait))
601             {
602                 SCALABILITY_CHK_STATUS_RETURN(SendMiAtomicDwordCmd(
603                     &m_resSemaphoreOnePipeWait, i, m_currentPass + 1, MHW_MI_ATOMIC_DEC, cmdBuffer));
604 
605             }
606         }
607     }
608 
609     return MOS_STATUS_SUCCESS;
610 }
611 
SyncPipe(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)612 MOS_STATUS VpScalabilityMultiPipeNext::SyncPipe(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
613 {
614     VP_FUNC_CALL();
615 
616     SCALABILITY_FUNCTION_ENTER;
617 
618     if (syncType == syncAllPipes)
619     {
620         return SyncAllPipes(cmdBuffer);
621     }
622     else if (syncType == syncOnePipeWaitOthers)
623     {
624         return SyncOnePipeWaitOthers(cmdBuffer, semaphoreId);
625     }
626     else
627     {
628         return MOS_STATUS_INVALID_PARAMETER;
629     }
630 }
631 
ResetSemaphore(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)632 MOS_STATUS VpScalabilityMultiPipeNext::ResetSemaphore(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
633 {
634     VP_FUNC_CALL();
635 
636     SCALABILITY_FUNCTION_ENTER;
637     // Don't need to reset semaphore
638     return MOS_STATUS_SUCCESS;
639 }
640 
UpdateState(void * statePars)641 MOS_STATUS VpScalabilityMultiPipeNext::UpdateState(void *statePars)
642 {
643     VP_FUNC_CALL();
644 
645     SCALABILITY_FUNCTION_ENTER;
646 
647     StateParams *vpStatePars = (StateParams *)statePars;
648     if (vpStatePars->currentPipe >= m_pipeNum)
649     {
650         SCALABILITY_ASSERTMESSAGE("UpdateState failed with invalid parameter: currentPipe %d!",
651             vpStatePars->currentPipe);
652         return MOS_STATUS_INVALID_PARAMETER;
653     }
654     m_currentPipe              = vpStatePars->currentPipe;
655     m_currentPass              = vpStatePars->currentPass;
656     m_singleTaskPhaseSupported = vpStatePars->singleTaskPhaseSupported;
657     m_statusReport             = vpStatePars->statusReport;
658     m_currentRow               = vpStatePars->currentRow;
659     m_currentSubPass           = vpStatePars->currentSubPass;
660 
661     return MOS_STATUS_SUCCESS;
662 }
663 
SendAttrWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)664 MOS_STATUS VpScalabilityMultiPipeNext::SendAttrWithFrameTracking(
665     MOS_COMMAND_BUFFER &cmdBuffer,
666     bool                frameTrackingRequested)
667 {
668     VP_FUNC_CALL();
669 
670     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
671 
672     SCALABILITY_FUNCTION_ENTER;
673 
674     bool renderEngineUsed = m_mediaContext->IsRenderEngineUsed();
675 
676     // Initialize command buffer attributes
677     if (frameTrackingRequested && m_frameTrackingEnabled)
678     {
679         PMOS_RESOURCE gpuStatusBuffer = nullptr;
680 
681         SCALABILITY_CHK_NULL_RETURN(m_osInterface);
682         SCALABILITY_CHK_NULL_RETURN(m_osInterface->pfnGetGpuStatusBufferResource);
683         SCALABILITY_CHK_NULL_RETURN(m_osInterface->pfnRegisterResource);
684         SCALABILITY_CHK_NULL_RETURN(m_osInterface->pfnGetGpuStatusTag);
685         SCALABILITY_CHK_NULL_RETURN(m_osInterface->pfnGetGpuStatusTagOffset);
686 
687         // Get GPU Status buffer
688         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource(m_osInterface, gpuStatusBuffer));
689         SCALABILITY_CHK_NULL_RETURN(gpuStatusBuffer);
690         // Register the buffer
691         SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnRegisterResource(m_osInterface, gpuStatusBuffer, true, true));
692 
693         cmdBuffer.Attributes.bEnableMediaFrameTracking      = true;
694         cmdBuffer.Attributes.resMediaFrameTrackingSurface   = gpuStatusBuffer;
695         cmdBuffer.Attributes.dwMediaFrameTrackingTag        = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
696         cmdBuffer.Attributes.dwMediaFrameTrackingAddrOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
697 
698         // Increment GPU Status Tag
699         m_osInterface->pfnIncrementGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
700     }
701 
702     return eStatus;
703 }
704 
705 //!
706 //! \brief    Send hw semphore wait cmd
707 //! \details  Send hw semphore wait cmd for sync perpose
708 //!
709 //! \param    [in] semaMem
710 //!           Reource of Hw semphore
711 //! \param    [in] offset
712 //!           offset of semMem
713 //! \param    [in] semaData
714 //!           Data of Hw semphore
715 //! \param    [in] opCode
716 //!           Operation code
717 //! \param    [in,out] cmdBuffer
718 //!           command buffer
719 //!
720 //! \return   MOS_STATUS
721 //!           MOS_STATUS_SUCCESS if success, else fail reason
722 //!
SendHwSemaphoreWaitCmd(PMOS_RESOURCE semaMem,uint32_t offset,uint32_t semaData,MHW_COMMON_MI_SEMAPHORE_COMPARE_OPERATION opCode,PMOS_COMMAND_BUFFER cmdBuffer)723 MOS_STATUS VpScalabilityMultiPipeNext::SendHwSemaphoreWaitCmd(
724     PMOS_RESOURCE                             semaMem,
725     uint32_t                                  offset,
726     uint32_t                                  semaData,
727     MHW_COMMON_MI_SEMAPHORE_COMPARE_OPERATION opCode,
728     PMOS_COMMAND_BUFFER                       cmdBuffer)
729 {
730     VP_FUNC_CALL();
731 
732     MOS_STATUS                   eStatus = MOS_STATUS_SUCCESS;
733     MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams;
734 
735     VP_RENDER_CHK_NULL_RETURN(m_hwInterface);
736 
737     auto &params             = m_miItf->MHW_GETPAR_F(MI_SEMAPHORE_WAIT)();
738     params                   = {};
739     params.presSemaphoreMem = semaMem;
740     params.dwResourceOffset = offset;
741     params.bPollingWaitMode = true;
742     params.dwSemaphoreData  = semaData;
743     params.CompareOperation = (mhw::mi::MHW_COMMON_MI_SEMAPHORE_COMPARE_OPERATION) opCode;
744     eStatus                 = m_miItf->MHW_ADDCMD_F(MI_SEMAPHORE_WAIT)(cmdBuffer);
745 
746     return eStatus;
747 }
748 
749 //!
750 //! \brief    Send mi atomic dword cmd
751 //! \details  Send mi atomic dword cmd for sync perpose
752 //!
753 //! \param    [in] resource
754 //!           Reource used in mi atomic dword cmd
755 //! \param    [in] offset
756 //!           offset of resource
757 //! \param    [in] immData
758 //!           Immediate data
759 //! \param    [in] opCode
760 //!           Operation code
761 //! \param    [in,out] cmdBuffer
762 //!           command buffer
763 //!
764 //! \return   MOS_STATUS
765 //!           MOS_STATUS_SUCCESS if success, else fail reason
766 //!
SendMiAtomicDwordCmd(PMOS_RESOURCE resource,uint32_t offset,uint32_t immData,MHW_COMMON_MI_ATOMIC_OPCODE opCode,PMOS_COMMAND_BUFFER cmdBuffer)767 MOS_STATUS VpScalabilityMultiPipeNext::SendMiAtomicDwordCmd(
768     PMOS_RESOURCE               resource,
769     uint32_t                    offset,
770     uint32_t                    immData,
771     MHW_COMMON_MI_ATOMIC_OPCODE opCode,
772     PMOS_COMMAND_BUFFER         cmdBuffer)
773 {
774     VP_FUNC_CALL();
775 
776     MOS_STATUS           eStatus = MOS_STATUS_SUCCESS;
777     MHW_MI_ATOMIC_PARAMS atomicParams;
778 
779     VP_RENDER_CHK_NULL_RETURN(m_hwInterface);
780     VP_RENDER_CHK_NULL_RETURN(m_miItf);
781 
782     auto &params             = m_miItf->MHW_GETPAR_F(MI_ATOMIC)();
783     params                   = {};
784     params.pOsResource       = resource;
785     params.dwResourceOffset  = offset;
786     params.dwDataSize        = sizeof(uint32_t);
787     params.Operation         = (mhw::mi::MHW_COMMON_MI_ATOMIC_OPCODE) opCode;
788     params.bInlineData       = true;
789     params.dwOperand1Data[0] = immData;
790     eStatus                  = m_miItf->MHW_ADDCMD_F(MI_ATOMIC)(cmdBuffer);
791 
792     return eStatus;
793 }
794 
795 //!
796 //! \brief    Send mi flush dword cmd
797 //! \details  Send mi flush dword cmd for sync perpose
798 //!
799 //! \param    [in] semMem
800 //!           Reource used in mi flush dword cmd
801 //! \param    [in] semaData
802 //!           Immediate data
803 //! \param    [in,out] cmdBuffer
804 //!           command buffer
805 //!
806 //! \return   MOS_STATUS
807 //!           MOS_STATUS_SUCCESS if success, else fail reason
808 //!
AddMiFlushDwCmd(PMOS_RESOURCE semaMem,uint32_t semaData,PMOS_COMMAND_BUFFER cmdBuffer)809 MOS_STATUS VpScalabilityMultiPipeNext::AddMiFlushDwCmd(
810     PMOS_RESOURCE                             semaMem,
811     uint32_t                                  semaData,
812     PMOS_COMMAND_BUFFER                       cmdBuffer)
813 {
814     MOS_STATUS           eStatus = MOS_STATUS_SUCCESS;
815     MHW_MI_ATOMIC_PARAMS atomicParams;
816 
817     VP_RENDER_CHK_NULL_RETURN(m_hwInterface);
818     VP_RENDER_CHK_NULL_RETURN(m_miItf);
819 
820     // Send MI_FLUSH command
821     auto& parFlush = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
822     parFlush = {};
823     parFlush.bVideoPipelineCacheInvalidate = true;
824     if (!Mos_ResourceIsNull(semaMem))
825     {
826         parFlush.pOsResource = semaMem;
827         parFlush.dwDataDW1   = semaData + 1;
828     }
829     VP_RENDER_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer));
830 
831     return eStatus;
832 }
833 
834 //!
835 //! \brief    Send mi store data dword cmd
836 //! \details  Send mi store dat dword cmd for sync perpose
837 //!
838 //! \param    [in] resource
839 //!           Reource used in mi store dat dword cmd
840 //! \param    [in] offset
841 //!           offset of resource
842 //! \param    [in,out] cmdBuffer
843 //!           command buffer
844 //!
845 //! \return   MOS_STATUS
846 //!           MOS_STATUS_SUCCESS if success, else fail reason
847 //!
AddMiStoreDataImmCmd(PMOS_RESOURCE resource,uint32_t offset,PMOS_COMMAND_BUFFER cmdBuffer)848 MOS_STATUS VpScalabilityMultiPipeNext::AddMiStoreDataImmCmd(
849     PMOS_RESOURCE               resource,
850     uint32_t                    offset,
851     PMOS_COMMAND_BUFFER         cmdBuffer)
852 {
853     VP_FUNC_CALL();
854 
855     MOS_STATUS           eStatus = MOS_STATUS_SUCCESS;
856     MHW_MI_ATOMIC_PARAMS atomicParams;
857 
858     VP_RENDER_CHK_NULL_RETURN(m_hwInterface);
859     VP_RENDER_CHK_NULL_RETURN(m_miItf);
860 
861     auto &params             = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
862     params                   = {};
863     params.pOsResource       = resource;
864     params.dwResourceOffset  = offset;
865     params.dwValue           = 0;
866     eStatus                  = m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(cmdBuffer);
867 
868     return eStatus;
869 }
870 
CreateMultiPipe(void * hwInterface,MediaContext * mediaContext,uint8_t componentType)871 MOS_STATUS VpScalabilityMultiPipeNext::CreateMultiPipe(void *hwInterface, MediaContext *mediaContext, uint8_t componentType)
872 {
873     SCALABILITY_CHK_NULL_RETURN(hwInterface);
874     SCALABILITY_CHK_NULL_RETURN(mediaContext);
875 
876     ((PVP_MHWINTERFACE)hwInterface)->m_multiPipeScalability = MOS_New(VpScalabilityMultiPipeNext, hwInterface, mediaContext, scalabilityVp);
877     SCALABILITY_CHK_NULL_RETURN(((PVP_MHWINTERFACE)hwInterface)->m_multiPipeScalability);
878     return MOS_STATUS_SUCCESS;
879 }
880 
881 }
882