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     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;
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     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderInterface->AddMediaObjectWalkerCmd(
245         &cmdBuffer,
246         &walkerParams));
247 
248     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->EndStatusReport(&cmdBuffer, encFunctionType));
249 
250     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->SubmitBlocks(kernelState));
251     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
252     {
253         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->UpdateGlobalCmdBufId());
254         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
255     }
256     CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(&cmdBuffer, encFunctionType)));
257 
258     m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase);
259     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
260 
261     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
262     {
263         HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface->pOsContext);
264         m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw);
265         m_lastTaskInPhase = false;
266     }
267 
268     return MOS_STATUS_SUCCESS;
269 }
270 
CleanUpResource(PMOS_RESOURCE resource,PMOS_ALLOC_GFXRES_PARAMS allocParam)271 MOS_STATUS CodechalKernelBase::CleanUpResource(PMOS_RESOURCE resource, PMOS_ALLOC_GFXRES_PARAMS allocParam)
272 {
273     CODECHAL_ENCODE_FUNCTION_ENTER;
274     CODECHAL_ENCODE_CHK_NULL_RETURN(resource);
275     CODECHAL_ENCODE_CHK_NULL_RETURN(allocParam);
276 
277     MOS_LOCK_PARAMS lockFlag;
278     memset(&lockFlag, 0, sizeof(lockFlag));
279     lockFlag.WriteOnly = true;
280 
281     uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, resource, &lockFlag);
282     if (data == 0)
283     {
284         return MOS_STATUS_NULL_POINTER;
285     }
286 
287     if (allocParam->Format == Format_Buffer)
288     {
289         memset(data, 0, allocParam->dwBytes);
290     }
291     else if (allocParam->Format == Format_Buffer_2D)
292     {
293         memset(data, 0, allocParam->dwHeight * allocParam->dwWidth);
294     }
295     else
296     {
297         return MOS_STATUS_INVALID_PARAMETER;
298     }
299 
300     m_osInterface->pfnUnlockResource(m_osInterface, resource);
301 
302     return MOS_STATUS_SUCCESS;
303 }
304 
GetSurface(uint32_t surfaceId)305 PMOS_SURFACE CodechalKernelBase::GetSurface( uint32_t surfaceId )
306 {
307     auto it = m_surfacePool.find(surfaceId);
308     if (it != m_surfacePool.end())
309     {
310         return it->second;
311     }
312     return nullptr;
313 }
314 
AllocateSurface(PMOS_ALLOC_GFXRES_PARAMS param,PMOS_SURFACE surface,uint32_t surfaceId)315 MOS_STATUS CodechalKernelBase::AllocateSurface(PMOS_ALLOC_GFXRES_PARAMS param, PMOS_SURFACE surface, uint32_t surfaceId)
316 {
317     CODECHAL_ENCODE_CHK_NULL_RETURN(param);
318     CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
319     m_surfacePool.insert(std::make_pair(surfaceId, surface));
320 
321     CODECHAL_ENCODE_CHK_STATUS_RETURN(
322         m_osInterface->pfnAllocateResource(
323             m_osInterface,
324             param,
325             &surface->OsResource));
326     CleanUpResource(&surface->OsResource, param);
327 
328     return MOS_STATUS_SUCCESS;
329 }
330