• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_post_process_flare_node.h"
17 
18 #include <base/containers/unique_ptr.h>
19 #include <base/math/matrix_util.h>
20 #include <core/log.h>
21 #include <core/property/property_handle_util.h>
22 #include <core/property_tools/property_api_impl.inl>
23 #include <render/device/intf_gpu_resource_manager.h>
24 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
25 #include <render/nodecontext/intf_node_context_pso_manager.h>
26 #include <render/nodecontext/intf_render_command_list.h>
27 #include <render/nodecontext/intf_render_node_context_manager.h>
28 #include <render/nodecontext/intf_render_node_parser_util.h>
29 #include <render/nodecontext/intf_render_node_util.h>
30 #include <render/property/property_types.h>
31 
32 #include "default_engine_constants.h"
33 #include "postprocesses/render_post_process_flare.h"
34 #include "util/log.h"
35 
36 using namespace BASE_NS;
37 using namespace CORE_NS;
38 using namespace RENDER_NS;
39 
40 CORE_BEGIN_NAMESPACE()
41 DATA_TYPE_METADATA(RenderPostProcessFlareNode::NodeInputs, MEMBER_PROPERTY(input, "input", 0))
42 DATA_TYPE_METADATA(RenderPostProcessFlareNode::NodeOutputs, MEMBER_PROPERTY(output, "output", 0))
43 CORE_END_NAMESPACE()
44 
45 RENDER_BEGIN_NAMESPACE()
46 namespace {
47 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
48 
49 constexpr string_view SHADER_NAME { "rendershaders://shader/fullscreen_flare.shader" };
50 
GetImageRenderArea(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle handle)51 RenderPassDesc::RenderArea GetImageRenderArea(
52     const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle handle)
53 {
54     const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(handle);
55     return { 0U, 0U, desc.width, desc.height };
56 }
57 } // namespace
58 
RenderPostProcessFlareNode()59 RenderPostProcessFlareNode::RenderPostProcessFlareNode()
60     : inputProperties_(
61           &nodeInputsData, array_view(PropertyType::DataType<RenderPostProcessFlareNode::NodeInputs>::properties)),
62       outputProperties_(
63           &nodeOutputsData, array_view(PropertyType::DataType<RenderPostProcessFlareNode::NodeOutputs>::properties))
64 
65 {}
66 
GetRenderInputProperties()67 IPropertyHandle* RenderPostProcessFlareNode::GetRenderInputProperties()
68 {
69     return inputProperties_.GetData();
70 }
71 
GetRenderOutputProperties()72 IPropertyHandle* RenderPostProcessFlareNode::GetRenderOutputProperties()
73 {
74     return outputProperties_.GetData();
75 }
76 
GetRenderDescriptorCounts() const77 DescriptorCounts RenderPostProcessFlareNode::GetRenderDescriptorCounts() const
78 {
79     return descriptorCounts_;
80 }
81 
SetRenderAreaRequest(const RenderAreaRequest & renderAreaRequest)82 void RenderPostProcessFlareNode::SetRenderAreaRequest(const RenderAreaRequest& renderAreaRequest)
83 {
84     useRequestedRenderArea_ = true;
85     renderAreaRequest_ = renderAreaRequest;
86 }
87 
Init(const IRenderPostProcess::Ptr & postProcess,IRenderNodeContextManager & renderNodeContextMgr)88 void RenderPostProcessFlareNode::Init(
89     const IRenderPostProcess::Ptr& postProcess, IRenderNodeContextManager& renderNodeContextMgr)
90 {
91     // clear
92     pipelineData_ = {};
93 
94     renderNodeContextMgr_ = &renderNodeContextMgr;
95     postProcess_ = postProcess;
96 
97     // default inputs
98     IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
99     defaultInput_.handle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
100     defaultInput_.samplerHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
101 
102     // load shaders
103     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
104     pipelineData_.gsd = shaderMgr.GetGraphicsShaderDataByShaderHandle(shaderMgr.GetShaderHandle(SHADER_NAME));
105 
106     // create psos
107     INodeContextPsoManager& psoMgr = renderNodeContextMgr_->GetPsoManager();
108     pipelineData_.pso = psoMgr.GetGraphicsPsoHandle(pipelineData_.gsd, {}, DYNAMIC_STATES);
109 
110     // get needed descriptor set counts
111     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
112     descriptorCounts_ = renderNodeUtil.GetDescriptorCounts(pipelineData_.gsd.pipelineLayoutData);
113 
114     valid_ = true;
115 }
116 
PreExecute()117 void RenderPostProcessFlareNode::PreExecute()
118 {
119     if (valid_ && postProcess_) {
120         const array_view<const uint8_t> propertyView = postProcess_->GetData();
121         // this node is directly dependant
122         PLUGIN_ASSERT(propertyView.size_bytes() == sizeof(RenderPostProcessFlareNode::EffectProperties));
123         if (propertyView.size_bytes() == sizeof(RenderPostProcessFlareNode::EffectProperties)) {
124             effectProperties_ = (const RenderPostProcessFlareNode::EffectProperties&)(*propertyView.data());
125         }
126     } else {
127         effectProperties_.enabled = false;
128     }
129 
130     if (effectProperties_.enabled) {
131         // check input and output
132         EvaluateOutput();
133     }
134 }
135 
GetExecuteFlags() const136 IRenderNode::ExecuteFlags RenderPostProcessFlareNode::GetExecuteFlags() const
137 {
138     if (effectProperties_.enabled) {
139         return 0;
140     } else {
141         return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
142     }
143 }
144 
Execute(IRenderCommandList & cmdList)145 void RenderPostProcessFlareNode::Execute(IRenderCommandList& cmdList)
146 {
147     CORE_ASSERT(effectProperties_.enabled);
148 
149     EvaluateOutput();
150 
151     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderLensFlare", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
152 
153     BindableImage currOutput = nodeOutputsData.output;
154     if (!RenderHandleUtil::IsValid(currOutput.handle)) {
155         return;
156     }
157     // update the output
158     nodeOutputsData.output = currOutput;
159 
160     const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
161     const RenderPassDesc::RenderArea renderArea =
162         useRequestedRenderArea_ ? renderAreaRequest_.area : GetImageRenderArea(gpuResourceMgr, currOutput.handle);
163     if ((renderArea.extentWidth == 0) || (renderArea.extentHeight == 0)) {
164         return;
165     }
166 
167     // render
168     RenderPass renderPass;
169     renderPass.renderPassDesc.attachmentCount = 1;
170     renderPass.renderPassDesc.renderArea = renderArea;
171     renderPass.renderPassDesc.subpassCount = 1;
172     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_LOAD;
173     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
174     renderPass.renderPassDesc.attachmentHandles[0] = { currOutput.handle };
175     renderPass.subpassStartIndex = 0;
176     auto& subpass = renderPass.subpassDesc;
177     subpass.colorAttachmentCount = 1;
178     subpass.colorAttachmentIndices[0] = 0;
179 
180     cmdList.BeginRenderPass(renderPass.renderPassDesc, 0U, renderPass.subpassDesc);
181 
182     // dynamic state
183     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
184     cmdList.SetDynamicStateViewport(renderNodeUtil.CreateDefaultViewport(renderPass));
185     cmdList.SetDynamicStateScissor(renderNodeUtil.CreateDefaultScissor(renderPass));
186 
187     // bind pso
188     cmdList.BindPipeline(pipelineData_.pso);
189 
190     if (pipelineData_.gsd.pipelineLayoutData.pushConstant.byteSize > 0U) {
191         const PushConstantStruct pc = GetPushDataStruct(renderArea.extentWidth, renderArea.extentHeight);
192         cmdList.PushConstantData(pipelineData_.gsd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
193     }
194 
195     // draw
196     cmdList.Draw(3U, 1U, 0U, 0U);
197 
198     cmdList.EndRenderPass();
199 }
200 
GetPushDataStruct(const uint32_t width,const uint32_t height) const201 RenderPostProcessFlareNode::PushConstantStruct RenderPostProcessFlareNode::GetPushDataStruct(
202     const uint32_t width, const uint32_t height) const
203 {
204     const Math::Vec3 flarePos = effectProperties_.flarePos;
205     float intensity = effectProperties_.intensity;
206     // NOTE: the shader is currently still run even though the intensity is zero
207     // signed culling for z
208     if ((flarePos.x < 0.0f) || (flarePos.x > 1.0f) || (flarePos.y < 0.0f) || (flarePos.y > 1.0f) ||
209         (flarePos.z < 0.0f)) {
210         intensity = 0.0f;
211     }
212 
213     const float time = renderNodeContextMgr_->GetRenderNodeGraphData().renderingConfiguration.renderTimings.z;
214     PushConstantStruct pcV { { time, flarePos.x, flarePos.y, flarePos.z },
215         { static_cast<float>(width), static_cast<float>(height), intensity, 0.0f } };
216 
217     return pcV;
218 }
219 
EvaluateOutput()220 void RenderPostProcessFlareNode::EvaluateOutput()
221 {
222     if (RenderHandleUtil::IsValid(nodeInputsData.input.handle)) {
223         nodeOutputsData.output = nodeInputsData.input;
224     }
225 }
226 RENDER_END_NAMESPACE()
227