1 /*
2 * Copyright (c) 2018-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 //!
24 //! \file encode_pipeline.cpp
25 //! \brief Defines the common interface for encode pipeline
26 //! \details The encode pipeline interface is further sub-divided by codec standard,
27 //! this file is for the base interface which is shared by all codecs.
28 //!
29 #include "encode_pipeline.h"
30 #include "encode_utils.h"
31 #include "media_packet.h"
32
33 #include "codechal_setting.h"
34 #include "encode_status_report_defs.h"
35 #include "encode_status_report.h"
36 #include "mos_solo_generic.h"
37
38 namespace encode {
EncodePipeline(CodechalHwInterfaceNext * hwInterface,CodechalDebugInterface * debugInterface)39 EncodePipeline::EncodePipeline(
40 CodechalHwInterfaceNext *hwInterface,
41 CodechalDebugInterface *debugInterface):
42 MediaPipeline(hwInterface ? hwInterface->GetOsInterface() : nullptr),
43 m_hwInterface(hwInterface)
44 {
45
46 }
47
Initialize(void * settings)48 MOS_STATUS EncodePipeline::Initialize(void *settings)
49 {
50 ENCODE_FUNC_CALL();
51 ENCODE_CHK_STATUS_RETURN(InitUserSetting(m_userSettingPtr));
52 ENCODE_CHK_STATUS_RETURN(MediaPipeline::InitPlatform());
53 ENCODE_CHK_STATUS_RETURN(MediaPipeline::CreateMediaCopyWrapper());
54 ENCODE_CHK_NULL_RETURN(m_mediaCopyWrapper);
55
56 ENCODE_CHK_NULL_RETURN(m_hwInterface);
57 ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
58
59 m_osInterface = m_hwInterface->GetOsInterface();
60 ENCODE_CHK_NULL_RETURN(m_osInterface);
61
62 if (m_mediaCopyWrapper->MediaCopyStateIsNull())
63 {
64 m_mediaCopyWrapper->SetMediaCopyState(m_hwInterface->CreateMediaCopy(m_osInterface));
65 }
66
67 m_mediaContext = MOS_New(MediaContext, scalabilityEncoder, m_hwInterface, m_osInterface);
68 ENCODE_CHK_NULL_RETURN(m_mediaContext);
69
70 m_allocator = MOS_New(EncodeAllocator, m_osInterface);
71 ENCODE_CHK_NULL_RETURN(m_allocator);
72
73 m_trackedBuf = MOS_New(TrackedBuffer, m_allocator, (uint8_t)CODEC_NUM_REF_BUFFERS, (uint8_t)CODEC_NUM_NON_REF_BUFFERS);
74 ENCODE_CHK_NULL_RETURN(m_trackedBuf);
75
76 m_recycleBuf = MOS_New(RecycleResource, m_allocator);
77 ENCODE_CHK_NULL_RETURN(m_recycleBuf);
78
79 CodechalSetting *codecSettings = (CodechalSetting*)settings;
80 m_standard = codecSettings->standard;
81 m_mode = codecSettings->mode;
82 m_codecFunction = codecSettings->codecFunction;
83
84 CODECHAL_DEBUG_TOOL(
85 m_debugInterface = MOS_New(CodechalDebugInterface);
86 ENCODE_CHK_NULL_RETURN(m_debugInterface);
87 ENCODE_CHK_STATUS_RETURN(
88 m_debugInterface->Initialize(m_hwInterface, m_codecFunction, m_mediaCopyWrapper)
89 );
90
91 m_statusReportDebugInterface = MOS_New(CodechalDebugInterface);
92 ENCODE_CHK_NULL_RETURN(m_statusReportDebugInterface);
93 ENCODE_CHK_STATUS_RETURN(
94 m_statusReportDebugInterface->Initialize(m_hwInterface, m_codecFunction, m_mediaCopyWrapper));
95 );
96
97 MediaUserSetting::Value outValue;
98 ReadUserSetting(
99 m_userSettingPtr,
100 outValue,
101 "Single Task Phase Enable",
102 MediaUserSetting::Group::Sequence);
103 m_singleTaskPhaseSupported = outValue.Get<bool>();
104
105 ENCODE_CHK_STATUS_RETURN(CreateFeatureManager());
106 ENCODE_CHK_NULL_RETURN(m_featureManager);
107
108 m_encodecp = MOS_New(EncodeCp, m_hwInterface);
109 m_encodecp->RegisterParams(codecSettings);
110 bool cpenable = m_encodecp->isCpEnabled();
111
112 ENCODE_CHK_STATUS_RETURN(m_featureManager->Init(codecSettings));
113
114 m_packetUtilities = MOS_New(PacketUtilities, m_hwInterface, m_featureManager);
115 ENCODE_CHK_NULL_RETURN(m_packetUtilities);
116 ENCODE_CHK_STATUS_RETURN(m_packetUtilities->Init());
117
118 m_statusReport = MOS_New(EncoderStatusReport, m_allocator, m_osInterface, true, true, cpenable);
119 ENCODE_CHK_NULL_RETURN(m_statusReport);
120 ENCODE_CHK_STATUS_RETURN(m_statusReport->Create());
121
122 m_encodecp->setStatusReport(m_statusReport);
123
124 return MOS_STATUS_SUCCESS;
125 }
126
Uninitialize()127 MOS_STATUS EncodePipeline::Uninitialize()
128 {
129 ENCODE_FUNC_CALL();
130
131 MOS_Delete(m_mediaContext);
132
133 MOS_Delete(m_encodecp);
134
135 MOS_Delete(m_statusReport);
136
137 CODECHAL_DEBUG_TOOL(
138 MOS_Delete(m_debugInterface);
139 MOS_Delete(m_statusReportDebugInterface);
140 );
141
142 MOS_Delete(m_trackedBuf);
143
144 MOS_Delete(m_recycleBuf);
145
146 if (m_featureManager != nullptr)
147 {
148 m_featureManager->Destroy();
149 MOS_Delete(m_featureManager);
150 }
151
152 // Allocator should not be destroyed until all resources released.
153 if (m_allocator != nullptr)
154 {
155 m_allocator->DestroyAllResources();
156 MOS_Delete(m_allocator);
157 }
158
159 MOS_Delete(m_packetUtilities);
160
161 return MOS_STATUS_SUCCESS;
162 }
163
UserFeatureReport()164 MOS_STATUS EncodePipeline::UserFeatureReport()
165 {
166 ENCODE_FUNC_CALL();
167 ENCODE_CHK_STATUS_RETURN(MediaPipeline::UserFeatureReport());
168
169 // Encode HW Walker Reporting
170 // WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_ID, m_hwWalker);
171 // if (m_hwWalker)
172 // {
173 // // Encode HW Walker m_mode Reporting
174 //#if (_DEBUG || _RELEASE_INTERNAL)
175 // WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_ENCODE_HW_WALKER_MODE_ID, m_walkerMode);
176 //#endif // _DEBUG || _RELEASE_INTERNAL
177 // }
178 //
179 // if (MEDIA_IS_SKU(m_skuTable, FtrSliceShutdown))
180 // {
181 // // SliceShutdownEnable Reporting
182 // WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_SLICE_SHUTDOWN_ENABLE_ID, m_sliceShutdownEnable);
183 // }
184 #if (_DEBUG || _RELEASE_INTERNAL)
185 ReportUserSettingForDebug(
186 m_userSettingPtr,
187 "Media Encode Used VDBOX Number",
188 GetPipeNum(),
189 MediaUserSetting::Group::Sequence);
190
191 ReportUserSettingForDebug(
192 m_userSettingPtr,
193 "Media Encode DDI TargetUsage",
194 GetDDITU(),
195 MediaUserSetting::Group::Sequence);
196 #endif // _DEBUG || _RELEASE_INTERNAL
197
198 return MOS_STATUS_SUCCESS;
199 }
200
Prepare(void * params)201 MOS_STATUS EncodePipeline::Prepare(void *params)
202 {
203 ENCODE_FUNC_CALL();
204
205 ENCODE_CHK_NULL_RETURN(params);
206 ENCODE_CHK_NULL_RETURN(m_hwInterface);
207
208 ENCODE_CHK_NULL_RETURN(m_featureManager);
209 ENCODE_CHK_STATUS_RETURN(m_featureManager->CheckFeatures(params));
210 ENCODE_CHK_STATUS_RETURN(m_featureManager->Update(params));
211 m_encodecp->UpdateParams(true);
212
213 ENCODE_CHK_STATUS_RETURN(WaitForBatchBufferComplete());
214
215 EncoderParams *encodeParams = (EncoderParams *)params;
216 ENCODE_CHK_STATUS_RETURN(Mos_Solo_SetGpuAppTaskEvent(m_osInterface, encodeParams->gpuAppTaskEvent));
217
218 m_osInterface->pfnIncPerfFrameID(m_osInterface);
219
220 return MOS_STATUS_SUCCESS;
221 }
222
ContextSwitchBack()223 MOS_STATUS EncodePipeline::ContextSwitchBack()
224 {
225 ENCODE_FUNC_CALL();
226
227 ENCODE_CHK_NULL_RETURN(m_scalPars);
228
229 m_scalPars->IsContextSwitchBack = true;
230 m_mediaContext->SwitchContext(VdboxEncodeFunc, m_scalPars.get(), &m_scalability);
231 m_scalPars->IsContextSwitchBack = false;
232
233 ENCODE_CHK_NULL_RETURN(m_scalability);
234
235 m_scalability->SetPassNumber(m_featureManager->GetNumPass());
236
237 return MOS_STATUS_SUCCESS;
238 }
239
GetSystemVdboxNumber()240 MOS_STATUS EncodePipeline::GetSystemVdboxNumber()
241 {
242 MEDIA_SYSTEM_INFO *gtSystemInfo = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
243 MEDIA_ENGINE_INFO mediaSysInfo;
244 MOS_ZeroMemory(&mediaSysInfo, sizeof(MEDIA_ENGINE_INFO));
245 MOS_STATUS eStatus = m_osInterface->pfnGetMediaEngineInfo(m_osInterface, mediaSysInfo);
246
247 if (eStatus == MOS_STATUS_SUCCESS && (!MEDIA_IS_SKU(m_skuTable, FtrWithSlimVdbox)))
248 {
249 // Both VE mode and media solo mode should be able to get the VDBOX number via the same interface
250 m_numVdbox = (uint8_t)(mediaSysInfo.VDBoxInfo.NumberOfVDBoxEnabled);
251 }
252 else
253 {
254 m_numVdbox = 1;
255 }
256
257 return MOS_STATUS_SUCCESS;
258 }
259
WaitForBatchBufferComplete()260 MOS_STATUS EncodePipeline::WaitForBatchBufferComplete()
261 {
262 ENCODE_CHK_NULL_RETURN(m_statusReport);
263
264 const uint32_t completedFrames = m_statusReport->GetCompletedCount();
265
266 if (!m_hwInterface->IsSimActive() &&
267 m_recycledBufStatusNum[m_currRecycledBufIdx] > completedFrames)
268 {
269 uint32_t waitMs;
270
271 // Wait for Batch Buffer complete event OR timeout
272 for (waitMs = MHW_TIMEOUT_MS_DEFAULT; waitMs > 0; waitMs -= MHW_EVENT_TIMEOUT_MS)
273 {
274 if (m_recycledBufStatusNum[m_currRecycledBufIdx] <= completedFrames)
275 {
276 break;
277 }
278
279 MosUtilities::MosSleep(MHW_EVENT_TIMEOUT_MS);
280 }
281
282 ENCODE_VERBOSEMESSAGE("Waited for %d ms", (MHW_TIMEOUT_MS_DEFAULT - waitMs));
283
284 if (m_recycledBufStatusNum[m_currRecycledBufIdx] > completedFrames)
285 {
286 ENCODE_ASSERTMESSAGE("No recycled buffers available, wait timed out at %d ms!", MHW_TIMEOUT_MS_DEFAULT);
287 ENCODE_ASSERTMESSAGE("m_storeData = %d, m_recycledBufStatusNum[%d] = %d, data = %d",
288 m_statusReport->GetSubmittedCount(),
289 m_currRecycledBufIdx,
290 m_recycledBufStatusNum[m_currRecycledBufIdx],
291 completedFrames);
292 return MOS_STATUS_CLIENT_AR_NO_SPACE;
293 }
294 }
295
296 m_recycledBufStatusNum[m_currRecycledBufIdx] = m_statusReport->GetSubmittedCount();
297
298 return MOS_STATUS_SUCCESS;
299 }
300
ExecuteActivePackets()301 MOS_STATUS EncodePipeline::ExecuteActivePackets()
302 {
303 ENCODE_FUNC_CALL();
304 MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
305
306 for (auto prop : m_activePacketList)
307 {
308 prop.stateProperty.singleTaskPhaseSupported = m_singleTaskPhaseSupported;
309 prop.stateProperty.statusReport = m_statusReport;
310 MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_INFO, &prop.packetId, sizeof(uint32_t), nullptr, 0);
311
312 MediaTask *task = prop.packet->GetActiveTask();
313 ENCODE_CHK_STATUS_RETURN(task->AddPacket(&prop));
314 if (prop.immediateSubmit)
315 {
316 ENCODE_CHK_STATUS_RETURN(task->Submit(true, m_scalability, m_debugInterface));
317 }
318 }
319
320 m_activePacketList.clear();
321 MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
322 return MOS_STATUS_SUCCESS;
323 }
324
ExecuteResolveMetaData(PMOS_RESOURCE pInput,PMOS_RESOURCE pOutput)325 MOS_STATUS EncodePipeline::ExecuteResolveMetaData(PMOS_RESOURCE pInput, PMOS_RESOURCE pOutput)
326 {
327 ENCODE_FUNC_CALL();
328 MOS_COMMAND_BUFFER cmdBuffer;
329 MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
330
331 ENCODE_CHK_NULL_RETURN(m_scalability);
332 ENCODE_CHK_STATUS_RETURN(m_scalability->GetCmdBuffer(&cmdBuffer));
333
334 auto basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
335 ENCODE_CHK_NULL_RETURN(basicFeature);
336 uint32_t bufSize = basicFeature->m_metaDataOffset.dwMetaDataSize + basicFeature->m_numSlices * basicFeature->m_metaDataOffset.dwMetaDataSubRegionSize +
337 basicFeature->m_metaDataOffset.dwTilePartitionSize + basicFeature->m_metaDataOffset.dwPostFeatueSize;
338 m_packetUtilities->AddMemCopyCmd(&cmdBuffer, pOutput, pInput, bufSize);
339 ENCODE_CHK_STATUS_RETURN(m_scalability->ReturnCmdBuffer(&cmdBuffer));
340 ENCODE_CHK_STATUS_RETURN(m_scalability->SubmitCmdBuffer(&cmdBuffer));
341
342 return MOS_STATUS_SUCCESS;
343 }
344
ReportErrorFlag(PMOS_RESOURCE pMetadataBuffer,uint32_t size,uint32_t offset,uint32_t flag)345 MOS_STATUS EncodePipeline::ReportErrorFlag(PMOS_RESOURCE pMetadataBuffer,
346 uint32_t size, uint32_t offset, uint32_t flag)
347 {
348 ENCODE_FUNC_CALL();
349 MOS_COMMAND_BUFFER cmdBuffer;
350 MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
351
352 ENCODE_CHK_NULL_RETURN(m_scalability);
353 ENCODE_CHK_STATUS_RETURN(m_scalability->GetCmdBuffer(&cmdBuffer));
354
355 auto basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
356 ENCODE_CHK_NULL_RETURN(basicFeature);
357
358 basicFeature->m_metaDataOffset.dwMetaDataSize = size;
359 m_packetUtilities->AddStoreDataImmCmd(&cmdBuffer, pMetadataBuffer, offset, flag);
360 ENCODE_CHK_STATUS_RETURN(m_scalability->ReturnCmdBuffer(&cmdBuffer));
361 ENCODE_CHK_STATUS_RETURN(m_scalability->SubmitCmdBuffer(&cmdBuffer));
362 return MOS_STATUS_SUCCESS;
363 }
364
SetFrameTrackingForMultiTaskPhase()365 void EncodePipeline::SetFrameTrackingForMultiTaskPhase()
366 {
367 if (!IsSingleTaskPhaseSupported())
368 {
369 for_each(m_activePacketList.begin(), m_activePacketList.end() - 1, [&](PacketProperty &blk) { blk.frameTrackingRequested = false; });
370 }
371 }
372
373 }
374