• 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_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     // special handling for bloom and blur
193     RenderHandle output = builtInVariables_.output;
194     if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
195         ppLocalConfig_.variables.enabled) {
196         const RenderBloom::BloomInfo bloomInfo { GetBindableImage(builtInVariables_.input),
197             GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
198             ppGlobalConfig_.bloomConfiguration.useCompute };
199         renderBloom_.Init(renderNodeContextMgr, bloomInfo);
200         output = renderBloom_.GetFinalTarget();
201     } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
202                ppLocalConfig_.variables.enabled) {
203         RenderBlur::BlurInfo blurInfo { GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
204             false };
205         renderBlur_.Init(renderNodeContextMgr, blurInfo);
206     }
207     renderCopy_.Init(renderNodeContextMgr);
208     RegisterOutputs(output);
209 }
210 
PreExecuteFrame()211 void RenderNodeSinglePostProcess::PreExecuteFrame()
212 {
213     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
214     if (jsonInputs_.hasChangeableResourceHandles) {
215         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
216     }
217     UpdateImageData();
218 
219     ProcessPostProcessConfiguration();
220 
221     // special handling for bloom and blur
222     RenderHandle output = builtInVariables_.output;
223     if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
224         ppLocalConfig_.variables.enabled) {
225         const RenderBloom::BloomInfo bloomInfo { GetBindableImage(builtInVariables_.input),
226             GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
227             ppGlobalConfig_.bloomConfiguration.useCompute };
228         renderBloom_.PreExecute(*renderNodeContextMgr_, bloomInfo, ppGlobalConfig_);
229         output = renderBloom_.GetFinalTarget();
230     } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
231                ppLocalConfig_.variables.enabled) {
232         RenderBlur::BlurInfo blurInfo { GetBindableImage(builtInVariables_.input), ubos_.postProcess.GetHandle(),
233             false };
234         renderBlur_.PreExecute(*renderNodeContextMgr_, blurInfo);
235     }
236     {
237         renderCopy_.PreExecute();
238     }
239     RegisterOutputs(output);
240 }
241 
ExecuteFrame(IRenderCommandList & cmdList)242 void RenderNodeSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
243 {
244     if ((!ppLocalConfig_.variables.enabled) &&
245         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
246         return;
247     }
248 
249     if (ppLocalConfig_.variables.enabled) {
250         // ppConfig_ is already up-to-date from PreExecuteFrame
251         if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
252             ppLocalConfig_.variables.enabled) {
253             renderBloom_.Execute(*renderNodeContextMgr_, cmdList, ppGlobalConfig_);
254             return;
255         } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
256                    ppLocalConfig_.variables.enabled) {
257             renderBlur_.Execute(*renderNodeContextMgr_, cmdList, ppGlobalConfig_);
258             return;
259         }
260         if (valid_) {
261             ExecuteSinglePostProcess(cmdList);
262         }
263     } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
264         IRenderNodeCopyUtil::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
265             GetBindableImage(builtInVariables_.output), {} };
266         renderCopy_.Execute(cmdList, copyInfo);
267     }
268 }
269 
ExecuteSinglePostProcess(IRenderCommandList & cmdList)270 void RenderNodeSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
271 {
272     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
273     if (jsonInputs_.hasChangeableRenderPassHandles) {
274         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
275     }
276     if (jsonInputs_.hasChangeableResourceHandles) {
277         // input resources updated in preExecuteFrame
278         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
279     }
280     if (jsonInputs_.hasChangeableDispatchHandles) {
281         dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
282     }
283     if (useAutoBindSet0_) {
284         UpdateGlobalPostProcessUbo();
285     }
286 
287     RenderPass renderPass;
288     DispatchResources dispatchResources;
289     if (graphics_) {
290         renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
291         if ((renderPass.renderPassDesc.attachmentCount == 0) ||
292             !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
293 #if (RENDER_VALIDATION_ENABLED == 1)
294             PLUGIN_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(),
295                 "RENDER_VALIDATION: RN: %s, invalid attachment", renderNodeContextMgr_->GetName().data());
296 #endif
297             return;
298         }
299     } else {
300         dispatchResources = GetDispatchResources(dispatchResources_);
301         if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
302             (!RenderHandleUtil::IsValid(dispatchResources.image))) {
303             return; // no way to evaluate dispatch size
304         }
305     }
306 
307     const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
308     const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
309     const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
310     for (const auto refIndex : setIndices) {
311         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
312         // handle automatic set 0 bindings
313         if ((refIndex == 0) && useAutoBindSet0_) {
314             auto& binder = *pipelineDescriptorSetBinder_;
315             binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 0u, BindableBuffer { ubos_.postProcess.GetHandle() });
316             binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 1u,
317                 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
318         } else if (invalidBindings) {
319             const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
320             BindDefaultResources(refIndex, bindings);
321         }
322         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
323         cmdList.UpdateDescriptorSet(descHandle, bindings);
324     }
325 #if (RENDER_VALIDATION_ENABLED == 1)
326     if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
327         PLUGIN_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
328     }
329 #endif
330 
331     if (graphics_) {
332         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
333     }
334 
335     cmdList.BindPipeline(psoHandle_);
336 
337     // bind all sets
338     cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
339 
340     if (graphics_) {
341         // dynamic state
342         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
343         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
344         cmdList.SetDynamicStateViewport(viewportDesc);
345         cmdList.SetDynamicStateScissor(scissorDesc);
346 
347         if (pipelineLayout_.pushConstant.byteSize > 0) {
348             const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
349             const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
350             const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
351                 ppLocalConfig_.variables.factor };
352             cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
353         }
354 
355         cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
356         cmdList.EndRenderPass();
357     } else {
358         if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
359             cmdList.DispatchIndirect(dispatchResources.buffer, 0);
360         } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
361             const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
362             const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
363             const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
364             if (pipelineLayout_.pushConstant.byteSize > 0) {
365                 const auto fWidth = static_cast<float>(targetSize.x);
366                 const auto fHeight = static_cast<float>(targetSize.y);
367                 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
368                     ppLocalConfig_.variables.factor };
369                 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
370             }
371 
372             cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
373                 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
374                 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
375         }
376     }
377 }
378 
RegisterOutputs(const RenderHandle output)379 void RenderNodeSinglePostProcess::RegisterOutputs(const RenderHandle output)
380 {
381     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
382     RenderHandle registerOutput;
383     if (ppLocalConfig_.variables.enabled) {
384         if (RenderHandleUtil::IsValid(output)) {
385             registerOutput = output;
386         }
387     }
388     if (!RenderHandleUtil::IsValid(registerOutput)) {
389         if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
390                 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
391             RenderHandleUtil::IsValid(output)) {
392             registerOutput = output;
393         } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
394                    RenderHandleUtil::IsValid(builtInVariables_.input)) {
395             registerOutput = builtInVariables_.input;
396         } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
397             registerOutput = builtInVariables_.defWhiteImage;
398         } else {
399             registerOutput = builtInVariables_.defBlackImage;
400         }
401     }
402     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
403 }
404 
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)405 void RenderNodeSinglePostProcess::BindDefaultResources(
406     const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
407 {
408     if (pipelineDescriptorSetBinder_) {
409         auto& binder = *pipelineDescriptorSetBinder_;
410         for (const auto& ref : bindings.buffers) {
411             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
412                 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
413             }
414         }
415         for (const auto& ref : bindings.images) {
416             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
417                 BindableImage bi;
418                 bi.handle = builtInVariables_.defBlackImage;
419                 bi.samplerHandle = builtInVariables_.defSampler;
420                 binder.BindImage(set, ref.binding.binding, bi);
421             }
422         }
423         for (const auto& ref : bindings.samplers) {
424             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
425                 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
426             }
427         }
428     }
429 }
430 
ProcessPostProcessConfiguration()431 void RenderNodeSinglePostProcess::ProcessPostProcessConfiguration()
432 {
433     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
434         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
435         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
436             if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
437                 auto* const dataStore = static_cast<const IRenderDataStorePostProcess*>(ds);
438                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
439             }
440         }
441         if (const auto* ds =
442                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
443             ds) {
444             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
445             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
446                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
447             }
448         }
449     } else if (jsonInputs_.ppName.empty()) {
450         // if trying to just use shader without post processing we enable running by default
451         ppLocalConfig_.variables.enabled = true;
452     }
453 }
454 
UpdateGlobalPostProcessUbo()455 void RenderNodeSinglePostProcess::UpdateGlobalPostProcessUbo()
456 {
457     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
458     const RenderPostProcessConfiguration rppc =
459         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
460     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
461     PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
462                          sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
463     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
464         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
465         // global data
466         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
467         // local data
468         data += sizeof(GlobalPostProcessStruct);
469         CloneData(
470             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
471         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
472     }
473 }
474 
InitCreateBinders()475 void RenderNodeSinglePostProcess::InitCreateBinders()
476 {
477     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
478     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
479     DescriptorCounts dc;
480     if (builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) {
481         dc = RenderBloom::GetDescriptorCounts();
482     } else if (builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) {
483         dc = RenderBlur::GetDescriptorCounts();
484     } else {
485         dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
486     }
487     if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
488         const DescriptorCounts copyDc = renderCopy_.GetRenderDescriptorCounts();
489         for (const auto& ref : copyDc.counts) {
490             dc.counts.push_back(ref);
491         }
492     }
493     descriptorSetMgr.ResetAndReserve(dc);
494 
495     pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
496     if (pipelineDescriptorSetBinder_) {
497         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
498         if (NeedsAutoBindingSet0(inputResources_)) {
499             useAutoBindSet0_ = true;
500         }
501     } else {
502         valid_ = false;
503     }
504 }
505 
ParseRenderNodeInputs()506 void RenderNodeSinglePostProcess::ParseRenderNodeInputs()
507 {
508     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
509     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
510     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
511     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
512     jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
513     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
514 
515     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
516     builtInVariables_.postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
517 
518 #if (RENDER_VALIDATION_ENABLED == 1)
519     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
520         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
521             renderNodeContextMgr_->GetName().data());
522     }
523     if (jsonInputs_.ppName.empty()) {
524         PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
525     }
526 #endif
527 
528     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
529     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
530     if (!shaderName.empty()) {
531         shader_ = shaderMgr.GetShaderHandle(shaderName);
532     }
533     const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
534     if (!defaultOutput.empty()) {
535         if (defaultOutput == "output") {
536             jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
537         } else if (defaultOutput == "input_output_copy") {
538             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
539         } else if (defaultOutput == "input") {
540             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
541         } else if (defaultOutput == "black") {
542             jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
543         } else if (defaultOutput == "white") {
544             jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
545         } else {
546             PLUGIN_LOG_W("RenderNodeSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
547         }
548     }
549 
550     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
551     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
552     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
553     dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
554 
555     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
556     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
557     jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
558 
559     // process custom resources
560     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
561         const auto& ref = jsonInputs_.resources.customInputImages[idx];
562         if (ref.usageName == INPUT) {
563             jsonInputs_.inputIdx = idx;
564         }
565     }
566     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
567         const auto& ref = jsonInputs_.resources.customOutputImages[idx];
568         if (ref.usageName == OUTPUT) {
569             jsonInputs_.outputIdx = idx;
570         }
571     }
572 }
573 
UpdateImageData()574 void RenderNodeSinglePostProcess::UpdateImageData()
575 {
576     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
577     if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
578         builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
579     }
580     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
581         builtInVariables_.defBlackImage =
582             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
583     }
584     if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
585         builtInVariables_.defWhiteImage =
586             gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
587     }
588     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
589         builtInVariables_.defSampler =
590             gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
591     }
592     if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
593         builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
594     }
595     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
596         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
597     }
598 }
599 
600 // for plugin / factory interface
Create()601 IRenderNode* RenderNodeSinglePostProcess::Create()
602 {
603     return new RenderNodeSinglePostProcess();
604 }
605 
Destroy(IRenderNode * instance)606 void RenderNodeSinglePostProcess::Destroy(IRenderNode* instance)
607 {
608     delete static_cast<RenderNodeSinglePostProcess*>(instance);
609 }
610 RENDER_END_NAMESPACE()
611