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_buffer_rt.cpp
24 //! \brief Contains implementation of CmBuffer_RT.
25 //!
26
27 #include "cm_buffer_rt.h"
28
29 #include "cm_surface_manager.h"
30 #include "cm_event_rt.h"
31 #include "cm_device_rt.h"
32 #include "cm_log.h"
33 #include "cm_mem.h"
34 #include "cm_hal.h"
35 namespace CMRT_UMD
36 {
37 //*-----------------------------------------------------------------------------
38 //| Purpose: Create CM Buffer
39 //| Returns: Result of the operation
40 //*-----------------------------------------------------------------------------
Create(uint32_t index,uint32_t handle,size_t size,bool isCmCreated,CmSurfaceManager * surfaceManager,uint32_t bufferType,bool isCMRTAllocatedSVM,void * sysMem,CmBuffer_RT * & surface,bool isConditionalBuffer,uint32_t comparisonValue,uint64_t gfxMem,bool enableCompareMask)41 int32_t CmBuffer_RT::Create(uint32_t index, uint32_t handle, size_t size,
42 bool isCmCreated, CmSurfaceManager *surfaceManager,
43 uint32_t bufferType, bool isCMRTAllocatedSVM, void *sysMem,
44 CmBuffer_RT *&surface, bool isConditionalBuffer,
45 uint32_t comparisonValue, uint64_t gfxMem, bool enableCompareMask)
46 {
47 int32_t result = CM_SUCCESS;
48
49 surface = new (std::nothrow)CmBuffer_RT(handle, size, isCmCreated, surfaceManager, bufferType,
50 isCMRTAllocatedSVM, sysMem, isConditionalBuffer,
51 comparisonValue, gfxMem, enableCompareMask);
52 if( surface )
53 {
54 result = surface->Initialize( index );
55 if( result != CM_SUCCESS )
56 {
57 CmSurface* baseSurface = surface;
58 CmSurface::Destroy( baseSurface );
59 }
60 }
61 else
62 {
63 CM_ASSERTMESSAGE("Error: Failed to create cmBuffer due to out of system memory.");
64 result = CM_OUT_OF_HOST_MEMORY;
65 }
66
67 return result;
68 }
69
CmBuffer_RT(uint32_t handle,size_t size,bool isCmCreated,CmSurfaceManager * surfaceManager,uint32_t bufferType,bool isCMRTAllocatedSVM,void * sysMem,bool isConditionalBuffer,uint32_t comparisonValue,uint64_t gfxAddr,bool enableCompareMask)70 CmBuffer_RT::CmBuffer_RT(uint32_t handle, size_t size, bool isCmCreated,
71 CmSurfaceManager* surfaceManager, uint32_t bufferType,
72 bool isCMRTAllocatedSVM, void *sysMem, bool isConditionalBuffer,
73 uint32_t comparisonValue, uint64_t gfxAddr, bool enableCompareMask ):
74 CmSurface(surfaceManager, isCmCreated),
75 m_handle(handle),
76 m_size(size),
77 m_bufferType(bufferType),
78 m_sysMem(sysMem),
79 m_gfxMem(gfxAddr),
80 m_isCMRTAllocatedSVMBuffer(isCMRTAllocatedSVM),
81 m_isConditionalBuffer(isConditionalBuffer),
82 m_comparisonValue(comparisonValue),
83 m_enableCompareMask(enableCompareMask),
84 m_numAliases(0)
85 {
86 CmSurface::SetMemoryObjectControl(MEMORY_OBJECT_CONTROL_UNKNOW, CM_USE_PTE, 0);
87 CmSafeMemSet(m_aliasIndexes, 0, sizeof(SurfaceIndex*) * CM_HAL_MAX_NUM_BUFFER_ALIASES);
88 }
89
~CmBuffer_RT(void)90 CmBuffer_RT::~CmBuffer_RT( void )
91 {
92 for( uint32_t i = 0; i < CM_HAL_MAX_NUM_BUFFER_ALIASES; ++i )
93 {
94 MosSafeDelete(m_aliasIndexes[i]);
95 }
96 }
97
Initialize(uint32_t index)98 int32_t CmBuffer_RT::Initialize( uint32_t index )
99 {
100 return CmSurface::Initialize( index );
101 }
102
GetHandle(uint32_t & handle)103 int32_t CmBuffer_RT::GetHandle( uint32_t& handle)
104 {
105 handle = m_handle;
106 return CM_SUCCESS;
107 }
108
109 //*-----------------------------------------------------------------------------
110 //| Purpose: Write data from sysMem to Buffer
111 //| Returns: Result of the operation
112 //*-----------------------------------------------------------------------------
WriteBuffer(const unsigned char * sysMem,CmEvent * event,uint64_t sysMemSize,size_t offset)113 int32_t CmBuffer_RT::WriteBuffer( const unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize, size_t offset)
114 {
115 INSERT_API_CALL_LOG(nullptr);
116
117 CM_RETURN_CODE hr = CM_SUCCESS;
118 uint8_t *dst = nullptr;
119 uint8_t *surf = nullptr;
120 size_t copySize = MOS_MIN((size_t)sysMemSize, m_size);
121
122 if (sysMem == nullptr)
123 {
124 CM_ASSERTMESSAGE("Error: Pointer to system memory is null.");
125 return CM_NULL_POINTER;
126 }
127
128 // It makes sense to flush the whole enqueued tasks for each surface read
129 // because usually we read the output of the last task.
130 // Update: using event not to flush the whole enqueued tasks
131 if( event )
132 {
133 CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
134 if (eventRT)
135 {
136 FlushDeviceQueue(eventRT);
137 }
138 else
139 {
140 event->WaitForTaskFinished();
141 }
142 }
143
144 WaitForReferenceFree(); // wait all owner task finished
145
146 // Lock Buffer first
147 CmDeviceRT * cmDevice = nullptr;
148 m_surfaceMgr->GetCmDevice(cmDevice);
149 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
150
151 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
152 CM_CHK_NULL_RETURN_CMERROR(cmData);
153 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
154
155 CM_HAL_BUFFER_PARAM inParam;
156 CmSafeMemSet( &inParam, 0, sizeof( CM_HAL_BUFFER_PARAM ) );
157 inParam.lockFlag = CM_HAL_LOCKFLAG_WRITEONLY;
158 inParam.handle = m_handle;
159
160 // Lock Buffer:
161 // Lock Buffer may fail due to the out of memory/out of page-in in KMD.
162 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam));
163 CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
164
165 // Memory copy : Source ->System Memory Dest -> Video Memory
166 dst = ( uint8_t *)(inParam.data) + offset;
167 surf = ( uint8_t *)sysMem;
168
169 CmFastMemCopyWC(dst, surf, copySize);
170
171 //Unlock Buffer
172 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam));
173
174 finish:
175 if (hr < CM_MOS_STATUS_CONVERTED_CODE_OFFSET) {
176 hr = CM_LOCK_SURFACE_FAIL;
177 }
178 return hr;
179 }
180
181 //*-----------------------------------------------------------------------------
182 //| Purpose: Read data from sysMem to Buffer
183 //| Returns: Result of the operation
184 //*-----------------------------------------------------------------------------
ReadBuffer(unsigned char * sysMem,CmEvent * event,uint64_t sysMemSize,size_t offset)185 int32_t CmBuffer_RT::ReadBuffer( unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize, size_t offset)
186 {
187 INSERT_API_CALL_LOG(nullptr);
188
189 CM_RETURN_CODE hr = CM_SUCCESS;
190 uint8_t* surf = nullptr;
191 uint8_t* dst = nullptr;
192 size_t copySize = MOS_MIN((size_t)sysMemSize, m_size);
193
194 if (sysMem == nullptr)
195 {
196 CM_ASSERTMESSAGE("Error: Pointer to system memory is null.");
197 return CM_NULL_POINTER;
198 }
199
200 // It makes sense to flush the whole enqueued tasks for each surface read
201 // because usually we read the output of the last task.
202 // Update: using event not to flush the whole enqueued tasks
203 if( event )
204 {
205 CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
206 if (eventRT)
207 {
208 FlushDeviceQueue(eventRT);
209 }
210 else
211 {
212 event->WaitForTaskFinished();
213 }
214 }
215
216 WaitForReferenceFree(); // wait all owner task finished
217
218 // Lock Buffer first
219 CmDeviceRT * cmDevice = nullptr;
220 m_surfaceMgr->GetCmDevice(cmDevice);
221 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
222 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
223 CM_CHK_NULL_RETURN_CMERROR(cmData);
224 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
225
226 CM_HAL_BUFFER_PARAM inParam;
227 CmSafeMemSet( &inParam, 0, sizeof( CM_HAL_BUFFER_PARAM ) );
228 inParam.lockFlag = CM_HAL_LOCKFLAG_READONLY;
229 inParam.handle = m_handle;
230
231 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam));
232 CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
233
234 // Memory copy : Dest ->System Memory Source -> Vedio Memory
235 // CmFastMemCopyFromWC(sysMem, (void*)(&((unsigned char*)inParam.data)[offset]), copySize, GetCpuInstructionLevel());
236 // Memory copy : Source ->System Memory Dest -> Video Memory
237 surf = (uint8_t *)(inParam.data) + offset;
238 dst = (uint8_t *)sysMem;
239 CmFastMemCopyFromWC(dst, surf, copySize, GetCpuInstructionLevel());
240 //MOS_SecureMemcpy(dst, copySize, surf, copySize);
241 //Unlock Buffer
242 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam));
243
244 finish:
245 if (hr < CM_MOS_STATUS_CONVERTED_CODE_OFFSET) {
246 hr = CM_LOCK_SURFACE_FAIL;
247 }
248 return hr;
249 }
250
GetIndex(SurfaceIndex * & index)251 CM_RT_API int32_t CmBuffer_RT::GetIndex( SurfaceIndex*& index )
252 {
253 index = m_index;
254 return CM_SUCCESS;
255 }
256
257
258 //*-----------------------------------------------------------------------------
259 //| Purpose: Write data from sysMem to Buffer
260 //| Returns: Result of the operation
261 //*-----------------------------------------------------------------------------
WriteSurface(const unsigned char * sysMem,CmEvent * event,uint64_t sysMemSize)262 CM_RT_API int32_t CmBuffer_RT::WriteSurface(const unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize)
263 {
264 INSERT_API_CALL_LOG(nullptr);
265
266 CM_RETURN_CODE hr = CM_SUCCESS;
267 uint8_t* dst = nullptr;
268 uint8_t* surf = nullptr;
269 size_t copySize = MOS_MIN((size_t)sysMemSize, m_size);
270
271 if (sysMem == nullptr)
272 {
273 CM_ASSERTMESSAGE("Error: Pointer to system memory is null.");
274 return CM_NULL_POINTER;
275 }
276
277 // It makes sense to flush the whole enqueued tasks for each surface read
278 // because usually we read the output of the last task.
279 // Update: using event not to flush the whole enqueued tasks
280 if (event)
281 {
282 CmEventRT* eventRT = dynamic_cast<CmEventRT*>(event);
283 if (eventRT)
284 {
285 FlushDeviceQueue(eventRT);
286 }
287 else
288 {
289 event->WaitForTaskFinished();
290 }
291 }
292
293 WaitForReferenceFree(); // wait all owner task finished
294
295 // Lock Buffer first
296 CmDeviceRT* cmDevice = nullptr;
297 m_surfaceMgr->GetCmDevice(cmDevice);
298 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
299
300 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
301 CM_CHK_NULL_RETURN_CMERROR(cmData);
302 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
303
304 CM_HAL_BUFFER_PARAM inParam;
305 CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_BUFFER_PARAM));
306 inParam.lockFlag = CM_HAL_LOCKFLAG_WRITEONLY;
307 inParam.handle = m_handle;
308
309 // Lock Buffer:
310 // Lock Buffer may fail due to the out of memory/out of page-in in KMD.
311 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam));
312 CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
313
314 // Memory copy : Source ->System Memory Dest -> Vedio Memory
315 dst = (uint8_t*)(inParam.data);
316 surf = (uint8_t*)sysMem;
317
318 CmFastMemCopyWC(dst, surf, copySize);
319
320 //Unlock Buffer
321 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam));
322
323 finish:
324 if (hr < CM_MOS_STATUS_CONVERTED_CODE_OFFSET) {
325 hr = CM_LOCK_SURFACE_FAIL;
326 }
327 return hr;
328 }
329
330 //*-----------------------------------------------------------------------------
331 //| Purpose: Read data from sysMem to Buffer
332 //| Returns: Result of the operation
333 //*-----------------------------------------------------------------------------
ReadSurface(unsigned char * sysMem,CmEvent * event,uint64_t sysMemSize)334 CM_RT_API int32_t CmBuffer_RT::ReadSurface(unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize)
335 {
336 INSERT_API_CALL_LOG(nullptr);
337
338 CM_RETURN_CODE hr = CM_SUCCESS;
339
340 size_t copySize = MOS_MIN((size_t)sysMemSize, m_size);
341
342 if (sysMem == nullptr)
343 {
344 CM_ASSERTMESSAGE("Error: Pointer to system memory is null.");
345 return CM_NULL_POINTER;
346 }
347
348 // It makes sense to flush the whole enqueued tasks for each surface read
349 // because usually we read the output of the last task.
350 // Update: using event not to flush the whole enqueued tasks
351 if (event)
352 {
353 CmEventRT* eventRT = dynamic_cast<CmEventRT*>(event);
354 if (eventRT)
355 {
356 FlushDeviceQueue(eventRT);
357 }
358 else
359 {
360 event->WaitForTaskFinished();
361 }
362 }
363
364 WaitForReferenceFree(); // wait all owner task finished
365
366 // Lock Buffer first
367 CmDeviceRT* cmDevice = nullptr;
368 m_surfaceMgr->GetCmDevice(cmDevice);
369 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
370 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
371 CM_CHK_NULL_RETURN_CMERROR(cmData);
372 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
373
374 CM_HAL_BUFFER_PARAM inParam;
375 CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_BUFFER_PARAM));
376 inParam.lockFlag = CM_HAL_LOCKFLAG_READONLY;
377 inParam.handle = m_handle;
378
379 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam));
380 CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
381
382 // Memory copy : Dest ->System Memory Source -> Vedio Memory
383 CmFastMemCopyFromWC(sysMem, inParam.data, copySize, GetCpuInstructionLevel());
384
385 //Unlock Buffer
386 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam));
387
388 finish:
389 if (hr < CM_MOS_STATUS_CONVERTED_CODE_OFFSET) {
390 hr = CM_LOCK_SURFACE_FAIL;
391 }
392 return hr;
393 }
394
395
InitSurface(const uint32_t initValue,CmEvent * event)396 CM_RT_API int32_t CmBuffer_RT::InitSurface(const uint32_t initValue, CmEvent* event)
397 {
398 INSERT_API_CALL_LOG(nullptr);
399
400 CM_RETURN_CODE hr = CM_SUCCESS;
401
402 // It makes sense to flush the whole enqueued tasks for each surface read
403 // because usually we read the output of the last task.
404 // Update: using event not to flush the whole enqueued tasks
405 if( event )
406 {
407 CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
408 if (eventRT)
409 {
410 FlushDeviceQueue(eventRT);
411 }
412 else
413 {
414 event->WaitForTaskFinished();
415 }
416 }
417
418 CmDeviceRT* cmDevice = nullptr;
419 m_surfaceMgr->GetCmDevice( cmDevice );
420 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
421
422 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
423 CM_CHK_NULL_RETURN_CMERROR(cmData);
424 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
425
426 CM_HAL_BUFFER_PARAM inParam;
427 CmSafeMemSet( &inParam, 0, sizeof( CM_HAL_BUFFER_PARAM ) );
428 inParam.handle = m_handle;
429 inParam.lockFlag = CM_HAL_LOCKFLAG_WRITEONLY;
430
431 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam));
432 CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
433
434 CmDwordMemSet(inParam.data, initValue, m_size);
435
436 // unlock
437 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam));
438
439 finish:
440 if (hr < CM_MOS_STATUS_CONVERTED_CODE_OFFSET) {
441 hr = CM_LOCK_SURFACE_FAIL;
442 }
443 return hr;
444 }
445
SetMemoryObjectControl(MEMORY_OBJECT_CONTROL memCtrl,MEMORY_TYPE memType,uint32_t age)446 int32_t CmBuffer_RT::SetMemoryObjectControl( MEMORY_OBJECT_CONTROL memCtrl, MEMORY_TYPE memType, uint32_t age)
447 {
448
449 int32_t hr = CM_SUCCESS;
450 uint16_t mocs = 0;
451 hr = CmSurface::SetMemoryObjectControl( memCtrl, memType, age );
452
453 CmDeviceRT *cmDevice = nullptr;
454 m_surfaceMgr->GetCmDevice(cmDevice);
455 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
456 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
457 CM_CHK_NULL_RETURN_CMERROR(cmData);
458 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
459
460 mocs = (m_memObjCtrl.mem_ctrl << 8) | (m_memObjCtrl.mem_type<<4) | m_memObjCtrl.age;
461 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetSurfaceMOCS(cmData->cmHalState, m_handle, mocs, ARG_KIND_SURFACE_1D));
462 ++ m_propertyIndex;
463 finish:
464 return hr;
465 }
466
SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL memCtrl)467 CM_RT_API int32_t CmBuffer_RT::SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL memCtrl)
468 {
469 INSERT_API_CALL_LOG(nullptr);
470 ++ m_propertyIndex;
471 return SetMemoryObjectControl(memCtrl, CM_USE_PTE, 0);
472 }
473
SetResourceUsage(const MOS_HW_RESOURCE_DEF mosUsage)474 CMRT_UMD_API int32_t CmBuffer_RT::SetResourceUsage(const MOS_HW_RESOURCE_DEF mosUsage)
475 {
476 INSERT_API_CALL_LOG(nullptr);
477 int32_t hr = CM_SUCCESS;
478 uint16_t mocs = 0;
479 hr = CmSurface::SetResourceUsage(mosUsage);
480
481 CmDeviceRT *cmDevice = nullptr;
482 m_surfaceMgr->GetCmDevice(cmDevice);
483 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
484 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
485 CM_CHK_NULL_RETURN_CMERROR(cmData);
486 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
487
488 mocs = (m_memObjCtrl.mem_ctrl << 8) | (m_memObjCtrl.mem_type << 4) | m_memObjCtrl.age;
489 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetSurfaceMOCS(cmData->cmHalState, m_handle, mocs, ARG_KIND_SURFACE_1D));
490 ++ m_propertyIndex;
491 finish:
492 return hr;
493 }
494
SetSurfaceStateParam(SurfaceIndex * surfIndex,const CM_BUFFER_STATE_PARAM * bufferStateParam)495 CM_RT_API int32_t CmBuffer_RT::SetSurfaceStateParam(SurfaceIndex *surfIndex, const CM_BUFFER_STATE_PARAM *bufferStateParam)
496 {
497 CM_RETURN_CODE hr = CM_SUCCESS;
498 size_t newSize = 0;
499 if(bufferStateParam->uiBaseAddressOffset + bufferStateParam->uiSize > m_size)
500 {
501 CM_ASSERTMESSAGE("Error: The offset exceeds the buffer size.");
502 return CM_INVALID_ARG_VALUE;
503 }
504 if(bufferStateParam->uiBaseAddressOffset%16) // the offset must be 16-aligned, otherwise it will cause a GPU hang
505 {
506 CM_ASSERTMESSAGE("Error: The offset must be 16-aligned, otherwise it will cause GPU hang.");
507 return CM_INVALID_ARG_VALUE;
508 }
509
510 if (bufferStateParam->uiSize)
511 {
512 newSize = bufferStateParam->uiSize;
513 }
514 else
515 {
516 newSize = m_size - bufferStateParam->uiBaseAddressOffset;
517 }
518 CmDeviceRT* cmDevice = nullptr;
519 m_surfaceMgr->GetCmDevice( cmDevice );
520 CM_CHK_NULL_RETURN_CMERROR(cmDevice);
521
522 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
523 CM_CHK_NULL_RETURN_CMERROR(cmData);
524 CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
525
526 CM_HAL_BUFFER_SURFACE_STATE_PARAM inParam;
527 CmSafeMemSet( &inParam, 0, sizeof( inParam ) );
528
529 if( surfIndex )
530 {
531 inParam.aliasIndex = surfIndex->get_data();
532 }
533 else
534 {
535 inParam.aliasIndex = m_index->get_data();
536 }
537 inParam.handle = m_handle;
538 inParam.offset = bufferStateParam->uiBaseAddressOffset;
539 inParam.size = newSize;
540 inParam.mocs = (uint16_t)((bufferStateParam->mocs.mem_ctrl << 8)|(bufferStateParam->mocs.mem_type << 4)|(bufferStateParam->mocs.age));
541
542 CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetBufferSurfaceStatePara(cmData->cmHalState, &inParam));
543 ++ m_propertyIndex;
544
545 finish:
546 return hr;
547 }
548
SetSize(size_t size)549 void CmBuffer_RT::SetSize( size_t size )
550 {
551 m_size = size;
552 }
553
IsUpSurface()554 bool CmBuffer_RT::IsUpSurface()
555 {
556 return (m_bufferType == CM_BUFFER_UP);
557 }
558
IsSVMSurface()559 bool CmBuffer_RT::IsSVMSurface()
560 {
561 return (m_bufferType == CM_BUFFER_SVM);
562 }
563
GetAddress(void * & addr)564 CM_RT_API int32_t CmBuffer_RT::GetAddress( void *&addr)
565 {
566
567 addr = m_sysMem;
568 return CM_SUCCESS;
569 }
570
IsCMRTAllocatedSVMBuffer()571 bool CmBuffer_RT::IsCMRTAllocatedSVMBuffer()
572 {
573 return m_isCMRTAllocatedSVMBuffer;
574 }
575
IsConditionalSurface()576 bool CmBuffer_RT::IsConditionalSurface()
577 {
578 return m_isConditionalBuffer;
579 }
580
GetConditionalCompareValue()581 uint32_t CmBuffer_RT::GetConditionalCompareValue()
582 {
583 return m_comparisonValue;
584 }
585
IsCompareMaskEnabled()586 bool CmBuffer_RT::IsCompareMaskEnabled()
587 {
588 return m_enableCompareMask;
589 }
590
CreateBufferAlias(SurfaceIndex * & aliasIndex)591 int32_t CmBuffer_RT::CreateBufferAlias(SurfaceIndex* & aliasIndex)
592 {
593 uint32_t surfArraySize = 0;
594
595 if( m_numAliases < CM_HAL_MAX_NUM_BUFFER_ALIASES )
596 {
597 uint32_t origIndex = m_index->get_data();
598 m_surfaceMgr->GetSurfaceArraySize(surfArraySize);
599 uint32_t newIndex = origIndex + ( (m_numAliases + 1) * surfArraySize);
600 m_aliasIndexes[m_numAliases] = MOS_New(SurfaceIndex, newIndex);
601 if( m_aliasIndexes[m_numAliases] )
602 {
603 aliasIndex = m_aliasIndexes[m_numAliases];
604 m_numAliases++;
605 return CM_SUCCESS;
606 }
607 else
608 {
609 CM_ASSERTMESSAGE("Error: Failed to create CmBufferAlias due to out of system memory.");
610 return CM_OUT_OF_HOST_MEMORY;
611 }
612 }
613 else
614 {
615 return CM_EXCEED_MAX_NUM_BUFFER_ALIASES;
616 }
617 }
618
GetNumAliases(uint32_t & numAliases)619 int32_t CmBuffer_RT::GetNumAliases(uint32_t& numAliases)
620 {
621 numAliases = m_numAliases;
622 return CM_SUCCESS;
623 }
624
Log(std::ostringstream & oss)625 void CmBuffer_RT::Log(std::ostringstream &oss)
626 {
627 #if CM_LOG_ON
628 oss << " Surface Buffer Info "
629 << " Size:" << m_size
630 << " Buffer Type:" << m_bufferType
631 << " Sys Address:" << m_sysMem
632 << " Handle:" << m_handle
633 << " SurfaceIndex:" << m_index->get_data()
634 << " IsCmCreated:" << m_isCmCreated
635 << std::endl;
636 #endif
637 }
638
639 //*-----------------------------------------------------------------------------
640 //| Purpose: Dump Surface's data into files
641 //| Returns: None
642 //| Notes: Must be called after task finished.
643 //*-----------------------------------------------------------------------------
DumpContent(uint32_t kernelNumber,char * kernelName,int32_t taskId,uint32_t argIndex,uint32_t vectorIndex)644 void CmBuffer_RT::DumpContent(uint32_t kernelNumber, char *kernelName, int32_t taskId, uint32_t argIndex, uint32_t vectorIndex)
645 {
646 #if MDF_SURFACE_CONTENT_DUMP
647 std::ostringstream outputFileName;
648 static uint32_t bufferDumpNumber = 0;
649 char fileNamePrefix[MAX_PATH] = {0};
650 std::ofstream outputFileStream;
651
652 outputFileName << "t_" << taskId
653 << "_k_" << kernelNumber
654 << "_" << kernelName
655 <<"_argi_"<< argIndex
656 <<"_vector_index_"<< vectorIndex
657 << "_buffer_surfi_" << m_index->get_data()
658 <<"_w_"<< m_size
659 <<"_"<< bufferDumpNumber;
660
661 GetLogFileLocation(outputFileName.str().c_str(), fileNamePrefix,
662 GetMosContext());
663 // Open file
664 outputFileStream.open(fileNamePrefix, std::ios::app | std::ios::binary);
665 CM_ASSERT(outputFileStream);
666
667 if (m_sysMem != nullptr)
668 { // Buffer Up
669 outputFileStream.write((char *)m_sysMem, m_size);
670 }
671 else
672 { // Buffer
673 std::vector<char>buffer(m_size);
674
675 CmDeviceRT *cmDevice = nullptr;
676 m_surfaceMgr->GetCmDevice(cmDevice);
677 CM_ASSERT(cmDevice);
678
679 PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
680 CM_ASSERT(cmData);
681 CM_ASSERT(cmData->cmHalState);
682
683 CM_HAL_BUFFER_PARAM inParam;
684 CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_BUFFER_PARAM));
685 inParam.lockFlag = CM_HAL_LOCKFLAG_READONLY;
686 inParam.handle = m_handle;
687 cmData->cmHalState->pfnLockBuffer(cmData->cmHalState, &inParam);
688 if (inParam.data == nullptr)
689 return;
690 CmFastMemCopyFromWC((unsigned char *)&buffer[0], inParam.data, m_size, GetCpuInstructionLevel());
691 cmData->cmHalState->pfnUnlockBuffer(cmData->cmHalState, &inParam);
692
693 outputFileStream.write(&buffer[0], m_size);
694 }
695 outputFileStream.close();
696 bufferDumpNumber++;
697 #endif
698 }
699
UpdateResource(MOS_RESOURCE * resource)700 int32_t CmBuffer_RT::UpdateResource(MOS_RESOURCE *resource)
701 {
702 // get index
703 int index = m_index->get_data();
704 return m_surfaceMgr->UpdateBuffer(resource, index, m_handle);
705 }
706
UpdateProperty(uint32_t size)707 int32_t CmBuffer_RT::UpdateProperty(uint32_t size)
708 {
709 if( ( size < CM_MIN_SURF_WIDTH ) || ( size > CM_MAX_1D_SURF_WIDTH ) )
710 {
711 CM_ASSERTMESSAGE("Error: Invalid buffer size.");
712 return CM_INVALID_WIDTH;
713 }
714 m_size = size;
715 return CM_SUCCESS;
716 }
717
GetGfxAddress(uint64_t & gfxAddr)718 CM_RT_API int32_t CmBuffer_RT::GetGfxAddress(uint64_t &gfxAddr)
719 {
720 gfxAddr = m_gfxMem;
721 return CM_SUCCESS;
722 }
723
GetSysAddress(void * & sysAddr)724 CM_RT_API int32_t CmBuffer_RT::GetSysAddress(void *&sysAddr)
725 {
726 sysAddr = m_sysMem;
727 return CM_SUCCESS;
728 }
729 }
730