1 /*
2 * Copyright (c) 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 //! \file     encode_huc_la_update_packet.cpp
24 //! \brief    Defines the implementation of Huc Lookahead update packet
25 //!
26 
27 #include "encode_huc_la_update_packet.h"
28 #include "encode_vdenc_lpla_analysis.h"
29 
30 namespace encode
31 {
Init()32     MOS_STATUS HucLaUpdatePkt::Init()
33     {
34         ENCODE_FUNC_CALL();
35         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
36 
37         HUC_CHK_STATUS_RETURN(EncodeHucPkt::Init());
38 
39         ENCODE_CHK_NULL_RETURN(m_featureManager);
40         m_basicFeature = dynamic_cast<HevcBasicFeature *>(m_featureManager->GetFeature(HevcFeatureIDs::basicFeature));
41         ENCODE_CHK_NULL_RETURN(m_basicFeature);
42 
43         return eStatus;
44     }
45 
AllocateResources()46     MOS_STATUS HucLaUpdatePkt::AllocateResources()
47     {
48         ENCODE_FUNC_CALL();
49         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
50 
51         ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::AllocateResources());
52 
53         return eStatus;
54     }
55 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)56     MOS_STATUS HucLaUpdatePkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
57     {
58         ENCODE_FUNC_CALL();
59 
60         bool firstTaskInPhase = packetPhase & firstPacket;
61         bool requestProlog    = false;
62         bool isLaAnalysisRequired = true;
63 
64 #if _SW_BRC
65         if (!m_pipeline->IsFirstPass())
66         {
67             auto pdwData = (uint32_t *)m_allocator->LockResourceForRead(m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0));
68             ENCODE_CHK_NULL_RETURN(pdwData);
69             isLaAnalysisRequired = (*pdwData == CODECHAL_VDENC_HEVC_BRC_HUC_STATUS_REENCODE_MASK);
70             m_allocator->UnLock(m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0));
71 
72             if (m_swBrc && m_swBrc->SwBrcEnabled() && !isLaAnalysisRequired)
73             {
74                 RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, CalculateLaRecords, true);
75                 return MOS_STATUS_SUCCESS;
76             }
77         }
78 #endif
79         if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
80         {
81             // Send command buffer header at the beginning (OS dependent)
82             requestProlog = true;
83         }
84 
85         uint16_t orig_perf_tag = (uint16_t)m_osInterface->pfnGetPerfTag(m_osInterface);
86         SetPerfTag(CODECHAL_ENCODE_PERFTAG_CALL_HEVC_LA_UPDATE, (uint16_t)m_basicFeature->m_mode, (uint16_t)m_basicFeature->m_pictureCodingType);
87         ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog, LA_UPDATE));
88         SetPerfTag(orig_perf_tag, (uint16_t)m_basicFeature->m_mode, (uint16_t)m_basicFeature->m_pictureCodingType);
89 
90 #if _SW_BRC
91         if (!m_swBrc || !m_swBrc->SwBrcEnabled())
92         {
93 #endif
94             if (!m_pipeline->IsLastPass())
95             {
96                 // Write HUC_STATUS mask: DW1 (mask value)
97                 auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
98                 storeDataParams                  = {};
99                 storeDataParams.pOsResource      = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
100                 storeDataParams.dwResourceOffset = sizeof(uint32_t);
101                 storeDataParams.dwValue          = CODECHAL_VDENC_HEVC_BRC_HUC_STATUS_REENCODE_MASK;
102                 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(commandBuffer));
103 
104                 // store HUC_STATUS register: DW0 (actual value)
105                 ENCODE_CHK_COND_RETURN((m_vdboxIndex > MHW_VDBOX_NODE_1), "ERROR - vdbox index exceed the maximum");
106                 auto mmioRegisters             = m_hucItf->GetMmioRegisters(m_vdboxIndex);
107                 auto &storeRegParams           = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
108                 storeDataParams                = {};
109                 storeRegParams.presStoreBuffer = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
110                 storeRegParams.dwOffset        = 0;
111                 storeRegParams.dwRegister      = mmioRegisters->hucStatusRegOffset;
112                 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(commandBuffer));
113             }
114 #if _SW_BRC
115         }
116         else
117         {
118             //add force wake up for ladll path, to avoid that ladll path directly use MI_COPY to get data in ReadLPLAData
119             if (requestProlog)
120             {
121                 ENCODE_CHK_STATUS_RETURN(AddForceWakeup(*commandBuffer));
122                 ENCODE_CHK_STATUS_RETURN(SendPrologCmds(*commandBuffer));
123             }
124         }
125 #endif
126 
127         ReadLPLAData(commandBuffer);
128 
129         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, CalculateLaRecords, m_pipeline->IsLastPass());
130 
131         return MOS_STATUS_SUCCESS;
132     }
133 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)134     MOS_STATUS HucLaUpdatePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
135     {
136         ENCODE_FUNC_CALL();
137 
138         auto osInterface = m_hwInterface->GetOsInterface();
139         ENCODE_CHK_NULL_RETURN(osInterface);
140 
141         uint32_t hucCommandsSize = 0;
142         uint32_t hucPatchListSize = 0;
143         MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
144 
145         ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize(
146             m_basicFeature->m_mode, (uint32_t *)&hucCommandsSize, (uint32_t *)&hucPatchListSize, &stateCmdSizeParams));
147 
148         commandBufferSize      = hucCommandsSize;
149         requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0;
150 
151         if (m_pipeline->IsSingleTaskPhaseSupported())
152         {
153             commandBufferSize *= m_pipeline->GetPassNum();
154         }
155 
156         // 4K align since allocation is in chunks of 4K bytes.
157         commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE);
158 
159         return MOS_STATUS_SUCCESS;
160     }
161 
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)162     MOS_STATUS HucLaUpdatePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
163     {
164         ENCODE_FUNC_CALL();
165 
166         ENCODE_CHK_NULL_RETURN(mfxStatus);
167         ENCODE_CHK_NULL_RETURN(statusReport);
168         ENCODE_CHK_NULL_RETURN(m_basicFeature);
169 
170         ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::Completed(mfxStatus, rcsStatus, statusReport));
171 
172         EncodeStatusMfx *       encodeStatusMfx  = (EncodeStatusMfx *)mfxStatus;
173         EncodeStatusReportData *statusReportData = (EncodeStatusReportData *)statusReport;
174 
175         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, GetLplaStatusReport, encodeStatusMfx, statusReportData);
176         return MOS_STATUS_SUCCESS;
177     }
178 
DumpOutput()179     MOS_STATUS HucLaUpdatePkt::DumpOutput()
180     {
181         ENCODE_FUNC_CALL();
182 
183 #if USE_CODECHAL_DEBUG_TOOL
184         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, DumpLaResource, m_pipeline, false);
185 #endif
186 
187         return MOS_STATUS_SUCCESS;
188     }
189 
190 #if USE_CODECHAL_DEBUG_TOOL
DumpInput()191     MOS_STATUS HucLaUpdatePkt::DumpInput()
192     {
193         ENCODE_FUNC_CALL();
194 
195         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, DumpLaResource, m_pipeline, true);
196 
197         return MOS_STATUS_SUCCESS;
198     }
199 #endif
200 
ReadLPLAData(MOS_COMMAND_BUFFER * commandBuffer)201     MOS_STATUS HucLaUpdatePkt::ReadLPLAData(MOS_COMMAND_BUFFER* commandBuffer)
202     {
203         ENCODE_FUNC_CALL();
204 
205         PMOS_RESOURCE osResource = nullptr;
206         uint32_t      offset     = 0;
207 
208         m_statusReport->GetAddress(statusReportLpla, osResource, offset);
209 
210         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, ReadLPLAData, commandBuffer, osResource, offset);
211 
212         return MOS_STATUS_SUCCESS;
213     }
214 
MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,HucLaUpdatePkt)215     MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, HucLaUpdatePkt)
216     {
217         params.kernelDescriptor = VDBOX_HUC_LA_ANALYSIS_KERNEL_DESCRIPTOR;
218 
219         return MOS_STATUS_SUCCESS;
220     }
221 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,HucLaUpdatePkt)222     MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, HucLaUpdatePkt)
223     {
224         params.function = LA_UPDATE;
225         RUN_FEATURE_INTERFACE_RETURN(VdencLplaAnalysis, HevcFeatureIDs::vdencLplaAnalysisFeature, SetLaUpdateDmemParameters,
226             params, m_pipeline->m_currRecycledBufIdx, m_pipeline->GetCurrentPass(), m_pipeline->GetPassNum());
227 
228         auto laAnalysisFeature = dynamic_cast<VdencLplaAnalysis *>(m_featureManager->GetFeature(HevcFeatureIDs::vdencLplaAnalysisFeature));
229         if (laAnalysisFeature && laAnalysisFeature->IsLastPicInStream())
230         {
231             m_pipeline->m_currRecycledBufIdx =
232                 (m_pipeline->m_currRecycledBufIdx + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
233         }
234         return MOS_STATUS_SUCCESS;
235     }
236 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,HucLaUpdatePkt)237     MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, HucLaUpdatePkt)
238     {
239         params.function = LA_UPDATE;
240         return MOS_STATUS_SUCCESS;
241     }
242 
243 }  // namespace encode
244