1 /*
2 * Copyright (c) 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 CMRTKernelBase.cpp
24 //! \brief HEVC FEI MDF structure base class for GEN9 SKL.
25 //!
26
27 #include "CMRTKernelBase.h"
28
CMRTKernelBase()29 CMRTKernelBase::CMRTKernelBase()
30 {
31 m_cmDev = nullptr;
32 m_cmProgram = nullptr;
33 m_cmQueue = nullptr;
34 m_cmTask = nullptr; //Can be reused for each kernel
35 m_cmThreadSpace = nullptr;
36 m_cmKernel = nullptr;
37 m_cmSurface2D = nullptr;
38 m_cmSurfaceRef0 = nullptr;
39 m_cmSurfaceRef1 = nullptr;
40 m_cmBuffer = nullptr;
41 m_cmVmeSurf = nullptr;
42 m_surfIndex = nullptr;
43 m_isaName = nullptr;
44 m_kernelName = nullptr;
45 m_curbe = nullptr;
46 m_isaSize = 0;
47 m_cmSurface2DCount = 0;
48 m_cmSurfaceRef0Count = 0;
49 m_cmSurfaceRef1Count = 0;
50 m_cmBufferCount = 0;
51 m_cmVmeSurfCount = 0;
52 }
53
~CMRTKernelBase()54 CMRTKernelBase::~CMRTKernelBase()
55 {
56 }
57
LoadProgramISA(const uint32_t * isaCode,uint32_t isaSize,CmProgram * & program)58 CM_RETURN_CODE CMRTKernelBase::LoadProgramISA(const uint32_t *isaCode, uint32_t isaSize, CmProgram * &program)
59 {
60 int32_t result;
61
62 // Load Program
63 result = m_cmDev->LoadProgram((void *)isaCode, isaSize, program, "-nojitter");
64 if (result != CM_SUCCESS)
65 {
66 printf("MDF LoadProgram error: %d\n", result);
67 }
68
69 return CM_SUCCESS;
70
71 }
72
Init(void * osContext,CmDevice * cmDev,CmQueue * cmQueue,CmTask * cmTask,CmProgram * cmProgram)73 CM_RETURN_CODE CMRTKernelBase::Init(void *osContext, CmDevice *cmDev, CmQueue *cmQueue, CmTask *cmTask, CmProgram *cmProgram)
74 {
75 int32_t result;
76
77 if (cmDev)
78 {
79 m_cmDev = cmDev;
80 }
81 else
82 {
83 #ifdef ENABLE_CMRT_KERNEL_ULT
84 uint32_t version = 0;
85 result = CreateCmDevice(m_cmDev, version);
86 #else
87 result = CreateCmDevice((PMOS_CONTEXT)osContext, m_cmDev, CM_DEVICE_CREATE_OPTION_FOR_HEVC);
88 #endif
89 if (result != CM_SUCCESS)
90 {
91 printf("CmDevice creation error\n");
92 return CM_FAILURE;
93 }
94 }
95
96 if (cmQueue)
97 {
98 m_cmQueue = cmQueue;
99 }
100 else
101 {
102 #ifdef ENABLE_CMRT_KERNEL_ULT
103 result = m_cmDev->CreateQueue(m_cmQueue);
104 #else
105 result = m_cmDev->CreateQueue(m_cmQueue);
106 #endif
107 if (result != CM_SUCCESS)
108 {
109 printf("CM CreateQueue error\n");
110 return CM_FAILURE;
111 }
112 }
113
114 if (cmTask)
115 {
116 m_cmTask = cmTask;
117 }
118 else
119 {
120 #ifdef ENABLE_CMRT_KERNEL_ULT
121 result = m_cmDev->CreateTask(m_cmTask);
122 #else
123 result = m_cmDev->CreateTask(m_cmTask);
124 #endif
125 if (result != CM_SUCCESS)
126 {
127 printf("CmDevice CreateTask error\n");
128 return CM_FAILURE;
129 }
130 }
131
132 if (cmProgram)
133 {
134 m_cmProgram = cmProgram;
135 }
136 else
137 {
138 result = LoadProgramISA(m_isaName, m_isaSize, m_cmProgram);
139 if (result != CM_SUCCESS)
140 {
141 printf("CmDevice LoadProgramISA error\n");
142 return CM_FAILURE;
143 }
144 }
145
146 result = m_cmDev->CreateKernel(m_cmProgram, m_kernelName, m_cmKernel);
147 if (result != CM_SUCCESS)
148 {
149 printf("CmDevice CreateKernel error\n");
150 return CM_FAILURE;
151 }
152
153 return CM_SUCCESS;
154 }
155
CreateThreadSpace(uint32_t threadSpaceWidth,uint32_t threadSpaceHeight)156 int32_t CMRTKernelBase::CreateThreadSpace(uint32_t threadSpaceWidth, uint32_t threadSpaceHeight)
157 {
158 int32_t result = CM_SUCCESS;
159
160 if (!m_cmThreadSpace)
161 {
162 result = m_cmDev->CreateThreadSpace(threadSpaceWidth, threadSpaceHeight, m_cmThreadSpace);
163 }
164 else
165 {
166 //Destory thread space used before
167 result = m_cmDev->DestroyThreadSpace(m_cmThreadSpace);
168 if (result != CM_SUCCESS)
169 {
170 printf("CM Destroy ThreadSpace error : %d", result);
171 return (CM_RETURN_CODE)result;
172 }
173 result = m_cmDev->CreateThreadSpace(threadSpaceWidth, threadSpaceHeight, m_cmThreadSpace);
174 }
175
176 return result;
177 }
178
AddKernel(CmEvent * & cmEvent,bool destroyEvent,bool isEnqueue)179 CM_RETURN_CODE CMRTKernelBase::AddKernel(CmEvent *&cmEvent, bool destroyEvent, bool isEnqueue)
180 {
181 if (m_cmTask == nullptr)
182 {
183 CM_CHK_STATUS_RETURN(m_cmDev->CreateTask(m_cmTask));
184 }
185
186 if (m_cmQueue == nullptr)
187 {
188 CM_CHK_STATUS_RETURN(m_cmDev->CreateQueue(m_cmQueue));//CreateQueue is just get queue of CmDev, so just need call once.
189 }
190
191 CM_CHK_STATUS_RETURN(m_cmKernel->AssociateThreadSpace(m_cmThreadSpace));
192 CM_CHK_STATUS_RETURN(m_cmTask->AddKernel(m_cmKernel));
193
194 if (isEnqueue)
195 {
196 CM_CHK_STATUS_RETURN(m_cmQueue->Enqueue(m_cmTask, cmEvent));
197 CM_CHK_STATUS_RETURN(m_cmTask->Reset());
198 if(destroyEvent)
199 {
200 CM_CHK_STATUS_RETURN(m_cmQueue->DestroyEvent(cmEvent));
201 }
202 }
203 else
204 {
205 CM_CHK_STATUS_RETURN(m_cmTask->AddSync());
206 }
207
208 return CM_SUCCESS;
209 }
210
WaitAndDestroyEvent(CmEvent * & cmEvent)211 CM_RETURN_CODE CMRTKernelBase::WaitAndDestroyEvent(CmEvent *&cmEvent)
212 {
213 int32_t dwTimeOutMs = -1;
214
215 CM_CHK_STATUS_RETURN(cmEvent->WaitForTaskFinished(dwTimeOutMs));
216
217 CM_CHK_STATUS_RETURN(m_cmQueue->DestroyEvent(cmEvent));
218 cmEvent = nullptr;
219
220 return CM_SUCCESS;
221 }
222
223 //This is kernelbased, We need to call for all the kernels in the kernellist.
DestroySurfResources()224 void CMRTKernelBase::DestroySurfResources()
225 {
226 uint32_t i = 0;
227
228 for (i = 0; i < m_cmSurface2DCount; i++)
229 {
230 if (m_cmSurface2D[i])
231 {
232 m_cmDev->DestroySurface(m_cmSurface2D[i]);
233 m_cmSurface2D[i] = nullptr;
234 }
235 }
236
237 for (i = 0; i < m_cmSurfaceRef0Count; i++)
238 {
239 if (m_cmSurfaceRef0[i])
240 {
241 m_cmDev->DestroySurface(m_cmSurfaceRef0[i]);
242 m_cmSurfaceRef0[i] = nullptr;
243 }
244 }
245
246 for (i = 0; i < m_cmSurfaceRef1Count; i++)
247 {
248 if (m_cmSurfaceRef1[i])
249 {
250 m_cmDev->DestroySurface(m_cmSurfaceRef1[i]);
251 m_cmSurfaceRef1[i] = nullptr;
252 }
253 }
254
255 for (i = 0; i < m_cmBufferCount; i++)
256 {
257 if (m_cmBuffer[i])
258 {
259 m_cmDev->DestroySurface(m_cmBuffer[i]);
260 m_cmBuffer[i] = nullptr;
261 }
262 }
263 for (i = 0; i < m_cmVmeSurfCount; i++)
264 {
265 if (m_cmVmeSurf[i])
266 {
267 m_cmDev->DestroyVmeSurfaceG7_5(m_cmVmeSurf[i]);
268 m_cmVmeSurf[i] = nullptr;
269 }
270 }
271 }
272
273 //IF called init for /kernel/program/TS per frame, then we call this per frame;
274 //if called init for all the kernels per process, then call this per process.
275 //We can also init every first the kernel is called, then we just need to call this per process for all the kernels in kernelList.
DestroyKernelResources()276 void CMRTKernelBase::DestroyKernelResources()
277 {
278 if(m_cmKernel)
279 {
280 m_cmDev->DestroyKernel(m_cmKernel);
281 m_cmKernel = nullptr;
282 }
283
284 if (m_cmThreadSpace)
285 {
286 m_cmDev->DestroyThreadSpace(m_cmThreadSpace);
287 m_cmThreadSpace = nullptr;
288 }
289 }
290
DestroyProgramResources()291 void CMRTKernelBase::DestroyProgramResources()
292 {
293 if(m_cmProgram)
294 {
295 m_cmDev->DestroyProgram(m_cmProgram);
296 m_cmProgram = nullptr;
297 }
298 }
299
Destroy()300 void CMRTKernelBase::Destroy()
301 {
302 //Only keep one Task/Dev/Queue in one Process.
303 if (m_cmTask)
304 {
305 m_cmDev->DestroyTask(m_cmTask);
306 m_cmTask = nullptr;
307 }
308
309 if(m_cmDev)
310 {
311 DestroyCmDevice(m_cmDev);
312 m_cmDev = nullptr;
313 }
314 }
315
316