1 /*
2 * Copyright (c) 2018, 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)37 HVSDenoise::HVSDenoise(const PRENDERHAL_INTERFACE vphalRenderer, void *kernelBinary, int32_t kerneBinarySize):
38     VPCmRenderer("HVSDenoise"),
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     CmDevice *dev = CmContext::GetCmContext().GetCmDevice();
50     int result = dev->CreateKernel(m_cmProgram, _NAME(getDenoiseFactor), m_cmKernel);
51     if (result != CM_SUCCESS)
52     {
53         VPHAL_RENDER_ASSERTMESSAGE("[%s]: CM CreateKernel error %d\n", mName.c_str(), result);
54     }
55 }
56 
~HVSDenoise()57 HVSDenoise::~HVSDenoise()
58 {
59     CmDevice *dev = CmContext::GetCmContext().GetCmDevice();
60     if (m_cmKernel)
61     {
62         dev->DestroyKernel(m_cmKernel);
63     }
64 
65     if (m_cmProgram)
66     {
67         dev->DestroyProgram(m_cmProgram);
68     }
69 
70     m_payload           = nullptr;
71 }
72 
AttachPayload(void * payload)73 void HVSDenoise::AttachPayload(void *payload)
74 {
75     m_payload = static_cast<HVSDenoisePayload *>(payload);
76 }
77 
GetKernelToRun(std::string & name)78 CmKernel* HVSDenoise::GetKernelToRun(std::string &name)
79 {
80     name = "HVSDenoise";
81     return m_cmKernel;
82 }
83 
GetThreadSpaceDimension(int & tsWidth,int & tsHeight,int & tsColor)84 void HVSDenoise::GetThreadSpaceDimension(int &tsWidth, int &tsHeight, int &tsColor)
85 {
86     tsWidth = tsHeight = tsColor = 1;
87 }
88 
PrepareKernel(CmKernel * kernel)89 void HVSDenoise::PrepareKernel(CmKernel *kernel)
90 {
91     uint16_t value_QP = 0;
92 
93     if (m_payload->QP <= 18)
94     {
95         value_QP = 0;
96     }
97     else if (m_payload->QP <= 22)
98     {
99         value_QP = 1;
100     }
101     else if (m_payload->QP <= 27)
102     {
103         value_QP = 2;
104     }
105     else if (m_payload->QP <= 32)
106     {
107         value_QP = 3;
108     }
109     else if (m_payload->QP <= 37)
110     {
111         value_QP = 4;
112     }
113 
114     kernel->SetKernelArg(0, sizeof(SurfaceIndex), m_payload->denoiseParam->GetCmSurfaceIndex());
115     kernel->SetKernelArg(1, sizeof(uint16_t),     &value_QP);
116     kernel->SetKernelArg(2, sizeof(uint16_t),     &m_payload->Strength);
117 }
118 
Dump()119 void HVSDenoise::Dump()
120 {
121     int width = 0, height = 0, depth = 0;
122     m_payload->denoiseParam->DumpSurfaceToFile(OutputDumpDirectory + std::to_string(width) + "x" + std::to_string(height) + ".dat");
123 }
124 
VphalHVSDenoiser(PRENDERHAL_INTERFACE renderHal)125 VphalHVSDenoiser::VphalHVSDenoiser(PRENDERHAL_INTERFACE renderHal) :
126     m_eventManager(nullptr),
127     m_renderHal(renderHal),
128     m_hvsDenoiseCmSurface(nullptr),
129     m_hvsDenoiseParam(nullptr),
130     m_hvsDenoise(nullptr),
131     m_savedQP(0),
132     m_savedStrength(0),
133     m_initHVSDenoise(false)
134 {
135     m_eventManager = MOS_New(EventManager, "HVSEventManager");
136     VPHAL_RENDER_NORMALMESSAGE("Constructor!");
137 }
138 
~VphalHVSDenoiser()139 VphalHVSDenoiser::~VphalHVSDenoiser()
140 {
141     FreeResources();
142     MOS_Delete(m_hvsDenoise);
143     MOS_Delete(m_eventManager);
144     if (m_initHVSDenoise)
145     {
146         CmContext::GetCmContext().DecRefCount();
147         m_initHVSDenoise = false;
148     }
149 
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 
AllocateResouces(const uint32_t width,const uint32_t height)159 void VphalHVSDenoiser::AllocateResouces(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);
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         CmContext::sOsContext = m_renderHal->pOsInterface->pOsContext;
198         CmContext::GetCmContext().AddRefCount();
199 
200         m_hvsDenoise = MOS_New(HVSDenoise, m_renderHal, m_kernelBinary, m_kernelBinarySize);
201         AllocateResouces(m_denoiseBufferInBytes, 1);
202 
203         m_initHVSDenoise = true;
204 
205         VPHAL_RENDER_NORMALMESSAGE("[0x%x] Init HVSDenoise[0x%x] and Allocate necessary resource!", this, m_hvsDenoise);
206     }
207 
208     if (qp != m_savedQP || strength != m_savedStrength)
209     {
210         HVSDenoise::HVSDenoisePayload denoisePayload    = {0};
211         denoisePayload.denoiseParam                     = m_hvsDenoiseCmSurface;
212         denoisePayload.Strength                         = strength;
213         denoisePayload.QP                               = qp;
214 
215         CmContext::GetCmContext().ConnectEventListener(m_eventManager);
216         m_hvsDenoise->Render(&denoisePayload);
217         CmContext::GetCmContext().FlushBatchTask(false);
218         CmContext::GetCmContext().ConnectEventListener(nullptr);
219 
220         m_hvsDenoiseCmSurface->GetCmSurface()->ReadSurface((uint8_t *)m_hvsDenoiseParam, nullptr, m_denoiseBufferInBytes);
221 
222         m_savedQP           = qp;
223         m_savedStrength     = strength;
224 
225         VPHAL_RENDER_NORMALMESSAGE("Render qp %d, strength %d!", qp, strength);
226     }
227 
228     return eStatus;
229 }
230 
231 #endif  //!EMUL
232