• 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_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                         break;
94                     }
95                 }
96                 if (rpp) {
97                     ppNodeRef.ppNode->Init(*rpp, *renderNodeContextMgr_);
98                     descriptorCounts.push_back(ppNodeRef.ppNode->GetRenderDescriptorCounts());
99                 }
100             }
101         }
102         // add copy descriptor sets
103         descriptorCounts.push_back(renderCopy_.GetRenderDescriptorCounts());
104 
105         // reset descriptor sets
106         INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
107         dsMgr.ResetAndReserve(descriptorCounts);
108 
109         renderCopy_.Init(*renderNodeContextMgr_);
110     } else if (copyInitNeeded_) {
111         vector<DescriptorCounts> descriptorCounts;
112 
113         // add copy descriptor sets
114         descriptorCounts.push_back(renderCopy_.GetRenderDescriptorCounts());
115 
116         // reset descriptor sets
117         INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
118         dsMgr.ResetAndReserve(descriptorCounts);
119 
120         renderCopy_.Init(*renderNodeContextMgr_);
121     }
122     copyInitNeeded_ = false;
123 
124     RenderPassDesc::RenderArea renderArea =
125         GetImageRenderArea(renderNodeContextMgr_->GetGpuResourceManager(), builtInVariables_.output);
126     allPostProcesses_.postProcessCount = 0U;
127 
128     const RenderHandle output =
129         RenderHandleUtil::IsValid(builtInVariables_.output) ? builtInVariables_.output : builtInVariables_.defOutput;
130     BindableImage biInput;
131     biInput.handle =
132         RenderHandleUtil::IsValid(builtInVariables_.input) ? builtInVariables_.input : builtInVariables_.defInput;
133     BindableImage biOutput;
134     biOutput.handle = output;
135 
136     // pre-execute in correct order
137     const auto ppCount = static_cast<uint32_t>(allPostProcesses_.pipeline.postProcesses.size());
138     for (uint32_t ppIndex = 0; ppIndex < ppCount; ++ppIndex) {
139         const auto& ppRef = allPostProcesses_.pipeline.postProcesses[ppIndex];
140         for (auto& ppNodeRef : allPostProcesses_.postProcessNodeInstances) {
141             if (ppNodeRef.ppNode && (ppNodeRef.id == ppRef.id)) {
142                 auto& ppNode = *ppNodeRef.ppNode;
143 
144                 CORE_NS::SetPropertyValue(ppNode.GetRenderInputProperties(), "input", biInput);
145                 // try to force the final target for the final post process
146                 // the effect might not accept this and then we need an extra blit in the end
147                 if (ppIndex == (ppCount - 1U)) {
148                     CORE_NS::SetPropertyValue(ppNode.GetRenderOutputProperties(), "output", biOutput);
149                 }
150 
151                 ppNodeRef.ppNode->SetRenderAreaRequest({ renderArea });
152                 ppNodeRef.ppNode->PreExecute();
153 
154                 // take output and route to next input
155                 biInput = CORE_NS::GetPropertyValue<BindableImage>(ppNode.GetRenderOutputProperties(), "output");
156 
157                 allPostProcesses_.postProcessCount++;
158                 break;
159             }
160         }
161     }
162 }
163 
GetExecuteFlags() const164 IRenderNode::ExecuteFlags RenderNodeRenderPostProcessesGeneric::GetExecuteFlags() const
165 {
166     if (valid_ && (!allPostProcesses_.pipeline.postProcesses.empty())) {
167         return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DEFAULT;
168     } else {
169         return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
170     }
171 }
172 
ExecuteFrame(IRenderCommandList & cmdList)173 void RenderNodeRenderPostProcessesGeneric::ExecuteFrame(IRenderCommandList& cmdList)
174 {
175     const RenderHandle output =
176         RenderHandleUtil::IsValid(builtInVariables_.output) ? builtInVariables_.output : builtInVariables_.defOutput;
177     BindableImage biInput;
178     biInput.handle =
179         RenderHandleUtil::IsValid(builtInVariables_.input) ? builtInVariables_.input : builtInVariables_.defInput;
180     BindableImage biOutput;
181     biOutput.handle = output;
182     const auto ppCount = static_cast<uint32_t>(allPostProcesses_.pipeline.postProcesses.size());
183     // execute in correct order
184     for (uint32_t ppIndex = 0; ppIndex < ppCount; ++ppIndex) {
185         const auto& ppRef = allPostProcesses_.pipeline.postProcesses[ppIndex];
186         for (auto& ppNodeRef : allPostProcesses_.postProcessNodeInstances) {
187             if (ppNodeRef.ppNode && (ppNodeRef.id == ppRef.id) && (ppNodeRef.ppNode->GetExecuteFlags() == 0U)) {
188                 auto& ppNode = *ppNodeRef.ppNode;
189 
190                 CORE_NS::SetPropertyValue(ppNode.GetRenderInputProperties(), "input", biInput);
191                 // try to force the final target for the final post process
192                 // the effect might not accept this and then we need an extra blit in the end
193                 if (ppIndex == (allPostProcesses_.postProcessCount - 1U)) {
194                     CORE_NS::SetPropertyValue(ppNode.GetRenderOutputProperties(), "output", biOutput);
195                 }
196 
197                 ppNode.Execute(cmdList);
198 
199                 // take output and route to next input
200                 biInput = CORE_NS::GetPropertyValue<BindableImage>(ppNode.GetRenderOutputProperties(), "output");
201             }
202         }
203     }
204 
205     if (biInput.handle != biOutput.handle) {
206         IRenderNodeCopyUtil::CopyInfo copyInfo;
207         copyInfo.input = biInput;
208         copyInfo.output = biOutput;
209         renderCopy_.PreExecute();
210         renderCopy_.Execute(cmdList, copyInfo);
211     }
212 }
213 
RegisterOutputs()214 void RenderNodeRenderPostProcessesGeneric::RegisterOutputs()
215 {
216     const RenderHandle output = builtInVariables_.output;
217     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
218     RenderHandle registerOutput;
219     if (valid_) {
220         if (RenderHandleUtil::IsValid(output)) {
221             registerOutput = output;
222         }
223     }
224     if (!RenderHandleUtil::IsValid(registerOutput)) {
225         if (((jsonInputs_.defaultOutputImage == DefaultInOutImage::OUTPUT) ||
226                 (jsonInputs_.defaultOutputImage == DefaultInOutImage::INPUT_OUTPUT_COPY)) &&
227             RenderHandleUtil::IsValid(output)) {
228             registerOutput = output;
229         } else if ((jsonInputs_.defaultOutputImage == DefaultInOutImage::INPUT) &&
230                    RenderHandleUtil::IsValid(builtInVariables_.input)) {
231             registerOutput = builtInVariables_.input;
232         } else {
233             registerOutput = builtInVariables_.defOutput;
234         }
235     }
236     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
237 }
238 
ProcessPostProcessConfiguration()239 void RenderNodeRenderPostProcessesGeneric::ProcessPostProcessConfiguration()
240 {
241     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
242         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
243         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
244             if (jsonInputs_.renderDataStore.typeName == RenderDataStoreRenderPostProcesses::TYPE_NAME) {
245                 auto* const dataStore = static_cast<const IRenderDataStoreRenderPostProcesses*>(ds);
246                 allPostProcesses_.pipeline = dataStore->GetData(jsonInputs_.renderDataStore.configurationName);
247                 valid_ = true;
248             }
249         }
250     }
251     // process new instances
252     auto* renderClassFactory = renderNodeContextMgr_->GetRenderContext().GetInterface<IClassFactory>();
253     if (valid_ && renderClassFactory) {
254         auto& pp = allPostProcesses_;
255         for (const auto& ppRef : pp.pipeline.postProcesses) {
256             if (!ppRef.postProcess) {
257                 continue;
258             }
259             bool createNew = true;
260             for (const auto& iRef : pp.postProcessNodeInstances) {
261                 if (iRef.id == ppRef.id) {
262                     createNew = false;
263                     break;
264                 }
265             }
266             if (createNew) {
267                 IRenderPostProcessNode::Ptr rppn = CreateInstance<IRenderPostProcessNode>(
268                     *renderClassFactory, ppRef.postProcess->GetRenderPostProcessNodeUid());
269                 if (rppn) {
270                     pp.postProcessNodeInstances.push_back({ ppRef.id, rppn });
271                     pp.newPostProcesses = true; // flag for init and descriptor set management
272                 } else {
273                     PLUGIN_LOG_ONCE_W("pp_node_not_found_" + to_string(ppRef.id),
274                         "Post process node not found (uid:%s)",
275                         to_string(ppRef.postProcess->GetRenderPostProcessNodeUid()).c_str());
276                 }
277             }
278         }
279     }
280 }
281 
ParseRenderNodeInputs()282 void RenderNodeRenderPostProcessesGeneric::ParseRenderNodeInputs()
283 {
284     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
285     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
286     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
287     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
288 
289 #if (RENDER_VALIDATION_ENABLED == 1)
290     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
291         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
292             renderNodeContextMgr_->GetName().data());
293     }
294     if (jsonInputs_.renderDataStore.configurationName.empty()) {
295         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
296     }
297 #endif
298 
299     auto GetDefaultInOutImage = [](const string& ioStr, const DefaultInOutImage defaultImg) {
300         DefaultInOutImage defImg = defaultImg;
301         if (!ioStr.empty()) {
302             if (ioStr == "output") {
303                 defImg = DefaultInOutImage::OUTPUT;
304             } else if (ioStr == "input_output_copy") {
305                 defImg = DefaultInOutImage::INPUT_OUTPUT_COPY;
306             } else if (ioStr == "input") {
307                 defImg = DefaultInOutImage::INPUT;
308             } else if (ioStr == "black") {
309                 defImg = DefaultInOutImage::BLACK;
310             } else if (ioStr == "white") {
311                 defImg = DefaultInOutImage::WHITE;
312             } else {
313                 PLUGIN_LOG_W("RenderNodeRenderPostProcessesGeneric default input/output image not supported (%s)",
314                     ioStr.c_str());
315             }
316         }
317         return defImg;
318     };
319     const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
320     jsonInputs_.defaultOutputImage = GetDefaultInOutImage(defaultOutput, jsonInputs_.defaultOutputImage);
321     const auto defaultInput = parserUtil.GetStringValue(jsonVal, "defaultInputImage");
322     jsonInputs_.defaultInputImage = GetDefaultInOutImage(defaultOutput, jsonInputs_.defaultInputImage);
323 
324     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
325     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
326 
327     // process custom resources
328     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
329         const auto& ref = jsonInputs_.resources.customInputImages[idx];
330         if (ref.usageName == INPUT) {
331             jsonInputs_.inputIdx = idx;
332         }
333     }
334     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
335         const auto& ref = jsonInputs_.resources.customOutputImages[idx];
336         if (ref.usageName == OUTPUT) {
337             jsonInputs_.outputIdx = idx;
338         }
339     }
340 }
341 
UpdateImageData()342 void RenderNodeRenderPostProcessesGeneric::UpdateImageData()
343 {
344     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
345     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
346         builtInVariables_.defBlackImage =
347             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
348     }
349     if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
350         builtInVariables_.defWhiteImage =
351             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
352     }
353     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
354         builtInVariables_.defSampler =
355             gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
356     }
357     if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
358         builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
359     }
360     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
361         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
362     }
363 
364     // default in / out if not correct
365     if (!RenderHandleUtil::IsValid(builtInVariables_.defInput)) {
366         if (jsonInputs_.defaultInputImage == DefaultInOutImage::WHITE) {
367             builtInVariables_.defInput = builtInVariables_.defWhiteImage;
368         } else if (jsonInputs_.defaultInputImage == DefaultInOutImage::BLACK) {
369             builtInVariables_.defInput = builtInVariables_.defBlackImage;
370         }
371     }
372     if (!RenderHandleUtil::IsValid(builtInVariables_.defOutput)) {
373         if (jsonInputs_.defaultOutputImage == DefaultInOutImage::WHITE) {
374             builtInVariables_.defOutput = builtInVariables_.defWhiteImage;
375         } else if (jsonInputs_.defaultOutputImage == DefaultInOutImage::BLACK) {
376             builtInVariables_.defOutput = builtInVariables_.defBlackImage;
377         }
378     }
379 }
380 
381 // for plugin / factory interface
Create()382 IRenderNode* RenderNodeRenderPostProcessesGeneric::Create()
383 {
384     return new RenderNodeRenderPostProcessesGeneric();
385 }
386 
Destroy(IRenderNode * instance)387 void RenderNodeRenderPostProcessesGeneric::Destroy(IRenderNode* instance)
388 {
389     delete static_cast<RenderNodeRenderPostProcessesGeneric*>(instance);
390 }
391 RENDER_END_NAMESPACE()
392