xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/cm/cm_buffer_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_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