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 ¶ms = 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 ¶ms = 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 ¶ms = 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