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     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->CreateThreadSpace(
142         ResolutionX,
143         ResolutionY,
144         m_threadSpace));
145 
146     if (m_groupIdSelectSupported)
147     {
148         m_threadSpace->SetMediaWalkerGroupSelect((CM_MW_GROUP_SELECT)m_groupId);
149     }
150 
151     CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKrn->AssociateThreadSpace(m_threadSpace));
152 
153     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgs(wpKrnIdx));
154 
155     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->AddKernel(cmKrn));
156 
157     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
158     {
159         CmEvent * event = CM_NO_EVENT;
160         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmQueue->EnqueueFast(m_encoder->m_cmTask, event));
161         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmTask->Reset());
162         m_lastTaskInPhase = false;
163     }
164     else
165     {
166         m_encoder->m_cmTask->AddSync();
167     }
168 
169     if (params->useRefPicList1 == false)
170     {
171         // Dump all the surfaces for debugging
172         CODECHAL_DEBUG_TOOL(
173             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
174                 m_surfaceParams.refFrameInput,
175                 CodechalDbgAttr::attrEncodeRawInputSurface,
176                 "WP_input_Surface_L0")));
177 
178         CODECHAL_DEBUG_TOOL(
179             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
180                 &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx],
181                 CodechalDbgAttr::attrReferenceSurfaces,
182                 "WP_output_Surface_L0")));
183     }
184     else
185     {
186         // Dump all the surfaces for debugging
187         CODECHAL_DEBUG_TOOL(
188             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
189                 m_surfaceParams.refFrameInput,
190                 CodechalDbgAttr::attrEncodeRawInputSurface,
191                 "WP_input_Surface_L1")));
192 
193         CODECHAL_DEBUG_TOOL(
194             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
195                 &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx],
196                 CodechalDbgAttr::attrReferenceSurfaces,
197                 "WP_output_Surface_L1")));
198     }
199     return eStatus;
200 }
201 
SetupKernelArgs(uint8_t wpKrnIdx)202 MOS_STATUS CodechalEncodeWPMdfG12::SetupKernelArgs(uint8_t wpKrnIdx)
203 {
204     CODECHAL_ENCODE_FUNCTION_ENTER;
205     int idx = 0;
206     CurbeData curbe;
207     SurfaceIndex * pSurfIndex = nullptr;
208     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbe(curbe));
209     CODECHAL_ENCODE_CHK_NULL_RETURN(m_wpInputSurface[wpKrnIdx]);
210     CODECHAL_ENCODE_CHK_NULL_RETURN(m_wpOutputSurface[wpKrnIdx]);
211 
212     // SetKernelArg will copy curbe data
213     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(curbe), &curbe));
214     CODECHAL_DEBUG_TOOL(
215         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpMDFCurbe(
216             CODECHAL_MEDIA_STATE_ENC_WP,
217             (uint8_t *)&curbe,
218             sizeof(curbe)));)
219 
220     m_wpInputSurface[wpKrnIdx]->GetIndex(pSurfIndex);
221     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex));
222 
223     m_wpOutputSurface[wpKrnIdx]->GetIndex(pSurfIndex);
224     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrn[wpKrnIdx]->SetKernelArg(idx++, sizeof(SurfaceIndex), pSurfIndex));
225 
226     return MOS_STATUS_SUCCESS;
227 }
228 
SetupSurfaces(uint8_t wpKrnIdx)229 MOS_STATUS CodechalEncodeWPMdfG12::SetupSurfaces(uint8_t wpKrnIdx)
230 {
231     CODECHAL_ENCODE_FUNCTION_ENTER;
232     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->UpdateSurface2D(
233         &m_surfaceParams.refFrameInput->OsResource,
234         m_wpInputSurface[wpKrnIdx]));
235 
236     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->UpdateSurface2D(
237         &m_surfaceParams.weightedPredOutputPicList[m_surfaceParams.wpOutListIdx].OsResource,
238         m_wpOutputSurface[wpKrnIdx]));
239 
240     return MOS_STATUS_SUCCESS;
241 }
242 
ReleaseResources()243 MOS_STATUS CodechalEncodeWPMdfG12::ReleaseResources()
244 {
245     CODECHAL_ENCODE_FUNCTION_ENTER;
246     for (uint8_t i = 0; i < CODEC_NUM_WP_FRAME; i++)
247     {
248         if (m_wpInputSurface[i])
249         {
250             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroySurface(m_wpInputSurface[i]));
251             m_wpInputSurface[i] = nullptr;
252         }
253 
254         if (m_wpOutputSurface[i])
255         {
256             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_encoder->m_cmDev->DestroySurface(m_wpOutputSurface[i]));
257             m_wpOutputSurface[i] = nullptr;
258         }
259     }
260 
261     return MOS_STATUS_SUCCESS;
262 }
263