1 /*
2 * Copyright (c) 2018-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 vphal_render_vebox_denoise.cpp
24 //! \brief Handles rendering operations for vebox denoise
25 //! \details Handles rendering operations for vebox denoise
26 //!
27 #include "vphal_render_vebox_denoise.h"
28 #include <cstring>
29 #include <new>
30 #include <string>
31 #include <vector>
32
33 #if !EMUL
34 const std::string DumpRoot("C:\\temp\\HVS\\");
35 const std::string OutputDumpDirectory(DumpRoot + "Output\\");
36
HVSDenoise(const PRENDERHAL_INTERFACE vphalRenderer,void * kernelBinary,int32_t kerneBinarySize,CmContext * cmContext)37 HVSDenoise::HVSDenoise(const PRENDERHAL_INTERFACE vphalRenderer, void *kernelBinary, int32_t kerneBinarySize, CmContext *cmContext) :
38 VPCmRenderer("HVSDenoise", cmContext),
39 m_cmProgram(nullptr),
40 m_cmKernel(nullptr),
41 m_payload(nullptr)
42 {
43 m_cmProgram = LoadProgram(kernelBinary, kerneBinarySize);
44 if (!m_cmProgram)
45 {
46 VPHAL_RENDER_ASSERTMESSAGE("CM LoadProgram error\n");
47 }
48
49 VPHAL_RENDER_CHK_NULL_NO_STATUS_RETURN(cmContext);
50 CmDevice *dev = cmContext->GetCmDevice();
51 int result = dev->CreateKernel(m_cmProgram, _NAME(getDenoiseFactor), m_cmKernel);
52 if (result != CM_SUCCESS)
53 {
54 VPHAL_RENDER_ASSERTMESSAGE("[%s]: CM CreateKernel error %d\n", mName.c_str(), result);
55 }
56 }
57
~HVSDenoise()58 HVSDenoise::~HVSDenoise()
59 {
60 VPHAL_RENDER_CHK_NULL_NO_STATUS_RETURN(m_cmContext);
61 CmDevice *dev = m_cmContext->GetCmDevice();
62 if (m_cmKernel)
63 {
64 dev->DestroyKernel(m_cmKernel);
65 }
66
67 if (m_cmProgram)
68 {
69 dev->DestroyProgram(m_cmProgram);
70 }
71
72 m_payload = nullptr;
73 }
74
AttachPayload(void * payload)75 void HVSDenoise::AttachPayload(void *payload)
76 {
77 m_payload = static_cast<HVSDenoisePayload *>(payload);
78 }
79
GetKernelToRun(std::string & name)80 CmKernel* HVSDenoise::GetKernelToRun(std::string &name)
81 {
82 name = "HVSDenoise";
83 return m_cmKernel;
84 }
85
GetThreadSpaceDimension(int & tsWidth,int & tsHeight,int & tsColor)86 void HVSDenoise::GetThreadSpaceDimension(int &tsWidth, int &tsHeight, int &tsColor)
87 {
88 tsWidth = tsHeight = tsColor = 1;
89 }
90
PrepareKernel(CmKernel * kernel)91 void HVSDenoise::PrepareKernel(CmKernel *kernel)
92 {
93 uint16_t value_QP = 0;
94
95 if (m_payload->QP <= 18)
96 {
97 value_QP = 0;
98 }
99 else if (m_payload->QP <= 22)
100 {
101 value_QP = 1;
102 }
103 else if (m_payload->QP <= 27)
104 {
105 value_QP = 2;
106 }
107 else if (m_payload->QP <= 32)
108 {
109 value_QP = 3;
110 }
111 else if (m_payload->QP <= 37)
112 {
113 value_QP = 4;
114 }
115
116 kernel->SetKernelArg(0, sizeof(SurfaceIndex), m_payload->denoiseParam->GetCmSurfaceIndex());
117 kernel->SetKernelArg(1, sizeof(uint16_t), &value_QP);
118 kernel->SetKernelArg(2, sizeof(uint16_t), &m_payload->Strength);
119 }
120
Dump()121 void HVSDenoise::Dump()
122 {
123 int width = 0, height = 0, depth = 0;
124 m_payload->denoiseParam->DumpSurfaceToFile(OutputDumpDirectory + std::to_string(width) + "x" + std::to_string(height) + ".dat");
125 }
126
VphalHVSDenoiser(PRENDERHAL_INTERFACE renderHal)127 VphalHVSDenoiser::VphalHVSDenoiser(PRENDERHAL_INTERFACE renderHal) :
128 m_eventManager(nullptr),
129 m_renderHal(renderHal),
130 m_hvsDenoiseCmSurface(nullptr),
131 m_hvsDenoiseParam(nullptr),
132 m_hvsDenoise(nullptr),
133 m_savedQP(0),
134 m_savedStrength(0),
135 m_initHVSDenoise(false)
136 {
137 VPHAL_RENDER_CHK_NULL_NO_STATUS_RETURN(m_renderHal);
138 VPHAL_RENDER_CHK_NULL_NO_STATUS_RETURN(m_renderHal->pOsInterface);
139 m_cmContext = MOS_New(CmContext, m_renderHal->pOsInterface);
140 m_eventManager = MOS_New(EventManager, "HVSEventManager", m_cmContext);
141 VPHAL_RENDER_NORMALMESSAGE("Constructor!");
142 }
143
~VphalHVSDenoiser()144 VphalHVSDenoiser::~VphalHVSDenoiser()
145 {
146 FreeResources();
147 MOS_Delete(m_hvsDenoise);
148 MOS_Delete(m_eventManager);
149 MOS_Delete(m_cmContext);
150 VPHAL_RENDER_NORMALMESSAGE("Destructor!");
151 }
152
InitKernelParams(void * kernelBinary,const int32_t kerneBinarySize)153 void VphalHVSDenoiser::InitKernelParams(void *kernelBinary, const int32_t kerneBinarySize)
154 {
155 m_kernelBinary = kernelBinary;
156 m_kernelBinarySize = kerneBinarySize;
157 }
158
AllocateResources(const uint32_t width,const uint32_t height)159 void VphalHVSDenoiser::AllocateResources(const uint32_t width, const uint32_t height)
160 {
161 uint32_t size = width * height;
162
163 m_hvsDenoiseCmSurface = MOS_New(VpCmSurfaceHolder<CmBuffer>, size, 1, 1, GMM_FORMAT_A8_UNORM_TYPE, m_cmContext);
164 if (nullptr == m_hvsDenoiseCmSurface)
165 {
166 VPHAL_RENDER_NORMALMESSAGE("[0x%x] Failed to Allocate m_hvsDenoiseCmSurface(gpu memory) GMM_FORMAT_A8_UNORM_TYPE %d*%d!", this, width, height);
167 }
168 m_hvsDenoiseParam = MOS_NewArray(uint8_t, size);
169 if (nullptr == m_hvsDenoiseParam)
170 {
171 VPHAL_RENDER_NORMALMESSAGE("[0x%x] Failed to Allocate m_hvsDenoiseParam(cpu memory) uint8_t %d*%d!", this, width, height);
172 }
173 }
174
FreeResources()175 void VphalHVSDenoiser::FreeResources()
176 {
177 MOS_DeleteArray(m_hvsDenoiseParam);
178 MOS_Delete(m_hvsDenoiseCmSurface);
179 }
180
Render(const PVPHAL_SURFACE pSrcSuface)181 MOS_STATUS VphalHVSDenoiser::Render(const PVPHAL_SURFACE pSrcSuface)
182 {
183 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
184 uint16_t qp = 18;
185 uint16_t strength = 10;
186
187 VPHAL_RENDER_CHK_NULL_RETURN(pSrcSuface);
188 VPHAL_RENDER_CHK_NULL_RETURN(pSrcSuface->pDenoiseParams);
189
190 qp = pSrcSuface->pDenoiseParams->HVSDenoise.QP;
191 strength = pSrcSuface->pDenoiseParams->HVSDenoise.Strength;
192
193 VPHAL_RENDER_NORMALMESSAGE("qp: %d, strength: %d", qp, strength);
194
195 if (nullptr == m_hvsDenoise)
196 {
197 VPHAL_RENDER_CHK_NULL_RETURN(m_cmContext);
198
199 m_hvsDenoise = MOS_New(HVSDenoise, m_renderHal, m_kernelBinary, m_kernelBinarySize, m_cmContext);
200 AllocateResources(m_denoiseBufferInBytes, 1);
201
202 VPHAL_RENDER_NORMALMESSAGE("[0x%x] Init HVSDenoise[0x%x] and Allocate necessary resource!", this, m_hvsDenoise);
203 }
204
205 if (qp != m_savedQP || strength != m_savedStrength)
206 {
207 HVSDenoise::HVSDenoisePayload denoisePayload = {0};
208 denoisePayload.denoiseParam = m_hvsDenoiseCmSurface;
209 denoisePayload.Strength = strength;
210 denoisePayload.QP = qp;
211
212 VPHAL_RENDER_CHK_NULL_RETURN(m_cmContext);
213 m_cmContext->ConnectEventListener(m_eventManager);
214 m_hvsDenoise->Render(&denoisePayload);
215 m_cmContext->FlushBatchTask(false);
216 m_cmContext->ConnectEventListener(nullptr);
217
218 m_hvsDenoiseCmSurface->GetCmSurface()->ReadSurface((uint8_t *)m_hvsDenoiseParam, nullptr, m_denoiseBufferInBytes);
219
220 m_savedQP = qp;
221 m_savedStrength = strength;
222
223 VPHAL_RENDER_NORMALMESSAGE("Render qp %d, strength %d!", qp, strength);
224 }
225
226 return eStatus;
227 }
228
229 #endif //!EMUL
230