1 /*
2 * Copyright (c) 2018-2019, 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_ish_base.cpp
24 //! \brief Contains Class CmISHBase definitions
25 //!
26
27 #include "cm_ish.h"
28 #include "cm_kernel_ex.h"
29
30 using namespace CMRT_UMD;
31
CmISHBase()32 CmISHBase::CmISHBase():
33 m_osInterface(nullptr),
34 m_resource(nullptr),
35 m_lockedData(nullptr),
36 m_size(0),
37 m_offset(0),
38 m_trackerProducer(nullptr),
39 m_lastTrackerToken(nullptr),
40 m_addedKernelCount(0),
41 m_isSipKernelLoaded(false),
42 m_sipKernel(nullptr),
43 m_sipKernelSize(0),
44 m_sipKernelOffset(0)
45 {
46
47 }
48
~CmISHBase()49 CmISHBase::~CmISHBase()
50 {
51 MOS_GFXRES_FREE_FLAGS resFreeFlags = {0};
52
53 resFreeFlags.AssumeNotInUse = 1;
54
55 while (m_destroyedTrackers.size())
56 {
57 MOS_RESOURCE *res = m_destroyedResources.back();
58 m_osInterface->pfnFreeResourceWithFlag(m_osInterface, res, resFreeFlags.Value);
59
60 FrameTrackerToken *trackerToken = m_destroyedTrackers.back();
61
62 MOS_FreeMemory(res);
63 MOS_Delete(trackerToken);
64 m_destroyedResources.pop_back();
65 m_destroyedTrackers.pop_back();
66 }
67 // delete current resource
68 if (m_resource)
69 {
70 m_osInterface->pfnUnlockResource(m_osInterface, m_resource);
71 m_osInterface->pfnFreeResourceWithFlag(m_osInterface, m_resource, resFreeFlags.Value);
72 MOS_FreeMemory(m_resource);
73 }
74
75 if (m_lastTrackerToken)
76 {
77 MOS_Delete(m_lastTrackerToken);
78 }
79
80 if (m_sipKernel)
81 {
82 MOS_FreeMemory(m_sipKernel);
83 }
84 }
85
Initialize(CM_HAL_STATE * cmhal,FrameTrackerProducer * trackerProducer)86 MOS_STATUS CmISHBase::Initialize(CM_HAL_STATE *cmhal, FrameTrackerProducer *trackerProducer)
87 {
88 m_osInterface = cmhal->osInterface;
89 m_trackerProducer = trackerProducer;
90 ExpandHeapSize(m_initSize);
91
92 if (!cmhal->midThreadPreemptionDisabled)
93 {
94 CM_CHK_MOSSTATUS_RETURN(CreateSipKernel(cmhal)); // generate sip kernel in m_sipKernel
95 }
96
97 return MOS_STATUS_SUCCESS;
98 }
99
LoadKernels(CmKernelEx ** kernels,int count)100 MOS_STATUS CmISHBase::LoadKernels(CmKernelEx **kernels, int count)
101 {
102 uint32_t blockSizes[CM_MAX_KERNELS_PER_TASK];
103 uint32_t blockIdx = 0;
104 uint32_t totalSize = 0;
105 for (int i = 0; i < count; i++)
106 {
107 CmKernelEx *kernel = kernels[i];
108 // check if the kernel is in ish
109 CmISHBase *rIsh = nullptr;
110 int rIdx = -1;
111 kernel->GetRecordedInfo(&rIsh, &rIdx);
112 if (rIsh == this && rIdx >= 0 && rIdx < (int)m_addedKernelCount && m_addedKernels[rIdx] == kernel)
113 {
114 //printf("HFDebug: reUse kernel %p in ish, name %s\n", kernel, kernel->GetName());
115 continue;
116 }
117 auto ite = m_addedHashValues.find(kernel->GetHashValue());
118 if (ite != m_addedHashValues.end())
119 {
120 continue;
121 }
122 //printf("HFDebug: add a new kernel %p in ish, name %s\n", kernel, kernel->GetName());
123 uint8_t *nkernel = nullptr;
124 uint32_t size = 0;
125 kernel->GetNativeKernel(&nkernel, &size);
126 uint32_t temp = MOS_ALIGN_CEIL(size + m_kernelPadding, m_kernelAlign);
127 blockSizes[blockIdx ++] = temp;
128 totalSize += temp;
129 }
130
131 uint32_t neededSize = totalSize;
132 if (!m_isSipKernelLoaded && m_sipKernelSize)
133 {
134 neededSize += MOS_ALIGN_CEIL(m_sipKernelSize + m_kernelPadding, m_kernelAlign);
135 }
136 if (m_offset + neededSize > m_size)
137 {
138 ExpandHeapSize(neededSize);
139 }
140
141 if (!m_isSipKernelLoaded && m_sipKernelSize)
142 {
143 uint32_t temp = MOS_ALIGN_CEIL(m_sipKernelSize + m_kernelPadding, m_kernelAlign);
144
145 // Copy Cm Kernel Binary
146 MOS_SecureMemcpy(m_lockedData + m_offset, m_size - m_offset, m_sipKernel, m_sipKernelSize);
147
148 // Padding bytes dummy instructions after kernel binary to resolve page fault issue
149 MOS_ZeroMemory(m_lockedData + m_offset + m_sipKernelSize, temp - m_sipKernelSize);
150 m_sipKernelOffset = m_offset;
151 m_offset += temp;
152
153 m_isSipKernelLoaded = true;
154 }
155
156 for (int i = 0; i < count; i++)
157 {
158 CmKernelEx *kernel = kernels[i];
159 // check if the kernel is in ish
160 CmISHBase *rIsh = nullptr;
161 int rIdx = -1;
162 kernel->GetRecordedInfo(&rIsh, &rIdx);
163 if (rIsh == this && rIdx >= 0 && rIdx < (int)m_addedKernelCount && m_addedKernels[rIdx] == kernel)
164 {
165 continue;
166 }
167 auto ite = m_addedHashValues.find(kernel->GetHashValue());
168 if (ite != m_addedHashValues.end())
169 {
170 uint32_t offset = ite->second;
171 kernel->Recorded(this, -1, offset);
172 continue;
173 }
174 // copy kernel binary
175 uint8_t *nkernel = nullptr;
176 uint32_t size = 0;
177 kernel->GetNativeKernel(&nkernel, &size);
178 uint32_t temp = MOS_ALIGN_CEIL(size + m_kernelPadding, m_kernelAlign);
179
180 // Copy Cm Kernel Binary
181 MOS_SecureMemcpy(m_lockedData + m_offset, m_size - m_offset, nkernel, size);
182
183 // Padding bytes dummy instructions after kernel binary to resolve page fault issue
184 MOS_ZeroMemory(m_lockedData + m_offset + size, temp - size);
185
186 // record
187 m_addedKernels.push_back(kernel);
188 kernel->Recorded(this, (int)m_addedKernelCount, m_offset);
189 m_addedHashValues[kernel->GetHashValue()] = m_offset;
190 m_addedKernelCount ++;
191 m_offset += temp;
192 }
193 return MOS_STATUS_SUCCESS;
194 }
195
ExpandHeapSize(uint32_t extraSize)196 MOS_STATUS CmISHBase::ExpandHeapSize(uint32_t extraSize)
197 {
198 uint32_t addSize = MOS_ALIGN_CEIL(extraSize, m_expandStep);
199 // destroy the old resource
200 if (m_resource)
201 {
202 m_destroyedResources.push_front(m_resource);
203 m_destroyedTrackers.push_front(m_lastTrackerToken);
204 }
205
206 // allocate new resource
207 m_resource = (PMOS_RESOURCE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE));
208 CM_CHK_NULL_RETURN_MOSERROR(m_resource);
209 MOS_ALLOC_GFXRES_PARAMS allocParams;
210 MOS_ZeroMemory(&allocParams, sizeof(allocParams));
211 allocParams.Type = MOS_GFXRES_BUFFER;
212 allocParams.TileType = MOS_TILE_LINEAR;
213 allocParams.Format = Format_Buffer;
214 allocParams.dwBytes = m_size + addSize;
215 allocParams.pBufName = "ISHeap";
216
217 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnAllocateResource(m_osInterface, &allocParams,
218 m_resource));
219 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnRegisterResource(m_osInterface, m_resource,
220 true, true));
221 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnSkipResourceSync(m_resource));
222
223 m_size += addSize;
224 m_offset = 0;
225
226 MOS_LOCK_PARAMS lockParams;
227 MOS_ZeroMemory(&lockParams, sizeof(lockParams));
228 lockParams.WriteOnly = 1;
229 lockParams.NoOverWrite = 1;
230 lockParams.Uncached = 1;
231 m_lockedData = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, m_resource, &lockParams);
232
233 // one new tracker token with one new resource
234 m_lastTrackerToken = MOS_New(FrameTrackerToken);
235 m_lastTrackerToken->SetProducer(m_trackerProducer);
236
237 // no kernel is in the new heap
238 m_addedKernels.clear();
239 m_addedKernelCount = 0;
240 m_addedHashValues.clear();
241 Refresh();
242 m_isSipKernelLoaded = false;
243
244 return MOS_STATUS_SUCCESS;
245 }
246
Refresh()247 MOS_STATUS CmISHBase::Refresh()
248 {
249 MOS_GFXRES_FREE_FLAGS resFreeFlags = {0};
250
251 resFreeFlags.AssumeNotInUse = 1;
252
253 // goes from back to front to handle tracker overflow
254 while (m_destroyedTrackers.size())
255 {
256 FrameTrackerToken *trackerToken = m_destroyedTrackers.back();
257 if (!trackerToken->IsExpired())
258 {
259 break;
260 }
261 MOS_RESOURCE *res = m_destroyedResources.back();
262 m_osInterface->pfnUnlockResource(m_osInterface, res);
263 m_osInterface->pfnFreeResourceWithFlag(m_osInterface, res, resFreeFlags.Value);
264
265 m_destroyedResources.pop_back();
266 m_destroyedTrackers.pop_back();
267
268 MOS_FreeMemory(res);
269 MOS_Delete(trackerToken);
270 }
271
272 return MOS_STATUS_SUCCESS;
273 }
274
Clean()275 void CmISHBase::Clean()
276 {
277 m_offset = 0;
278 m_addedKernels.clear();
279 m_addedKernelCount = 0;
280 Refresh();
281 m_isSipKernelLoaded = false;
282 }
283
284