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