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_camera_single_post_process.h"
17 
18 #include <3d/render/intf_render_data_store_default_camera.h>
19 #include <3d/render/intf_render_data_store_default_light.h>
20 #include <3d/render/intf_render_data_store_default_scene.h>
21 #include <base/math/mathf.h>
22 #include <core/log.h>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/intf_render_data_store_post_process.h>
26 #include <render/datastore/render_data_store_render_pods.h>
27 #include <render/device/intf_gpu_resource_manager.h>
28 #include <render/device/intf_shader_manager.h>
29 #include <render/device/pipeline_layout_desc.h>
30 #include <render/device/pipeline_state_desc.h>
31 #include <render/namespace.h>
32 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
33 #include <render/nodecontext/intf_node_context_pso_manager.h>
34 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
35 #include <render/nodecontext/intf_render_command_list.h>
36 #include <render/nodecontext/intf_render_node_context_manager.h>
37 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
38 #include <render/nodecontext/intf_render_node_parser_util.h>
39 #include <render/nodecontext/intf_render_node_util.h>
40 
41 // shaders
42 #include <render/shaders/common/render_post_process_structs_common.h>
43 
44 using namespace BASE_NS;
45 using namespace RENDER_NS;
46 
47 CORE3D_BEGIN_NAMESPACE()
48 namespace {
49 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
50 
51 constexpr uint32_t GLOBAL_POST_PROCESS_SET { 0u };
52 constexpr string_view RENDER_DATA_STORE_POD_NAME { "RenderDataStorePod" };
53 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_NAME { "RenderDataStorePostProcess" };
54 
55 constexpr string_view CORE_DEFAULT_GPU_IMAGE_BLACK { "CORE_DEFAULT_GPU_IMAGE" };
56 constexpr string_view CORE_DEFAULT_GPU_IMAGE_WHITE { "CORE_DEFAULT_GPU_IMAGE_WHITE" };
57 
58 constexpr string_view INPUT = "input";
59 constexpr string_view OUTPUT = "output";
60 #if (CORE3D_VALIDATION_ENABLED == 1)
61 constexpr string_view POST_PROCESS_BASE_PIPELINE_LAYOUT { "renderpipelinelayouts://post_process_common.shaderpl" };
62 #endif
63 constexpr string_view POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT { "3dpipelinelayouts://core3d_post_process.shaderpl" };
64 
65 #if (CORE3D_VALIDATION_ENABLED == 1)
GetPostProcessFlag(const string_view ppName)66 uint32_t GetPostProcessFlag(const string_view ppName)
67 {
68     // get built-in flags
69     if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_FXAA]) {
70         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
71     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_TAA]) {
72         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT;
73     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) {
74         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT;
75     } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR]) {
76         return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT;
77     } else {
78         return 0;
79     }
80 }
81 #endif
82 
GetShadowBufferNodeData(const IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view sceneName)83 RenderNodeCameraSinglePostProcess::ShadowBuffers GetShadowBufferNodeData(
84     const IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view sceneName)
85 {
86     RenderNodeCameraSinglePostProcess::ShadowBuffers sb;
87     sb.vsmSamplerHandle =
88         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER);
89     sb.pcfSamplerHandle =
90         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER);
91 
92     sb.pcfDepthHandle =
93         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME);
94     sb.vsmColorHandle =
95         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME);
96     if (!RenderHandleUtil::IsValid(sb.pcfDepthHandle)) {
97         sb.pcfDepthHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
98     }
99     if (!RenderHandleUtil::IsValid(sb.vsmColorHandle)) {
100         sb.vsmColorHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
101     }
102 
103     return sb;
104 }
105 
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)106 RenderHandleReference CreatePostProcessDataUniformBuffer(
107     IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
108 {
109     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
110     CORE_STATIC_ASSERT(
111         sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
112     return gpuResourceMgr.Create(
113         handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
114                     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
115                     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
116                     sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
117 }
118 
NeedsAutoBindingSet0(const RenderNodeHandles::InputResources & inputRes)119 bool NeedsAutoBindingSet0(const RenderNodeHandles::InputResources& inputRes)
120 {
121     uint32_t set0Bindings = 0;
122     for (const auto& res : inputRes.buffers) {
123         if (res.set == GLOBAL_POST_PROCESS_SET) {
124             set0Bindings++;
125         }
126     }
127     return (set0Bindings == 0);
128 }
129 
GetDefaultImagesAndSamplers(const IRenderNodeGpuResourceManager & gpuResourceMgr)130 RenderNodeCameraSinglePostProcess::DefaultImagesAndSamplers GetDefaultImagesAndSamplers(
131     const IRenderNodeGpuResourceManager& gpuResourceMgr)
132 {
133     RenderNodeCameraSinglePostProcess::DefaultImagesAndSamplers dias;
134     dias.cubemapHandle =
135         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
136     dias.linearHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
137     dias.nearestHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
138     dias.linearMipHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
139     dias.colorPrePassHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
140     return dias;
141 }
142 
143 struct DispatchResources {
144     RenderHandle buffer {};
145     RenderHandle image {};
146 };
147 
GetDispatchResources(const RenderNodeHandles::InputResources & ir)148 DispatchResources GetDispatchResources(const RenderNodeHandles::InputResources& ir)
149 {
150     DispatchResources dr;
151     if (!ir.customInputBuffers.empty()) {
152         dr.buffer = ir.customInputBuffers[0].handle;
153     }
154     if (!ir.customInputImages.empty()) {
155         dr.image = ir.customInputImages[0].handle;
156     }
157     return dr;
158 }
159 } // namespace
160 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)161 void RenderNodeCameraSinglePostProcess::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
162 {
163     renderNodeContextMgr_ = &renderNodeContextMgr;
164 
165     valid_ = true;
166     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
167     ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
168 
169     ParseRenderNodeInputs();
170     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
171     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
172         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
173     currentScene_ = {};
174 
175     shadowBuffers_ = GetShadowBufferNodeData(gpuResourceMgr, stores_.dataStoreNameScene);
176     defaultImagesAndSamplers_ = GetDefaultImagesAndSamplers(gpuResourceMgr);
177 
178     UpdateImageData();
179     ProcessPostProcessConfiguration();
180     GetSceneUniformBuffers(stores_.dataStoreNameScene);
181     if (!RenderHandleUtil::IsValid(shader_)) {
182         shader_ = ppLocalConfig_.shader.GetHandle();
183     }
184 
185     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
186     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
187     const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
188     pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
189     if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
190         graphics_ = true;
191         const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
192         psoHandle_ = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
193             shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
194     } else if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
195         graphics_ = false;
196         psoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(shader_, pipelineLayout_, {});
197         threadGroupSize_ = shaderMgr.GetReflectionThreadGroupSize(shader_);
198         if (dispatchResources_.customInputBuffers.empty() && dispatchResources_.customInputImages.empty()) {
199             valid_ = false;
200             CORE_LOG_W("RenderNodeCameraSinglePostProcess: dispatchResources (GPU buffer or GPU image) needed");
201         }
202     } else {
203         CORE_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
204     }
205     {
206         // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
207         const RenderHandle baseCamPlHandle =
208             shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT);
209         // when validation enabled compare to render post process pipeline layout as well
210 #if (CORE3D_VALIDATION_ENABLED == 1)
211         {
212             const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
213             const IShaderManager::CompatibilityFlags compatibilityFlags =
214                 shaderMgr.GetCompatibilityFlags(baseCamPlHandle, basePlHandle);
215             if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
216                 CORE_LOG_E("RN:%s uncompatible render vs 3D pipeline layout (%s)",
217                     renderNodeContextMgr_->GetName().data(), POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
218             }
219         }
220 #endif
221         const IShaderManager::CompatibilityFlags compatibilityFlags =
222             shaderMgr.GetCompatibilityFlags(baseCamPlHandle, plHandle);
223         if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
224             CORE_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
225                 POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
226         }
227     }
228 
229 #if (CORE3D_VALIDATION_ENABLED == 1)
230     // 3d does not operate on render built-in post processes
231     const uint32_t postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
232     if (postProcessFlag != 0) {
233         valid_ = false;
234         CORE_LOG_W("RN:%s does not execute render built-in post processes.", renderNodeContextMgr_->GetName().data());
235     }
236 #endif
237     InitCreateBinders();
238 
239     renderCopy_.Init(renderNodeContextMgr, {});
240 
241     RegisterOutputs();
242 }
243 
PreExecuteFrame()244 void RenderNodeCameraSinglePostProcess::PreExecuteFrame()
245 {
246     {
247         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
248         const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
249             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
250         const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
251             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
252         const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
253             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
254         const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
255         if (validRenderDataStore) {
256             UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
257         }
258     }
259 
260     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
261     if (jsonInputs_.hasChangeableResourceHandles) {
262         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
263     }
264     UpdateImageData();
265     ProcessPostProcessConfiguration();
266     RegisterOutputs();
267 }
268 
ExecuteFrame(IRenderCommandList & cmdList)269 void RenderNodeCameraSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
270 {
271     if ((!ppLocalConfig_.variables.enabled) &&
272         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
273         return;
274     }
275 
276     if (ppLocalConfig_.variables.enabled && valid_) {
277         ExecuteSinglePostProcess(cmdList);
278     } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
279         renderCopy_.Execute(*renderNodeContextMgr_, cmdList);
280     }
281 }
282 
ExecuteSinglePostProcess(IRenderCommandList & cmdList)283 void RenderNodeCameraSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
284 {
285     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
286     if (jsonInputs_.hasChangeableRenderPassHandles) {
287         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
288     }
289     if (jsonInputs_.hasChangeableResourceHandles) {
290         // input resources updated in preExecuteFrame
291         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
292     }
293     if (jsonInputs_.hasChangeableDispatchHandles) {
294         dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
295     }
296     if (useAutoBindSet0_) {
297         UpdateGlobalPostProcessUbo();
298     }
299 
300     RenderPass renderPass;
301     DispatchResources dispatchResources;
302     if (graphics_) {
303         renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
304         if ((renderPass.renderPassDesc.attachmentCount == 0) ||
305             !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
306 #if (CORE3D_VALIDATION_ENABLED == 1)
307             CORE_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(), "RN: %s, invalid attachment",
308                 renderNodeContextMgr_->GetName().data());
309 #endif
310             return;
311         }
312     } else {
313         dispatchResources = GetDispatchResources(dispatchResources_);
314         if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
315             (!RenderHandleUtil::IsValid(dispatchResources.image))) {
316             return; // no way to evaluate dispatch size
317         }
318     }
319 
320     const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
321     const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
322     const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
323     for (const auto refIndex : setIndices) {
324         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
325         // handle automatic set 0 bindings
326         if ((refIndex == 0) && useAutoBindSet0_) {
327             UpdateSet0(cmdList);
328         } else if (invalidBindings) {
329             const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
330             BindDefaultResources(refIndex, bindings);
331         }
332         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
333         cmdList.UpdateDescriptorSet(descHandle, bindings);
334     }
335 #if (CORE3D_VALIDATION_ENABLED == 1)
336     if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
337         CORE_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
338     }
339 #endif
340 
341     if (graphics_) {
342         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
343     }
344 
345     cmdList.BindPipeline(psoHandle_);
346 
347     // bind all sets
348     cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
349 
350     if (graphics_) {
351         // dynamic state
352         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
353         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
354         cmdList.SetDynamicStateViewport(viewportDesc);
355         cmdList.SetDynamicStateScissor(scissorDesc);
356         // push constants
357         if (pipelineLayout_.pushConstant.byteSize > 0) {
358             const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
359             const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
360             const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
361                 ppLocalConfig_.variables.factor };
362             cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
363         }
364 
365         cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
366         cmdList.EndRenderPass();
367     } else {
368         if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
369             cmdList.DispatchIndirect(dispatchResources.buffer, 0);
370         } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
371             const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
372             const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
373             const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
374             if (pipelineLayout_.pushConstant.byteSize > 0) {
375                 const float fWidth = static_cast<float>(targetSize.x);
376                 const float fHeight = static_cast<float>(targetSize.y);
377                 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
378                     ppLocalConfig_.variables.factor };
379                 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
380             }
381 
382             cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
383                 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
384                 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
385         }
386     }
387 }
388 
RegisterOutputs()389 void RenderNodeCameraSinglePostProcess::RegisterOutputs()
390 {
391     const RenderHandle output = builtInVariables_.output;
392     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
393     RenderHandle registerOutput;
394     if (ppLocalConfig_.variables.enabled) {
395         if (RenderHandleUtil::IsValid(output)) {
396             registerOutput = output;
397         }
398     }
399     if (!RenderHandleUtil::IsValid(registerOutput)) {
400         if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
401                 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
402             RenderHandleUtil::IsValid(output)) {
403             registerOutput = output;
404         } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
405                    RenderHandleUtil::IsValid(builtInVariables_.input)) {
406             registerOutput = builtInVariables_.input;
407         } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
408             registerOutput = builtInVariables_.defWhiteImage;
409         } else {
410             registerOutput = builtInVariables_.defBlackImage;
411         }
412     }
413     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
414 }
415 
UpdateSet0(IRenderCommandList & cmdList)416 void RenderNodeCameraSinglePostProcess::UpdateSet0(IRenderCommandList& cmdList)
417 {
418     const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
419     const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
420                                           ? currentScene_.prePassColorTarget
421                                           : defaultImagesAndSamplers_.colorPrePassHandle;
422 
423     auto& binder = *pipelineDescriptorSetBinder_;
424     uint32_t bindingIndex = 0;
425     // global
426     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
427     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++,
428         BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
429 
430     // scene and camera global
431     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { sceneBuffers_.camera });
432     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.generalData });
433 
434     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.environment });
435     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.fog });
436     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.light });
437     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.postProcess });
438     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.lightCluster });
439 
440     // scene and camera global images
441     BindableImage bi;
442     bi.handle = colorPrePass;
443     bi.samplerHandle = defaultImagesAndSamplers_.linearMipHandle;
444     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
445     bi.handle = shadowBuffers_.vsmColorHandle;
446     bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
447     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
448     bi.handle = shadowBuffers_.pcfDepthHandle;
449     bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
450     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
451     bi.handle = radianceCubemap;
452     bi.samplerHandle = defaultImagesAndSamplers_.cubemapHandle;
453     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
454 
455     // NOTE: UpdateDescriptorSets is done when called
456 }
457 
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)458 void RenderNodeCameraSinglePostProcess::BindDefaultResources(
459     const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
460 {
461     if (pipelineDescriptorSetBinder_) {
462         auto& binder = *pipelineDescriptorSetBinder_;
463         for (const auto& ref : bindings.buffers) {
464             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
465                 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
466             }
467         }
468         for (const auto& ref : bindings.images) {
469             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
470                 BindableImage bi;
471                 bi.handle = builtInVariables_.defBlackImage;
472                 bi.samplerHandle = builtInVariables_.defSampler;
473                 binder.BindImage(set, ref.binding.binding, bi);
474             }
475         }
476         for (const auto& ref : bindings.samplers) {
477             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
478                 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
479             }
480         }
481     }
482 }
483 
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)484 void RenderNodeCameraSinglePostProcess::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
485     const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
486 {
487     const auto scene = dataStoreScene.GetScene();
488     uint32_t cameraIdx = scene.cameraIndex;
489     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
490         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
491     } else if (!(jsonInputs_.customCameraName.empty())) {
492         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
493     }
494 
495     if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
496         // store current frame camera
497         currentScene_.camera = cameras[cameraIdx];
498     }
499     const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
500         *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
501     currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
502 
503     const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
504     currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
505     currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
506     currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
507 }
508 
ProcessPostProcessConfiguration()509 void RenderNodeCameraSinglePostProcess::ProcessPostProcessConfiguration()
510 {
511     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
512         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
513         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
514             if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
515                 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
516                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
517             }
518         }
519         if (const IRenderDataStorePod* ds =
520                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
521             ds) {
522             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
523             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
524                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
525             }
526         }
527     } else if (jsonInputs_.ppName.empty()) {
528         // if trying to just use shader without post processing we enable running by default
529         ppLocalConfig_.variables.enabled = true;
530     }
531 }
532 
UpdateGlobalPostProcessUbo()533 void RenderNodeCameraSinglePostProcess::UpdateGlobalPostProcessUbo()
534 {
535     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
536     const RenderPostProcessConfiguration rppc =
537         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
538     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
539     CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
540                        sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
541     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
542         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
543         // global data
544         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
545         // local data
546         data += sizeof(GlobalPostProcessStruct);
547         CloneData(
548             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
549         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
550     }
551 }
552 
GetSceneUniformBuffers(const string_view us)553 void RenderNodeCameraSinglePostProcess::GetSceneUniformBuffers(const string_view us)
554 {
555     sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
556 
557     string camName;
558     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
559         camName = to_string(jsonInputs_.customCameraId);
560     } else if (!(jsonInputs_.customCameraName.empty())) {
561         camName = jsonInputs_.customCameraName;
562     }
563     cameraBuffers_ =
564         RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
565 }
566 
InitCreateBinders()567 void RenderNodeCameraSinglePostProcess::InitCreateBinders()
568 {
569     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
570     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
571     {
572         DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
573         if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
574             const DescriptorCounts copyDc = renderCopy_.GetDescriptorCounts();
575             for (const auto& ref : copyDc.counts) {
576                 dc.counts.push_back(ref);
577             }
578         }
579         descriptorSetMgr.ResetAndReserve(dc);
580     }
581 
582     pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
583     if (pipelineDescriptorSetBinder_) {
584         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
585         if (NeedsAutoBindingSet0(inputResources_)) {
586             useAutoBindSet0_ = true;
587         }
588     } else {
589         valid_ = false;
590     }
591     if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
592         valid_ = false;
593     }
594 }
595 
ParseRenderNodeInputs()596 void RenderNodeCameraSinglePostProcess::ParseRenderNodeInputs()
597 {
598     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
599     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
600     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
601     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
602     jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
603     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
604 
605     jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
606     jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
607 
608     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
609 
610 #if (CORE3D_VALIDATION_ENABLED == 1)
611     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
612         CORE_LOG_W("CORE3D_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
613             renderNodeContextMgr_->GetName().data());
614     }
615     if (jsonInputs_.ppName.empty()) {
616         CORE_LOG_W("CORE3D_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
617     }
618 #endif
619 
620     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
621     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
622     if (!shaderName.empty()) {
623         shader_ = shaderMgr.GetShaderHandle(shaderName);
624     }
625     const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
626     if (!defaultOutput.empty()) {
627         if (defaultOutput == "output") {
628             jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
629         } else if (defaultOutput == "input_output_copy") {
630             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
631         } else if (defaultOutput == "input") {
632             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
633         } else if (defaultOutput == "black") {
634             jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
635         } else if (defaultOutput == "white") {
636             jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
637         } else {
638             CORE_LOG_W(
639                 "RenderNodeCameraSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
640         }
641     }
642 
643     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
644     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
645     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
646     dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
647 
648     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
649     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
650     jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
651 
652     // process custom resources
653     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
654         const auto& ref = jsonInputs_.resources.customInputImages[idx];
655         if (ref.usageName == INPUT) {
656             jsonInputs_.inputIdx = idx;
657         }
658     }
659     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
660         const auto& ref = jsonInputs_.resources.customOutputImages[idx];
661         if (ref.usageName == OUTPUT) {
662             jsonInputs_.outputIdx = idx;
663         }
664     }
665 }
666 
UpdateImageData()667 void RenderNodeCameraSinglePostProcess::UpdateImageData()
668 {
669     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
670     if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
671         builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
672     }
673     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
674         builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
675     }
676     if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
677         builtInVariables_.defWhiteImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
678     }
679     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
680         builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
681     }
682     if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
683         builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
684     }
685     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
686         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
687     }
688 }
689 
690 // for plugin / factory interface
Create()691 IRenderNode* RenderNodeCameraSinglePostProcess::Create()
692 {
693     return new RenderNodeCameraSinglePostProcess();
694 }
695 
Destroy(IRenderNode * instance)696 void RenderNodeCameraSinglePostProcess::Destroy(IRenderNode* instance)
697 {
698     delete static_cast<RenderNodeCameraSinglePostProcess*>(instance);
699 }
700 CORE3D_END_NAMESPACE()
701