• 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_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