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