1 /*
2 * Copyright (c) 2017-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     codechal_encode_wp_mdf_g12.cpp
24 //! \brief    This file implements the wp init feature for all codecs on Gen12 platform
25 //!
26 
27 #include "codechal_encoder_base.h"
28 #include "codechal_encode_wp_mdf_g12.h"
29 #include "codeckrnheader.h"
30 #include "Gen12LP_WeightedPrediction_genx.h"
31 
InitKernelStateIsa(void * kernelIsa,uint32_t kernelIsaSize)32 MOS_STATUS CodechalEncodeWPMdfG12::InitKernelStateIsa(void *kernelIsa, uint32_t kernelIsaSize)
33 {
34     CODECHAL_ENCODE_FUNCTION_ENTER;
35     if (!m_cmProgram)
36     {
37         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->LoadProgram(kernelIsa,
38             kernelIsaSize,
39             m_cmProgram,
40             "-nojitter"));
41     }
42     for (uint8_t i = 0; i < CODEC_NUM_WP_FRAME; i++)
43     {
44         if (m_cmKrn[i] == nullptr)
45         {
46             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateKernel(m_cmProgram,
47                 "Scale_frame",
48                 m_cmKrn[i]));
49         }
50     }
51 
52     return MOS_STATUS_SUCCESS;
53 }
54 
SetCurbe(CurbeData & curbe)55 MOS_STATUS CodechalEncodeWPMdfG12::SetCurbe(CurbeData &curbe)
56 {
57     CODECHAL_ENCODE_FUNCTION_ENTER;
58     MOS_ZeroMemory(&curbe, sizeof(CurbeData));
59 
60     /* Weights[i][j][k][m] is interpreted as:
61 
62     i refers to reference picture list 0 or 1;
63     j refers to reference list entry 0-31;
64     k refers to data for the luma (Y) component when it is 0, the Cb chroma component when it is 1 and the Cr chroma component when it is 2;
65     m refers to weight when it is 0 and offset when it is 1
66     */
67     //C Model hard code log2WeightDenom = 6. No need to send WD paramters to WP Kernel.
68     curbe.DW0.defaultWeight = m_curbeParams.slcParams->weights[m_curbeParams.refPicListIdx][m_curbeParams.wpIdx][0][0];
69     curbe.DW0.defaultOffset = m_curbeParams.slcParams->weights[m_curbeParams.refPicListIdx][m_curbeParams.wpIdx][0][1];
70 
71     curbe.DW49.lumaLog2WeightDenom = m_curbeParams.slcParams->luma_log2_weight_denom;
72 
73     return MOS_STATUS_SUCCESS;
74 }
75 
76 //!
77 //! \brief    WP init kernel function
78 //!
79 //! \param    [in] params
80 //!           Pointer to KernelParams
81 //!
82 //! \return   MOS_STATUS
83 //!           MOS_STATUS_SUCCESS if success, else fail reason
84 //!
Execute(KernelParams * params)85 MOS_STATUS CodechalEncodeWPMdfG12::Execute(KernelParams *params)
86 {
87     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
88     CODECHAL_ENCODE_FUNCTION_ENTER;
89 
90     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
91 
92     if (params->slcWPParams && params->slcWPParams->luma_log2_weight_denom != 6)
93     {
94         eStatus = MOS_STATUS_INVALID_PARAMETER;
95         CODECHAL_ENCODE_ASSERTMESSAGE("Weighted Prediction Kernel does not support Log2LumaWeightDenom != 6!");
96         return eStatus;
97     }
98 
99     PerfTagSetting perfTag;
100     CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_WP_KERNEL);
101 
102     // Allocate output surface
103     if (params->useRefPicList1)
104     {
105         *(params->useWeightedSurfaceForL1) = true;
106         m_surfaceParams.wpOutListIdx       = CODEC_WP_OUTPUT_L1_START + params->wpIndex;
107     }
108     else
109     {
110         *(params->useWeightedSurfaceForL0) = true;
111         m_surfaceParams.wpOutListIdx       = CODEC_WP_OUTPUT_L0_START + params->wpIndex;
112     }
113     if (m_surfaceParams.wpOutListIdx >= CODEC_NUM_WP_FRAME)
114     {
115         eStatus = MOS_STATUS_INVALID_PARAMETER;
116         CODECHAL_ENCODE_ASSERTMESSAGE("index exceeds maximum value of array weightedPredOutputPicList.");
117         return eStatus;
118     }
119     uint8_t   wpKrnIdx = m_surfaceParams.wpOutListIdx;
120     CmKernel *cmKrn    = m_cmKrn[wpKrnIdx];
121 
122     // Setup Curbe
123     m_curbeParams.refPicListIdx = (params->useRefPicList1) ? LIST_1 : LIST_0;
124     m_curbeParams.wpIdx         = params->wpIndex;
125     m_curbeParams.slcParams     = params->slcWPParams;
126 
127     //Set Surface States
128     m_surfaceParams.refFrameInput    = params->refFrameInput;
129     m_surfaceParams.refIsBottomField = params->refIsBottomField;
130 
131     CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources());
132 
133     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupSurfaces(wpKrnIdx));
134 
135     uint32_t ResolutionX = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth);
136     uint32_t ResolutionY = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight);
137 
138     uint32_t threadCount = ResolutionX * ResolutionY;
139     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKrn->SetThreadCount(threadCount));
140 
141     if (m_encoder->m_resolutionChanged && m_threadSpace != nullptr)
142     {
143         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroyThreadSpace(m_threadSpace));
144         m_threadSpace = nullptr;
145     }
146 
147     if (m_threadSpace == nullptr)
148     {
149         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateThreadSpace(
150             ResolutionX,
151             ResolutionY,
152             m_threadSpace));
153 
154         if (m_groupIdSelectSupported)
155         {
156             m_threadSpace->SetMediaWalkerGroupSelect((CM_MW_GROUP_SELECT)m_groupId);
157         }
158     }
159 
160     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKrn->AssociateThreadSpace(m_threadSpace));
161 
162     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgs(wpKrnIdx));
163 
164     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->AddKernel(cmKrn));
165 
166     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
167     {
168         CmEvent *event = CM_NO_EVENT;
169         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmQueue->EnqueueFast(m_encoder->m_cmTask, event));
170         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->Reset());
171         m_lastTaskInPhase = false;
172     }
173     else
174     {
175         m_encoder->m_cmTask->AddSync();
176     }
177 
178     if (params->useRefPicList1 == false)
179     {
180         // Dump all the surfaces for debugging
181         CODECHAL_DEBUG_TOOL(
182             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
183                 m_surfaceParams.refFrameInput,
184                 CodechalDbgAttr::attrEncodeRawInputSurface,
185                 "WP_input_Surface_L0")));
186 
187         CODECHAL_DEBUG_TOOL(
188             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
189                 &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx],
190                 CodechalDbgAttr::attrReferenceSurfaces,
191                 "WP_output_Surface_L0")));
192     }
193     else
194     {
195         // Dump all the surfaces for debugging
196         CODECHAL_DEBUG_TOOL(
197             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
198                 m_surfaceParams.refFrameInput,
199                 CodechalDbgAttr::attrEncodeRawInputSurface,
200                 "WP_input_Surface_L1")));
201 
202         CODECHAL_DEBUG_TOOL(
203             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
204                 &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx],
205                 CodechalDbgAttr::attrReferenceSurfaces,
206                 "WP_output_Surface_L1")));
207     }
208     return eStatus;
209 }
210 
SetupKernelArgs(uint8_t wpKrnIdx)211 MOS_STATUS CodechalEncodeWPMdfG12::SetupKernelArgs(uint8_t wpKrnIdx)
212 {
213     CODECHAL_ENCODE_FUNCTION_ENTER;
214     int           idx = 0;
215     CurbeData     curbe;
216     SurfaceIndex *pSurfIndex = nullptr;
217     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbe(curbe));
218     CODECHAL_ENCODE_CHK_NULL_RETURN(m_wpInputSurface[wpKrnIdx]);
219     CODECHAL_ENCODE_CHK_NULL_RETURN(m_wpOutputSurface[wpKrnIdx]);
220 
221     // SetKernelArg will copy curbe data
222     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(curbe), &curbe));
223     CODECHAL_DEBUG_TOOL(
224         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpMDFCurbe(
225             CODECHAL_MEDIA_STATE_ENC_WP,
226             (uint8_t *)&curbe,
227             sizeof(curbe)));)
228 
229     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_wpInputSurface[wpKrnIdx]->GetIndex(pSurfIndex));
230     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex));
231 
232     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_wpOutputSurface[wpKrnIdx]->GetIndex(pSurfIndex));
233     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex));
234 
235     return MOS_STATUS_SUCCESS;
236 }
237 
SetupSurfaces(uint8_t wpKrnIdx)238 MOS_STATUS CodechalEncodeWPMdfG12::SetupSurfaces(uint8_t wpKrnIdx)
239 {
240     CODECHAL_ENCODE_FUNCTION_ENTER;
241     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->UpdateSurface2D(
242         &m_surfaceParams.refFrameInput->OsResource,
243         m_wpInputSurface[wpKrnIdx]));
244 
245     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->UpdateSurface2D(
246         &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx].OsResource,
247         m_wpOutputSurface[wpKrnIdx]));
248 
249     return MOS_STATUS_SUCCESS;
250 }
251 
ReleaseResources()252 MOS_STATUS CodechalEncodeWPMdfG12::ReleaseResources()
253 {
254     CODECHAL_ENCODE_FUNCTION_ENTER;
255     if (m_threadSpace)
256     {
257         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroyThreadSpace(m_threadSpace));
258         m_threadSpace = nullptr;
259     }
260 
261     for (uint8_t i = 0; i < CODEC_NUM_WP_FRAME; i++)
262     {
263         if (m_wpInputSurface[i])
264         {
265             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroySurface(m_wpInputSurface[i]));
266             m_wpInputSurface[i] = nullptr;
267         }
268 
269         if (m_wpOutputSurface[i])
270         {
271             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroySurface(m_wpOutputSurface[i]));
272             m_wpOutputSurface[i] = nullptr;
273         }
274 
275         if (m_cmKrn[i])
276         {
277             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroyKernel(m_cmKrn[i]));
278             m_cmKrn[i] = nullptr;
279         }
280     }
281 
282     if (m_cmProgram)
283     {
284         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroyProgram(m_cmProgram));
285         m_cmProgram = nullptr;
286     }
287 
288     return MOS_STATUS_SUCCESS;
289 }
290