• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_node_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     RegisterOutputs();
240 }
241 
PreExecuteFrame()242 void RenderNodeCameraSinglePostProcess::PreExecuteFrame()
243 {
244     {
245         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
246         const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
247             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
248         const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
249             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
250         const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
251             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
252         const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
253         if (validRenderDataStore) {
254             UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
255         }
256     }
257 
258     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
259     if (jsonInputs_.hasChangeableResourceHandles) {
260         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
261     }
262     UpdateImageData();
263     ProcessPostProcessConfiguration();
264     RegisterOutputs();
265 }
266 
ExecuteFrame(IRenderCommandList & cmdList)267 void RenderNodeCameraSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
268 {
269     if ((!ppLocalConfig_.variables.enabled) &&
270         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
271         return;
272     }
273 
274     if (ppLocalConfig_.variables.enabled && valid_) {
275         ExecuteSinglePostProcess(cmdList);
276     }
277 }
278 
ExecuteSinglePostProcess(IRenderCommandList & cmdList)279 void RenderNodeCameraSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
280 {
281     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
282     if (jsonInputs_.hasChangeableRenderPassHandles) {
283         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
284     }
285     if (jsonInputs_.hasChangeableResourceHandles) {
286         // input resources updated in preExecuteFrame
287         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
288     }
289     if (jsonInputs_.hasChangeableDispatchHandles) {
290         dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
291     }
292     if (useAutoBindSet0_) {
293         UpdateGlobalPostProcessUbo();
294     }
295 
296     RenderPass renderPass;
297     DispatchResources dispatchResources;
298     if (graphics_) {
299         renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
300         if ((renderPass.renderPassDesc.attachmentCount == 0) ||
301             !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
302 #if (CORE3D_VALIDATION_ENABLED == 1)
303             CORE_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(), "RN: %s, invalid attachment",
304                 renderNodeContextMgr_->GetName().data());
305 #endif
306             return;
307         }
308     } else {
309         dispatchResources = GetDispatchResources(dispatchResources_);
310         if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
311             (!RenderHandleUtil::IsValid(dispatchResources.image))) {
312             return; // no way to evaluate dispatch size
313         }
314     }
315 
316     const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
317     const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
318     const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
319     for (const auto refIndex : setIndices) {
320         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
321         // handle automatic set 0 bindings
322         if ((refIndex == 0) && useAutoBindSet0_) {
323             UpdateSet0(cmdList);
324         } else if (invalidBindings) {
325             const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
326             BindDefaultResources(refIndex, bindings);
327         }
328         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
329         cmdList.UpdateDescriptorSet(descHandle, bindings);
330     }
331 #if (CORE3D_VALIDATION_ENABLED == 1)
332     if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
333         CORE_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
334     }
335 #endif
336 
337     if (graphics_) {
338         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
339     }
340 
341     cmdList.BindPipeline(psoHandle_);
342 
343     // bind all sets
344     cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
345 
346     if (graphics_) {
347         // dynamic state
348         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
349         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
350         cmdList.SetDynamicStateViewport(viewportDesc);
351         cmdList.SetDynamicStateScissor(scissorDesc);
352         // push constants
353         if (pipelineLayout_.pushConstant.byteSize > 0) {
354             const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
355             const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
356             const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
357                 ppLocalConfig_.variables.factor };
358             cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
359         }
360 
361         cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
362         cmdList.EndRenderPass();
363     } else {
364         if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
365             cmdList.DispatchIndirect(dispatchResources.buffer, 0);
366         } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
367             const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
368             const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
369             const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
370             if (pipelineLayout_.pushConstant.byteSize > 0) {
371                 const float fWidth = static_cast<float>(targetSize.x);
372                 const float fHeight = static_cast<float>(targetSize.y);
373                 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
374                     ppLocalConfig_.variables.factor };
375                 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
376             }
377 
378             cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
379                 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
380                 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
381         }
382     }
383 }
384 
RegisterOutputs()385 void RenderNodeCameraSinglePostProcess::RegisterOutputs()
386 {
387     const RenderHandle output = builtInVariables_.output;
388     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
389     RenderHandle registerOutput;
390     if (ppLocalConfig_.variables.enabled) {
391         if (RenderHandleUtil::IsValid(output)) {
392             registerOutput = output;
393         }
394     }
395     if (!RenderHandleUtil::IsValid(registerOutput)) {
396         if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
397                 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
398             RenderHandleUtil::IsValid(output)) {
399             registerOutput = output;
400         } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
401                    RenderHandleUtil::IsValid(builtInVariables_.input)) {
402             registerOutput = builtInVariables_.input;
403         } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
404             registerOutput = builtInVariables_.defWhiteImage;
405         } else {
406             registerOutput = builtInVariables_.defBlackImage;
407         }
408     }
409     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
410 }
411 
UpdateSet0(IRenderCommandList & cmdList)412 void RenderNodeCameraSinglePostProcess::UpdateSet0(IRenderCommandList& cmdList)
413 {
414     const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
415     const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
416                                           ? currentScene_.prePassColorTarget
417                                           : defaultImagesAndSamplers_.colorPrePassHandle;
418 
419     auto& binder = *pipelineDescriptorSetBinder_;
420     uint32_t bindingIndex = 0;
421     // global
422     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
423     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++,
424         BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
425 
426     // scene and camera global
427     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { sceneBuffers_.camera });
428     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.generalData });
429 
430     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.environment });
431     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.fog });
432     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.light });
433     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.postProcess });
434     binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.lightCluster });
435 
436     // scene and camera global images
437     BindableImage bi;
438     bi.handle = colorPrePass;
439     bi.samplerHandle = defaultImagesAndSamplers_.linearMipHandle;
440     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
441     bi.handle = shadowBuffers_.vsmColorHandle;
442     bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
443     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
444     bi.handle = shadowBuffers_.pcfDepthHandle;
445     bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
446     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
447     bi.handle = radianceCubemap;
448     bi.samplerHandle = defaultImagesAndSamplers_.cubemapHandle;
449     binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
450 
451     // NOTE: UpdateDescriptorSets is done when called
452 }
453 
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)454 void RenderNodeCameraSinglePostProcess::BindDefaultResources(
455     const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
456 {
457     if (pipelineDescriptorSetBinder_) {
458         auto& binder = *pipelineDescriptorSetBinder_;
459         for (const auto& ref : bindings.buffers) {
460             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
461                 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
462             }
463         }
464         for (const auto& ref : bindings.images) {
465             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
466                 BindableImage bi;
467                 bi.handle = builtInVariables_.defBlackImage;
468                 bi.samplerHandle = builtInVariables_.defSampler;
469                 binder.BindImage(set, ref.binding.binding, bi);
470             }
471         }
472         for (const auto& ref : bindings.samplers) {
473             if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
474                 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
475             }
476         }
477     }
478 }
479 
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)480 void RenderNodeCameraSinglePostProcess::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
481     const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
482 {
483     const auto scene = dataStoreScene.GetScene();
484     uint32_t cameraIdx = scene.cameraIndex;
485     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
486         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
487     } else if (!(jsonInputs_.customCameraName.empty())) {
488         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
489     }
490 
491     if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
492         // store current frame camera
493         currentScene_.camera = cameras[cameraIdx];
494     }
495     const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
496         *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
497     currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
498 
499     const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
500     currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
501     currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
502     currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
503 }
504 
ProcessPostProcessConfiguration()505 void RenderNodeCameraSinglePostProcess::ProcessPostProcessConfiguration()
506 {
507     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
508         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
509         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
510             if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
511                 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
512                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
513             }
514         }
515         if (const IRenderDataStorePod* ds =
516                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
517             ds) {
518             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
519             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
520                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
521             }
522         }
523     } else if (jsonInputs_.ppName.empty()) {
524         // if trying to just use shader without post processing we enable running by default
525         ppLocalConfig_.variables.enabled = true;
526     }
527 }
528 
UpdateGlobalPostProcessUbo()529 void RenderNodeCameraSinglePostProcess::UpdateGlobalPostProcessUbo()
530 {
531     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
532     const RenderPostProcessConfiguration rppc =
533         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
534     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
535     CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
536                        sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
537     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
538         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
539         // global data
540         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
541         // local data
542         data += sizeof(GlobalPostProcessStruct);
543         CloneData(
544             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
545         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
546     }
547 }
548 
GetSceneUniformBuffers(const string_view us)549 void RenderNodeCameraSinglePostProcess::GetSceneUniformBuffers(const string_view us)
550 {
551     sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
552 
553     string camName;
554     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
555         camName = to_string(jsonInputs_.customCameraId);
556     } else if (!(jsonInputs_.customCameraName.empty())) {
557         camName = jsonInputs_.customCameraName;
558     }
559     cameraBuffers_ =
560         RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
561 }
562 
InitCreateBinders()563 void RenderNodeCameraSinglePostProcess::InitCreateBinders()
564 {
565     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
566     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
567     {
568         DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
569         descriptorSetMgr.ResetAndReserve(dc);
570     }
571 
572     pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
573     if (pipelineDescriptorSetBinder_) {
574         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
575         if (NeedsAutoBindingSet0(inputResources_)) {
576             useAutoBindSet0_ = true;
577         }
578     } else {
579         valid_ = false;
580     }
581     if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
582         valid_ = false;
583     }
584 }
585 
ParseRenderNodeInputs()586 void RenderNodeCameraSinglePostProcess::ParseRenderNodeInputs()
587 {
588     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
589     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
590     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
591     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
592     jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
593     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
594 
595     jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
596     jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
597 
598     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
599 
600 #if (CORE3D_VALIDATION_ENABLED == 1)
601     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
602         CORE_LOG_W("CORE3D_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
603             renderNodeContextMgr_->GetName().data());
604     }
605     if (jsonInputs_.ppName.empty()) {
606         CORE_LOG_W("CORE3D_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
607     }
608 #endif
609 
610     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
611     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
612     if (!shaderName.empty()) {
613         shader_ = shaderMgr.GetShaderHandle(shaderName);
614     }
615     const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
616     if (!defaultOutput.empty()) {
617         if (defaultOutput == "output") {
618             jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
619         } else if (defaultOutput == "input_output_copy") {
620             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
621         } else if (defaultOutput == "input") {
622             jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
623         } else if (defaultOutput == "black") {
624             jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
625         } else if (defaultOutput == "white") {
626             jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
627         } else {
628             CORE_LOG_W(
629                 "RenderNodeCameraSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
630         }
631     }
632 
633     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
634     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
635     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
636     dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
637 
638     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
639     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
640     jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
641 
642     // process custom resources
643     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
644         const auto& ref = jsonInputs_.resources.customInputImages[idx];
645         if (ref.usageName == INPUT) {
646             jsonInputs_.inputIdx = idx;
647         }
648     }
649     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
650         const auto& ref = jsonInputs_.resources.customOutputImages[idx];
651         if (ref.usageName == OUTPUT) {
652             jsonInputs_.outputIdx = idx;
653         }
654     }
655 }
656 
UpdateImageData()657 void RenderNodeCameraSinglePostProcess::UpdateImageData()
658 {
659     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
660     if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
661         builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
662     }
663     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
664         builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
665     }
666     if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
667         builtInVariables_.defWhiteImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
668     }
669     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
670         builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
671     }
672     if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
673         builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
674     }
675     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
676         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
677     }
678 }
679 
680 // for plugin / factory interface
Create()681 IRenderNode* RenderNodeCameraSinglePostProcess::Create()
682 {
683     return new RenderNodeCameraSinglePostProcess();
684 }
685 
Destroy(IRenderNode * instance)686 void RenderNodeCameraSinglePostProcess::Destroy(IRenderNode* instance)
687 {
688     delete static_cast<RenderNodeCameraSinglePostProcess*>(instance);
689 }
690 CORE3D_END_NAMESPACE()
691