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_node_render_post_processes_generic.h"
17
18 #include <base/math/mathf.h>
19 #include <base/util/uid_util.h>
20 #include <core/plugin/intf_class_factory.h>
21 #include <core/property/property_handle_util.h>
22 #include <render/datastore/intf_render_data_store_manager.h>
23 #include <render/device/intf_gpu_resource_manager.h>
24 #include <render/device/pipeline_layout_desc.h>
25 #include <render/device/pipeline_state_desc.h>
26 #include <render/intf_render_context.h>
27 #include <render/namespace.h>
28 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
29 #include <render/nodecontext/intf_node_context_pso_manager.h>
30 #include <render/nodecontext/intf_render_command_list.h>
31 #include <render/nodecontext/intf_render_node_context_manager.h>
32 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
33 #include <render/nodecontext/intf_render_node_parser_util.h>
34 #include <render/nodecontext/intf_render_node_util.h>
35 #include <render/nodecontext/intf_render_post_process.h>
36 #include <render/property/property_types.h>
37
38 #include "datastore/render_data_store_render_post_processes.h"
39 #include "default_engine_constants.h"
40 #include "device/gpu_resource_handle_util.h"
41 #include "util/log.h"
42
43 using namespace BASE_NS;
44 using namespace CORE_NS;
45
46 RENDER_BEGIN_NAMESPACE()
47 namespace {
48 constexpr string_view INPUT = "input";
49 constexpr string_view OUTPUT = "output";
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
InitNode(IRenderNodeContextManager & renderNodeContextMgr)59 void RenderNodeRenderPostProcessesGeneric::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
60 {
61 renderNodeContextMgr_ = &renderNodeContextMgr;
62
63 valid_ = false;
64 allPostProcesses_ = {};
65
66 ParseRenderNodeInputs();
67 UpdateImageData();
68 RegisterOutputs();
69 }
70
PreExecuteFrame()71 void RenderNodeRenderPostProcessesGeneric::PreExecuteFrame()
72 {
73 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
74 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
75 UpdateImageData();
76 ProcessPostProcessConfiguration();
77 RegisterOutputs();
78
79 // possible inits called here
80 if (allPostProcesses_.newPostProcesses) {
81 allPostProcesses_.newPostProcesses = false;
82
83 vector<DescriptorCounts> descriptorCounts;
84 descriptorCounts.reserve(allPostProcesses_.postProcessNodeInstances.size());
85
86 for (const auto& ppNodeRef : allPostProcesses_.postProcessNodeInstances) {
87 if (ppNodeRef.ppNode) {
88 const IRenderPostProcess::Ptr* rpp = nullptr;
89 for (const auto& ppRef : allPostProcesses_.pipeline.postProcesses) {
90 // match the id for client-side properties
91 if (ppNodeRef.id == ppRef.id) {
92 rpp = &ppRef.postProcess;
93 }
94 }
95 if (rpp) {
96 ppNodeRef.ppNode->Init(*rpp, *renderNodeContextMgr_);
97 descriptorCounts.push_back(ppNodeRef.ppNode->GetRenderDescriptorCounts());
98 }
99 }
100 }
101 // add copy descriptor sets
102 descriptorCounts.push_back(renderCopy_.GetRenderDescriptorCounts());
103
104 // reset descriptor sets
105 INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
106 dsMgr.ResetAndReserve(descriptorCounts);
107
108 renderCopy_.Init(*renderNodeContextMgr_);
109 } else if (copyInitNeeded_) {
110 vector<DescriptorCounts> descriptorCounts;
111
112 // add copy descriptor sets
113 descriptorCounts.push_back(renderCopy_.GetRenderDescriptorCounts());
114
115 // reset descriptor sets
116 INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
117 dsMgr.ResetAndReserve(descriptorCounts);
118
119 renderCopy_.Init(*renderNodeContextMgr_);
120 }
121 copyInitNeeded_ = false;
122
123 RenderPassDesc::RenderArea renderArea =
124 GetImageRenderArea(renderNodeContextMgr_->GetGpuResourceManager(), builtInVariables_.output);
125 allPostProcesses_.postProcessCount = 0U;
126 // pre-execute in correct order
127 for (const auto& ppRef : allPostProcesses_.pipeline.postProcesses) {
128 for (auto& ppNodeRef : allPostProcesses_.postProcessNodeInstances) {
129 if (ppNodeRef.ppNode && (ppNodeRef.id == ppRef.id)) {
130 ppNodeRef.ppNode->SetRenderAreaRequest({ renderArea });
131 ppNodeRef.ppNode->PreExecute();
132 allPostProcesses_.postProcessCount++;
133 break;
134 }
135 }
136 }
137 }
138
GetExecuteFlags() const139 IRenderNode::ExecuteFlags RenderNodeRenderPostProcessesGeneric::GetExecuteFlags() const
140 {
141 if (valid_ && (!allPostProcesses_.pipeline.postProcesses.empty())) {
142 return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DEFAULT;
143 } else {
144 return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
145 }
146 }
147
ExecuteFrame(IRenderCommandList & cmdList)148 void RenderNodeRenderPostProcessesGeneric::ExecuteFrame(IRenderCommandList& cmdList)
149 {
150 const RenderHandle output =
151 RenderHandleUtil::IsValid(builtInVariables_.output) ? builtInVariables_.output : builtInVariables_.defOutput;
152 BindableImage biInput;
153 biInput.handle =
154 RenderHandleUtil::IsValid(builtInVariables_.input) ? builtInVariables_.input : builtInVariables_.defInput;
155 BindableImage biOutput;
156 biOutput.handle = output;
157 const auto ppCount = static_cast<uint32_t>(allPostProcesses_.pipeline.postProcesses.size());
158 // execute in correct order
159 for (uint32_t ppIndex = 0; ppIndex < ppCount; ++ppIndex) {
160 const auto& ppRef = allPostProcesses_.pipeline.postProcesses[ppIndex];
161 for (auto& ppNodeRef : allPostProcesses_.postProcessNodeInstances) {
162 if (ppNodeRef.ppNode && (ppNodeRef.id == ppRef.id) && (ppNodeRef.ppNode->GetExecuteFlags() == 0U)) {
163 auto& ppNode = *ppNodeRef.ppNode;
164
165 CORE_NS::SetPropertyValue(ppNode.GetRenderInputProperties(), "input", biInput);
166 // try to force the final target for the final post process
167 // the effect might not accept this and then we need an extra blit in the end
168 if (ppIndex == (allPostProcesses_.postProcessCount - 1U)) {
169 CORE_NS::SetPropertyValue(ppNode.GetRenderOutputProperties(), "output", biOutput);
170 }
171
172 ppNode.Execute(cmdList);
173
174 // take output and route to next input
175 biInput = CORE_NS::GetPropertyValue<BindableImage>(ppNode.GetRenderOutputProperties(), "output");
176 }
177 }
178 }
179
180 if (biInput.handle != biOutput.handle) {
181 IRenderNodeCopyUtil::CopyInfo copyInfo;
182 copyInfo.input = biInput;
183 copyInfo.output = biOutput;
184 renderCopy_.PreExecute();
185 renderCopy_.Execute(cmdList, copyInfo);
186 }
187 }
188
RegisterOutputs()189 void RenderNodeRenderPostProcessesGeneric::RegisterOutputs()
190 {
191 const RenderHandle output = builtInVariables_.output;
192 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
193 RenderHandle registerOutput;
194 if (valid_) {
195 if (RenderHandleUtil::IsValid(output)) {
196 registerOutput = output;
197 }
198 }
199 if (!RenderHandleUtil::IsValid(registerOutput)) {
200 if (((jsonInputs_.defaultOutputImage == DefaultInOutImage::OUTPUT) ||
201 (jsonInputs_.defaultOutputImage == DefaultInOutImage::INPUT_OUTPUT_COPY)) &&
202 RenderHandleUtil::IsValid(output)) {
203 registerOutput = output;
204 } else if ((jsonInputs_.defaultOutputImage == DefaultInOutImage::INPUT) &&
205 RenderHandleUtil::IsValid(builtInVariables_.input)) {
206 registerOutput = builtInVariables_.input;
207 } else {
208 registerOutput = builtInVariables_.defOutput;
209 }
210 }
211 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
212 }
213
ProcessPostProcessConfiguration()214 void RenderNodeRenderPostProcessesGeneric::ProcessPostProcessConfiguration()
215 {
216 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
217 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
218 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
219 if (jsonInputs_.renderDataStore.typeName == RenderDataStoreRenderPostProcesses::TYPE_NAME) {
220 auto* const dataStore = static_cast<const IRenderDataStoreRenderPostProcesses*>(ds);
221 allPostProcesses_.pipeline = dataStore->GetData(jsonInputs_.renderDataStore.configurationName);
222 valid_ = true;
223 }
224 }
225 }
226 // process new instances
227 auto* renderClassFactory = renderNodeContextMgr_->GetRenderContext().GetInterface<IClassFactory>();
228 if (valid_ && renderClassFactory) {
229 auto& pp = allPostProcesses_;
230 for (const auto& ppRef : pp.pipeline.postProcesses) {
231 if (!ppRef.postProcess) {
232 continue;
233 }
234 bool createNew = true;
235 for (const auto& iRef : pp.postProcessNodeInstances) {
236 if (iRef.id == ppRef.id) {
237 createNew = false;
238 break;
239 }
240 }
241 if (createNew) {
242 IRenderPostProcessNode::Ptr rppn = CreateInstance<IRenderPostProcessNode>(
243 *renderClassFactory, ppRef.postProcess->GetRenderPostProcessNodeUid());
244 if (rppn) {
245 pp.postProcessNodeInstances.push_back({ ppRef.id, rppn });
246 pp.newPostProcesses = true; // flag for init and descriptor set management
247 } else {
248 PLUGIN_LOG_ONCE_W("pp_node_not_found_" + to_string(ppRef.id),
249 "Post process node not found (uid:%s)",
250 to_string(ppRef.postProcess->GetRenderPostProcessNodeUid()).c_str());
251 }
252 }
253 }
254 }
255 }
256
ParseRenderNodeInputs()257 void RenderNodeRenderPostProcessesGeneric::ParseRenderNodeInputs()
258 {
259 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
260 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
261 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
262 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
263
264 #if (RENDER_VALIDATION_ENABLED == 1)
265 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
266 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
267 renderNodeContextMgr_->GetName().data());
268 }
269 if (jsonInputs_.renderDataStore.configurationName.empty()) {
270 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
271 }
272 #endif
273
274 auto GetDefaultInOutImage = [](const string& ioStr, const DefaultInOutImage defaultImg) {
275 DefaultInOutImage defImg = defaultImg;
276 if (!ioStr.empty()) {
277 if (ioStr == "output") {
278 defImg = DefaultInOutImage::OUTPUT;
279 } else if (ioStr == "input_output_copy") {
280 defImg = DefaultInOutImage::INPUT_OUTPUT_COPY;
281 } else if (ioStr == "input") {
282 defImg = DefaultInOutImage::INPUT;
283 } else if (ioStr == "black") {
284 defImg = DefaultInOutImage::BLACK;
285 } else if (ioStr == "white") {
286 defImg = DefaultInOutImage::WHITE;
287 } else {
288 PLUGIN_LOG_W("RenderNodeRenderPostProcessesGeneric default input/output image not supported (%s)",
289 ioStr.c_str());
290 }
291 }
292 return defImg;
293 };
294 const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
295 jsonInputs_.defaultOutputImage = GetDefaultInOutImage(defaultOutput, jsonInputs_.defaultOutputImage);
296 const auto defaultInput = parserUtil.GetStringValue(jsonVal, "defaultInputImage");
297 jsonInputs_.defaultInputImage = GetDefaultInOutImage(defaultOutput, jsonInputs_.defaultInputImage);
298
299 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
300 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
301
302 // process custom resources
303 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
304 const auto& ref = jsonInputs_.resources.customInputImages[idx];
305 if (ref.usageName == INPUT) {
306 jsonInputs_.inputIdx = idx;
307 }
308 }
309 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
310 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
311 if (ref.usageName == OUTPUT) {
312 jsonInputs_.outputIdx = idx;
313 }
314 }
315 }
316
UpdateImageData()317 void RenderNodeRenderPostProcessesGeneric::UpdateImageData()
318 {
319 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
320 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
321 builtInVariables_.defBlackImage =
322 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
323 }
324 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
325 builtInVariables_.defWhiteImage =
326 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
327 }
328 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
329 builtInVariables_.defSampler =
330 gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
331 }
332 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
333 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
334 }
335 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
336 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
337 }
338
339 // default in / out if not correct
340 if (!RenderHandleUtil::IsValid(builtInVariables_.defInput)) {
341 if (jsonInputs_.defaultInputImage == DefaultInOutImage::WHITE) {
342 builtInVariables_.defInput = builtInVariables_.defWhiteImage;
343 } else if (jsonInputs_.defaultInputImage == DefaultInOutImage::BLACK) {
344 builtInVariables_.defInput = builtInVariables_.defBlackImage;
345 }
346 }
347 if (!RenderHandleUtil::IsValid(builtInVariables_.defOutput)) {
348 if (jsonInputs_.defaultOutputImage == DefaultInOutImage::WHITE) {
349 builtInVariables_.defOutput = builtInVariables_.defWhiteImage;
350 } else if (jsonInputs_.defaultOutputImage == DefaultInOutImage::BLACK) {
351 builtInVariables_.defOutput = builtInVariables_.defBlackImage;
352 }
353 }
354 }
355
356 // for plugin / factory interface
Create()357 IRenderNode* RenderNodeRenderPostProcessesGeneric::Create()
358 {
359 return new RenderNodeRenderPostProcessesGeneric();
360 }
361
Destroy(IRenderNode * instance)362 void RenderNodeRenderPostProcessesGeneric::Destroy(IRenderNode* instance)
363 {
364 delete static_cast<RenderNodeRenderPostProcessesGeneric*>(instance);
365 }
366 RENDER_END_NAMESPACE()
367