1 /*
2 * Copyright (c) 2018-2022, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 //!
24 //! \file encode_scalability_multipipe.cpp
25 //! \brief Defines the common interface for encode scalability multipipe mode.
26 //!
27
28 #include "encode_scalability_multipipe.h"
29
30 #include "media_context.h"
31 #include "media_status_report.h"
32 #include "mhw_utilities.h"
33 #include "encode_status_report_defs.h"
34 #include "hal_oca_interface_next.h"
35 #include "mos_os_virtualengine_next.h"
36 #include "mos_interface.h"
37
38 namespace encode
39 {
EncodeScalabilityMultiPipe(void * hwInterface,MediaContext * mediaContext,uint8_t componentType)40 EncodeScalabilityMultiPipe::EncodeScalabilityMultiPipe(void *hwInterface, MediaContext *mediaContext, uint8_t componentType) :
41 MediaScalabilityMultiPipe(mediaContext)
42 {
43 m_hwInterface = (CodechalHwInterfaceNext *)hwInterface;
44 m_componentType = componentType;
45 }
46
~EncodeScalabilityMultiPipe()47 EncodeScalabilityMultiPipe::~EncodeScalabilityMultiPipe()
48 {
49 }
AllocateSemaphore()50 MOS_STATUS EncodeScalabilityMultiPipe::AllocateSemaphore()
51 {
52 SCALABILITY_FUNCTION_ENTER;
53 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
54 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
55
56 uint32_t * data = nullptr;
57 MOS_LOCK_PARAMS lockFlagsWriteOnly;
58 MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
59 lockFlagsWriteOnly.WriteOnly = 1;
60 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
61 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
62 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
63 allocParamsForBufferLinear.Format = Format_Buffer;
64 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
65 allocParamsForBufferLinear.dwBytes = sizeof(uint32_t);
66 allocParamsForBufferLinear.pBufName = "Sync All Pipes SemaphoreMemory";
67
68 for (auto i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_resSemaphoreAllPipes); i++)
69 {
70 SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
71 m_osInterface,
72 &allocParamsForBufferLinear,
73 &m_resSemaphoreAllPipes[i]),
74 "Cannot create HW semaphore for scalability all pipes sync.");
75 data = (uint32_t *)m_osInterface->pfnLockResource(
76 m_osInterface,
77 &m_resSemaphoreAllPipes[i],
78 &lockFlagsWriteOnly);
79 SCALABILITY_CHK_NULL_RETURN(data);
80 *data = 0;
81 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
82 m_osInterface,
83 &m_resSemaphoreAllPipes[i]));
84 }
85
86 allocParamsForBufferLinear.pBufName = "Sync One Pipe Wait SemaphoreMemory";
87
88 for (auto i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_resSemaphoreOnePipeWait); i++)
89 {
90 SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
91 m_osInterface,
92 &allocParamsForBufferLinear,
93 &m_resSemaphoreOnePipeWait[i]),
94 "Cannot create HW semaphore for scalability one pipe sync.");
95 data = (uint32_t *)m_osInterface->pfnLockResource(
96 m_osInterface,
97 &m_resSemaphoreOnePipeWait[i],
98 &lockFlagsWriteOnly);
99 SCALABILITY_CHK_NULL_RETURN(data);
100 *data = 0;
101 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
102 m_osInterface,
103 &m_resSemaphoreOnePipeWait[i]));
104 }
105
106 allocParamsForBufferLinear.pBufName = "HW semaphore delay buffer";
107
108 SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
109 m_osInterface,
110 &allocParamsForBufferLinear,
111 &m_resDelayMinus),
112 "Cannot create HW semaphore delay buffer.");
113 data = (uint32_t *)m_osInterface->pfnLockResource(
114 m_osInterface,
115 &m_resDelayMinus,
116 &lockFlagsWriteOnly);
117 SCALABILITY_CHK_NULL_RETURN(data);
118 *data = 0;
119 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
120 m_osInterface,
121 &m_resDelayMinus));
122
123 allocParamsForBufferLinear.pBufName = "Sync One Pipe For Another SemaphoreMemory";
124
125 SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
126 m_osInterface,
127 &allocParamsForBufferLinear,
128 &m_resSemaphoreOnePipeForAnother),
129 "Cannot create HW semaphore for scalability one pipe wait for another.");
130 data = (uint32_t *)m_osInterface->pfnLockResource(
131 m_osInterface,
132 &m_resSemaphoreOnePipeForAnother,
133 &lockFlagsWriteOnly);
134 SCALABILITY_CHK_NULL_RETURN(data);
135 *data = 0;
136 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
137 m_osInterface,
138 &m_resSemaphoreOnePipeForAnother));
139
140 allocParamsForBufferLinear.pBufName = "Sync Other Pipes For One SemaphoreMemory";
141
142 SCALABILITY_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
143 m_osInterface,
144 &allocParamsForBufferLinear,
145 &m_resSemaphoreOtherPipesForOne),
146 "Cannot create HW semaphore for scalability other pipes wait for one.");
147 data = (uint32_t *)m_osInterface->pfnLockResource(
148 m_osInterface,
149 &m_resSemaphoreOtherPipesForOne,
150 &lockFlagsWriteOnly);
151 SCALABILITY_CHK_NULL_RETURN(data);
152 *data = 0;
153 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
154 m_osInterface,
155 &m_resSemaphoreOtherPipesForOne));
156
157 return eStatus;
158 }
Initialize(const MediaScalabilityOption & option)159 MOS_STATUS EncodeScalabilityMultiPipe::Initialize(const MediaScalabilityOption &option)
160 {
161 SCALABILITY_FUNCTION_ENTER;
162
163 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
164 m_osInterface = m_hwInterface->GetOsInterface();
165 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
166 m_miItf = m_hwInterface->GetMiInterfaceNext();
167 SCALABILITY_CHK_NULL_RETURN(m_miItf);
168 m_userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
169 if (!m_userSettingPtr)
170 {
171 ENCODE_NORMALMESSAGE("Initialize m_userSettingPtr instance failed!");
172 }
173
174 m_scalabilityOption = MOS_New(EncodeScalabilityOption, (const EncodeScalabilityOption &)option);
175 SCALABILITY_CHK_NULL_RETURN(m_scalabilityOption);
176
177 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
178
179 MediaUserSetting::Value outValue;
180 auto statusKey = ReadUserSetting(
181 m_userSettingPtr,
182 outValue,
183 "Enable Frame Tracking",
184 MediaUserSetting::Group::Sequence);
185
186 if (statusKey == MOS_STATUS_SUCCESS)
187 {
188 m_frameTrackingEnabled = outValue.Get<bool>();
189 }
190 else
191 {
192 m_frameTrackingEnabled = m_osInterface->bEnableKmdMediaFrameTracking ? true : false;
193 }
194
195 //virtual engine init with scalability
196 MOS_VIRTUALENGINE_INIT_PARAMS veInitParms;
197 MOS_ZeroMemory(&veInitParms, sizeof(veInitParms));
198 veInitParms.bScalabilitySupported = true;
199
200 // Disabling the Secondary command buffer creation in MOS_VE
201 // To be programmed once Encode moves to using secondary command buffers in MOS VE interface
202 veInitParms.ucMaxNumPipesInUse = MOS_MAX_ENGINE_INSTANCE_PER_CLASS;
203 veInitParms.ucNumOfSdryCmdBufSets = 16;
204 veInitParms.ucMaxNumOfSdryCmdBufInOneFrame = veInitParms.ucMaxNumPipesInUse * m_maxNumBRCPasses;
205
206 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnVirtualEngineInit(m_osInterface, &m_veHitParams, veInitParms));
207 SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState);
208 m_veState = m_osInterface->osStreamState->virtualEngineInterface;
209 SCALABILITY_CHK_NULL_RETURN(m_veState);
210 SCALABILITY_CHK_NULL_RETURN(m_veHitParams);
211
212 m_pipeNum = m_scalabilityOption->GetNumPipe();
213 if (m_pipeNum > m_maxPipeNum)
214 {
215 SCALABILITY_ASSERTMESSAGE("numPipe exceed max supported pipe number!");
216 return MOS_STATUS_INVALID_PARAMETER;
217 }
218 m_pipeIndexForSubmit = m_pipeNum;
219
220 PMOS_GPUCTX_CREATOPTIONS_ENHANCED gpuCtxCreateOption = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
221 SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
222 gpuCtxCreateOption->LRCACount = m_scalabilityOption->GetNumPipe();
223 gpuCtxCreateOption->UsingSFC = false;
224
225 EncodeScalabilityOption *scalabilityOption =
226 dynamic_cast<EncodeScalabilityOption *>(m_scalabilityOption);
227 if (scalabilityOption != nullptr && scalabilityOption->IsVdencEnabled())
228 {
229 gpuCtxCreateOption->Flags |= (1 << 2);
230 }
231 #if (_DEBUG || _RELEASE_INTERNAL)
232 if (m_osInterface->bEnableDbgOvrdInVE)
233 {
234 gpuCtxCreateOption->DebugOverride = true;
235 for (uint32_t i = 0; i < m_osInterface->pfnGetVeEngineCount(m_osInterface->osStreamState); i++)
236 {
237 gpuCtxCreateOption->EngineInstance[i] =
238 m_osInterface->pfnGetEngineLogicIdByIdx(m_osInterface->osStreamState, i);
239 }
240 }
241 #endif
242 m_gpuCtxCreateOption = (PMOS_GPUCTX_CREATOPTIONS)(gpuCtxCreateOption);
243
244 //Allocate and init for semaphores
245 SCALABILITY_CHK_STATUS_RETURN(AllocateSemaphore());
246
247 //Update encoder scalability status
248 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSetMultiEngineEnabled(m_osInterface, COMPONENT_Encode, true));
249 return eStatus;
250 }
251
GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS * gpuCtxCreateOption)252 MOS_STATUS EncodeScalabilityMultiPipe::GetGpuCtxCreationOption(MOS_GPUCTX_CREATOPTIONS *gpuCtxCreateOption)
253 {
254 SCALABILITY_FUNCTION_ENTER;
255 SCALABILITY_CHK_NULL_RETURN(gpuCtxCreateOption);
256 SCALABILITY_CHK_NULL_RETURN(m_gpuCtxCreateOption);
257
258 MOS_GPUCTX_CREATOPTIONS_ENHANCED *dest = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(gpuCtxCreateOption);
259 MOS_GPUCTX_CREATOPTIONS_ENHANCED *source = dynamic_cast<MOS_GPUCTX_CREATOPTIONS_ENHANCED *>(m_gpuCtxCreateOption);
260
261 SCALABILITY_CHK_NULL_RETURN(dest);
262 SCALABILITY_CHK_NULL_RETURN(source);
263
264 *dest = *source;
265 return MOS_STATUS_SUCCESS;
266 }
267
Destroy()268 MOS_STATUS EncodeScalabilityMultiPipe::Destroy()
269 {
270 SCALABILITY_FUNCTION_ENTER;
271
272 SCALABILITY_CHK_STATUS_RETURN(MediaScalability::Destroy());
273
274 if (m_gpuCtxCreateOption)
275 {
276 MOS_Delete(m_gpuCtxCreateOption);
277 }
278 if (m_scalabilityOption)
279 {
280 MOS_Delete(m_scalabilityOption);
281 }
282
283 for (auto i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_resSemaphoreAllPipes); i++)
284 {
285 m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreAllPipes[i]);
286 }
287 for (auto i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_resSemaphoreOnePipeWait); i++)
288 {
289 m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreOnePipeWait[i]);
290 }
291
292 m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreOnePipeForAnother);
293
294 m_osInterface->pfnFreeResource(m_osInterface, &m_resSemaphoreOtherPipesForOne);
295
296 m_osInterface->pfnFreeResource(m_osInterface, &m_resDelayMinus);
297
298 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSetMultiEngineEnabled(m_osInterface, COMPONENT_Encode, false));
299
300 return MOS_STATUS_SUCCESS;
301 }
302
ResizeCommandBufferAndPatchList(uint32_t requestedCommandBufferSize,uint32_t requestedPatchListSize)303 MOS_STATUS EncodeScalabilityMultiPipe::ResizeCommandBufferAndPatchList(
304 uint32_t requestedCommandBufferSize,
305 uint32_t requestedPatchListSize)
306 {
307 SCALABILITY_FUNCTION_ENTER;
308 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
309
310 return m_hwInterface->ResizeCommandBufferAndPatchList(requestedCommandBufferSize, requestedPatchListSize);
311 }
312
313 //Move it to MediaScalabiliyt if decode&VP can share it. Curryt only EncodeMultiPipe/SiglePipe can share it.
VerifySpaceAvailable(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)314 MOS_STATUS EncodeScalabilityMultiPipe::VerifySpaceAvailable(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
315 {
316 SCALABILITY_FUNCTION_ENTER;
317 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
318 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
319
320 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
321 MOS_STATUS statusPatchList = MOS_STATUS_SUCCESS;
322 MOS_STATUS statusCmdBuf = MOS_STATUS_SUCCESS;
323
324 bool bothPatchListAndCmdBufChkSuccess = false;
325 uint8_t looptimes = m_singleTaskPhaseSupported ? 2 : 1;
326
327 for(auto i = 0 ; i < looptimes ; i++)
328 {
329 SCALABILITY_CHK_STATUS_RETURN(MediaScalability::VerifySpaceAvailable(
330 requestedSize, requestedPatchListSize, bothPatchListAndCmdBufChkSuccess));
331 if (bothPatchListAndCmdBufChkSuccess == true)
332 {
333 singleTaskPhaseSupportedInPak = m_singleTaskPhaseSupported;
334 return eStatus;
335 }
336
337 if (requestedPatchListSize)
338 {
339 statusPatchList = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
340 m_osInterface,
341 requestedPatchListSize);
342 }
343 statusCmdBuf = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
344 m_osInterface,
345 requestedSize,
346 0);
347 if ((statusCmdBuf == MOS_STATUS_SUCCESS) && (statusPatchList == MOS_STATUS_SUCCESS))
348 {
349 singleTaskPhaseSupportedInPak = m_singleTaskPhaseSupported;
350 return eStatus;
351 }
352 }
353
354 eStatus = MOS_STATUS_NO_SPACE;
355 SCALABILITY_ASSERTMESSAGE("Resize Command buffer failed with no space!");
356 return eStatus;
357 }
358
VerifyCmdBuffer(uint32_t requestedSize,uint32_t requestedPatchListSize,bool & singleTaskPhaseSupportedInPak)359 MOS_STATUS EncodeScalabilityMultiPipe::VerifyCmdBuffer(uint32_t requestedSize, uint32_t requestedPatchListSize, bool &singleTaskPhaseSupportedInPak)
360 {
361 SCALABILITY_FUNCTION_ENTER;
362 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
363 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
364
365 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
366
367 // Verify Primary Cmd buffer.
368 SCALABILITY_CHK_STATUS_RETURN(VerifySpaceAvailable(
369 requestedSize, requestedPatchListSize, singleTaskPhaseSupportedInPak));
370
371 // Verify all pipes' secondary cmd buffers
372 for (uint8_t currentPipeVerify = 0; currentPipeVerify < m_pipeNum; currentPipeVerify++)
373 {
374 MOS_STATUS statusPatchList = MOS_STATUS_SUCCESS;
375 MOS_STATUS statusCmdBuf = MOS_STATUS_SUCCESS;
376
377
378 //Verify 2nd level BB;
379 uint32_t bufIdxPlus1 = currentPipeVerify + 1; //Make CMD buffer one next to one.
380
381 eStatus = MOS_STATUS_NO_SPACE;
382 for (auto i = 0; (i < 3) && (eStatus != MOS_STATUS_SUCCESS); i++)
383 {
384 // Verify secondary cmd buffer
385 eStatus = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
386 m_osInterface,
387 requestedSize,
388 bufIdxPlus1);
389 if (eStatus != MOS_STATUS_SUCCESS)
390 {
391 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnResizeCommandBufferAndPatchList(
392 m_osInterface,
393 requestedSize,
394 0,
395 bufIdxPlus1));
396 // Set status to NO_SPACE to enter the commaned buffer size verification on next loop.
397 eStatus = MOS_STATUS_NO_SPACE;
398 SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with no space!");
399 }
400 }
401 }
402 return eStatus;
403 }
404
GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer,bool frameTrackingRequested)405 MOS_STATUS EncodeScalabilityMultiPipe::GetCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer, bool frameTrackingRequested)
406 {
407 SCALABILITY_FUNCTION_ENTER;
408 SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
409 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
410
411 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
412 PMOS_COMMAND_BUFFER scdryCmdBuffer;
413
414 if (m_currentPipe >= m_pipeNum)
415 {
416 eStatus = MOS_STATUS_INVALID_PARAMETER;
417 SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPipe!");
418 return eStatus;
419 }
420 if (m_currentPass >= m_maxNumBRCPasses)
421 {
422 eStatus = MOS_STATUS_INVALID_PARAMETER;
423 SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPass!");
424 return eStatus;
425 }
426
427 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0));
428 uint32_t bufIdxPlus1 = m_currentPipe + 1; //Make CMD buffer one next to one.
429 m_osInterface->pfnGetCommandBuffer(m_osInterface, &m_secondaryCmdBuffer[bufIdxPlus1 - 1], bufIdxPlus1);
430
431 if (m_osInterface->apoMosEnabled)
432 {
433 int32_t submissionType = IsFirstPipe() ? SUBMISSION_TYPE_MULTI_PIPE_MASTER : SUBMISSION_TYPE_MULTI_PIPE_SLAVE;
434 if (IsLastPipe())
435 {
436 submissionType |= SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE;
437 }
438 SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState);
439 SCALABILITY_CHK_NULL_RETURN(m_osInterface->osStreamState->virtualEngineInterface);
440 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->osStreamState->virtualEngineInterface->SetSubmissionType(&(m_secondaryCmdBuffer[bufIdxPlus1 - 1]), submissionType));
441 }
442 else
443 {
444 m_secondaryCmdBuffer[bufIdxPlus1 - 1].iSubmissionType =
445 IsFirstPipe() ? SUBMISSION_TYPE_MULTI_PIPE_MASTER : SUBMISSION_TYPE_MULTI_PIPE_SLAVE;
446
447 if (IsLastPipe())
448 {
449 m_secondaryCmdBuffer[bufIdxPlus1 - 1].iSubmissionType |= SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE;
450 }
451 }
452 *cmdBuffer = m_secondaryCmdBuffer[bufIdxPlus1 - 1];
453
454 SCALABILITY_CHK_NULL_RETURN(m_osInterface->osCpInterface);
455 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
456
457 if (!m_attrReady)
458 {
459 SCALABILITY_CHK_STATUS_RETURN(SendAttrWithFrameTracking(m_primaryCmdBuffer, frameTrackingRequested));
460 m_attrReady = true;
461 }
462 return eStatus;
463 }
ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)464 MOS_STATUS EncodeScalabilityMultiPipe::ReturnCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
465 {
466 SCALABILITY_FUNCTION_ENTER;
467 SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
468 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
469
470 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
471
472 if (m_currentPipe >= m_pipeNum)
473 {
474 eStatus = MOS_STATUS_INVALID_PARAMETER;
475 SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPipe!");
476 return eStatus;
477 }
478 if (m_currentPass >= m_maxNumBRCPasses)
479 {
480 eStatus = MOS_STATUS_INVALID_PARAMETER;
481 SCALABILITY_ASSERTMESSAGE("Verify Command buffer failed with invalid parameter:currentPass!");
482 return eStatus;
483 }
484 uint32_t bufIdxPlus1 = m_currentPipe + 1; //Make CMD buffer one next to one.
485 m_secondaryCmdBuffer[bufIdxPlus1 - 1] = *cmdBuffer; //Need to record the iOffset, ptr and other data of CMD buffer, it's not maintain in the mos.
486 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_secondaryCmdBuffer[bufIdxPlus1 - 1], bufIdxPlus1);
487 m_primaryCmdBuffer.Attributes.bFrequencyBoost |= cmdBuffer->Attributes.bFrequencyBoost;
488 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &m_primaryCmdBuffer, 0);
489 return eStatus;
490 }
SetHintParams()491 MOS_STATUS EncodeScalabilityMultiPipe::SetHintParams()
492 {
493 SCALABILITY_FUNCTION_ENTER;
494
495 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
496
497 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
498 MOS_VIRTUALENGINE_SET_PARAMS veParams;
499 MOS_ZeroMemory(&veParams, sizeof(veParams));
500
501 veParams.ucScalablePipeNum = m_pipeNum;
502 veParams.bScalableMode = true;
503
504 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSetHintParams(m_osInterface, &veParams));
505 return eStatus;
506 }
PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)507 MOS_STATUS EncodeScalabilityMultiPipe::PopulateHintParams(PMOS_COMMAND_BUFFER cmdBuffer)
508 {
509 SCALABILITY_FUNCTION_ENTER;
510 SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
511 SCALABILITY_CHK_NULL_RETURN(m_veHitParams);
512 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
513
514 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
515 PMOS_CMD_BUF_ATTRI_VE attriVe = m_osInterface->pfnGetAttributeVeBuffer(cmdBuffer);
516 if (attriVe)
517 {
518 attriVe->VEngineHintParams = *(m_veHitParams);
519 attriVe->bUseVirtualEngineHint = true;
520 }
521 return eStatus;
522 }
523
SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)524 MOS_STATUS EncodeScalabilityMultiPipe::SubmitCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
525 {
526 SCALABILITY_FUNCTION_ENTER;
527 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
528
529 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
530
531 bool cmdBufferReadyForSubmit = IsPipeReadyToSubmit();
532
533 // Hold the actual command buffer submission till last pipe
534 if (!cmdBufferReadyForSubmit)
535 {
536 return eStatus;
537 }
538
539 // Add BB end for every secondary cmd buf when ready for submit
540 for (uint32_t pipe = 0; pipe < m_pipeNum; pipe++)
541 {
542 uint32_t bufIdxPlus1 = pipe + 1;
543
544 MOS_COMMAND_BUFFER& cmdBufferToAddBbEnd = m_secondaryCmdBuffer[bufIdxPlus1 - 1];
545 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBufferToAddBbEnd, bufIdxPlus1));
546 SCALABILITY_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(&cmdBufferToAddBbEnd, nullptr));
547 SCALABILITY_CHK_STATUS_RETURN(Oca1stLevelBBEnd(cmdBufferToAddBbEnd));
548 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBufferToAddBbEnd, bufIdxPlus1);
549 }
550
551 m_attrReady = false;
552
553 SCALABILITY_CHK_STATUS_RETURN(SetHintParams());
554 SCALABILITY_CHK_STATUS_RETURN(PopulateHintParams(&m_primaryCmdBuffer));
555
556 SCALABILITY_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &m_primaryCmdBuffer, false));
557
558 return eStatus;
559 }
SyncAllPipes(uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)560 MOS_STATUS EncodeScalabilityMultiPipe::SyncAllPipes(uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
561 {
562 SCALABILITY_FUNCTION_ENTER;
563 SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
564 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
565 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
566
567 if (semaphoreId >= m_maxSemaphoreNum)
568 {
569 SCALABILITY_ASSERTMESSAGE("SyncAllPipes failed with invalid parameter:semaphoreId!");
570 return MOS_STATUS_INVALID_PARAMETER;
571 }
572 if (Mos_ResourceIsNull(&m_resSemaphoreAllPipes[semaphoreId]))
573 {
574 return MOS_STATUS_UNKNOWN;
575 }
576 //Not stop watch dog here, expect to stop it in the packet when needed.
577 //HW Semaphore cmd to make sure all pipes start encode at the same time
578 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreAllPipes[semaphoreId], 1, MHW_MI_ATOMIC_INC, cmdBuffer));
579 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendHwSemaphoreWaitCmd(
580 &m_resSemaphoreAllPipes[semaphoreId],
581 m_pipeNum,
582 MHW_MI_SAD_EQUAL_SDD,
583 cmdBuffer));
584
585 // Program some placeholder cmds to resolve the hazard between pipe sync
586 auto &storeDataParams = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
587 storeDataParams = {};
588 storeDataParams.pOsResource = &m_resDelayMinus;
589 storeDataParams.dwResourceOffset = 0;
590 storeDataParams.dwValue = 0xDE1A;
591
592 for (uint32_t i = 0; i < m_numDelay; i++)
593 {
594 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(cmdBuffer));
595 }
596
597 //clean HW semaphore memory
598 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreAllPipes[semaphoreId], 1, MHW_MI_ATOMIC_DEC, cmdBuffer));
599 return eStatus;
600 }
SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer)601 MOS_STATUS EncodeScalabilityMultiPipe::SyncOnePipeWaitOthers(PMOS_COMMAND_BUFFER cmdBuffer)
602 {
603 SCALABILITY_FUNCTION_ENTER;
604 SCALABILITY_CHK_NULL_RETURN(cmdBuffer);
605
606 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
607
608 // Send MI_FLUSH command
609 auto &miFlushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
610 miFlushDwParams = {};
611 miFlushDwParams.bVideoPipelineCacheInvalidate = true;
612
613 if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait[m_currentPipe]))
614 {
615 miFlushDwParams.pOsResource = &m_resSemaphoreOnePipeWait[m_currentPipe];
616 miFlushDwParams.dwDataDW1 = m_currentPass + 1;
617 }
618 SCALABILITY_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer));
619
620 if (IsFirstPipe())
621 {
622 // first pipe needs to ensure all other pipes are ready
623 for (uint32_t i = 1; i < m_pipeNum; i++)
624 {
625 if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait[i]))
626 {
627 SCALABILITY_CHK_STATUS_RETURN(
628 m_hwInterface->SendHwSemaphoreWaitCmd(
629 &m_resSemaphoreOnePipeWait[i],
630 m_currentPass + 1,
631 MHW_MI_SAD_EQUAL_SDD,
632 cmdBuffer));
633 }
634 }
635 }
636 return eStatus;
637 }
SyncPipe(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)638 MOS_STATUS EncodeScalabilityMultiPipe::SyncPipe(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
639 {
640 SCALABILITY_FUNCTION_ENTER;
641 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
642 switch (syncType)
643 {
644 case syncAllPipes:
645 eStatus = SyncAllPipes(semaphoreId, cmdBuffer);
646 break;
647 case syncOnePipeWaitOthers:
648 eStatus = SyncOnePipeWaitOthers(cmdBuffer);
649 break;
650 case syncOnePipeForAnother:
651 eStatus = SyncOnePipeForAnother(cmdBuffer);
652 break;
653 case syncOtherPipesForOne:
654 eStatus = SyncOtherPipesForOne(cmdBuffer);
655 break;
656 default:
657 eStatus = MOS_STATUS_INVALID_PARAMETER;
658 break;
659 }
660 return eStatus;
661 }
ResetSemaphore(uint32_t syncType,uint32_t semaphoreId,PMOS_COMMAND_BUFFER cmdBuffer)662 MOS_STATUS EncodeScalabilityMultiPipe::ResetSemaphore(uint32_t syncType, uint32_t semaphoreId, PMOS_COMMAND_BUFFER cmdBuffer)
663 {
664 SCALABILITY_FUNCTION_ENTER;
665 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
666 switch (syncType)
667 {
668 case syncAllPipes:
669 if (semaphoreId >= m_maxSemaphoreNum)
670 {
671 SCALABILITY_ASSERTMESSAGE("SyncAllPipes failed with invalid parameter:semaphoreId!");
672 return MOS_STATUS_INVALID_PARAMETER;
673 }
674 if (!Mos_ResourceIsNull(&m_resSemaphoreAllPipes[semaphoreId]))
675 {
676 SCALABILITY_CHK_STATUS_RETURN(
677 m_hwInterface->SendMiStoreDataImm(
678 &m_resSemaphoreAllPipes[semaphoreId],
679 0,
680 cmdBuffer));
681 }
682 break;
683 case syncOnePipeWaitOthers:
684 if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeWait[semaphoreId]))
685 {
686 SCALABILITY_CHK_STATUS_RETURN(
687 m_hwInterface->SendMiStoreDataImm(
688 &m_resSemaphoreOnePipeWait[semaphoreId],
689 0,
690 cmdBuffer));
691 }
692 break;
693 case syncOnePipeForAnother:
694 if (!Mos_ResourceIsNull(&m_resSemaphoreOnePipeForAnother))
695 {
696 SCALABILITY_CHK_STATUS_RETURN(
697 m_hwInterface->SendMiStoreDataImm(
698 &m_resSemaphoreOnePipeForAnother,
699 0,
700 cmdBuffer));
701 }
702 break;
703 case syncOtherPipesForOne:
704 if (!Mos_ResourceIsNull(&m_resSemaphoreOtherPipesForOne))
705 {
706 SCALABILITY_CHK_STATUS_RETURN(
707 m_hwInterface->SendMiStoreDataImm(
708 &m_resSemaphoreOtherPipesForOne,
709 0,
710 cmdBuffer));
711 }
712 break;
713 default:
714 SCALABILITY_ASSERTMESSAGE("Reset semaphore failed with invalid parameter: syncType!");
715 eStatus = MOS_STATUS_INVALID_PARAMETER;
716 break;
717 }
718 return eStatus;
719 }
UpdateState(void * statePars)720 MOS_STATUS EncodeScalabilityMultiPipe::UpdateState(void *statePars)
721 {
722 SCALABILITY_FUNCTION_ENTER;
723 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
724 StateParams *encodeStatePars = (StateParams *)statePars;
725 if (encodeStatePars->currentPipe >= m_pipeNum)
726 {
727 eStatus = MOS_STATUS_INVALID_PARAMETER;
728 SCALABILITY_ASSERTMESSAGE("UpdateState failed with invalid parameter:currentPipe!");
729 return eStatus;
730 }
731 if (m_currentPass >= m_maxNumBRCPasses)
732 {
733 eStatus = MOS_STATUS_INVALID_PARAMETER;
734 SCALABILITY_ASSERTMESSAGE("UpdateState failed with invalid parameter:currentPass!");
735 return eStatus;
736 }
737 m_currentPipe = encodeStatePars->currentPipe;
738 m_currentPass = encodeStatePars->currentPass;
739 m_pipeIndexForSubmit = encodeStatePars->pipeIndexForSubmit;
740 m_singleTaskPhaseSupported = encodeStatePars->singleTaskPhaseSupported;
741 m_statusReport = encodeStatePars->statusReport;
742 m_currentRow = encodeStatePars->currentRow;
743 m_currentSubPass = encodeStatePars->currentSubPass;
744 return eStatus;
745 }
746
SendAttrWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)747 MOS_STATUS EncodeScalabilityMultiPipe::SendAttrWithFrameTracking(
748 MOS_COMMAND_BUFFER &cmdBuffer,
749 bool frameTrackingRequested)
750 {
751 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
752
753 SCALABILITY_FUNCTION_ENTER;
754
755 bool renderEngineUsed = m_mediaContext->IsRenderEngineUsed();
756
757 // initialize command buffer attributes
758 cmdBuffer.Attributes.bTurboMode = m_hwInterface->m_turboMode;
759 cmdBuffer.Attributes.bMediaPreemptionEnabled = renderEngineUsed ? m_hwInterface->GetRenderInterfaceNext()->IsPreemptionEnabled() : 0;
760 cmdBuffer.Attributes.dwNumRequestedEUSlices = m_hwInterface->m_numRequestedEuSlices;
761 cmdBuffer.Attributes.dwNumRequestedSubSlices = m_hwInterface->m_numRequestedSubSlices;
762 cmdBuffer.Attributes.dwNumRequestedEUs = m_hwInterface->m_numRequestedEus;
763 cmdBuffer.Attributes.bValidPowerGatingRequest = true;
764
765 PMOS_RESOURCE resource = nullptr;
766 uint32_t offset = 0;
767
768 if (frameTrackingRequested && m_frameTrackingEnabled)
769 {
770 m_statusReport->GetAddress(encode::statusReportGlobalCount, resource, offset);
771 cmdBuffer.Attributes.bEnableMediaFrameTracking = true;
772 cmdBuffer.Attributes.resMediaFrameTrackingSurface = resource;
773 cmdBuffer.Attributes.dwMediaFrameTrackingTag = m_statusReport->GetSubmittedCount() + 1;
774 // Set media frame tracking address offset(the offset from the encoder status buffer page)
775 cmdBuffer.Attributes.dwMediaFrameTrackingAddrOffset = 0;
776 }
777
778 return eStatus;
779 }
780
SyncOnePipeForAnother(PMOS_COMMAND_BUFFER cmdBuffer)781 MOS_STATUS EncodeScalabilityMultiPipe::SyncOnePipeForAnother(PMOS_COMMAND_BUFFER cmdBuffer)
782 {
783 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
784
785 SCALABILITY_FUNCTION_ENTER;
786
787 if (m_currentPipe == 0)
788 {
789 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreOnePipeForAnother, 1, MHW_MI_ATOMIC_INC, cmdBuffer));
790 }
791 else
792 {
793 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendHwSemaphoreWaitCmd(
794 &m_resSemaphoreOnePipeForAnother,
795 1,
796 MHW_MI_SAD_EQUAL_SDD,
797 cmdBuffer));
798 //clean HW semaphore memory
799 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreOnePipeForAnother, 1, MHW_MI_ATOMIC_DEC, cmdBuffer));
800 }
801
802 return eStatus;
803 }
804
SyncOtherPipesForOne(PMOS_COMMAND_BUFFER cmdBuffer)805 MOS_STATUS EncodeScalabilityMultiPipe::SyncOtherPipesForOne(PMOS_COMMAND_BUFFER cmdBuffer)
806 {
807 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
808
809 SCALABILITY_FUNCTION_ENTER;
810
811 if (m_currentPipe == 0)
812 {
813 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreOtherPipesForOne, m_pipeNum - 1, MHW_MI_ATOMIC_INC, cmdBuffer));
814 }
815 else
816 {
817 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendHwSemaphoreWaitCmd(
818 &m_resSemaphoreOtherPipesForOne,
819 0,
820 MHW_MI_SAD_NOT_EQUAL_SDD,
821 cmdBuffer));
822 //clean HW semaphore memory
823 SCALABILITY_CHK_STATUS_RETURN(m_hwInterface->SendMiAtomicDwordCmd(&m_resSemaphoreOtherPipesForOne, 1, MHW_MI_ATOMIC_DEC, cmdBuffer));
824 }
825
826 return eStatus;
827 }
828
Oca1stLevelBBStart(MOS_COMMAND_BUFFER & cmdBuffer)829 MOS_STATUS EncodeScalabilityMultiPipe::Oca1stLevelBBStart(MOS_COMMAND_BUFFER &cmdBuffer)
830 {
831 MHW_MI_MMIOREGISTERS mmioRegister;
832 SCALABILITY_CHK_NULL_RETURN(m_hwInterface);
833
834 auto vdencItf = m_hwInterface->GetVdencInterfaceNext();
835 SCALABILITY_CHK_NULL_RETURN(vdencItf);
836 bool validMmio = vdencItf->ConvertToMiRegister(MHW_VDBOX_NODE_1, mmioRegister);
837
838 if (validMmio)
839 {
840 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
841 SCALABILITY_CHK_NULL_RETURN(m_osInterface->pOsContext);
842
843 HalOcaInterfaceNext::On1stLevelBBStart(
844 cmdBuffer,
845 (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext,
846 m_osInterface->CurrentGpuContextHandle,
847 m_miItf,
848 mmioRegister);
849 }
850
851 return MOS_STATUS_SUCCESS;
852 }
853
Oca1stLevelBBEnd(MOS_COMMAND_BUFFER & cmdBuffer)854 MOS_STATUS EncodeScalabilityMultiPipe::Oca1stLevelBBEnd(MOS_COMMAND_BUFFER &cmdBuffer)
855 {
856 SCALABILITY_CHK_NULL_RETURN(m_osInterface);
857 HalOcaInterfaceNext::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
858
859 return MOS_STATUS_SUCCESS;
860 }
861
862 }
863