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