• 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_single_post_process.h"
17 
18 #include <base/math/mathf.h>
19 #include <render/datastore/intf_render_data_store_manager.h>
20 #include <render/datastore/intf_render_data_store_post_process.h>
21 #include <render/device/intf_gpu_resource_manager.h>
22 #include <render/device/intf_shader_manager.h>
23 #include <render/device/pipeline_layout_desc.h>
24 #include <render/device/pipeline_state_desc.h>
25 #include <render/namespace.h>
26 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
27 #include <render/nodecontext/intf_node_context_pso_manager.h>
28 #include <render/nodecontext/intf_render_command_list.h>
29 #include <render/nodecontext/intf_render_node_context_manager.h>
30 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
31 #include <render/nodecontext/intf_render_node_parser_util.h>
32 #include <render/nodecontext/intf_render_node_util.h>
33 
34 #include "datastore/render_data_store_pod.h"
35 #include "datastore/render_data_store_post_process.h"
36 #include "default_engine_constants.h"
37 #include "device/gpu_resource_handle_util.h"
38 #include "util/log.h"
39 
40 // shaders
41 #include <render/shaders/common/render_post_process_structs_common.h>
42 
43 using namespace BASE_NS;
44 
45 RENDER_BEGIN_NAMESPACE()
46 namespace {
47 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
48 
49 constexpr uint32_t GLOBAL_POST_PROCESS_SET { 0u };
50 constexpr string_view RENDER_DATA_STORE_POD_NAME { RenderDataStorePod::TYPE_NAME };
51 
52 constexpr string_view INPUT = "input";
53 constexpr string_view OUTPUT = "output";
54 
55 constexpr string_view POST_PROCESS_BASE_PIPELINE_LAYOUT { "renderpipelinelayouts://post_process_common.shaderpl" };
56 
57 struct DispatchResources {
58     RenderHandle buffer {};
59     RenderHandle image {};
60 };
61 
GetDispatchResources(const RenderNodeHandles::InputResources & ir)62 DispatchResources GetDispatchResources(const RenderNodeHandles::InputResources& ir)
63 {
64     DispatchResources dr;
65     if (!ir.customInputBuffers.empty()) {
66         dr.buffer = ir.customInputBuffers[0].handle;
67     }
68     if (!ir.customInputImages.empty()) {
69         dr.image = ir.customInputImages[0].handle;
70     }
71     return dr;
72 }
73 
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)74 RenderHandleReference CreatePostProcessDataUniformBuffer(
75     IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
76 {
77     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
78     PLUGIN_STATIC_ASSERT(
79         sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
80     return gpuResourceMgr.Create(
81         handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
82                     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
83                     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
84                     sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
85 }
86 
GetPostProcessFlag(const string_view ppName)87 uint32_t GetPostProcessFlag(const string_view ppName)
88 {
89     if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_FXAA]) {
90         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
91     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_TAA]) {
92         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT;
93     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) {
94         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT;
95     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR]) {
96         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT;
97     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_DOF]) {
98         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT;
99     } else {
100         return 0;
101     }
102 }
103 
NeedsShader(const string_view ppName)104 bool NeedsShader(const string_view ppName)
105 {
106     if ((ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) ||
107         (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR])) {
108         return false;
109     } else {
110         return true;
111     }
112 }
113 
NeedsAutoBindingSet0(const RenderNodeHandles::InputResources & inputRes)114 bool NeedsAutoBindingSet0(const RenderNodeHandles::InputResources& inputRes)
115 {
116     uint32_t set0Bindings = 0;
117     for (const auto& res : inputRes.buffers) {
118         if (res.set == GLOBAL_POST_PROCESS_SET) {
119             set0Bindings++;
120         }
121     }
122     return (set0Bindings == 0);
123 }
124 
GetBindableImage(const RenderHandle & res)125 inline BindableImage GetBindableImage(const RenderHandle& res)
126 {
127     return BindableImage { res, PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS,
128         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS, ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, {} };
129 }
130 } // namespace
131 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)132 void RenderNodeSinglePostProcess::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
133 {
134     renderNodeContextMgr_ = &renderNodeContextMgr;
135 
136     valid_ = true;
137     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
138     ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
139 
140     ParseRenderNodeInputs();
141     UpdateImageData();
142     ProcessPostProcessConfiguration();
143     if (!RenderHandleUtil::IsValid(shader_)) {
144         shader_ = ppLocalConfig_.shader.GetHandle();
145     }
146     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
147     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
148     if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
149         graphics_ = true;
150     } else if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
151         graphics_ = false;
152         threadGroupSize_ = shaderMgr.GetReflectionThreadGroupSize(shader_);
153         if (dispatchResources_.customInputBuffers.empty() && dispatchResources_.customInputImages.empty()) {
154             valid_ = false;
155             PLUGIN_LOG_W("RenderNodeSinglePostProcess: dispatchResources (GPU buffer or GPU image) needed");
156         }
157     }
158 
159     pipelineLayout_ = renderNodeContextMgr.GetRenderNodeUtil().CreatePipelineLayout(shader_);
160 
161     const bool needsShader = NeedsShader(jsonInputs_.ppName);
162     if (needsShader) {
163         if (!((handleType == RenderHandleType::SHADER_STATE_OBJECT) ||
164                 (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
165             PLUGIN_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
166         }
167         const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
168         pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
169         if (graphics_) {
170             const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
171             psoHandle_ = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
172                 shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
173         } else {
174             psoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(shader_, pipelineLayout_, {});
175         }
176 
177         // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
178         const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
179         const IShaderManager::CompatibilityFlags compatibilityFlags =
180             shaderMgr.GetCompatibilityFlags(basePlHandle, plHandle);
181         if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
182             PLUGIN_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
183                 POST_PROCESS_BASE_PIPELINE_LAYOUT.data());
184         }
185     }
186     InitCreateBinders();
187 
188     if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
189         valid_ = false;
190     }
191 
192     RenderHandle output = builtInVariables_.output;
193     renderCopy_.Init(renderNodeContextMgr);
194     RegisterOutputs(output);
195 }
196 
PreExecuteFrame()197 void RenderNodeSinglePostProcess::PreExecuteFrame()
198 {
199     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
200     if (jsonInputs_.hasChangeableResourceHandles) {
201         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
202     }
203     UpdateImageData();
204 
205     ProcessPostProcessConfiguration();
206 
207     RenderHandle output = builtInVariables_.output;
208     renderCopy_.PreExecute();
209     RegisterOutputs(output);
210 }
211 
ExecuteFrame(IRenderCommandList & cmdList)212 void RenderNodeSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
213 {
214     if ((!ppLocalConfig_.variables.enabled) &&
215         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
216         return;
217     }
218 
219     if (ppLocalConfig_.variables.enabled) {
220         // ppConfig_ is already up-to-date from PreExecuteFrame
221         if (valid_) {
222             ExecuteSinglePostProcess(cmdList);
223         }
224     } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
225         IRenderNodeCopyUtil::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
226             GetBindableImage(builtInVariables_.output), {} };
227         renderCopy_.Execute(cmdList, copyInfo);
228     }
229 }
230 
ExecuteSinglePostProcess(IRenderCommandList & cmdList)231 void RenderNodeSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
232 {
233     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
234     if (jsonInputs_.hasChangeableRenderPassHandles) {
235         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
236     }
237     if (jsonInputs_.hasChangeableResourceHandles) {
238         // input resources updated in preExecuteFrame
239         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
240     }
241     if (jsonInputs_.hasChangeableDispatchHandles) {
242         dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
243     }
244     if (useAutoBindSet0_) {
245         UpdateGlobalPostProcessUbo();
246     }
247 
248     RenderPass renderPass;
249     DispatchResources dispatchResources;
250     if (graphics_) {
251         renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
252         if ((renderPass.renderPassDesc.attachmentCount == 0) ||
253             !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
254 #if (RENDER_VALIDATION_ENABLED == 1)
255             PLUGIN_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(),
256                 "RENDER_VALIDATION: RN: %s, invalid attachment", renderNodeContextMgr_->GetName().data());
257 #endif
258             return;
259         }
260     } else {
261         dispatchResources = GetDispatchResources(dispatchResources_);
262         if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
263             (!RenderHandleUtil::IsValid(dispatchResources.image))) {
264             return; // no way to evaluate dispatch size
265         }
266     }
267 
268     const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
269     const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
270     const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
271     for (const auto refIndex : setIndices) {
272         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
273         // handle automatic set 0 bindings
274         if ((refIndex == 0) && useAutoBindSet0_) {
275             auto& binder = *pipelineDescriptorSetBinder_;
276             binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 0u, BindableBuffer { ubos_.postProcess.GetHandle() });
277             binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 1u,
278                 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
279         } else if (invalidBindings) {
280             const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
281             BindDefaultResources(refIndex, bindings);
282         }
283         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
284         cmdList.UpdateDescriptorSet(descHandle, bindings);
285     }
286 #if (RENDER_VALIDATION_ENABLED == 1)
287     if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
288         PLUGIN_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
289     }
290 #endif
291 
292     if (graphics_) {
293         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
294     }
295 
296     cmdList.BindPipeline(psoHandle_);
297 
298     // bind all sets
299     cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
300 
301     if (graphics_) {
302         // dynamic state
303         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
304         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
305         cmdList.SetDynamicStateViewport(viewportDesc);
306         cmdList.SetDynamicStateScissor(scissorDesc);
307 
308         if (pipelineLayout_.pushConstant.byteSize > 0) {
309             const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
310             const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
311             const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
312                 ppLocalConfig_.variables.factor };
313             cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
314         }
315 
316         cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
317         cmdList.EndRenderPass();
318     } else {
319         if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
320             cmdList.DispatchIndirect(dispatchResources.buffer, 0);
321         } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
322             const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
323             const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
324             const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
325             if (pipelineLayout_.pushConstant.byteSize > 0) {
326                 const auto fWidth = static_cast<float>(targetSize.x);
327                 const auto fHeight = static_cast<float>(targetSize.y);
328                 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
329                     ppLocalConfig_.variables.factor };
330                 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
331             }
332 
333             cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
334                 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
335                 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
336         }
337     }
338 }
339 
RegisterOutputs(const RenderHandle output)340 void RenderNodeSinglePostProcess::RegisterOutputs(const RenderHandle output)
341 {
342     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
343     RenderHandle registerOutput;
344     if (ppLocalConfig_.variables.enabled) {
345         if (RenderHandleUtil::IsValid(output)) {
346             registerOutput = output;
347         }
348     }
349     if (!RenderHandleUtil::IsValid(registerOutput)) {
350         if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
351                 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
352             RenderHandleUtil::IsValid(output)) {
353             registerOutput = output;
354         } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
355                    RenderHandleUtil::IsValid(builtInVariables_.input)) {
356             registerOutput = builtInVariables_.input;
357         } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
358             registerOutput = builtInVariables_.defWhiteImage;
359         } else {
360             registerOutput = builtInVariables_.defBlackImage;
361         }
362     }
363     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
364 }
365 
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)366 void RenderNodeSinglePostProcess::BindDefaultResources(
367     const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
368 {
369     if (pipelineDescriptorSetBinder_) {
370         auto& binder = *pipelineDescriptorSetBinder_;
371         for (const auto& ref : bindings.buffers) {
372             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
373                 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
374             }
375         }
376         for (const auto& ref : bindings.images) {
377             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
378                 BindableImage bi;
379                 bi.handle = builtInVariables_.defBlackImage;
380                 bi.samplerHandle = builtInVariables_.defSampler;
381                 binder.BindImage(set, ref.binding.binding, bi);
382             }
383         }
384         for (const auto& ref : bindings.samplers) {
385             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
386                 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
387             }
388         }
389     }
390 }
391 
ProcessPostProcessConfiguration()392 void RenderNodeSinglePostProcess::ProcessPostProcessConfiguration()
393 {
394     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
395         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
396         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
397             if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
398                 auto* const dataStore = static_cast<const IRenderDataStorePostProcess*>(ds);
399                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
400             }
401         }
402         if (const auto* ds =
403                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
404             ds) {
405             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
406             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
407                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
408             }
409         }
410     } else if (jsonInputs_.ppName.empty()) {
411         // if trying to just use shader without post processing we enable running by default
412         ppLocalConfig_.variables.enabled = true;
413     }
414 }
415 
UpdateGlobalPostProcessUbo()416 void RenderNodeSinglePostProcess::UpdateGlobalPostProcessUbo()
417 {
418     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
419     const RenderPostProcessConfiguration rppc =
420         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
421     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
422     PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
423                          sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
424     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
425         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
426         // global data
427         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
428         // local data
429         data += sizeof(GlobalPostProcessStruct);
430         CloneData(
431             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
432         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
433     }
434 }
435 
InitCreateBinders()436 void RenderNodeSinglePostProcess::InitCreateBinders()
437 {
438     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
439     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
440     DescriptorCounts dc;
441 
442     dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
443 
444     if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
445         const DescriptorCounts copyDc = renderCopy_.GetRenderDescriptorCounts();
446         for (const auto& ref : copyDc.counts) {
447             dc.counts.push_back(ref);
448         }
449     }
450     descriptorSetMgr.ResetAndReserve(dc);
451 
452     pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
453     if (pipelineDescriptorSetBinder_) {
454         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
455         if (NeedsAutoBindingSet0(inputResources_)) {
456             useAutoBindSet0_ = true;
457         }
458     } else {
459         valid_ = false;
460     }
461 }
462 
ParseRenderNodeInputs()463 void RenderNodeSinglePostProcess::ParseRenderNodeInputs()
464 {
465     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
466     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
467     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
468     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
469     jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
470     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
471 
472     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
473     builtInVariables_.postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
474 
475 #if (RENDER_VALIDATION_ENABLED == 1)
476     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
477         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
478             renderNodeContextMgr_->GetName().data());
479     }
480     if (jsonInputs_.ppName.empty()) {
481         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
482     }
483 #endif
484 
485     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
486     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
487     if (!shaderName.empty()) {
488         shader_ = shaderMgr.GetShaderHandle(shaderName);
489     }
490     const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
491     if (!defaultOutput.empty()) {
492         if (defaultOutput == "output") {
493             jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
494         } else if (defaultOutput == "input_output_copy") {
495             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
496         } else if (defaultOutput == "input") {
497             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
498         } else if (defaultOutput == "black") {
499             jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
500         } else if (defaultOutput == "white") {
501             jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
502         } else {
503             PLUGIN_LOG_W("RenderNodeSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
504         }
505     }
506 
507     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
508     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
509     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
510     dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
511 
512     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
513     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
514     jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
515 
516     // process custom resources
517     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
518         const auto& ref = jsonInputs_.resources.customInputImages[idx];
519         if (ref.usageName == INPUT) {
520             jsonInputs_.inputIdx = idx;
521         }
522     }
523     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
524         const auto& ref = jsonInputs_.resources.customOutputImages[idx];
525         if (ref.usageName == OUTPUT) {
526             jsonInputs_.outputIdx = idx;
527         }
528     }
529 }
530 
UpdateImageData()531 void RenderNodeSinglePostProcess::UpdateImageData()
532 {
533     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
534     if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
535         builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
536     }
537     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
538         builtInVariables_.defBlackImage =
539             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
540     }
541     if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
542         builtInVariables_.defWhiteImage =
543             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
544     }
545     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
546         builtInVariables_.defSampler =
547             gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
548     }
549     if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
550         builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
551     }
552     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
553         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
554     }
555 }
556 
557 // for plugin / factory interface
Create()558 IRenderNode* RenderNodeSinglePostProcess::Create()
559 {
560     return new RenderNodeSinglePostProcess();
561 }
562 
Destroy(IRenderNode * instance)563 void RenderNodeSinglePostProcess::Destroy(IRenderNode* instance)
564 {
565     delete static_cast<RenderNodeSinglePostProcess*>(instance);
566 }
567 RENDER_END_NAMESPACE()
568