1 /*
2 * Copyright (c) 2018-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file mos_gpucontext_specific.cpp
24 //! \brief Container class for the Linux specific gpu context
25 //!
26
27 #include <unistd.h>
28 #include "mos_context_specific.h"
29 #include "mos_gpucontext_specific.h"
30 #include "mos_graphicsresource_specific.h"
31 #include "mos_commandbuffer_specific.h"
32 #include "mos_util_devult_specific.h"
33 #include "mos_cmdbufmgr.h"
34 #include "mos_os_virtualengine.h"
35 #include "mos_os_cp_interface_specific.h"
36
37 #define MI_BATCHBUFFER_END 0x05000000
38 static pthread_mutex_t command_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
39
GpuContextSpecific(const MOS_GPU_NODE gpuNode,MOS_GPU_CONTEXT mosGpuCtx,CmdBufMgr * cmdBufMgr,GpuContext * reusedContext)40 GpuContextSpecific::GpuContextSpecific(
41 const MOS_GPU_NODE gpuNode,
42 MOS_GPU_CONTEXT mosGpuCtx,
43 CmdBufMgr *cmdBufMgr,
44 GpuContext *reusedContext)
45 {
46 MOS_OS_FUNCTION_ENTER;
47
48 m_nodeOrdinal = gpuNode;
49 m_cmdBufMgr = cmdBufMgr;
50 m_gpuContext = mosGpuCtx;
51 m_statusBufferResource = nullptr;
52 m_maxPatchLocationsize = PATCHLOCATIONLIST_SIZE;
53
54 if (reusedContext)
55 {
56 MOS_OS_NORMALMESSAGE("gpucontex reusing not enabled on Linux.");
57 }
58
59 #if (_DEBUG || _RELEASE_INTERNAL)
60 // get user engine instance setting from environment variable
61 char *engineInstances = getenv("INTEL_ENGINE_INSTANCE");
62 if (engineInstances != nullptr)
63 {
64 errno = 0;
65 long int instance = strtol(engineInstances, nullptr, 16);
66 /* Check for various possible errors. */
67 if ((errno == ERANGE && instance == LONG_MAX) || (instance < 0))
68 {
69 MOS_OS_NORMALMESSAGE("Invalid INTEL_ENGINE_INSTANCE setting.(%s)\n", engineInstances);
70 m_engineInstanceSelect = 0x0;
71 }
72 else
73 {
74 m_engineInstanceSelect = (uint32_t)instance;
75 }
76 }
77 #endif
78 }
79
~GpuContextSpecific()80 GpuContextSpecific::~GpuContextSpecific()
81 {
82 MOS_OS_FUNCTION_ENTER;
83
84 Clear();
85 }
86
Init(OsContext * osContext,PMOS_INTERFACE osInterface,MOS_GPU_NODE GpuNode,PMOS_GPUCTX_CREATOPTIONS createOption)87 MOS_STATUS GpuContextSpecific::Init(OsContext *osContext,
88 PMOS_INTERFACE osInterface,
89 MOS_GPU_NODE GpuNode,
90 PMOS_GPUCTX_CREATOPTIONS createOption)
91 {
92 MOS_OS_FUNCTION_ENTER;
93
94 MOS_OS_CHK_NULL_RETURN(osContext);
95
96 if (m_cmdBufPoolMutex == nullptr)
97 {
98 m_cmdBufPoolMutex = MosUtilities::MosCreateMutex();
99 }
100
101 MOS_OS_CHK_NULL_RETURN(m_cmdBufPoolMutex);
102
103 MosUtilities::MosLockMutex(m_cmdBufPoolMutex);
104
105 m_cmdBufPool.clear();
106
107 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
108
109 m_commandBufferSize = COMMAND_BUFFER_SIZE;
110
111 m_nextFetchIndex = 0;
112
113 m_cmdBufFlushed = true;
114
115 m_osContext = osContext;
116
117 MOS_OS_CHK_STATUS_RETURN(AllocateGPUStatusBuf());
118
119 m_commandBuffer = (PMOS_COMMAND_BUFFER)MOS_AllocAndZeroMemory(sizeof(MOS_COMMAND_BUFFER));
120
121 MOS_OS_CHK_NULL_RETURN(m_commandBuffer);
122
123 m_IndirectHeapSize = 0;
124
125 // each thread has its own GPU context, so do not need any lock as guarder here
126 m_allocationList = (ALLOCATION_LIST *)MOS_AllocAndZeroMemory(sizeof(ALLOCATION_LIST) * ALLOCATIONLIST_SIZE);
127 MOS_OS_CHK_NULL_RETURN(m_allocationList);
128 m_maxNumAllocations = ALLOCATIONLIST_SIZE;
129
130 m_patchLocationList = (PATCHLOCATIONLIST *)MOS_AllocAndZeroMemory(sizeof(PATCHLOCATIONLIST) * PATCHLOCATIONLIST_SIZE);
131 MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
132 m_maxPatchLocationsize = PATCHLOCATIONLIST_SIZE;
133
134 m_attachedResources = (PMOS_RESOURCE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE) * ALLOCATIONLIST_SIZE);
135 MOS_OS_CHK_NULL_RETURN(m_attachedResources);
136
137 m_writeModeList = (bool *)MOS_AllocAndZeroMemory(sizeof(bool) * ALLOCATIONLIST_SIZE);
138 MOS_OS_CHK_NULL_RETURN(m_writeModeList);
139
140 m_GPUStatusTag = 1;
141
142 m_createOptionEnhanced = (MOS_GPUCTX_CREATOPTIONS_ENHANCED*)MOS_AllocAndZeroMemory(sizeof(MOS_GPUCTX_CREATOPTIONS_ENHANCED));
143 MOS_OS_CHK_NULL_RETURN(m_createOptionEnhanced);
144 m_createOptionEnhanced->SSEUValue = createOption->SSEUValue;
145
146 if (typeid(*createOption) == typeid(MOS_GPUCTX_CREATOPTIONS_ENHANCED))
147 {
148 PMOS_GPUCTX_CREATOPTIONS_ENHANCED createOptionEnhanced = static_cast<PMOS_GPUCTX_CREATOPTIONS_ENHANCED>(createOption);
149 m_createOptionEnhanced->UsingSFC = createOptionEnhanced->UsingSFC;
150 }
151
152 for (int i=0; i<MAX_ENGINE_INSTANCE_NUM+1; i++)
153 {
154 m_i915Context[i] = nullptr;
155 }
156
157 if (osInterface->ctxBasedScheduling)
158 {
159 unsigned int nengine = 0;
160 struct i915_engine_class_instance *engine_map = nullptr;
161
162 MOS_TraceEventExt(EVENT_GPU_CONTEXT_CREATE, EVENT_TYPE_START,
163 &GpuNode, sizeof(GpuNode), nullptr, 0);
164
165 m_i915Context[0] = mos_context_create_shared(osInterface->pOsContext->bufmgr,
166 osInterface->pOsContext->intel_context,
167 I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE,
168 false,
169 (void *)engine_map,
170 1,
171 nengine,
172 0);
173 if (m_i915Context[0] == nullptr)
174 {
175 MOS_OS_ASSERTMESSAGE("Failed to create context.\n");
176 return MOS_STATUS_UNKNOWN;
177 }
178 m_i915Context[0]->pOsContext = osInterface->pOsContext;
179
180 m_i915ExecFlag = I915_EXEC_DEFAULT;
181
182 if (mos_query_engines_count(osInterface->pOsContext->bufmgr, &nengine) || (nengine == 0))
183 {
184 MOS_OS_ASSERTMESSAGE("Failed to query engines count.\n");
185 return MOS_STATUS_UNKNOWN;
186 }
187 engine_map = (struct i915_engine_class_instance *)MOS_AllocAndZeroMemory(nengine * sizeof(struct i915_engine_class_instance));
188 MOS_OS_CHK_NULL_RETURN(engine_map);
189
190 if (GpuNode == MOS_GPU_NODE_3D)
191 {
192 __u16 engine_class = I915_ENGINE_CLASS_RENDER;
193 __u64 caps = 0;
194
195 if (mos_query_engines(osInterface->pOsContext->bufmgr, engine_class, caps, &nengine, (void *)engine_map))
196 {
197 MOS_OS_ASSERTMESSAGE("Failed to query engines.\n");
198 MOS_SafeFreeMemory(engine_map);
199 return MOS_STATUS_UNKNOWN;
200 }
201
202 if (mos_set_context_param_load_balance(m_i915Context[0], engine_map, nengine))
203 {
204 MOS_OS_ASSERTMESSAGE("Failed to set balancer extension.\n");
205 MOS_SafeFreeMemory(engine_map);
206 return MOS_STATUS_UNKNOWN;
207 }
208
209 if (createOption->SSEUValue != 0)
210 {
211 struct drm_i915_gem_context_param_sseu sseu;
212 MOS_ZeroMemory(&sseu, sizeof(sseu));
213 sseu.flags = I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX;
214 sseu.engine.engine_instance = m_i915ExecFlag;
215
216 if (mos_get_context_param_sseu(m_i915Context[0], &sseu))
217 {
218 MOS_OS_ASSERTMESSAGE("Failed to get sseu configuration.");
219 MOS_SafeFreeMemory(engine_map);
220 return MOS_STATUS_UNKNOWN;
221 }
222
223 if (mos_hweight8(m_i915Context[0], sseu.subslice_mask) > createOption->packed.SubSliceCount)
224 {
225 sseu.subslice_mask = mos_switch_off_n_bits(m_i915Context[0], sseu.subslice_mask,
226 mos_hweight8(m_i915Context[0], sseu.subslice_mask)-createOption->packed.SubSliceCount);
227 }
228
229 if (mos_set_context_param_sseu(m_i915Context[0], sseu))
230 {
231 MOS_OS_ASSERTMESSAGE("Failed to set sseu configuration.");
232 MOS_SafeFreeMemory(engine_map);
233 return MOS_STATUS_UNKNOWN;
234 }
235 }
236 }
237 else if (GpuNode == MOS_GPU_NODE_COMPUTE)
238 {
239 __u16 engine_class = 4; //To change later when linux define the name
240 __u64 caps = 0;
241
242 if (mos_query_engines(osInterface->pOsContext->bufmgr, engine_class, caps, &nengine, (void *)engine_map))
243 {
244 MOS_OS_ASSERTMESSAGE("Failed to query engines.\n");
245 MOS_SafeFreeMemory(engine_map);
246 return MOS_STATUS_UNKNOWN;
247 }
248
249 #if (_DEBUG || _RELEASE_INTERNAL)
250 SelectEngineInstanceByUser(engine_map, &nengine, m_engineInstanceSelect, GpuNode);
251 #endif
252 if (mos_set_context_param_load_balance(m_i915Context[0], engine_map, nengine))
253 {
254 MOS_OS_ASSERTMESSAGE("Failed to set balancer extension.\n");
255 MOS_SafeFreeMemory(engine_map);
256 return MOS_STATUS_UNKNOWN;
257 }
258 }
259 else if (GpuNode == MOS_GPU_NODE_VIDEO || GpuNode == MOS_GPU_NODE_VIDEO2
260 || GpuNode == MOS_GPU_NODE_VE)
261 {
262 __u16 engine_class = (GpuNode == MOS_GPU_NODE_VE)? I915_ENGINE_CLASS_VIDEO_ENHANCE : I915_ENGINE_CLASS_VIDEO;
263 __u64 caps = 0;
264
265 SetEngineQueryFlags(createOption, caps);
266
267 if (mos_query_engines(osInterface->pOsContext->bufmgr, engine_class, caps, &nengine, (void *)engine_map))
268 {
269 MOS_OS_ASSERTMESSAGE("Failed to query engines.\n");
270 MOS_SafeFreeMemory(engine_map);
271 return MOS_STATUS_UNKNOWN;
272 }
273
274 #if (_DEBUG || _RELEASE_INTERNAL)
275 SelectEngineInstanceByUser(engine_map, &nengine, m_engineInstanceSelect, GpuNode);
276 #endif
277 if (mos_set_context_param_load_balance(m_i915Context[0], engine_map, nengine))
278 {
279 MOS_OS_ASSERTMESSAGE("Failed to set balancer extension.\n");
280 MOS_SafeFreeMemory(engine_map);
281 return MOS_STATUS_UNKNOWN;
282 }
283
284 if (nengine >= 2)
285 {
286 int i;
287 //master queue
288 m_i915Context[1] = mos_context_create_shared(osInterface->pOsContext->bufmgr,
289 osInterface->pOsContext->intel_context,
290 I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE,
291 false,
292 (void *)engine_map,
293 1,
294 1,
295 0);
296 if (m_i915Context[1] == nullptr)
297 {
298 MOS_OS_ASSERTMESSAGE("Failed to create master context.\n");
299 MOS_SafeFreeMemory(engine_map);
300 return MOS_STATUS_UNKNOWN;
301 }
302 m_i915Context[1]->pOsContext = osInterface->pOsContext;
303
304 if (mos_set_context_param_load_balance(m_i915Context[1], engine_map, 1))
305 {
306 MOS_OS_ASSERTMESSAGE("Failed to set master context bond extension.\n");
307 MOS_SafeFreeMemory(engine_map);
308 return MOS_STATUS_UNKNOWN;
309 }
310
311 //slave queue
312 for (i=1; i<nengine; i++)
313 {
314 m_i915Context[i+1] = mos_context_create_shared(osInterface->pOsContext->bufmgr,
315 osInterface->pOsContext->intel_context,
316 I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE,
317 false,
318 (void *)engine_map,
319 1,
320 1,
321 0);
322 if (m_i915Context[i+1] == nullptr)
323 {
324 MOS_OS_ASSERTMESSAGE("Failed to create slave context.\n");
325 MOS_SafeFreeMemory(engine_map);
326 return MOS_STATUS_UNKNOWN;
327 }
328 m_i915Context[i+1]->pOsContext = osInterface->pOsContext;
329
330 if (mos_set_context_param_bond(m_i915Context[i+1], engine_map[0], &engine_map[i], 1) != S_SUCCESS)
331 {
332 int err = errno;
333 if (err == ENODEV)
334 {
335 mos_context_destroy(m_i915Context[1]);
336 mos_context_destroy(m_i915Context[i+1]);
337 m_i915Context[i+1] = nullptr;
338 break;
339 }
340 else
341 {
342 MOS_OS_ASSERTMESSAGE("Failed to set slave context bond extension. errno=%d\n",err);
343 MOS_SafeFreeMemory(engine_map);
344 return MOS_STATUS_UNKNOWN;
345 }
346 }
347 }
348 if (i == nengine)
349 {
350 osInterface->bParallelSubmission = false;
351 }
352 else
353 {
354 osInterface->bParallelSubmission = true;
355 //create context with different width
356 for(i = 1; i < nengine; i++)
357 {
358 unsigned int ctxWidth = i + 1;
359 m_i915Context[i] = mos_context_create_shared(osInterface->pOsContext->bufmgr,
360 osInterface->pOsContext->intel_context,
361 0, // I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE not allowed for parallel submission
362 false,
363 (void *)engine_map,
364 ctxWidth,
365 1,
366 0);
367 if (mos_set_context_param_parallel(m_i915Context[i], engine_map, ctxWidth) != S_SUCCESS)
368 {
369 MOS_OS_ASSERTMESSAGE("Failed to set parallel extension since discontinuous logical engine.\n");
370 mos_context_destroy(m_i915Context[i]);
371 m_i915Context[i] = nullptr;
372 break;
373 }
374 }
375 }
376 }
377 }
378 else if (GpuNode == MOS_GPU_NODE_BLT)
379 {
380 __u16 engine_class = I915_ENGINE_CLASS_COPY;
381 __u64 caps = 0;
382
383 if (mos_query_engines(osInterface->pOsContext->bufmgr, engine_class, caps, &nengine, (void *)engine_map))
384 {
385 MOS_OS_ASSERTMESSAGE("Failed to query engines.\n");
386 MOS_SafeFreeMemory(engine_map);
387 return MOS_STATUS_UNKNOWN;
388 }
389
390 if (mos_set_context_param_load_balance(m_i915Context[0], engine_map, nengine))
391 {
392 MOS_OS_ASSERTMESSAGE("Failed to set balancer extension.\n");
393 MOS_SafeFreeMemory(engine_map);
394 return MOS_STATUS_UNKNOWN;
395 }
396 }
397 else
398 {
399 MOS_OS_ASSERTMESSAGE("Unknown engine class.\n");
400 MOS_SafeFreeMemory(engine_map);
401 return MOS_STATUS_UNKNOWN;
402 }
403 MOS_SafeFreeMemory(engine_map);
404 MOS_TraceEventExt(EVENT_GPU_CONTEXT_CREATE, EVENT_TYPE_END,
405 m_i915Context, sizeof(void *),
406 &nengine, sizeof(nengine));
407 }
408 return MOS_STATUS_SUCCESS;
409 }
410
Clear()411 void GpuContextSpecific::Clear()
412 {
413 MOS_OS_FUNCTION_ENTER;
414
415 MOS_TraceEventExt(EVENT_GPU_CONTEXT_DESTROY, EVENT_TYPE_START,
416 m_i915Context, sizeof(void *), nullptr, 0);
417 // hanlde the status buf bundled w/ the specified gpucontext
418 if (m_statusBufferResource)
419 {
420 if (m_statusBufferResource->Unlock(m_osContext) != MOS_STATUS_SUCCESS)
421 {
422 MOS_OS_ASSERTMESSAGE("failed to unlock the status buf bundled w/ the specified gpucontext");
423 }
424 m_statusBufferResource->Free(m_osContext, 0);
425 MOS_Delete(m_statusBufferResource);
426 }
427 MOS_FreeMemAndSetNull(m_statusBufferMosResource);
428
429 MosUtilities::MosLockMutex(m_cmdBufPoolMutex);
430
431 if (m_cmdBufMgr)
432 {
433 for (auto& curCommandBuffer : m_cmdBufPool)
434 {
435 auto curCommandBufferSpecific = static_cast<CommandBufferSpecific *>(curCommandBuffer);
436 if (curCommandBufferSpecific == nullptr)
437 continue;
438 curCommandBufferSpecific->waitReady(); // wait ready and return to comamnd buffer manager.
439 m_cmdBufMgr->ReleaseCmdBuf(curCommandBuffer);
440 }
441 }
442
443 m_cmdBufPool.clear();
444
445 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
446 MosUtilities::MosDestroyMutex(m_cmdBufPoolMutex);
447 m_cmdBufPoolMutex = nullptr;
448 MOS_SafeFreeMemory(m_commandBuffer);
449 MOS_SafeFreeMemory(m_allocationList);
450 MOS_SafeFreeMemory(m_patchLocationList);
451 MOS_SafeFreeMemory(m_attachedResources);
452 MOS_SafeFreeMemory(m_writeModeList);
453 MOS_SafeFreeMemory(m_createOptionEnhanced);
454
455 for (int i=0; i<MAX_ENGINE_INSTANCE_NUM; i++)
456 {
457 if (m_i915Context[i])
458 {
459 mos_context_destroy(m_i915Context[i]);
460 m_i915Context[i] = nullptr;
461 }
462 }
463 MOS_TraceEventExt(EVENT_GPU_CONTEXT_DESTROY, EVENT_TYPE_END,
464 nullptr, 0, nullptr, 0);
465 }
466
RegisterResource(PMOS_RESOURCE osResource,bool writeFlag)467 MOS_STATUS GpuContextSpecific::RegisterResource(
468 PMOS_RESOURCE osResource,
469 bool writeFlag)
470 {
471 MOS_OS_FUNCTION_ENTER;
472
473 MOS_OS_CHK_NULL_RETURN(osResource);
474
475 MOS_OS_CHK_NULL_RETURN(m_attachedResources);
476
477 PMOS_RESOURCE registeredResources = m_attachedResources;
478 uint32_t allocationIndex = 0;
479
480 for ( allocationIndex = 0; allocationIndex < m_resCount; allocationIndex++, registeredResources++)
481 {
482 if (osResource->bo == registeredResources->bo)
483 {
484 break;
485 }
486 }
487
488 // Allocation list to be updated
489 if (allocationIndex < m_maxNumAllocations)
490 {
491 // New buffer
492 if (allocationIndex == m_resCount)
493 {
494 m_resCount++;
495 }
496
497 // Set allocation
498 if (m_gpuContext >= MOS_GPU_CONTEXT_MAX)
499 {
500 MOS_OS_ASSERTMESSAGE("Gpu context exceeds max.");
501 return MOS_STATUS_UNKNOWN;
502 }
503
504 osResource->iAllocationIndex[m_gpuContext] = (allocationIndex);
505 m_attachedResources[allocationIndex] = *osResource;
506 m_writeModeList[allocationIndex] |= writeFlag;
507 m_allocationList[allocationIndex].hAllocation = &m_attachedResources[allocationIndex];
508 m_allocationList[allocationIndex].WriteOperation |= writeFlag;
509 m_numAllocations = m_resCount;
510 }
511 else
512 {
513 MOS_OS_ASSERTMESSAGE("Reached max # registrations.");
514 return MOS_STATUS_UNKNOWN;
515 }
516
517 return MOS_STATUS_SUCCESS;
518 }
519
SetPatchEntry(PMOS_INTERFACE osInterface,PMOS_PATCH_ENTRY_PARAMS params)520 MOS_STATUS GpuContextSpecific::SetPatchEntry(
521 PMOS_INTERFACE osInterface,
522 PMOS_PATCH_ENTRY_PARAMS params)
523 {
524 MOS_OS_FUNCTION_ENTER;
525
526 MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
527 MOS_OS_CHK_NULL_RETURN(osInterface);
528 MOS_OS_CHK_NULL_RETURN(params);
529
530 m_patchLocationList[m_currentNumPatchLocations].AllocationIndex = params->uiAllocationIndex;
531 m_patchLocationList[m_currentNumPatchLocations].AllocationOffset = params->uiResourceOffset;
532 m_patchLocationList[m_currentNumPatchLocations].PatchOffset = params->uiPatchOffset;
533 m_patchLocationList[m_currentNumPatchLocations].uiWriteOperation = params->bWrite ? true: false;
534 m_patchLocationList[m_currentNumPatchLocations].cmdBo =
535 params->cmdBuffer != nullptr ? params->cmdBuffer->OsResource.bo : nullptr;
536
537 if (osInterface->osCpInterface &&
538 osInterface->osCpInterface->IsHMEnabled())
539 {
540 if (MOS_STATUS_SUCCESS != osInterface->osCpInterface->RegisterPatchForHM(
541 (uint32_t *)(params->cmdBufBase + params->uiPatchOffset),
542 params->bWrite,
543 params->HwCommandType,
544 params->forceDwordOffset,
545 params->presResource,
546 &m_patchLocationList[m_currentNumPatchLocations]))
547 {
548 MOS_OS_ASSERTMESSAGE("Failed to RegisterPatchForHM.");
549 }
550 }
551
552 m_currentNumPatchLocations++;
553
554 return MOS_STATUS_SUCCESS;
555 }
556
GetCommandBuffer(PMOS_COMMAND_BUFFER comamndBuffer,uint32_t flags)557 MOS_STATUS GpuContextSpecific::GetCommandBuffer(
558 PMOS_COMMAND_BUFFER comamndBuffer,
559 uint32_t flags)
560 {
561 MOS_OS_FUNCTION_ENTER;
562
563 MOS_OS_CHK_NULL_RETURN(comamndBuffer);
564 MOS_OS_CHK_NULL_RETURN(m_cmdBufMgr);
565 MOS_OS_CHK_NULL_RETURN(m_commandBuffer);
566
567 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
568 CommandBuffer* cmdBuf = nullptr;
569
570 uint32_t secondaryIdx = flags;
571 bool isPrimaryCmdBuffer = (secondaryIdx == 0);
572 bool hasSecondaryCmdBuffer = (!isPrimaryCmdBuffer &&
573 (m_secondaryCmdBufs.count(secondaryIdx) != 0));
574
575 bool needToAlloc = ((isPrimaryCmdBuffer && m_cmdBufFlushed) ||
576 (!isPrimaryCmdBuffer && !hasSecondaryCmdBuffer));
577
578 if (needToAlloc)
579 {
580 MosUtilities::MosLockMutex(m_cmdBufPoolMutex);
581 if (m_cmdBufPool.size() < MAX_CMD_BUF_NUM)
582 {
583 cmdBuf = m_cmdBufMgr->PickupOneCmdBuf(m_commandBufferSize);
584 if (cmdBuf == nullptr)
585 {
586 MOS_OS_ASSERTMESSAGE("Invalid (nullptr) Pointer.");
587 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
588 return MOS_STATUS_NULL_POINTER;
589 }
590 if ((eStatus = cmdBuf->BindToGpuContext(this)) != MOS_STATUS_SUCCESS)
591 {
592 MOS_OS_ASSERTMESSAGE("Invalid status of BindToGpuContext.");
593 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
594 return eStatus;
595 }
596 m_cmdBufPool.push_back(cmdBuf);
597 }
598 else if (m_cmdBufPool.size() == MAX_CMD_BUF_NUM && m_nextFetchIndex < m_cmdBufPool.size())
599 {
600 auto cmdBufOld = m_cmdBufPool[m_nextFetchIndex];
601 auto cmdBufSpecificOld = static_cast<CommandBufferSpecific *>(cmdBufOld);
602 if (cmdBufSpecificOld == nullptr)
603 {
604 MOS_OS_ASSERTMESSAGE("Invalid (nullptr) Pointer.");
605 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
606 return MOS_STATUS_NULL_POINTER;
607 }
608 cmdBufSpecificOld->waitReady();
609 cmdBufSpecificOld->UnBindToGpuContext();
610 m_cmdBufMgr->ReleaseCmdBuf(cmdBufOld); // here just return old command buffer to available pool
611
612 //pick up new comamnd buffer
613 cmdBuf = m_cmdBufMgr->PickupOneCmdBuf(m_commandBufferSize);
614 if (cmdBuf == nullptr)
615 {
616 MOS_OS_ASSERTMESSAGE("Invalid (nullptr) Pointer.");
617 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
618 return MOS_STATUS_NULL_POINTER;
619 }
620 if ((eStatus = cmdBuf->BindToGpuContext(this)) != MOS_STATUS_SUCCESS)
621 {
622 MOS_OS_ASSERTMESSAGE("Invalid status of BindToGpuContext.");
623 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
624 return eStatus;
625 }
626 m_cmdBufPool[m_nextFetchIndex] = cmdBuf;
627 }
628 else
629 {
630 MOS_OS_ASSERTMESSAGE("Command buffer bool size exceed max.");
631 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
632 return MOS_STATUS_UNKNOWN;
633 }
634 MosUtilities::MosUnlockMutex(m_cmdBufPoolMutex);
635
636 // util now, we got new command buffer from CmdBufMgr, next step to fill in the input command buffer
637 MOS_OS_CHK_STATUS_RETURN(cmdBuf->GetResource()->ConvertToMosResource(&comamndBuffer->OsResource));
638 comamndBuffer->pCmdBase = (uint32_t *)cmdBuf->GetLockAddr();
639 comamndBuffer->pCmdPtr = (uint32_t *)cmdBuf->GetLockAddr();
640 comamndBuffer->iOffset = 0;
641 comamndBuffer->iRemaining = cmdBuf->GetCmdBufSize();
642 comamndBuffer->iCmdIndex = m_nextFetchIndex;
643 comamndBuffer->iVdboxNodeIndex = MOS_VDBOX_NODE_INVALID;
644 comamndBuffer->iVeboxNodeIndex = MOS_VEBOX_NODE_INVALID;
645 comamndBuffer->is1stLvlBB = true;
646 comamndBuffer->Attributes.pAttriVe = nullptr;
647
648 // zero comamnd buffer
649 MOS_ZeroMemory(comamndBuffer->pCmdBase, comamndBuffer->iRemaining);
650 comamndBuffer->iSubmissionType = SUBMISSION_TYPE_SINGLE_PIPE;
651 MOS_ZeroMemory(&comamndBuffer->Attributes,sizeof(comamndBuffer->Attributes));
652
653 if (isPrimaryCmdBuffer)
654 {
655 // update command buffer relared filed in GPU context
656 m_cmdBufFlushed = false;
657
658 // keep a copy in GPU context
659 MOS_SecureMemcpy(m_commandBuffer, sizeof(MOS_COMMAND_BUFFER), comamndBuffer, sizeof(MOS_COMMAND_BUFFER));
660 }
661 else
662 {
663 PMOS_COMMAND_BUFFER tempCmdBuf = (PMOS_COMMAND_BUFFER)MOS_AllocAndZeroMemory(sizeof(MOS_COMMAND_BUFFER));
664 MOS_OS_CHK_NULL_RETURN(tempCmdBuf);
665 m_secondaryCmdBufs[secondaryIdx] = tempCmdBuf;
666 MOS_SecureMemcpy(tempCmdBuf, sizeof(MOS_COMMAND_BUFFER), comamndBuffer, sizeof(MOS_COMMAND_BUFFER));
667 }
668
669 // Command buffers are treated as cyclical buffers, the CB after the just submitted one
670 // has the minimal fence value that we should wait
671 m_nextFetchIndex++;
672 if (m_nextFetchIndex >= MAX_CMD_BUF_NUM)
673 {
674 m_nextFetchIndex = 0;
675 }
676 }
677 else
678 {
679 // current command buffer still active, directly copy to comamndBuffer
680 if (isPrimaryCmdBuffer)
681 {
682 MOS_SecureMemcpy(comamndBuffer, sizeof(MOS_COMMAND_BUFFER), m_commandBuffer, sizeof(MOS_COMMAND_BUFFER));
683 }
684 else
685 {
686 MOS_SecureMemcpy(comamndBuffer, sizeof(MOS_COMMAND_BUFFER), m_secondaryCmdBufs[secondaryIdx], sizeof(MOS_COMMAND_BUFFER));
687 }
688 }
689
690 if (isPrimaryCmdBuffer)
691 {
692 MOS_OS_CHK_STATUS_RETURN(RegisterResource(&m_commandBuffer->OsResource, false));
693 }
694 else
695 {
696 MOS_OS_CHK_STATUS_RETURN(RegisterResource(&m_secondaryCmdBufs[secondaryIdx]->OsResource, false));
697 }
698
699 return MOS_STATUS_SUCCESS;
700 }
701
ReturnCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer,uint32_t flags)702 void GpuContextSpecific::ReturnCommandBuffer(
703 PMOS_COMMAND_BUFFER cmdBuffer,
704 uint32_t flags)
705 {
706 MOS_OS_FUNCTION_ENTER;
707
708 MOS_OS_ASSERT(cmdBuffer);
709 MOS_OS_ASSERT(m_commandBuffer);
710
711 bool isPrimaryCmdBuf = (flags == 0);
712
713 if (isPrimaryCmdBuf)
714 {
715 m_commandBuffer->iOffset = cmdBuffer->iOffset;
716 m_commandBuffer->iRemaining = cmdBuffer->iRemaining;
717 m_commandBuffer->pCmdPtr = cmdBuffer->pCmdPtr;
718 m_commandBuffer->iVdboxNodeIndex = cmdBuffer->iVdboxNodeIndex;
719 m_commandBuffer->iVeboxNodeIndex = cmdBuffer->iVeboxNodeIndex;
720 }
721 else
722 {
723 uint32_t secondaryIdx = flags;
724 MOS_OS_ASSERT(m_secondaryCmdBufs.count(secondaryIdx));
725
726 MOS_SecureMemcpy(m_secondaryCmdBufs[secondaryIdx], sizeof(MOS_COMMAND_BUFFER), cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
727 }
728 }
729
ResetCommandBuffer()730 MOS_STATUS GpuContextSpecific::ResetCommandBuffer()
731 {
732 m_cmdBufFlushed = true;
733 auto it = m_secondaryCmdBufs.begin();
734 while(it != m_secondaryCmdBufs.end())
735 {
736 MOS_FreeMemory(it->second);
737 it++;
738 }
739 m_secondaryCmdBufs.clear();
740 return MOS_STATUS_SUCCESS;
741 }
742
SetIndirectStateSize(const uint32_t size)743 MOS_STATUS GpuContextSpecific::SetIndirectStateSize(const uint32_t size)
744 {
745 if(size < m_commandBufferSize)
746 {
747 m_IndirectHeapSize = size;
748 return MOS_STATUS_SUCCESS;
749 }
750 else
751 {
752 MOS_OS_ASSERTMESSAGE("Indirect State Size if out of boundry!");
753 return MOS_STATUS_UNKNOWN;
754 }
755 }
756
GetIndirectState(uint32_t * offset,uint32_t * size)757 MOS_STATUS GpuContextSpecific::GetIndirectState(
758 uint32_t *offset,
759 uint32_t *size)
760 {
761 MOS_OS_FUNCTION_ENTER;
762
763 if (offset)
764 {
765 *offset = m_commandBufferSize - m_IndirectHeapSize;
766 }
767
768 if (size)
769 {
770 *size = m_IndirectHeapSize;
771 }
772
773 return MOS_STATUS_SUCCESS;
774 }
775
GetIndirectStatePointer(uint8_t ** indirectState)776 MOS_STATUS GpuContextSpecific::GetIndirectStatePointer(
777 uint8_t **indirectState)
778 {
779 MOS_OS_FUNCTION_ENTER;
780
781 MOS_OS_CHK_NULL_RETURN(indirectState);
782
783 *indirectState = (uint8_t *)m_commandBuffer->pCmdBase + m_commandBufferSize - m_IndirectHeapSize;
784
785 return MOS_STATUS_SUCCESS;
786 }
787
ResizeCommandBufferAndPatchList(uint32_t requestedCommandBufferSize,uint32_t requestedPatchListSize,uint32_t flags)788 MOS_STATUS GpuContextSpecific::ResizeCommandBufferAndPatchList(
789 uint32_t requestedCommandBufferSize,
790 uint32_t requestedPatchListSize,
791 uint32_t flags)
792 {
793 MOS_OS_FUNCTION_ENTER;
794
795 // m_commandBufferSize is used for allocate command buffer and submit command buffer, in this moment, command buffer has not allocated yet.
796 // Linux KMD requires command buffer size align to 8 bytes, or it will not execute the commands.
797 m_commandBufferSize = MOS_ALIGN_CEIL(requestedCommandBufferSize, 8);
798
799 if (requestedPatchListSize > m_maxPatchLocationsize)
800 {
801 PPATCHLOCATIONLIST newPatchList = (PPATCHLOCATIONLIST)realloc(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * requestedPatchListSize);
802 MOS_OS_CHK_NULL_RETURN(newPatchList);
803
804 m_patchLocationList = newPatchList;
805
806 // now zero the extended portion
807 MOS_ZeroMemory((m_patchLocationList + m_maxPatchLocationsize), sizeof(PATCHLOCATIONLIST) * (requestedPatchListSize - m_maxPatchLocationsize));
808 m_maxPatchLocationsize = requestedPatchListSize;
809 }
810
811 return MOS_STATUS_SUCCESS;
812 }
813
ResizeCommandBuffer(uint32_t requestedSize)814 MOS_STATUS GpuContextSpecific::ResizeCommandBuffer(uint32_t requestedSize)
815 {
816 MOS_OS_FUNCTION_ENTER;
817
818 m_commandBufferSize = requestedSize;
819
820 return MOS_STATUS_SUCCESS;
821 }
822
GetVcsExecFlag(PMOS_INTERFACE osInterface,PMOS_COMMAND_BUFFER cmdBuffer,MOS_GPU_NODE gpuNode)823 uint32_t GetVcsExecFlag(PMOS_INTERFACE osInterface,
824 PMOS_COMMAND_BUFFER cmdBuffer,
825 MOS_GPU_NODE gpuNode)
826 {
827 if (osInterface == 0 ||
828 cmdBuffer == 0)
829 {
830 MOS_OS_ASSERTMESSAGE("Input invalid(null) parameter.");
831 return I915_EXEC_DEFAULT;
832 }
833
834 uint32_t vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
835
836 if (MOS_VDBOX_NODE_INVALID == cmdBuffer->iVdboxNodeIndex)
837 {
838 // That's those case when BB did not have any VDBOX# specific commands.
839 // Thus, we need to select VDBOX# here. Alternatively we can rely on KMD
840 // to make balancing for us, i.e. rely on Virtual Engine support.
841 cmdBuffer->iVdboxNodeIndex = osInterface->pfnGetVdboxNodeId(osInterface, cmdBuffer);
842 if (MOS_VDBOX_NODE_INVALID == cmdBuffer->iVdboxNodeIndex)
843 {
844 cmdBuffer->iVdboxNodeIndex = (gpuNode == MOS_GPU_NODE_VIDEO)?
845 MOS_VDBOX_NODE_1: MOS_VDBOX_NODE_2;
846 }
847 }
848
849 if (MOS_VDBOX_NODE_1 == cmdBuffer->iVdboxNodeIndex)
850 {
851 vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
852 }
853 else if (MOS_VDBOX_NODE_2 == cmdBuffer->iVdboxNodeIndex)
854 {
855 vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING2;
856 }
857
858 return vcsExecFlag;
859 }
860
MapResourcesToAuxTable(mos_linux_bo * cmd_bo)861 MOS_STATUS GpuContextSpecific::MapResourcesToAuxTable(mos_linux_bo *cmd_bo)
862 {
863 MOS_OS_CHK_NULL_RETURN(cmd_bo);
864
865 OsContextSpecific *osCtx = static_cast<OsContextSpecific*>(m_osContext);
866 MOS_OS_CHK_NULL_RETURN(osCtx);
867
868 AuxTableMgr *auxTableMgr = osCtx->GetAuxTableMgr();
869 if (auxTableMgr)
870 {
871 // Map compress allocations to aux table if it is not mapped.
872 for (uint32_t i = 0; i < m_numAllocations; i++)
873 {
874 auto res = (PMOS_RESOURCE)m_allocationList[i].hAllocation;
875 MOS_OS_CHK_NULL_RETURN(res);
876 MOS_OS_CHK_STATUS_RETURN(auxTableMgr->MapResource(res->pGmmResInfo, res->bo));
877 }
878 MOS_OS_CHK_STATUS_RETURN(auxTableMgr->EmitAuxTableBOList(cmd_bo));
879 }
880 return MOS_STATUS_SUCCESS;
881 }
882
SubmitCommandBuffer(PMOS_INTERFACE osInterface,PMOS_COMMAND_BUFFER cmdBuffer,bool nullRendering)883 MOS_STATUS GpuContextSpecific::SubmitCommandBuffer(
884 PMOS_INTERFACE osInterface,
885 PMOS_COMMAND_BUFFER cmdBuffer,
886 bool nullRendering)
887 {
888 MOS_OS_FUNCTION_ENTER;
889
890 MOS_TraceEventExt(EVENT_MOS_BATCH_SUBMIT, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
891
892 MOS_OS_CHK_NULL_RETURN(osInterface);
893 PMOS_CONTEXT osContext = osInterface->pOsContext;
894 MOS_OS_CHK_NULL_RETURN(osContext);
895 MOS_OS_CHK_NULL_RETURN(cmdBuffer);
896 MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
897
898 MOS_GPU_NODE gpuNode = OSKMGetGpuNode(m_gpuContext);
899 uint32_t execFlag = gpuNode;
900 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
901 int32_t ret = 0;
902 bool scalaEnabled = false;
903 auto it = m_secondaryCmdBufs.begin();
904
905 // Command buffer object DRM pointer
906 m_cmdBufFlushed = true;
907 auto cmd_bo = cmdBuffer->OsResource.bo;
908
909 // Map Resource to Aux if needed
910 MapResourcesToAuxTable(cmd_bo);
911 for(auto it : m_secondaryCmdBufs)
912 {
913 MapResourcesToAuxTable(it.second->OsResource.bo);
914 }
915
916 if (m_secondaryCmdBufs.size() >= 2)
917 {
918 scalaEnabled = true;
919 cmdBuffer->iSubmissionType = SUBMISSION_TYPE_MULTI_PIPE_MASTER;
920 }
921
922 std::vector<PMOS_RESOURCE> mappedResList;
923 std::vector<MOS_LINUX_BO *> skipSyncBoList;
924
925 // Now, the patching will be done, based on the patch list.
926 for (uint32_t patchIndex = 0; patchIndex < m_currentNumPatchLocations; patchIndex++)
927 {
928 auto currentPatch = &m_patchLocationList[patchIndex];
929 MOS_OS_CHK_NULL_RETURN(currentPatch);
930
931 auto tempCmdBo = currentPatch->cmdBo == nullptr ? cmd_bo : currentPatch->cmdBo;
932
933 // Following are for Nested BB buffer, if it's nested BB, we need to ensure it's locked.
934 if (tempCmdBo != cmd_bo)
935 {
936 bool isSecondaryCmdBuf = false;
937 it = m_secondaryCmdBufs.begin();
938 while(it != m_secondaryCmdBufs.end())
939 {
940 if (it->second->OsResource.bo == tempCmdBo)
941 {
942 isSecondaryCmdBuf = true;
943 break;
944 }
945 it++;
946 }
947
948 for(auto allocIdx = 0; allocIdx < m_numAllocations && (!isSecondaryCmdBuf); allocIdx++)
949 {
950 auto tempRes = (PMOS_RESOURCE)m_allocationList[allocIdx].hAllocation;
951 if (tempCmdBo == tempRes->bo)
952 {
953 GraphicsResource::LockParams param;
954 param.m_writeRequest = true;
955 tempRes->pGfxResource->Lock(m_osContext, param);
956 mappedResList.push_back(tempRes);
957 break;
958 }
959 }
960 }
961
962 // This is the resource for which patching will be done
963 auto resource = (PMOS_RESOURCE)m_allocationList[currentPatch->AllocationIndex].hAllocation;
964 MOS_OS_CHK_NULL_RETURN(resource);
965
966 // For now, we'll assume the system memory's DRM bo pointer
967 // is NULL. If nullptr is detected, then the resource has been
968 // placed inside the command buffer's indirect state area.
969 // We'll simply set alloc_bo to the command buffer's bo pointer.
970 MOS_OS_ASSERT(resource->bo);
971
972 auto alloc_bo = (resource->bo) ? resource->bo : tempCmdBo;
973
974 MOS_OS_CHK_STATUS_RETURN(osInterface->osCpInterface->PermeatePatchForHM(
975 tempCmdBo->virt,
976 currentPatch,
977 resource));
978
979 uint64_t boOffset = alloc_bo->offset64;
980 if (alloc_bo != tempCmdBo)
981 {
982 auto item_ctx = osContext->contextOffsetList.begin();
983 for (; item_ctx != osContext->contextOffsetList.end(); item_ctx++)
984 {
985 if (item_ctx->intel_context == osContext->intel_context && item_ctx->target_bo == alloc_bo)
986 {
987 boOffset = item_ctx->offset64;
988 break;
989 }
990 }
991 }
992
993 MOS_OS_CHK_NULL_RETURN(tempCmdBo->virt);
994 if (osContext->bUse64BitRelocs)
995 {
996 *((uint64_t *)((uint8_t *)tempCmdBo->virt + currentPatch->PatchOffset)) =
997 boOffset + currentPatch->AllocationOffset;
998 }
999 else
1000 {
1001 *((uint32_t *)((uint8_t *)tempCmdBo->virt + currentPatch->PatchOffset)) =
1002 boOffset + currentPatch->AllocationOffset;
1003 }
1004
1005 if (scalaEnabled)
1006 {
1007 it = m_secondaryCmdBufs.begin();
1008 while(it != m_secondaryCmdBufs.end())
1009 {
1010 if (it->second->OsResource.bo == tempCmdBo &&
1011 it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE &&
1012 !mos_bo_is_exec_object_async(alloc_bo))
1013 {
1014 skipSyncBoList.push_back(alloc_bo);
1015 break;
1016 }
1017 it++;
1018 }
1019 }
1020 else if (cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE &&
1021 !mos_bo_is_exec_object_async(alloc_bo))
1022 {
1023 skipSyncBoList.push_back(alloc_bo);
1024 }
1025
1026 #if (_DEBUG || _RELEASE_INTERNAL)
1027 {
1028 uint32_t evtData[] = {alloc_bo->handle, currentPatch->uiWriteOperation, currentPatch->AllocationOffset};
1029 MOS_TraceEventExt(EVENT_MOS_BATCH_SUBMIT, EVENT_TYPE_INFO,
1030 evtData, sizeof(evtData),
1031 &boOffset, sizeof(boOffset));
1032 }
1033 #endif
1034 if(mos_bo_is_softpin(alloc_bo))
1035 {
1036 if (alloc_bo != tempCmdBo)
1037 {
1038 ret = mos_bo_add_softpin_target(tempCmdBo, alloc_bo, currentPatch->uiWriteOperation);
1039 }
1040 }
1041 else
1042 {
1043 // This call will patch the command buffer with the offsets of the indirect state region of the command buffer
1044 ret = mos_bo_emit_reloc(
1045 tempCmdBo, // Command buffer
1046 currentPatch->PatchOffset, // Offset in the command buffer
1047 alloc_bo, // Allocation object for which the patch will be made.
1048 currentPatch->AllocationOffset, // Offset to the indirect state
1049 I915_GEM_DOMAIN_RENDER, // Read domain
1050 (currentPatch->uiWriteOperation) ? I915_GEM_DOMAIN_RENDER : 0x0, // Write domain
1051 boOffset);
1052 }
1053
1054 if (ret != 0)
1055 {
1056 MOS_OS_ASSERTMESSAGE("Error patching alloc_bo = 0x%x, cmd_bo = 0x%x.",
1057 (uintptr_t)alloc_bo,
1058 (uintptr_t)tempCmdBo);
1059 return MOS_STATUS_UNKNOWN;
1060 }
1061 }
1062
1063 for(auto res: mappedResList)
1064 {
1065 res->pGfxResource->Unlock(m_osContext);
1066 }
1067 mappedResList.clear();
1068
1069 if (scalaEnabled)
1070 {
1071 it = m_secondaryCmdBufs.begin();
1072 while(it != m_secondaryCmdBufs.end())
1073 {
1074 //Add Batch buffer End Command
1075 uint32_t batchBufferEndCmd = MI_BATCHBUFFER_END;
1076 if (MOS_FAILED(Mos_AddCommand(
1077 it->second,
1078 &batchBufferEndCmd,
1079 sizeof(uint32_t))))
1080 {
1081 MOS_OS_ASSERTMESSAGE("Inserting BB_END failed!");
1082 return MOS_STATUS_UNKNOWN;
1083 }
1084 it++;
1085 }
1086 }
1087 else
1088 {
1089 //Add Batch buffer End Command
1090 uint32_t batchBufferEndCmd = MI_BATCHBUFFER_END;
1091 if (MOS_FAILED(Mos_AddCommand(
1092 cmdBuffer,
1093 &batchBufferEndCmd,
1094 sizeof(uint32_t))))
1095 {
1096 MOS_OS_ASSERTMESSAGE("Inserting BB_END failed!");
1097 return MOS_STATUS_UNKNOWN;
1098 }
1099 }
1100 // dump before cmd buffer unmap
1101 MOS_TraceDumpExt("CmdBuffer", m_gpuContext, cmdBuffer->pCmdBase, cmdBuffer->iOffset);
1102
1103 // Now, we can unmap the video command buffer, since we don't need CPU access anymore.
1104 MOS_OS_CHK_NULL_RETURN(cmdBuffer->OsResource.pGfxResource);
1105 cmdBuffer->OsResource.pGfxResource->Unlock(m_osContext);
1106
1107 it = m_secondaryCmdBufs.begin();
1108 while(it != m_secondaryCmdBufs.end())
1109 {
1110 MOS_OS_CHK_NULL_RETURN(it->second->OsResource.pGfxResource);
1111 it->second->OsResource.pGfxResource->Unlock(m_osContext);
1112
1113 it++;
1114 }
1115
1116 int32_t perfData;
1117 if (osContext->pPerfData != nullptr)
1118 {
1119 perfData = *(int32_t *)(osContext->pPerfData);
1120 }
1121 else
1122 {
1123 perfData = 0;
1124 }
1125
1126 drm_clip_rect_t *cliprects = nullptr;
1127 int32_t num_cliprects = 0;
1128 int32_t DR4 = osContext->uEnablePerfTag ? perfData : 0;
1129
1130 //Since CB2 command is not supported, remove it and set cliprects to nullprt as default.
1131 if ((gpuNode == MOS_GPU_NODE_VIDEO || gpuNode == MOS_GPU_NODE_VIDEO2) &&
1132 (cmdBuffer->iSubmissionType & SUBMISSION_TYPE_SINGLE_PIPE_MASK))
1133 {
1134 if (osContext->bKMDHasVCS2)
1135 {
1136 if (osContext->bPerCmdBufferBalancing && osInterface->pfnGetVdboxNodeId)
1137 {
1138 execFlag = GetVcsExecFlag(osInterface, cmdBuffer, gpuNode);
1139 }
1140 else if (gpuNode == MOS_GPU_NODE_VIDEO)
1141 {
1142 execFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
1143 }
1144 else if (gpuNode == MOS_GPU_NODE_VIDEO2)
1145 {
1146 execFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING2;
1147 }
1148 else
1149 {
1150 MOS_OS_ASSERTMESSAGE("Invalid gpuNode.");
1151 }
1152 }
1153 else
1154 {
1155 execFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
1156 }
1157 }
1158
1159 #if (_DEBUG || _RELEASE_INTERNAL)
1160
1161 MOS_LINUX_BO *bad_cmd_bo = nullptr;
1162 MOS_LINUX_BO *nop_cmd_bo = nullptr;
1163 uint32_t dwComponentTag = 0;
1164 uint32_t dwCallType = 0;
1165
1166 //dwComponentTag 3: decode,5: vpp,6: encode
1167 //dwCallType 8: PAK(CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE)
1168 // 34: PREENC
1169 // 5: VPP
1170 dwComponentTag = (perfData & 0xF000) >> 12;
1171 dwCallType = (perfData & 0xFC) >> 2;
1172
1173 if (osInterface->bTriggerCodecHang &&
1174 (dwComponentTag == 3 || (dwComponentTag == 6 && dwCallType == 8) ||
1175 (dwComponentTag == 6 && dwCallType == 34) ||
1176 (dwComponentTag == 5 && dwCallType == 5)))
1177 {
1178 bad_cmd_bo = Mos_GetBadCommandBuffer_Linux(osInterface);
1179 if (bad_cmd_bo)
1180 {
1181 ret = mos_bo_mrb_exec(bad_cmd_bo,
1182 4096,
1183 nullptr,
1184 0,
1185 0,
1186 execFlag);
1187 }
1188 else
1189 {
1190 MOS_OS_ASSERTMESSAGE("Mos_GetBadCommandBuffer_Linux failed!");
1191 }
1192 }
1193 else if (osInterface->bTriggerVPHang == true)
1194 {
1195 bad_cmd_bo = Mos_GetBadCommandBuffer_Linux(osInterface);
1196
1197 if (bad_cmd_bo)
1198 {
1199 ret = mos_bo_mrb_exec(bad_cmd_bo,
1200 4096,
1201 nullptr,
1202 0,
1203 0,
1204 execFlag);
1205 }
1206 else
1207 {
1208 MOS_OS_ASSERTMESSAGE("Mos_GetBadCommandBuffer_Linux failed!");
1209 }
1210
1211 osInterface->bTriggerVPHang = false;
1212 }
1213
1214 nop_cmd_bo = nullptr;
1215 if (nullRendering == true)
1216 {
1217 nop_cmd_bo = Mos_GetNopCommandBuffer_Linux(osInterface);
1218
1219 if (nop_cmd_bo)
1220 {
1221 ret = mos_bo_mrb_exec(nop_cmd_bo,
1222 4096,
1223 nullptr,
1224 0,
1225 0,
1226 execFlag);
1227 }
1228 else
1229 {
1230 MOS_OS_ASSERTMESSAGE("Mos_GetNopCommandBuffer_Linux failed!");
1231 }
1232 }
1233
1234 #endif //(_DEBUG || _RELEASE_INTERNAL)
1235
1236 if (gpuNode != I915_EXEC_RENDER &&
1237 osInterface->osCpInterface->IsTearDownHappen())
1238 {
1239 // skip PAK command when CP tear down happen to avoid of GPU hang
1240 // conditonal batch buffer start PoC is in progress
1241 }
1242 else if (nullRendering == false)
1243 {
1244 UnlockPendingOcaBuffers(cmdBuffer, osContext);
1245 if (osInterface->ctxBasedScheduling && m_i915Context[0] != nullptr)
1246 {
1247 if (cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_MASK)
1248 {
1249 if (scalaEnabled && !osInterface->bParallelSubmission)
1250 {
1251 uint32_t secondaryIndex = 0;
1252 it = m_secondaryCmdBufs.begin();
1253 while(it != m_secondaryCmdBufs.end())
1254 {
1255 if (it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE)
1256 {
1257 if(execFlag == MOS_GPU_NODE_VE)
1258 {
1259 // decode excluded since init in other place
1260 it->second->iSubmissionType |= (secondaryIndex << SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_SHIFT);
1261 secondaryIndex++;
1262 }
1263 }
1264
1265 ret = SubmitPipeCommands(it->second,
1266 it->second->OsResource.bo,
1267 osContext,
1268 skipSyncBoList,
1269 execFlag,
1270 DR4);
1271 it++;
1272 }
1273 }
1274 else if(scalaEnabled && osInterface->bParallelSubmission)
1275 {
1276 ret = ParallelSubmitCommands(m_secondaryCmdBufs,
1277 osContext,
1278 execFlag,
1279 DR4);
1280 }
1281 else
1282 {
1283 ret = SubmitPipeCommands(cmdBuffer,
1284 cmd_bo,
1285 osContext,
1286 skipSyncBoList,
1287 execFlag,
1288 DR4);
1289 }
1290 }
1291 else
1292 {
1293 ret = mos_bo_context_exec2(cmd_bo,
1294 m_commandBufferSize,
1295 m_i915Context[0],
1296 cliprects,
1297 num_cliprects,
1298 DR4,
1299 m_i915ExecFlag,
1300 nullptr);
1301 }
1302 }
1303 else
1304 {
1305 ret = mos_bo_context_exec2(cmd_bo,
1306 m_commandBufferSize,
1307 osContext->intel_context,
1308 cliprects,
1309 num_cliprects,
1310 DR4,
1311 execFlag,
1312 nullptr);
1313 }
1314 if (ret != 0)
1315 {
1316 eStatus = MOS_STATUS_UNKNOWN;
1317 }
1318 }
1319
1320 if (eStatus != MOS_STATUS_SUCCESS)
1321 {
1322 MOS_OS_ASSERTMESSAGE("Command buffer submission failed!");
1323 }
1324
1325 MOS_DEVULT_FuncCall(pfnUltGetCmdBuf, cmdBuffer);
1326
1327 #if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
1328 pthread_mutex_lock(&command_dump_mutex);
1329 if (osInterface->bDumpCommandBuffer)
1330 {
1331 if (scalaEnabled)
1332 {
1333 it = m_secondaryCmdBufs.begin();
1334 while(it != m_secondaryCmdBufs.end())
1335 {
1336 mos_bo_map(it->second->OsResource.bo, 0);
1337 osInterface->pfnDumpCommandBuffer(osInterface, it->second);
1338 mos_bo_unmap(it->second->OsResource.bo);
1339 it++;
1340 }
1341 }
1342 else
1343 {
1344 mos_bo_map(cmd_bo, 0);
1345 osInterface->pfnDumpCommandBuffer(osInterface, cmdBuffer);
1346 mos_bo_unmap(cmd_bo);
1347 }
1348 }
1349 pthread_mutex_unlock(&command_dump_mutex);
1350 #endif // MOS_COMMAND_BUFFER_DUMP_SUPPORTED
1351
1352 #if (_DEBUG || _RELEASE_INTERNAL)
1353 if (bad_cmd_bo)
1354 {
1355 mos_bo_wait_rendering(bad_cmd_bo);
1356 mos_bo_unreference(bad_cmd_bo);
1357 }
1358 if (nop_cmd_bo)
1359 {
1360 mos_bo_unreference(nop_cmd_bo);
1361 }
1362 #endif //(_DEBUG || _RELEASE_INTERNAL)
1363
1364 //clear command buffer relocations to fix memory leak issue
1365 mos_bo_clear_relocs(cmd_bo, 0);
1366 it = m_secondaryCmdBufs.begin();
1367 while(it != m_secondaryCmdBufs.end())
1368 {
1369 mos_bo_clear_relocs(it->second->OsResource.bo, 0);
1370 MOS_FreeMemory(it->second);
1371 it++;
1372 }
1373 m_secondaryCmdBufs.clear();
1374 skipSyncBoList.clear();
1375
1376 // Reset resource allocation
1377 m_numAllocations = 0;
1378 MOS_ZeroMemory(m_allocationList, sizeof(ALLOCATION_LIST) * m_maxNumAllocations);
1379 m_currentNumPatchLocations = 0;
1380 MOS_ZeroMemory(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * m_maxNumAllocations);
1381 m_resCount = 0;
1382
1383 MOS_ZeroMemory(m_writeModeList, sizeof(bool) * m_maxNumAllocations);
1384 finish:
1385 MOS_TraceEventExt(EVENT_MOS_BATCH_SUBMIT, EVENT_TYPE_END, &eStatus, sizeof(eStatus), nullptr, 0);
1386 return eStatus;
1387 }
1388
UnlockPendingOcaBuffers(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_CONTEXT mosContext)1389 void GpuContextSpecific::UnlockPendingOcaBuffers(PMOS_COMMAND_BUFFER cmdBuffer, PMOS_CONTEXT mosContext)
1390 {
1391 MOS_OS_CHK_NULL_NO_STATUS_RETURN(cmdBuffer);
1392 MOS_OS_CHK_NULL_NO_STATUS_RETURN(mosContext);
1393 MosOcaInterface *pOcaInterface = &MosOcaInterfaceSpecific::GetInstance();
1394 if (nullptr == pOcaInterface || !((MosOcaInterfaceSpecific*)pOcaInterface)->IsOcaEnabled())
1395 {
1396 // Will come here for UMD_OCA not being enabled case.
1397 return;
1398 }
1399
1400 int count = 0;
1401 struct MOS_OCA_EXEC_LIST_INFO *info = nullptr;
1402 if ((cmdBuffer->iSubmissionType & SUBMISSION_TYPE_SINGLE_PIPE_MASK) && ((MosOcaInterfaceSpecific*)pOcaInterface)->IsOcaDumpExecListInfoEnabled())
1403 {
1404 info = mos_bo_get_softpin_targets_info(cmdBuffer->OsResource.bo, &count);
1405 }
1406
1407 pOcaInterface->UnlockPendingOcaBuffers(mosContext, info, count);
1408
1409 if(info)
1410 {
1411 free(info);
1412 }
1413 }
1414
SubmitPipeCommands(MOS_COMMAND_BUFFER * cmdBuffer,MOS_LINUX_BO * cmdBo,PMOS_CONTEXT osContext,const std::vector<MOS_LINUX_BO * > & skipSyncBoList,uint32_t execFlag,int32_t dr4)1415 int32_t GpuContextSpecific::SubmitPipeCommands(
1416 MOS_COMMAND_BUFFER *cmdBuffer,
1417 MOS_LINUX_BO *cmdBo,
1418 PMOS_CONTEXT osContext,
1419 const std::vector<MOS_LINUX_BO *> &skipSyncBoList,
1420 uint32_t execFlag,
1421 int32_t dr4)
1422 {
1423 int32_t ret = 0;
1424 int fence = -1;
1425 unsigned int fenceFlag = 0;
1426
1427 MOS_LINUX_CONTEXT *queue = m_i915Context[0];
1428 bool isVeboxSubmission = false;
1429
1430 if (execFlag == MOS_GPU_NODE_VIDEO || execFlag == MOS_GPU_NODE_VIDEO2)
1431 {
1432 execFlag = I915_EXEC_DEFAULT;
1433 }
1434 if (execFlag == MOS_GPU_NODE_VE)
1435 {
1436 execFlag = I915_EXEC_DEFAULT;
1437 isVeboxSubmission = true;
1438 }
1439
1440 if(cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE)
1441 {
1442 fence = osContext->submit_fence;
1443 fenceFlag = I915_EXEC_FENCE_SUBMIT;
1444 int slaveIndex = (cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_MASK) >> SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_SHIFT;
1445 if(slaveIndex < 7)
1446 {
1447 queue = m_i915Context[2 + slaveIndex]; //0 is for single pipe, 1 is for master, slave starts from 2
1448 }
1449 else
1450 {
1451 MOS_OS_ASSERTMESSAGE("slaveIndex value: %s is invalid!", slaveIndex);
1452 return -1;
1453 }
1454
1455 if (isVeboxSubmission)
1456 {
1457 queue = m_i915Context[cmdBuffer->iVeboxNodeIndex + 1];
1458 }
1459
1460 for(auto bo: skipSyncBoList)
1461 {
1462 mos_bo_set_exec_object_async(cmdBo, bo);
1463 }
1464 }
1465
1466 if(cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_MASTER)
1467 {
1468 //Only master pipe needs fence out flag
1469 fenceFlag = I915_EXEC_FENCE_OUT;
1470 queue = m_i915Context[1];
1471 }
1472
1473 ret = mos_bo_context_exec2(cmdBo,
1474 cmdBo->size,
1475 queue,
1476 nullptr,
1477 0,
1478 dr4,
1479 execFlag | fenceFlag,
1480 &fence);
1481
1482 if(cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_MASTER)
1483 {
1484 osContext->submit_fence = fence;
1485 }
1486
1487 if(cmdBuffer->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE)
1488 {
1489 close(fence);
1490 }
1491
1492 return ret;
1493 }
1494
ParallelSubmitCommands(std::map<uint32_t,PMOS_COMMAND_BUFFER> secondaryCmdBufs,PMOS_CONTEXT osContext,uint32_t execFlag,int32_t dr4)1495 int32_t GpuContextSpecific::ParallelSubmitCommands(
1496 std::map<uint32_t, PMOS_COMMAND_BUFFER> secondaryCmdBufs,
1497 PMOS_CONTEXT osContext,
1498 uint32_t execFlag,
1499 int32_t dr4)
1500 {
1501 int32_t ret = 0;
1502 int fence = -1;
1503 unsigned int fenceFlag = 0;
1504 auto it = m_secondaryCmdBufs.begin();
1505 MOS_LINUX_BO *cmdBos[MAX_PARALLEN_CMD_BO_NUM];
1506 int numBos = 0; // exclude FE bo
1507
1508 MOS_LINUX_CONTEXT *queue = m_i915Context[0];
1509 bool isVeboxSubmission = false;
1510
1511 if (execFlag == MOS_GPU_NODE_VIDEO || execFlag == MOS_GPU_NODE_VIDEO2)
1512 {
1513 execFlag = I915_EXEC_DEFAULT;
1514 }
1515 if (execFlag == MOS_GPU_NODE_VE)
1516 {
1517 execFlag = I915_EXEC_DEFAULT;
1518 isVeboxSubmission = true;
1519 }
1520
1521 while(it != m_secondaryCmdBufs.end())
1522 {
1523 if(it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_ALONE)
1524 {
1525 fenceFlag = I915_EXEC_FENCE_OUT;
1526 queue = m_i915Context[0];
1527
1528 ret = mos_bo_context_exec2(it->second->OsResource.bo,
1529 it->second->OsResource.bo->size,
1530 queue,
1531 nullptr,
1532 0,
1533 dr4,
1534 execFlag | fenceFlag,
1535 &fence);
1536
1537 osContext->submit_fence = fence;
1538 }
1539
1540 if((it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_MASTER)
1541 || (it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_SLAVE))
1542 {
1543 cmdBos[numBos++] = it->second->OsResource.bo;
1544
1545 if(it->second->iSubmissionType & SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE)
1546 {
1547 queue = m_i915Context[numBos - 1];
1548 MOS_OS_CHK_NULL_RETURN(queue);
1549 if(-1 != fence)
1550 {
1551 fenceFlag = I915_EXEC_FENCE_IN;
1552 }
1553
1554 ret = mos_bo_context_exec3(cmdBos,
1555 numBos,
1556 queue,
1557 nullptr,
1558 0,
1559 dr4,
1560 execFlag | fenceFlag,
1561 &fence);
1562
1563 for(int i = 0; i < numBos; i++)
1564 {
1565 cmdBos[i] = nullptr;
1566 }
1567 numBos = 0;
1568
1569 if(-1 != fence)
1570 {
1571 close(fence);
1572 }
1573 }
1574 }
1575
1576 it++;
1577 }
1578
1579 return ret;
1580 }
1581
IncrementGpuStatusTag()1582 void GpuContextSpecific::IncrementGpuStatusTag()
1583 {
1584 m_GPUStatusTag = m_GPUStatusTag % UINT_MAX + 1;
1585 if (m_GPUStatusTag == 0)
1586 {
1587 m_GPUStatusTag = 1;
1588 }
1589 }
1590
ResetGpuContextStatus()1591 void GpuContextSpecific::ResetGpuContextStatus()
1592 {
1593 MOS_ZeroMemory(m_allocationList, sizeof(ALLOCATION_LIST) * ALLOCATIONLIST_SIZE);
1594 m_numAllocations = 0;
1595 MOS_ZeroMemory(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * PATCHLOCATIONLIST_SIZE);
1596 m_currentNumPatchLocations = 0;
1597
1598 MOS_ZeroMemory(m_attachedResources, sizeof(MOS_RESOURCE) * ALLOCATIONLIST_SIZE);
1599 m_resCount = 0;
1600
1601 MOS_ZeroMemory(m_writeModeList, sizeof(bool) * ALLOCATIONLIST_SIZE);
1602
1603 if ((m_cmdBufFlushed == true) && m_commandBuffer->OsResource.bo)
1604 {
1605 m_commandBuffer->OsResource.bo = nullptr;
1606 }
1607 }
1608
AllocateGPUStatusBuf()1609 MOS_STATUS GpuContextSpecific::AllocateGPUStatusBuf()
1610 {
1611 MOS_OS_FUNCTION_ENTER;
1612
1613 m_statusBufferMosResource = (MOS_RESOURCE_HANDLE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE));
1614 MOS_OS_CHK_NULL_RETURN(m_statusBufferMosResource);
1615
1616 GraphicsResource::CreateParams params;
1617 params.m_tileType = MOS_TILE_LINEAR;
1618 params.m_type = MOS_GFXRES_BUFFER;
1619 params.m_format = Format_Buffer;
1620 params.m_width = sizeof(MOS_GPU_STATUS_DATA);
1621 params.m_height = 1;
1622 params.m_depth = 1;
1623 params.m_arraySize = 1;
1624 params.m_name = "GPU Status Buffer";
1625
1626 GraphicsResource *graphicsResource = GraphicsResource::CreateGraphicResource(GraphicsResource::osSpecificResource);
1627 MOS_OS_CHK_NULL_RETURN(graphicsResource);
1628
1629 MOS_OS_CHK_STATUS_RETURN(graphicsResource->Allocate(m_osContext, params));
1630
1631 GraphicsResource::LockParams lockParams;
1632 lockParams.m_writeRequest = true;
1633 auto gpuStatusData = (MOS_GPU_STATUS_DATA *)graphicsResource->Lock(m_osContext, lockParams);
1634 if (gpuStatusData == nullptr)
1635 {
1636 MOS_OS_ASSERTMESSAGE("Unable to lock gpu eStatus buffer for read.");
1637 graphicsResource->Free(m_osContext);
1638 MOS_Delete(graphicsResource);
1639 return MOS_STATUS_UNKNOWN;
1640 }
1641
1642 m_statusBufferResource = graphicsResource;
1643 return MOS_STATUS_SUCCESS;
1644 }
1645
1646 #if (_DEBUG || _RELEASE_INTERNAL)
SelectEngineInstanceByUser(struct i915_engine_class_instance * engineMap,uint32_t * engineNum,uint32_t userEngineInstance,MOS_GPU_NODE gpuNode)1647 bool GpuContextSpecific::SelectEngineInstanceByUser(struct i915_engine_class_instance *engineMap,
1648 uint32_t *engineNum, uint32_t userEngineInstance, MOS_GPU_NODE gpuNode)
1649 {
1650 uint32_t engineInstance = 0x0;
1651
1652 if(gpuNode == MOS_GPU_NODE_COMPUTE)
1653 {
1654 engineInstance = (userEngineInstance >> ENGINE_INSTANCE_SELECT_COMPUTE_INSTANCE_SHIFT)
1655 & (ENGINE_INSTANCE_SELECT_ENABLE_MASK >> (MAX_ENGINE_INSTANCE_NUM - *engineNum));
1656 }
1657 else if(gpuNode == MOS_GPU_NODE_VE)
1658 {
1659 engineInstance = (userEngineInstance >> ENGINE_INSTANCE_SELECT_VEBOX_INSTANCE_SHIFT)
1660 & (ENGINE_INSTANCE_SELECT_ENABLE_MASK >> (MAX_ENGINE_INSTANCE_NUM - *engineNum));
1661 }
1662 else if(gpuNode == MOS_GPU_NODE_VIDEO || gpuNode == MOS_GPU_NODE_VIDEO2)
1663 {
1664 engineInstance = (userEngineInstance >> ENGINE_INSTANCE_SELECT_VDBOX_INSTANCE_SHIFT)
1665 & (ENGINE_INSTANCE_SELECT_ENABLE_MASK >> (MAX_ENGINE_INSTANCE_NUM - *engineNum));
1666 }
1667 else
1668 {
1669 MOS_OS_NORMALMESSAGE("Invalid gpu node in use.");
1670 }
1671
1672 if(engineInstance)
1673 {
1674 auto unSelectIndex = 0;
1675 for(auto bit = 0; bit < *engineNum; bit++)
1676 {
1677 if(((engineInstance >> bit) & 0x1) && (bit > unSelectIndex))
1678 {
1679 engineMap[unSelectIndex].engine_class = engineMap[bit].engine_class;
1680 engineMap[unSelectIndex].engine_instance = engineMap[bit].engine_instance;
1681 engineMap[bit].engine_class = 0;
1682 engineMap[bit].engine_instance = 0;
1683 unSelectIndex++;
1684 }
1685 else if(((engineInstance >> bit) & 0x1) && (bit == unSelectIndex))
1686 {
1687 unSelectIndex++;
1688 }
1689 else if(!((engineInstance >> bit) & 0x1))
1690 {
1691 engineMap[bit].engine_class = 0;
1692 engineMap[bit].engine_instance = 0;
1693 }
1694 }
1695 *engineNum = unSelectIndex;
1696 }
1697 return engineInstance;
1698 }
1699 #endif
1700