• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
34 using namespace BASE_NS;
35 using namespace CORE_NS;
36 using namespace RENDER_NS;
37 
38 CORE_BEGIN_NAMESPACE()
39 DATA_TYPE_METADATA(RenderPostProcessFlareNode::NodeInputs, MEMBER_PROPERTY(input, "input", 0))
40 DATA_TYPE_METADATA(RenderPostProcessFlareNode::NodeOutputs, MEMBER_PROPERTY(output, "output", 0))
41 CORE_END_NAMESPACE()
42 
43 RENDER_BEGIN_NAMESPACE()
44 namespace {
45 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
46 
47 constexpr string_view SHADER_NAME { "rendershaders://shader/fullscreen_flare.shader" };
48 
GetImageRenderArea(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle handle)49 RenderPassDesc::RenderArea GetImageRenderArea(
50     const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle handle)
51 {
52     const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(handle);
53     return { 0U, 0U, desc.width, desc.height };
54 }
55 } // namespace
56 
RenderPostProcessFlareNode()57 RenderPostProcessFlareNode::RenderPostProcessFlareNode()
58     : inputProperties_(
59           &nodeInputsData_, array_view(PropertyType::DataType<RenderPostProcessFlareNode::NodeInputs>::properties)),
60       outputProperties_(
61           &nodeOutputsData_, array_view(PropertyType::DataType<RenderPostProcessFlareNode::NodeOutputs>::properties))
62 
63 {}
64 
GetRenderInputProperties()65 IPropertyHandle* RenderPostProcessFlareNode::GetRenderInputProperties()
66 {
67     return inputProperties_.GetData();
68 }
69 
GetRenderOutputProperties()70 IPropertyHandle* RenderPostProcessFlareNode::GetRenderOutputProperties()
71 {
72     return outputProperties_.GetData();
73 }
74 
GetRenderDescriptorCounts() const75 DescriptorCounts RenderPostProcessFlareNode::GetRenderDescriptorCounts() const
76 {
77     return descriptorCounts_;
78 }
79 
SetRenderAreaRequest(const RenderAreaRequest & renderAreaRequest)80 void RenderPostProcessFlareNode::SetRenderAreaRequest(const RenderAreaRequest& renderAreaRequest)
81 {
82     useRequestedRenderArea_ = true;
83     renderAreaRequest_ = renderAreaRequest;
84 }
85 
Init(const IRenderPostProcess::Ptr & postProcess,IRenderNodeContextManager & renderNodeContextMgr)86 void RenderPostProcessFlareNode::Init(
87     const IRenderPostProcess::Ptr& postProcess, IRenderNodeContextManager& renderNodeContextMgr)
88 {
89     // clear
90     pipelineData_ = {};
91 
92     renderNodeContextMgr_ = &renderNodeContextMgr;
93     postProcess_ = postProcess;
94 
95     // default inputs
96     IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
97     defaultInput_.handle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
98     defaultInput_.samplerHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
99 
100     // load shaders
101     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
102     pipelineData_.gsd = shaderMgr.GetGraphicsShaderDataByShaderHandle(shaderMgr.GetShaderHandle(SHADER_NAME));
103 
104     // create psos
105     INodeContextPsoManager& psoMgr = renderNodeContextMgr_->GetPsoManager();
106     pipelineData_.pso = psoMgr.GetGraphicsPsoHandle(pipelineData_.gsd, {}, DYNAMIC_STATES);
107 
108     // get needed descriptor set counts
109     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
110     descriptorCounts_ = renderNodeUtil.GetDescriptorCounts(pipelineData_.gsd.pipelineLayoutData);
111 
112     valid_ = true;
113 }
114 
PreExecute()115 void RenderPostProcessFlareNode::PreExecute()
116 {
117     if (valid_ && postProcess_) {
118         if (const auto* props = postProcess_->GetProperties(); props) {
119             enabled_ = CORE_NS::GetPropertyValue<bool>(props, "enabled");
120         }
121     } else {
122         enabled_ = false;
123     }
124 
125     if (enabled_) {
126         // check input and output
127         EvaluateOutput();
128     }
129 }
130 
GetExecuteFlags() const131 IRenderNode::ExecuteFlags RenderPostProcessFlareNode::GetExecuteFlags() const
132 {
133     if (enabled_) {
134         return 0;
135     } else {
136         return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
137     }
138 }
139 
Execute(IRenderCommandList & cmdList)140 void RenderPostProcessFlareNode::Execute(IRenderCommandList& cmdList)
141 {
142     CORE_ASSERT(enabled_);
143 
144     EvaluateOutput();
145 
146     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderLensFlare", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
147 
148     BindableImage currOutput = nodeOutputsData_.output;
149     if (!RenderHandleUtil::IsValid(currOutput.handle)) {
150         return;
151     }
152     // update the output
153     nodeOutputsData_.output = currOutput;
154 
155     const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
156     const RenderPassDesc::RenderArea renderArea =
157         useRequestedRenderArea_ ? renderAreaRequest_.area : GetImageRenderArea(gpuResourceMgr, currOutput.handle);
158     if ((renderArea.extentWidth == 0) || (renderArea.extentHeight == 0)) {
159         return;
160     }
161 
162     // render
163     RenderPass renderPass;
164     renderPass.renderPassDesc.attachmentCount = 1;
165     renderPass.renderPassDesc.renderArea = renderArea;
166     renderPass.renderPassDesc.subpassCount = 1;
167     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_LOAD;
168     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
169     renderPass.renderPassDesc.attachmentHandles[0] = { currOutput.handle };
170     renderPass.subpassStartIndex = 0;
171     auto& subpass = renderPass.subpassDesc;
172     subpass.colorAttachmentCount = 1;
173     subpass.colorAttachmentIndices[0] = 0;
174 
175     cmdList.BeginRenderPass(renderPass.renderPassDesc, 0U, renderPass.subpassDesc);
176 
177     // dynamic state
178     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
179     cmdList.SetDynamicStateViewport(renderNodeUtil.CreateDefaultViewport(renderPass));
180     cmdList.SetDynamicStateScissor(renderNodeUtil.CreateDefaultScissor(renderPass));
181 
182     // bind pso
183     cmdList.BindPipeline(pipelineData_.pso);
184 
185     if (pipelineData_.gsd.pipelineLayoutData.pushConstant.byteSize > 0U) {
186         const PushConstantStruct pc = GetPushDataStruct(renderArea.extentWidth, renderArea.extentHeight);
187         cmdList.PushConstantData(pipelineData_.gsd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
188     }
189 
190     // draw
191     cmdList.Draw(3U, 1U, 0U, 0U);
192 
193     cmdList.EndRenderPass();
194 }
195 
GetPushDataStruct(const uint32_t width,const uint32_t height) const196 RenderPostProcessFlareNode::PushConstantStruct RenderPostProcessFlareNode::GetPushDataStruct(
197     const uint32_t width, const uint32_t height) const
198 {
199     Math::Vec3 flarePos { 0.0f, 0.0f, 0.0f };
200     float intensity = 1.0f;
201     if (postProcess_) {
202         if (const auto* props = postProcess_->GetProperties(); props) {
203             flarePos = CORE_NS::GetPropertyValue<Math::Vec3>(props, "flarePos");
204             intensity = CORE_NS::GetPropertyValue<float>(props, "intensity");
205         }
206     }
207 
208     // NOTE: the shader is currently still run even though the intensity is zero
209     // signed culling for z
210     if ((flarePos.x < 0.0f) || (flarePos.x > 1.0f) || (flarePos.y < 0.0f) || (flarePos.y > 1.0f) ||
211         (flarePos.z < 0.0f)) {
212         intensity = 0.0f;
213     }
214 
215     const float time = renderNodeContextMgr_->GetRenderNodeGraphData().renderingConfiguration.renderTimings.z;
216     PushConstantStruct pcV { { time, flarePos.x, flarePos.y, flarePos.z },
217         { static_cast<float>(width), static_cast<float>(height), intensity, 0.0f } };
218 
219     return pcV;
220 }
221 
EvaluateOutput()222 void RenderPostProcessFlareNode::EvaluateOutput()
223 {
224     if (RenderHandleUtil::IsValid(nodeInputsData_.input.handle)) {
225         nodeOutputsData_.output = nodeInputsData_.input;
226     }
227 }
228 RENDER_END_NAMESPACE()
229