1 /*
2 * Copyright (c) 2021, 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 vp_pipeline_adapter_base.cpp
24 //! \brief vp pipeline adapter base clarification
25 //! \details vp pipeline adapter base clarification inlcuding:
26 //! some marcro, enum, structure, function
27 //!
28 #include "vp_pipeline_adapter_base.h"
29 #include "media_interfaces_vphal.h"
30 #include "vp_platform_interface.h"
31 #include "vp_debug.h"
32 #include "vp_user_setting.h"
33 #include "renderhal_platform_interface.h"
34
VpPipelineAdapterBase(vp::VpPlatformInterface & vpPlatformInterface,MOS_STATUS & eStatus,bool clearViewMode)35 VpPipelineAdapterBase::VpPipelineAdapterBase(
36 vp::VpPlatformInterface &vpPlatformInterface,
37 MOS_STATUS &eStatus,
38 bool clearViewMode) :
39 m_vpPlatformInterface(vpPlatformInterface)
40 {
41 m_osInterface = m_vpPlatformInterface.GetOsInterface();
42 if (m_osInterface)
43 {
44 m_userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
45 }
46 VpUserSetting::InitVpUserSetting(m_userSettingPtr, clearViewMode);
47
48 eStatus = MOS_STATUS_SUCCESS;
49 }
50
GetVpMhwInterface(VP_MHWINTERFACE & vpMhwinterface)51 MOS_STATUS VpPipelineAdapterBase::GetVpMhwInterface(
52 VP_MHWINTERFACE &vpMhwinterface)
53 {
54 VP_FUNC_CALL();
55
56 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
57 bool sfcNeeded = false;
58 bool veboxNeeded = false;
59 std::shared_ptr<mhw::vebox::Itf> veboxItf = nullptr;
60 std::shared_ptr<mhw::sfc::Itf> sfcItf = nullptr;
61 std::shared_ptr<mhw::mi::Itf> miItf = nullptr;
62 m_osInterface = m_vpPlatformInterface.GetOsInterface();
63 if (m_osInterface == nullptr)
64 {
65 eStatus = MOS_STATUS_NULL_POINTER;
66 return eStatus;
67 }
68
69 // Initialize platform, sku, wa tables
70 m_osInterface->pfnGetPlatform(m_osInterface, &m_platform);
71 m_skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
72 m_waTable = m_osInterface->pfnGetWaTable(m_osInterface);
73
74 m_vprenderHal = (PRENDERHAL_INTERFACE)MOS_AllocAndZeroMemory(sizeof(*m_vprenderHal));
75 if (m_vprenderHal == nullptr)
76 {
77 VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_NULL_POINTER);
78 }
79
80 eStatus = RenderHal_InitInterface(
81 m_vprenderHal,
82 &m_cpInterface,
83 m_osInterface);
84
85 VPHAL_DBG_OCA_DUMPER_CREATE(m_vprenderHal);
86
87 if (MOS_FAILED(eStatus))
88 {
89 MOS_OS_ASSERTMESSAGE("VpPipelineAdapterBase construct failed due to base class returned failure: eStatus = %d.", eStatus);
90 return eStatus;
91 }
92
93 veboxNeeded = MEDIA_IS_SKU(m_skuTable, FtrVERing);
94 sfcNeeded = MEDIA_IS_SKU(m_skuTable, FtrSFCPipe);
95 SetMhwMiItf(m_vprenderHal->pRenderHalPltInterface->GetMhwMiItf());
96 if ((veboxNeeded || sfcNeeded) && !m_clearVideoViewMode)
97 {
98 eStatus = VphalDevice::CreateVPMhwInterfaces(sfcNeeded, veboxNeeded, veboxItf, sfcItf, miItf, m_osInterface);
99 if (eStatus == MOS_STATUS_SUCCESS)
100 {
101 SetMhwVeboxItf(veboxItf);
102 SetMhwSfcItf(sfcItf);
103 }
104 else
105 {
106 VP_PUBLIC_ASSERTMESSAGE("Allocate MhwInterfaces failed");
107 VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_NO_SPACE);
108 }
109 }
110
111 vpMhwinterface.m_platform = m_platform;
112 vpMhwinterface.m_waTable = m_waTable;
113 vpMhwinterface.m_skuTable = m_skuTable;
114 vpMhwinterface.m_osInterface = m_osInterface;
115 vpMhwinterface.m_renderHal = m_vprenderHal;
116 vpMhwinterface.m_cpInterface = m_cpInterface;
117 vpMhwinterface.m_statusTable = &m_statusTable;
118 m_vpPlatformInterface.SetMhwSfcItf(m_sfcItf);
119 m_vpPlatformInterface.SetMhwVeboxItf(m_veboxItf);
120 m_vpPlatformInterface.SetMhwMiItf(m_miItf);
121 vpMhwinterface.m_vpPlatformInterface = &m_vpPlatformInterface;
122
123 return eStatus;
124 }
125
~VpPipelineAdapterBase()126 VpPipelineAdapterBase::~VpPipelineAdapterBase()
127 {
128 MOS_STATUS eStatus;
129
130 // Wait for all cmd before destroy gpu resource
131 if (m_osInterface && m_osInterface->pfnWaitAllCmdCompletion && m_osInterface->bDeallocateOnExit)
132 {
133 VP_PUBLIC_NORMALMESSAGE("WaitAllCmdCompletion in VpPipelineAdapterBase::~VpPipelineAdapterBase");
134 m_osInterface->pfnWaitAllCmdCompletion(m_osInterface);
135 }
136
137 if (m_vprenderHal)
138 {
139 VPHAL_DBG_OCA_DUMPER_DESTORY(m_vprenderHal);
140 if (m_vprenderHal->pfnDestroy)
141 {
142 eStatus = m_vprenderHal->pfnDestroy(m_vprenderHal);
143 if (eStatus != MOS_STATUS_SUCCESS)
144 {
145 VP_PUBLIC_ASSERTMESSAGE("Failed to destroy RenderHal, eStatus:%d.\n", eStatus);
146 }
147 }
148 MOS_FreeMemory(m_vprenderHal);
149 }
150
151 if (m_cpInterface)
152 {
153 if (m_osInterface)
154 {
155 m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
156 m_cpInterface = nullptr;
157 }
158 else
159 {
160 VP_PUBLIC_ASSERTMESSAGE("Failed to destroy cpInterface.");
161 }
162 }
163
164 if (m_sfcItf)
165 {
166 m_sfcItf = nullptr;
167 }
168
169 if (m_veboxItf)
170 {
171 eStatus = m_veboxItf->DestroyHeap();
172 m_veboxItf = nullptr;
173 }
174
175 // Destroy OS interface objects (CBs, etc)
176 if (m_osInterface)
177 {
178 if (m_osInterface->bDeallocateOnExit)
179 {
180 m_osInterface->pfnDestroy(m_osInterface, true);
181
182 // Deallocate OS interface structure (except if externally provided)
183 MOS_FreeMemory(m_osInterface);
184 }
185 }
186
187 vp::VpPlatformInterface *pIntf = &m_vpPlatformInterface;
188 MOS_Delete(pIntf);
189 }
190
191 //!
192 //! \brief Get Status Report
193 //! \details Get Status Report, will return back to app indicating if related frame id is done by gpu
194 //! \param [out] pQueryReport
195 //! Pointer to pQueryReport, the status query report array.
196 //! \param [in] wStatusNum
197 //! The size of array pQueryReport.
198 //! \return MOS_STATUS
199 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
GetStatusReport(PQUERY_STATUS_REPORT_APP pQueryReport,uint16_t wStatusNum)200 MOS_STATUS VpPipelineAdapterBase::GetStatusReport(
201 PQUERY_STATUS_REPORT_APP pQueryReport,
202 uint16_t wStatusNum)
203 {
204 VP_FUNC_CALL();
205 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
206
207 #if (!EMUL) // this function is dummy for emul
208 uint32_t i;
209 uint32_t uiTableLen;
210 PVPHAL_STATUS_TABLE pStatusTable;
211 PMOS_CONTEXT pOsContext;
212 uint32_t uiIndex;
213 uint32_t uiNewHead;
214 PVPHAL_STATUS_ENTRY pStatusEntry;
215 bool bMarkNotReadyForRemains = false;
216
217 VP_PUBLIC_CHK_NULL(pQueryReport);
218 VP_PUBLIC_CHK_NULL(m_osInterface);
219 VP_PUBLIC_CHK_NULL(m_osInterface->pOsContext);
220
221 // it should be ok if we don't consider the null render
222 // eNullRender = m_pOsInterface->pfnGetNullHWRenderFlags(m_pOsInterface);
223
224 pOsContext = m_osInterface->pOsContext;
225 pStatusTable = &m_statusTable;
226 uiNewHead = pStatusTable->uiHead; // uiNewHead start from previous head value
227 // entry length from head to tail
228 if (pStatusTable->uiCurrent < pStatusTable->uiHead)
229 {
230 uiTableLen = pStatusTable->uiCurrent + VPHAL_STATUS_TABLE_MAX_SIZE - pStatusTable->uiHead;
231 }
232 else
233 {
234 uiTableLen = pStatusTable->uiCurrent - pStatusTable->uiHead;
235 }
236
237 // step 1 - update pStatusEntry from driver if command associated with the dwTag is done by gpu
238 for (i = 0; i < wStatusNum && i < uiTableLen; i++)
239 {
240 uint32_t dwGpuTag; // hardware tag updated by gpu command pipectl
241 bool bDoneByGpu;
242 bool bFailedOnSubmitCmd;
243
244 uiIndex = (pStatusTable->uiHead + i) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
245 pStatusEntry = &pStatusTable->aTableEntries[uiIndex];
246
247 // for tasks using CM, different streamIndexes may be used
248 uint32_t oldStreamIndex = m_osInterface->streamIndex;
249 if (pStatusEntry->isStreamIndexSet)
250 {
251 m_osInterface->streamIndex = pStatusEntry->streamIndex;
252 }
253
254 if (bMarkNotReadyForRemains)
255 {
256 // the status is set as VPREP_NOTREADY while submitting commands
257 pQueryReport[i].dwStatus = pStatusEntry->dwStatus;
258 pQueryReport[i].StatusFeedBackID = pStatusEntry->StatusFeedBackID;
259 continue;
260 }
261
262 dwGpuTag = m_osInterface->pfnGetGpuStatusSyncTag(m_osInterface, pStatusEntry->GpuContextOrdinal);
263 bDoneByGpu = (dwGpuTag >= pStatusEntry->dwTag);
264 bFailedOnSubmitCmd = (pStatusEntry->dwStatus == VPREP_ERROR);
265
266 #if (_DEBUG || _RELEASE_INTERNAL)
267 MOS_NULL_RENDERING_FLAGS NullRender = m_osInterface->pfnGetNullHWRenderFlags(m_osInterface);
268 if (NullRender.Value != 0)
269 {
270 bDoneByGpu = true;
271 }
272 #endif
273
274 if (bFailedOnSubmitCmd)
275 {
276 uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
277 }
278 else if (bDoneByGpu)
279 {
280 pStatusEntry->dwStatus = VPREP_OK;
281 uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
282 }
283 else
284 { // here we have the first not ready entry.
285 #if (LINUX || ANDROID)
286 uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
287 #else
288 uiNewHead = uiIndex;
289 #endif
290
291 bMarkNotReadyForRemains = true;
292 }
293
294 if (m_osInterface->pfnIsGPUHung(m_osInterface))
295 {
296 pStatusEntry->dwStatus = VPREP_NOTREADY;
297 }
298
299 pQueryReport[i].dwStatus = pStatusEntry->dwStatus;
300 pQueryReport[i].StatusFeedBackID = pStatusEntry->StatusFeedBackID;
301
302 if (pStatusEntry->isStreamIndexSet)
303 {
304 m_osInterface->streamIndex = oldStreamIndex;
305 }
306 }
307 pStatusTable->uiHead = uiNewHead;
308
309 // step 2 - mark VPREP_NOTAVAILABLE for unused entry
310 for (/* continue from previous i */; i < wStatusNum; i++)
311 {
312 pQueryReport[i].dwStatus = VPREP_NOTAVAILABLE;
313 pQueryReport[i].StatusFeedBackID = 0;
314 }
315
316 finish:
317 #else
318 MOS_UNUSED(pQueryReport);
319 MOS_UNUSED(wStatusNum);
320 #endif // end (!EMUL && !ANDROID)
321 return eStatus;
322 }
323
GetStatusReportEntryLength(uint32_t * puiLength)324 MOS_STATUS VpPipelineAdapterBase::GetStatusReportEntryLength(
325 uint32_t* puiLength)
326 {
327 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
328 #if(!EMUL) // this function is dummy for emul
329 PVPHAL_STATUS_TABLE pStatusTable;
330
331 VP_PUBLIC_CHK_NULL(puiLength);
332
333 pStatusTable = &m_statusTable;
334
335 // entry length from head to tail
336 if (pStatusTable->uiCurrent < pStatusTable->uiHead)
337 {
338 *puiLength = pStatusTable->uiCurrent + VPHAL_STATUS_TABLE_MAX_SIZE - pStatusTable->uiHead;
339 }
340 else
341 {
342 *puiLength = pStatusTable->uiCurrent - pStatusTable->uiHead;
343 }
344
345 finish:
346 #else
347 MOS_UNUSED(puiLength);
348 #endif
349 return eStatus;
350 }
351