xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/cm/cm_task_rt.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2007-2017, 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      cm_task_rt.cpp
24 //! \brief     Contains OS-agnostic CmTaskRT member functions.
25 //!
26 
27 #include "cm_task_rt.h"
28 
29 #include "cm_kernel_rt.h"
30 #include "cm_mem.h"
31 #include "cm_thread_space_rt.h"
32 #include "cm_device_rt.h"
33 #include "cm_surface_manager.h"
34 #include "cm_buffer_rt.h"
35 
36 namespace CMRT_UMD
37 {
38 //*-----------------------------------------------------------------------------
39 //| Purpose:    Create CmTask
40 //| Returns:    Result of the operation.
41 //*-----------------------------------------------------------------------------
Create(CmDeviceRT * device,uint32_t index,uint32_t maxKernelCount,CmTaskRT * & kernelArray)42 int32_t CmTaskRT::Create(CmDeviceRT *device,
43                          uint32_t index,
44                          uint32_t maxKernelCount,
45                          CmTaskRT* &kernelArray)
46 {
47     int32_t result = CM_SUCCESS;
48     kernelArray = new (std::nothrow) CmTaskRT( device, index, maxKernelCount );
49     if( kernelArray )
50     {
51         device->m_memObjectCount.taskCount++;
52         result = kernelArray->Initialize();
53         if( result != CM_SUCCESS )
54         {
55             CmTaskRT::Destroy( kernelArray);
56         }
57     }
58     else
59     {
60         CM_ASSERTMESSAGE("Error: Failed to create CmTask due to out of system memory.");
61         result = CM_OUT_OF_HOST_MEMORY;
62     }
63     return result;
64 }
65 
66 //*-----------------------------------------------------------------------------
67 //| Purpose:    Destroy CmTask
68 //| Returns:    Result of the operation.
69 //*-----------------------------------------------------------------------------
Destroy(CmTaskRT * & kernelArray)70 int32_t CmTaskRT::Destroy( CmTaskRT* &kernelArray )
71 {
72     if( kernelArray )
73     {
74         kernelArray->m_device->m_memObjectCount.taskCount--;
75         delete kernelArray;
76         kernelArray = nullptr;
77     }
78 
79     return CM_SUCCESS;
80 }
81 
82 //*-----------------------------------------------------------------------------
83 //| Purpose:    Constructor of  CmTask
84 //| Returns:    Result of the operation.
85 //*-----------------------------------------------------------------------------
CmTaskRT(CmDeviceRT * device,uint32_t index,uint32_t maxKernelCount)86 CmTaskRT::CmTaskRT(CmDeviceRT *device,
87                    uint32_t index,
88                    uint32_t maxKernelCount):
89     m_kernelArray( nullptr ),
90     m_device( device ),
91     m_kernelCount(0),
92     m_maxKernelCount( maxKernelCount ),
93     m_indexTaskArray(index),
94     m_syncBitmap( 0 ),
95     m_conditionalEndBitmap( 0 )
96 {
97     CmSafeMemSet( &m_powerOption, 0, sizeof( m_powerOption ) );
98     CmSafeMemSet(&m_conditionalEndInfo, 0, sizeof(m_conditionalEndInfo));
99     CmSafeMemSet(&m_taskConfig, 0, sizeof(m_taskConfig));
100     m_taskConfig.turboBoostFlag = CM_TURBO_BOOST_DEFAULT;
101     PCM_HAL_STATE cmHalState = ((PCM_CONTEXT_DATA)m_device->GetAccelData())->cmHalState;
102     cmHalState->cmHalInterface->InitTaskProperty(m_taskConfig);
103 }
104 
105 //*-----------------------------------------------------------------------------
106 //| Purpose:    Destructor of  CmTask
107 //| Returns:    Result of the operation.
108 //*-----------------------------------------------------------------------------
~CmTaskRT(void)109 CmTaskRT::~CmTaskRT( void )
110 {
111     MosSafeDeleteArray(m_kernelArray );
112 }
113 
114 //*-----------------------------------------------------------------------------
115 //| Purpose:    Initialize CmTask
116 //| Returns:    Result of the operation.
117 //*-----------------------------------------------------------------------------
Initialize()118 int32_t CmTaskRT::Initialize( )
119 {
120     m_kernelArray = MOS_NewArray(CmKernelRT*, m_maxKernelCount);
121     if(m_kernelArray)
122     {
123         CmSafeMemSet( m_kernelArray, 0, sizeof(CmKernelRT*) * m_maxKernelCount );
124         return CM_SUCCESS;
125     }
126     else
127     {
128         CM_ASSERTMESSAGE("Error: Failed to initialize CmTask due to out of system memory.");
129         return CM_OUT_OF_HOST_MEMORY;
130     }
131 }
132 
133 //*-----------------------------------------------------------------------------
134 //| Purpose:    Common implementation of Add Kernel to task
135 //| Returns:    Result of the operation.
136 //*-----------------------------------------------------------------------------
AddKernelInternal(CmKernel * kernel,const CM_EXECUTION_CONFIG * config)137 int32_t CmTaskRT::AddKernelInternal( CmKernel *kernel, const CM_EXECUTION_CONFIG *config)
138 {
139     // already reached max kernel count
140     if(m_maxKernelCount <= m_kernelCount)
141     {
142         return CM_EXCEED_MAX_KERNEL_PER_ENQUEUE;
143     }
144     // passed in nullptr pointer
145     if(kernel == nullptr)
146     {
147         CM_ASSERTMESSAGE("Error: Pointer to kernel is null.");
148         return CM_INVALID_ARG_VALUE;
149     }
150 
151     CmKernelRT *kernelRT = static_cast<CmKernelRT *>(kernel);
152     m_kernelArray[m_kernelCount] = kernelRT;
153     kernelRT->SetIndexInTask(m_kernelCount);
154 
155     if(config)
156     {
157         m_kernelExecuteConfig[m_kernelCount] = *config;
158     }
159     else
160     {
161         MOS_ZeroMemory(&m_kernelExecuteConfig[m_kernelCount], sizeof(CM_EXECUTION_CONFIG));
162     }
163 
164     m_kernelCount++;
165 
166 #if USE_EXTENSION_CODE
167     AddKernelForGTPin(kernel);
168 #endif
169     return CM_SUCCESS;
170 }
171 
172 //*-----------------------------------------------------------------------------
173 //| Purpose:    Add Kernel to task
174 //| Returns:    Result of the operation.
175 //*-----------------------------------------------------------------------------
AddKernel(CmKernel * kernel)176 CM_RT_API int32_t CmTaskRT::AddKernel( CmKernel *kernel )
177 {
178     INSERT_API_CALL_LOG(GetHalState());
179     return AddKernelInternal(kernel, nullptr);
180 }
181 
182 //*-----------------------------------------------------------------------------
183 //| Purpose:    Add Kernel to task with execution configure
184 //| Returns:    Result of the operation.
185 //*-----------------------------------------------------------------------------
AddKernelWithConfig(CmKernel * kernel,const CM_EXECUTION_CONFIG * config)186 CM_RT_API int32_t CmTaskRT::AddKernelWithConfig( CmKernel *kernel,
187     const CM_EXECUTION_CONFIG *config )
188 {
189     INSERT_API_CALL_LOG(GetHalState());
190     return AddKernelInternal(kernel, config);
191 }
192 
193 //*-----------------------------------------------------------------------------
194 //| Purpose:    Reset task and clear all the kernel
195 //| Returns:    Result of the operation.
196 //*-----------------------------------------------------------------------------
Reset()197 CM_RT_API int32_t CmTaskRT::Reset()
198 {
199     INSERT_API_CALL_LOG(GetHalState());
200 
201     m_kernelCount = 0;
202     m_syncBitmap = 0;
203     m_conditionalEndBitmap = 0;
204     CmSafeMemSet(&m_conditionalEndInfo, 0, sizeof(m_conditionalEndInfo));
205     CmSafeMemSet(&m_taskConfig, 0, sizeof(m_taskConfig));
206     m_taskConfig.turboBoostFlag = CM_TURBO_BOOST_DEFAULT;
207     CM_CHK_NULL_RETURN_CMERROR(m_device);
208     CM_CHK_NULL_RETURN_CMERROR(m_device->GetAccelData());
209     PCM_HAL_STATE cmHalState = ((PCM_CONTEXT_DATA)m_device->GetAccelData())->cmHalState;
210     CM_CHK_NULL_RETURN_CMERROR(cmHalState);
211     CM_CHK_NULL_RETURN_CMERROR(cmHalState->cmHalInterface);
212     cmHalState->cmHalInterface->InitTaskProperty(m_taskConfig);
213 
214     if(m_kernelArray)
215     {
216         CmSafeMemSet( m_kernelArray, 0, sizeof(CmKernelRT*) * m_maxKernelCount );
217         return CM_SUCCESS;
218     }
219     else
220     {
221         CM_ASSERTMESSAGE("Error: Pointer to kernel array is null.");
222         return CM_NULL_POINTER;
223     }
224 }
225 
226 //*-----------------------------------------------------------------------------
227 //| Purpose:    Get the kernel count
228 //| Returns:    The count of kernels
229 //*-----------------------------------------------------------------------------
GetKernelCount()230 uint32_t CmTaskRT::GetKernelCount()
231 {
232     return m_kernelCount;
233 }
234 
235 //*-----------------------------------------------------------------------------
236 //| Purpose:    Get the kernel pointer by its index
237 //| Returns:    Result of the operation.
238 //*-----------------------------------------------------------------------------
GetKernelPointer(uint32_t index)239 CmKernelRT* CmTaskRT::GetKernelPointer(uint32_t index)
240 {
241     if(index >= m_kernelCount)
242     {
243         CM_ASSERTMESSAGE("Error: The kernel index exceeds the kernel count.");
244         return nullptr;
245     }
246     return m_kernelArray[index];
247 }
248 
GetIndexInTaskArray()249 uint32_t CmTaskRT::GetIndexInTaskArray()
250 {
251     return m_indexTaskArray;
252 }
253 
254 //*-----------------------------------------------------------------------------
255 //| Purpose:    Check the integrity of kernel threadspaces within a task
256 //| Returns:    True if all kernel threadspaces are valid, False otherwise
257 //*-----------------------------------------------------------------------------
IntegrityCheckKernelThreadspace(void)258 bool CmTaskRT::IntegrityCheckKernelThreadspace( void )
259 {
260     int32_t               hr                  = CM_SUCCESS;
261     uint32_t              kernelCount         = 0;
262     uint32_t              i                   = 0;
263     uint32_t              j                   = 0;
264     CmKernelRT*             kernelRT          = nullptr;
265     CmKernelRT*             kernelTmp            = nullptr;
266     uint32_t              threadCount         = 0;
267     CmThreadSpaceRT*        kernelThreadSpace           = nullptr;
268     uint32_t              width               = 0;
269     uint32_t              height              = 0;
270     uint8_t**             threadSpaceMapping  = nullptr;
271     uint8_t*              kernelInScoreboard  = nullptr;
272     CM_THREAD_SPACE_UNIT* threadSpaceUnit     = nullptr;
273     uint32_t              kernelIndex         = 0;
274     uint32_t              unassociated        = 0;
275 
276     kernelCount = this->GetKernelCount();
277 
278     threadSpaceMapping = MOS_NewArray(uint8_t*, kernelCount);
279     kernelInScoreboard = MOS_NewArray(uint8_t, kernelCount);
280 
281     CM_CHK_NULL_GOTOFINISH(threadSpaceMapping, CM_OUT_OF_HOST_MEMORY);
282     CM_CHK_NULL_GOTOFINISH(kernelInScoreboard, CM_OUT_OF_HOST_MEMORY);
283 
284     CmSafeMemSet(threadSpaceMapping, 0, kernelCount*sizeof(uint8_t *));
285     CmSafeMemSet(kernelInScoreboard, 0, kernelCount*sizeof(uint8_t));
286 
287     for( i = 0; i < kernelCount; ++i )
288     {
289         kernelRT = this->GetKernelPointer(i);
290         CM_CHK_NULL_GOTOFINISH_CMERROR(kernelRT);
291 
292         CM_CHK_CMSTATUS_GOTOFINISH(kernelRT->GetThreadSpace(kernelThreadSpace));
293         CM_CHK_NULL_GOTOFINISH(kernelThreadSpace, CM_KERNEL_THREADSPACE_NOT_SET);
294 
295         CM_CHK_CMSTATUS_GOTOFINISH(kernelThreadSpace->GetThreadSpaceSize(width, height));
296         CM_CHK_CMSTATUS_GOTOFINISH(kernelRT->GetThreadCount(threadCount));
297         if (threadCount == 0)
298         {
299             threadCount = width * height;
300         }
301 
302         if( kernelThreadSpace->IsThreadAssociated() )
303         {
304             threadSpaceMapping[i] = MOS_NewArray(uint8_t, threadCount);
305             CM_CHK_NULL_GOTOFINISH(threadSpaceMapping[i], CM_OUT_OF_HOST_MEMORY);
306             CmSafeMemSet(threadSpaceMapping[i], 0, threadCount * sizeof(uint8_t));
307             kernelInScoreboard[i] = false;
308 
309             hr = kernelThreadSpace->GetThreadSpaceUnit(threadSpaceUnit);
310             if( hr != CM_SUCCESS  || threadSpaceUnit == nullptr )
311             {
312                 CM_ASSERTMESSAGE("Error: Invalid thread space unit");
313                 MosSafeDeleteArray(threadSpaceMapping[i]);
314                 hr = CM_FAILURE;
315                 goto finish;
316             }
317 
318             for( j = 0; j < width * height; ++j )
319             {
320                 kernelTmp = static_cast<CmKernelRT*>(threadSpaceUnit[j].kernel);
321                 if( kernelTmp == nullptr )
322                 {
323                     if (kernelThreadSpace->GetNeedSetKernelPointer())
324                     {
325                         kernelTmp = kernelThreadSpace->GetKernelPointer();
326                     }
327                     if (kernelTmp == nullptr)
328                     {
329                         CM_ASSERTMESSAGE("Error: Invalid kernel pointer.");
330                         MosSafeDeleteArray(threadSpaceMapping[i]);
331                         hr = CM_FAILURE;
332                         goto finish;
333                     }
334                 }
335 
336                 kernelIndex = kernelTmp->GetIndexInTask();
337                 threadSpaceMapping[kernelIndex][threadSpaceUnit[j].threadId] = 1;
338                 kernelInScoreboard[kernelIndex] = 1;
339             }
340 
341             if( kernelInScoreboard[i] )
342             {
343                 kernelRT->SetAssociatedToTSFlag(true);
344                 for( j = 0; j < threadCount; ++j )
345                 {
346                     if( threadSpaceMapping[i][j] == 0 )
347                     {
348                         unassociated++;
349                         break;
350                     }
351                 }
352             }
353             MosSafeDeleteArray(threadSpaceMapping[i]);
354         }
355 
356         if( unassociated != 0 )
357         {
358             CM_ASSERTMESSAGE("Error: kernel threadspace is not associated.");
359             hr = CM_KERNEL_THREADSPACE_THREADS_NOT_ASSOCIATED;
360             goto finish;
361         }
362     }
363 
364 finish:
365 
366     MosSafeDeleteArray(threadSpaceMapping);
367     MosSafeDeleteArray(kernelInScoreboard);
368 
369     return (hr == CM_SUCCESS)? true: false;
370 }
371 
372 //*-----------------------------------------------------------------------------
373 //| Purpose:    Insert synchronization point before next kernel
374 //| Returns:    Result of the operation.
375 //*-----------------------------------------------------------------------------
AddSync()376 CM_RT_API int32_t CmTaskRT::AddSync()
377 {
378     INSERT_API_CALL_LOG(GetHalState());
379 
380     if (m_kernelCount > 0)
381     {
382         m_syncBitmap |= (uint64_t)1 << (m_kernelCount - 1);
383     }
384 
385     return CM_SUCCESS;
386 }
387 
GetSyncBitmap()388 uint64_t CmTaskRT::GetSyncBitmap()
389 {
390     return m_syncBitmap;
391 }
392 
393 //*-----------------------------------------------------------------------------
394 //| Purpose:    Set the conditional value, compare mask and handle for the
395 //|             surface associated with index
396 //| Returns:    Result of the operation.
397 //*-----------------------------------------------------------------------------
SetConditionalEndInfo(SurfaceIndex * index,uint32_t offset,CM_CONDITIONAL_END_PARAM * conditionalParam)398 int32_t CmTaskRT::SetConditionalEndInfo(SurfaceIndex* index,
399                                         uint32_t offset,
400                                         CM_CONDITIONAL_END_PARAM *conditionalParam)
401 {
402     CmSurface*        surface = nullptr;
403     CmSurfaceManager* surfaceMgr = nullptr;
404     uint32_t          surfIndex = 0;
405 
406     m_device->GetSurfaceManager(surfaceMgr);
407     if (!surfaceMgr)
408     {
409         CM_ASSERTMESSAGE("Error: Pointer to surface manager is null.");
410         return CM_NULL_POINTER;
411     }
412 
413     surfIndex = index->get_data();
414 
415     surfaceMgr->GetSurface(surfIndex, surface);
416     if (!surface)
417     {
418         CM_ASSERTMESSAGE("Error: Pointer to surface is null.");
419         return CM_NULL_POINTER;
420     }
421 
422     if (surface->Type() == CM_ENUM_CLASS_TYPE_CMBUFFER_RT)
423     {
424         uint32_t handle = 0;
425         CmBuffer_RT* surf1D = static_cast<CmBuffer_RT*> (surface);
426 
427         surf1D->GetHandle(handle);
428         m_conditionalEndInfo[m_kernelCount].compareValue = conditionalParam->opValue;
429         m_conditionalEndInfo[m_kernelCount].bufferTableIndex = handle;
430         m_conditionalEndInfo[m_kernelCount].disableCompareMask = !conditionalParam->opMask;
431         m_conditionalEndInfo[m_kernelCount].endCurrentLevel = conditionalParam->opLevel;
432         m_conditionalEndInfo[m_kernelCount].operatorCode = conditionalParam->opCode;
433         m_conditionalEndInfo[m_kernelCount].offset = offset;
434     }
435     else
436     {
437         return CM_NOT_IMPLEMENTED;
438     }
439 
440     return CM_SUCCESS;
441 }
442 
GetConditionalEndBitmap()443 uint64_t CmTaskRT::GetConditionalEndBitmap()
444 {
445     return m_conditionalEndBitmap;
446 }
447 
GetConditionalEndInfo()448 CM_HAL_CONDITIONAL_BB_END_INFO* CmTaskRT::GetConditionalEndInfo()
449 {
450     return m_conditionalEndInfo;
451 }
452 
GetPowerOption()453 PCM_POWER_OPTION CmTaskRT::GetPowerOption()
454 {
455     return &m_powerOption;
456 }
457 
458 #if CM_LOG_ON
Log()459 std::string CmTaskRT::Log()
460 {
461     std::ostringstream  oss;
462 
463     oss << " Kernel Count:" << m_kernelCount
464         << " Sync Bit:"<<m_syncBitmap
465         << " Conditional End Bit: " << m_conditionalEndBitmap
466         << std::endl;
467 
468     for (uint32_t i=0 ; i< m_kernelCount; i++)
469     {
470         CmKernelRT* kernel = (CmKernelRT*)m_kernelArray[i];
471         oss << kernel->Log(); // log each kernel
472     }
473     return oss.str();
474 }
475 
GetHalState()476 CM_HAL_STATE* CmTaskRT::GetHalState() { return m_device->GetHalState(); }
477 
478 #endif  // #if CM_LOG_ON
479 
SetProperty(const CM_TASK_CONFIG & taskConfig)480 CM_RT_API int32_t CmTaskRT::SetProperty(const CM_TASK_CONFIG &taskConfig)
481 {
482     m_taskConfig = taskConfig;
483     return CM_SUCCESS;
484 }
485 
GetProperty(CM_TASK_CONFIG & taskConfig)486 CM_RT_API int32_t CmTaskRT::GetProperty(CM_TASK_CONFIG &taskConfig)
487 {
488     taskConfig = m_taskConfig;
489     return CM_SUCCESS;
490 }
491 
492 CM_RT_API int32_t
AddConditionalEnd(SurfaceIndex * conditionalSurfaceIndex,uint32_t offset,CM_CONDITIONAL_END_PARAM * conditionalParam)493 CmTaskRT::AddConditionalEnd(SurfaceIndex* conditionalSurfaceIndex,
494                             uint32_t offset,
495                             CM_CONDITIONAL_END_PARAM *conditionalParam)
496 {
497     INSERT_API_CALL_LOG(GetHalState());
498 
499     int32_t hr = CM_SUCCESS;
500 
501     m_conditionalEndBitmap |= (uint64_t)1 << m_kernelCount;
502 
503     hr = SetConditionalEndInfo(conditionalSurfaceIndex, offset, conditionalParam);
504 
505     return hr;
506 }
507 }  // namespace CMRT_UMD
508