1 /*
2 * Copyright (c) 2017-2020, 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 codechal_kernel_base.cpp
24 //! \brief Defines base class for all kernels
25 //! \details Kernel base class abstracts all common functions and definitions
26 //! for all kernels, each kernel class should inherit from kernel base
27 //!
28
29 #include "codechal_kernel_base.h"
30 #include "codeckrnheader.h"
31 #include "hal_oca_interface.h"
32
CodechalKernelBase(CodechalEncoderState * encoder)33 CodechalKernelBase::CodechalKernelBase(CodechalEncoderState *encoder) :
34 m_encoder(encoder),
35 m_firstTaskInPhase(encoder->m_firstTaskInPhase),
36 m_lastTaskInPhase(encoder->m_lastTaskInPhase),
37 m_singleTaskPhaseSupported(encoder->m_singleTaskPhaseSupported),
38 m_renderContextUsesNullHw(encoder->m_renderContextUsesNullHw),
39 m_groupIdSelectSupported(encoder->m_groupIdSelectSupported),
40 m_fieldScalingOutputInterleaved(encoder->m_fieldScalingOutputInterleaved),
41 m_vdencEnabled(encoder->m_vdencEnabled),
42 m_groupId(encoder->m_groupId),
43 m_maxBtCount(encoder->m_maxBtCount),
44 m_vmeStatesSize(encoder->m_vmeStatesSize),
45 m_storeData(encoder->m_storeData),
46 m_verticalLineStride(encoder->m_verticalLineStride),
47 m_downscaledWidthInMb4x(encoder->m_downscaledWidthInMb4x),
48 m_downscaledHeightInMb4x(encoder->m_downscaledHeightInMb4x),
49 m_downscaledWidthInMb16x(encoder->m_downscaledWidthInMb16x),
50 m_downscaledHeightInMb16x(encoder->m_downscaledHeightInMb16x),
51 m_downscaledWidthInMb32x(encoder->m_downscaledWidthInMb32x),
52 m_downscaledHeightInMb32x(encoder->m_downscaledHeightInMb32x),
53 m_mode(encoder->m_mode),
54 m_pictureCodingType(encoder->m_pictureCodingType),
55 m_frameWidth(encoder->m_frameWidth),
56 m_frameHeight(encoder->m_frameHeight),
57 m_frameFieldHeight(encoder->m_frameFieldHeight),
58 m_standard(encoder->m_standard),
59 m_walkerMode(encoder->m_walkerMode)
60 {
61 m_osInterface = encoder->GetOsInterface();
62 m_hwInterface = encoder->GetHwInterface();
63 m_debugInterface = encoder->GetDebugInterface();
64 m_miInterface = m_hwInterface->GetMiInterface();
65 m_renderInterface = m_hwInterface->GetRenderInterface();
66 m_stateHeapInterface = m_renderInterface->m_stateHeapInterface->pStateHeapInterface;
67 }
68
~CodechalKernelBase()69 CodechalKernelBase::~CodechalKernelBase()
70 {
71 for (auto &it : m_kernelStatePool)
72 {
73 MOS_Delete(it.second);
74 }
75 m_kernelStatePool.clear();
76
77 for (auto &it : m_surfacePool)
78 {
79 if (it.second != nullptr)
80 {
81 m_osInterface->pfnFreeResource(m_osInterface, &it.second->OsResource);
82 MOS_Delete(it.second);
83 }
84 }
85 m_surfacePool.clear();
86 }
87
GetKernelBinaryAndSize(uint8_t * kernelBase,uint32_t kernelUID,uint8_t ** kernelBinary,uint32_t * size)88 MOS_STATUS CodechalKernelBase::GetKernelBinaryAndSize(
89 uint8_t * kernelBase,
90 uint32_t kernelUID,
91 uint8_t **kernelBinary,
92 uint32_t *size)
93 {
94 CODECHAL_ENCODE_CHK_NULL_RETURN(kernelBase);
95 CODECHAL_ENCODE_CHK_NULL_RETURN(kernelBinary);
96 CODECHAL_ENCODE_CHK_NULL_RETURN(size);
97
98 if (kernelUID >= IDR_CODEC_TOTAL_NUM_KERNELS)
99 {
100 return MOS_STATUS_INVALID_PARAMETER;
101 }
102
103 auto kernelOffsetTable = (uint32_t *)kernelBase;
104 auto binaryBase = (uint8_t *)(kernelOffsetTable + IDR_CODEC_TOTAL_NUM_KERNELS + 1);
105
106 *size = kernelOffsetTable[kernelUID + 1] - kernelOffsetTable[kernelUID];
107 *kernelBinary = (*size) > 0 ? binaryBase + kernelOffsetTable[kernelUID] : nullptr;
108
109 return MOS_STATUS_SUCCESS;
110 }
111
Initialize(KernelBinaryCallback callback,uint8_t * binaryBase,uint32_t kernelUID)112 MOS_STATUS CodechalKernelBase::Initialize(
113 KernelBinaryCallback callback,
114 uint8_t * binaryBase,
115 uint32_t kernelUID)
116 {
117 CODECHAL_ENCODE_CHK_NULL_RETURN(callback);
118 CODECHAL_ENCODE_CHK_NULL_RETURN(binaryBase);
119
120 m_callback = callback;
121
122 CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
123 CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface);
124 CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface);
125 CODECHAL_ENCODE_CHK_NULL_RETURN(m_renderInterface);
126 CODECHAL_ENCODE_CHK_NULL_RETURN(m_stateHeapInterface);
127
128 uint32_t binarySize = 0;
129 CODECHAL_ENCODE_CHK_STATUS_RETURN(GetKernelBinaryAndSize(binaryBase, kernelUID, &m_kernelBinary, &binarySize));
130 if (binarySize == 0)
131 {
132 return MOS_STATUS_INVALID_PARAMETER;
133 }
134
135 return MOS_STATUS_SUCCESS;
136 }
137
CreateKernelState(MHW_KERNEL_STATE ** kernelState,uint32_t kernelIndex,EncOperation operation,uint32_t kernelOffset)138 MOS_STATUS CodechalKernelBase::CreateKernelState(
139 MHW_KERNEL_STATE ** kernelState,
140 uint32_t kernelIndex,
141 EncOperation operation,
142 uint32_t kernelOffset)
143 {
144 CODECHAL_ENCODE_FUNCTION_ENTER;
145 CODECHAL_ENCODE_CHK_NULL_RETURN(m_callback);
146 CODECHAL_ENCODE_CHK_NULL_RETURN(m_kernelBinary);
147
148 CODECHAL_ENCODE_CHK_NULL_RETURN((*kernelState) = MOS_New(MHW_KERNEL_STATE));
149 m_kernelStatePool.insert(std::make_pair(kernelIndex, *kernelState));
150
151 CODECHAL_KERNEL_HEADER kernelHeader = {};
152 uint32_t kernelSize = 0;
153 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_callback(m_kernelBinary, operation, kernelOffset, &kernelHeader, &kernelSize));
154
155 (*kernelState)->KernelParams.iBTCount = GetBTCount();
156 (*kernelState)->KernelParams.iThreadCount = m_renderInterface->GetHwCaps()->dwMaxThreads;
157 (*kernelState)->KernelParams.iCurbeLength = GetCurbeSize();
158 (*kernelState)->KernelParams.iBlockWidth = CODECHAL_MACROBLOCK_WIDTH;
159 (*kernelState)->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT;
160 (*kernelState)->KernelParams.iIdCount = 1;
161 (*kernelState)->KernelParams.iInlineDataLength = GetInlineDataLength();
162
163 (*kernelState)->dwCurbeOffset = m_stateHeapInterface->GetSizeofCmdInterfaceDescriptorData();
164 (*kernelState)->KernelParams.pBinary = m_kernelBinary + (kernelHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
165 (*kernelState)->KernelParams.iSize = kernelSize;
166 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->CalculateSshAndBtSizesRequested(
167 (*kernelState)->KernelParams.iBTCount,
168 &(*kernelState)->dwSshSize,
169 &(*kernelState)->dwBindingTableSize));
170
171 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_renderInterface->m_stateHeapInterface, (*kernelState)));
172
173 return MOS_STATUS_SUCCESS;
174 }
175
Run()176 MOS_STATUS CodechalKernelBase::Run()
177 {
178 CODECHAL_ENCODE_FUNCTION_ENTER;
179
180 AddPerfTag();
181
182 MHW_KERNEL_STATE *kernelState = GetActiveKernelState();
183 CODECHAL_ENCODE_CHK_NULL_RETURN(kernelState);
184
185 // If Single Task Phase is not enabled, use BT count for the kernel state.
186 if (m_firstTaskInPhase == true || !m_singleTaskPhaseSupported)
187 {
188 uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount;
189 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->RequestSshSpaceForCmdBuf(maxBtCount));
190 m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount);
191 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->VerifySpaceAvailable());
192 }
193
194 auto stateHeapInterface = m_renderInterface->m_stateHeapInterface;
195 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
196 stateHeapInterface,
197 kernelState,
198 false,
199 0,
200 false,
201 m_storeData));
202
203 MHW_INTERFACE_DESCRIPTOR_PARAMS idParams;
204 MOS_ZeroMemory(&idParams, sizeof(idParams));
205 idParams.pKernelState = kernelState;
206 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SetInterfaceDescriptor(1, &idParams));
207
208 CODECHAL_MEDIA_STATE_TYPE encFunctionType = GetMediaStateType();
209
210 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbe(kernelState));
211
212 CODECHAL_DEBUG_TOOL(
213 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(encFunctionType, MHW_DSH_TYPE, kernelState));
214 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(encFunctionType, MHW_ISH_TYPE, kernelState));
215 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe(encFunctionType, kernelState)));
216
217 MOS_COMMAND_BUFFER cmdBuffer;
218 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
219
220 SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams();
221 sendKernelCmdsParams.EncFunctionType = encFunctionType;
222 sendKernelCmdsParams.pKernelState = kernelState;
223 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams));
224
225 // Add binding table
226 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SetBindingTable(kernelState));
227
228 CODECHAL_ENCODE_CHK_STATUS_RETURN(SendSurfaces(&cmdBuffer, kernelState));
229
230 CODECHAL_DEBUG_TOOL(
231 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(encFunctionType, MHW_SSH_TYPE, kernelState)));
232
233 CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams;
234 MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams));
235
236 InitWalkerCodecParams(walkerCodecParams);
237
238 MHW_WALKER_PARAMS walkerParams;
239 CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams(
240 m_hwInterface,
241 &walkerParams,
242 &walkerCodecParams));
243
244 HalOcaInterface::TraceMessage(cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, __FUNCTION__, sizeof(__FUNCTION__));
245 HalOcaInterface::OnDispatch(cmdBuffer, *m_osInterface, *m_miInterface, *m_renderInterface->GetMmioRegisters());
246
247 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderInterface->AddMediaObjectWalkerCmd(
248 &cmdBuffer,
249 &walkerParams));
250
251 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->EndStatusReport(&cmdBuffer, encFunctionType));
252
253 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SubmitBlocks(kernelState));
254 if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
255 {
256 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->UpdateGlobalCmdBufId());
257 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
258 }
259 CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(&cmdBuffer, encFunctionType)));
260
261 m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase);
262 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
263
264 if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
265 {
266 HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
267 m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw);
268 m_lastTaskInPhase = false;
269 }
270
271 return MOS_STATUS_SUCCESS;
272 }
273
CleanUpResource(PMOS_RESOURCE resource,PMOS_ALLOC_GFXRES_PARAMS allocParam)274 MOS_STATUS CodechalKernelBase::CleanUpResource(PMOS_RESOURCE resource, PMOS_ALLOC_GFXRES_PARAMS allocParam)
275 {
276 CODECHAL_ENCODE_FUNCTION_ENTER;
277 CODECHAL_ENCODE_CHK_NULL_RETURN(resource);
278 CODECHAL_ENCODE_CHK_NULL_RETURN(allocParam);
279
280 MOS_LOCK_PARAMS lockFlag;
281 memset(&lockFlag, 0, sizeof(lockFlag));
282 lockFlag.WriteOnly = true;
283
284 uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, resource, &lockFlag);
285 if (data == 0)
286 {
287 return MOS_STATUS_NULL_POINTER;
288 }
289
290 if (allocParam->Format == Format_Buffer)
291 {
292 memset(data, 0, allocParam->dwBytes);
293 }
294 else if (allocParam->Format == Format_Buffer_2D)
295 {
296 memset(data, 0, allocParam->dwHeight * allocParam->dwWidth);
297 }
298 else
299 {
300 return MOS_STATUS_INVALID_PARAMETER;
301 }
302
303 m_osInterface->pfnUnlockResource(m_osInterface, resource);
304
305 return MOS_STATUS_SUCCESS;
306 }
307
GetSurface(uint32_t surfaceId)308 PMOS_SURFACE CodechalKernelBase::GetSurface( uint32_t surfaceId )
309 {
310 auto it = m_surfacePool.find(surfaceId);
311 if (it != m_surfacePool.end())
312 {
313 return it->second;
314 }
315 return nullptr;
316 }
317
AllocateSurface(PMOS_ALLOC_GFXRES_PARAMS param,PMOS_SURFACE surface,uint32_t surfaceId)318 MOS_STATUS CodechalKernelBase::AllocateSurface(PMOS_ALLOC_GFXRES_PARAMS param, PMOS_SURFACE surface, uint32_t surfaceId)
319 {
320 CODECHAL_ENCODE_CHK_NULL_RETURN(param);
321 CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
322 m_surfacePool.insert(std::make_pair(surfaceId, surface));
323
324 CODECHAL_ENCODE_CHK_STATUS_RETURN(
325 m_osInterface->pfnAllocateResource(
326 m_osInterface,
327 param,
328 &surface->OsResource));
329 CleanUpResource(&surface->OsResource, param);
330
331 return MOS_STATUS_SUCCESS;
332 }
333