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