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