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_cubemap.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 uint32_t LOCAL_POST_PROCESS_SET { 1u };
53 constexpr uint32_t MAX_MIP_COUNT { 16U };
54 constexpr string_view RENDER_DATA_STORE_POD_NAME { "RenderDataStorePod" };
55 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_NAME { "RenderDataStorePostProcess" };
56 
57 constexpr string_view CORE_DEFAULT_GPU_IMAGE_BLACK { "CORE_DEFAULT_GPU_IMAGE" };
58 constexpr string_view CORE_DEFAULT_GPU_IMAGE_WHITE { "CORE_DEFAULT_GPU_IMAGE_WHITE" };
59 
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 
GetShadowBufferNodeData(const IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view sceneName)65 RenderNodeCameraCubemap::ShadowBuffers GetShadowBufferNodeData(
66     const IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view sceneName)
67 {
68     RenderNodeCameraCubemap::ShadowBuffers sb;
69     sb.vsmSamplerHandle =
70         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER);
71     sb.pcfSamplerHandle =
72         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER);
73 
74     sb.pcfDepthHandle =
75         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME);
76     sb.vsmColorHandle =
77         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME);
78     if (!RenderHandleUtil::IsValid(sb.pcfDepthHandle)) {
79         sb.pcfDepthHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
80     }
81     if (!RenderHandleUtil::IsValid(sb.vsmColorHandle)) {
82         sb.vsmColorHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
83     }
84 
85     return sb;
86 }
87 
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)88 RenderHandleReference CreatePostProcessDataUniformBuffer(
89     IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
90 {
91     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
92     CORE_STATIC_ASSERT(
93         sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
94     return gpuResourceMgr.Create(
95         handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
96                     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
97                     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
98                     sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
99 }
100 
GetDefaultImagesAndSamplers(const IRenderNodeGpuResourceManager & gpuResourceMgr)101 RenderNodeCameraCubemap::DefaultImagesAndSamplers GetDefaultImagesAndSamplers(
102     const IRenderNodeGpuResourceManager& gpuResourceMgr)
103 {
104     RenderNodeCameraCubemap::DefaultImagesAndSamplers dias;
105     dias.cubemapSamplerHandle =
106         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
107     dias.linearHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
108     dias.nearestHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
109     dias.linearMipHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
110     dias.colorPrePassHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
111     dias.skyBoxRadianceCubemapHandle =
112         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP);
113     return dias;
114 }
115 } // namespace
116 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)117 void RenderNodeCameraCubemap::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
118 {
119     renderNodeContextMgr_ = &renderNodeContextMgr;
120 
121     valid_ = true;
122     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
123     ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
124 
125     ParseRenderNodeInputs();
126     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
127     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
128         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
129     currentScene_ = {};
130 
131     shadowBuffers_ = GetShadowBufferNodeData(gpuResourceMgr, stores_.dataStoreNameScene);
132     defaultImagesAndSamplers_ = GetDefaultImagesAndSamplers(gpuResourceMgr);
133 
134     UpdateImageData();
135     ProcessPostProcessConfiguration();
136     GetSceneUniformBuffers(stores_.dataStoreNameScene);
137     if (!RenderHandleUtil::IsValid(shader_)) {
138         shader_ = ppLocalConfig_.shader.GetHandle();
139     }
140 
141     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
142     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
143     const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
144     pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
145     if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
146         const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
147         psoHandle_ = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
148             shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
149     } else {
150         CORE_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
151     }
152     {
153         // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
154         const RenderHandle baseCamPlHandle =
155             shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT);
156         // when validation enabled compare to render post process pipeline layout as well
157 #if (CORE3D_VALIDATION_ENABLED == 1)
158         {
159             const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
160             const IShaderManager::CompatibilityFlags compatibilityFlags =
161                 shaderMgr.GetCompatibilityFlags(baseCamPlHandle, basePlHandle);
162             if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
163                 CORE_LOG_E("RN:%s uncompatible render vs 3D pipeline layout (%s)",
164                     renderNodeContextMgr_->GetName().data(), POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
165             }
166         }
167 #endif
168         const IShaderManager::CompatibilityFlags compatibilityFlags =
169             shaderMgr.GetCompatibilityFlags(baseCamPlHandle, plHandle);
170         if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
171             CORE_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
172                 POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
173         }
174     }
175     InitCreateBinders();
176 
177     RegisterOutputs();
178 }
179 
PreExecuteFrame()180 void RenderNodeCameraCubemap::PreExecuteFrame()
181 {
182     {
183         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
184         const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
185             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
186         const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
187             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
188         const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
189             renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
190         const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
191         if (validRenderDataStore) {
192             UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
193         }
194     }
195 
196     UpdateImageData();
197     ProcessPostProcessConfiguration();
198     RegisterOutputs();
199 }
200 
ExecuteFrame(IRenderCommandList & cmdList)201 void RenderNodeCameraCubemap::ExecuteFrame(IRenderCommandList& cmdList)
202 {
203     if ((!ppLocalConfig_.variables.enabled)) {
204         return;
205     }
206 
207     if (ppLocalConfig_.variables.enabled && valid_ && RenderHandleUtil::IsValid(builtInVariables_.output)) {
208         ExecuteSinglePostProcess(cmdList);
209     }
210 }
211 
212 namespace {
213 constexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED };
214 constexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
215     CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
216 constexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
217     CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
218 } // namespace
219 
ExecuteSinglePostProcess(IRenderCommandList & cmdList)220 void RenderNodeCameraCubemap::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
221 {
222     Math::UVec2 currSize = builtInVariables_.outputSize;
223 
224     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
225     RenderPass renderPass;
226     renderPass.renderPassDesc.attachmentCount = 1U;
227     renderPass.renderPassDesc.attachmentHandles[0U] = builtInVariables_.output;
228     renderPass.renderPassDesc.attachments[0U].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
229     renderPass.renderPassDesc.attachments[0U].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
230     renderPass.renderPassDesc.attachments[0U].layer = 0U;
231     renderPass.renderPassDesc.renderArea = { 0U, 0U, currSize.x, currSize.y };
232     renderPass.renderPassDesc.subpassCount = 1U;
233     renderPass.subpassDesc.viewMask = 0x3f;
234     renderPass.subpassDesc.colorAttachmentCount = 1U;
235     renderPass.subpassDesc.colorAttachmentIndices[0U] = 0U;
236 
237     if ((renderPass.renderPassDesc.attachmentCount == 0) ||
238         !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
239 #if (CORE3D_VALIDATION_ENABLED == 1)
240         CORE_LOG_ONCE_W("rp_cm_missing_" + renderNodeContextMgr_->GetName(), "RN: %s, invalid attachment",
241             renderNodeContextMgr_->GetName().data());
242 #endif
243         return;
244     }
245 
246     UpdateGlobalPostProcessUbo();
247     {
248         // handle automatic set 0 bindings
249         UpdateSet0(cmdList);
250         const auto bindings = globalSet0_->GetDescriptorSetLayoutBindingResources();
251         cmdList.UpdateDescriptorSet(globalSet0_->GetDescriptorSetHandle(), bindings);
252     }
253     for (uint32_t mipIdx = 0; mipIdx < builtInVariables_.outputMipCount; ++mipIdx) {
254         // handle automatic set 1 bindings
255         UpdateSet1(cmdList, mipIdx);
256         const auto bindings = localSets_[mipIdx]->GetDescriptorSetLayoutBindingResources();
257         cmdList.UpdateDescriptorSet(localSets_[mipIdx]->GetDescriptorSetHandle(), bindings);
258     }
259 
260     cmdList.BeginDisableAutomaticBarrierPoints();
261 
262     // change all the layouts accordingly
263     {
264         ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0,
265             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
266         cmdList.CustomImageBarrier(builtInVariables_.output, SRC_UNDEFINED, COL_ATTACHMENT, imageSubresourceRange);
267         cmdList.AddCustomBarrierPoint();
268     }
269 
270     for (uint32_t mipIdx = 0; mipIdx < builtInVariables_.outputMipCount; ++mipIdx) {
271         renderPass.renderPassDesc.attachments[0U].mipLevel = mipIdx;
272         if (mipIdx != 0U) {
273             currSize.x = Math::max(1U, currSize.x / 2U);
274             currSize.y = Math::max(1U, currSize.y / 2U);
275         }
276         renderPass.renderPassDesc.renderArea = { 0U, 0U, currSize.x, currSize.y };
277 
278         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
279 
280         cmdList.BindPipeline(psoHandle_);
281         // bind all sets
282         {
283             RenderHandle sets[2U] { globalSet0_->GetDescriptorSetHandle(),
284                 localSets_[mipIdx]->GetDescriptorSetHandle() };
285             cmdList.BindDescriptorSets(0u, sets);
286         }
287 
288         // dynamic state
289         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
290         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
291         cmdList.SetDynamicStateViewport(viewportDesc);
292         cmdList.SetDynamicStateScissor(scissorDesc);
293         // push constants
294         if (pipelineLayout_.pushConstant.byteSize > 0) {
295             const float fWidth = static_cast<float>(currSize.x);
296             const float fHeight = static_cast<float>(currSize.y);
297             const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
298                 ppLocalConfig_.variables.factor };
299             cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
300         }
301 
302         cmdList.Draw(3u, 1u, 0u, 0u);
303         cmdList.EndRenderPass();
304     }
305 
306     // change all the layouts accordingly
307     {
308         ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0,
309             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
310         cmdList.CustomImageBarrier(builtInVariables_.output, COL_ATTACHMENT, SHDR_READ, imageSubresourceRange);
311         cmdList.AddCustomBarrierPoint();
312     }
313 
314     cmdList.EndDisableAutomaticBarrierPoints();
315 }
316 
RegisterOutputs()317 void RenderNodeCameraCubemap::RegisterOutputs()
318 {
319     const RenderHandle output = builtInVariables_.output;
320     IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
321     RenderHandle registerOutput;
322     if (ppLocalConfig_.variables.enabled) {
323         if (RenderHandleUtil::IsValid(output)) {
324             registerOutput = output;
325         }
326     }
327     if (!RenderHandleUtil::IsValid(registerOutput)) {
328         registerOutput = defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle;
329     }
330     shrMgr.RegisterRenderNodeOutput("output", registerOutput);
331 }
332 
UpdateSet0(IRenderCommandList & cmdList)333 void RenderNodeCameraCubemap::UpdateSet0(IRenderCommandList& cmdList)
334 {
335     const RenderHandle radianceCubemap = (currentScene_.camera.environment.radianceCubemap)
336                                              ? currentScene_.camera.environment.radianceCubemap.GetHandle()
337                                              : defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle;
338     const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
339                                           ? currentScene_.prePassColorTarget
340                                           : defaultImagesAndSamplers_.colorPrePassHandle;
341 
342     auto& binder = *globalSet0_;
343     uint32_t bindingIndex = 0;
344     // global
345     binder.BindBuffer(bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
346     binder.BindBuffer(
347         bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
348 
349     // scene and camera global
350     binder.BindBuffer(bindingIndex++, { sceneBuffers_.camera });
351     binder.BindBuffer(bindingIndex++, { cameraBuffers_.generalData });
352 
353     binder.BindBuffer(bindingIndex++, { cameraBuffers_.environment });
354     binder.BindBuffer(bindingIndex++, { cameraBuffers_.fog });
355     binder.BindBuffer(bindingIndex++, { cameraBuffers_.light });
356     binder.BindBuffer(bindingIndex++, { cameraBuffers_.postProcess });
357     binder.BindBuffer(bindingIndex++, { cameraBuffers_.lightCluster });
358 
359     // scene and camera global images
360     BindableImage bi;
361     bi.handle = colorPrePass;
362     bi.samplerHandle = defaultImagesAndSamplers_.linearMipHandle;
363     binder.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
364     bi.handle = shadowBuffers_.vsmColorHandle;
365     bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
366     binder.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
367     bi.handle = shadowBuffers_.pcfDepthHandle;
368     bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
369     binder.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
370     bi.handle = radianceCubemap;
371     bi.samplerHandle = defaultImagesAndSamplers_.cubemapSamplerHandle;
372     binder.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
373 
374     // NOTE: UpdateDescriptorSets is done when called
375 }
376 
UpdateSet1(IRenderCommandList & cmdList,const uint32_t idx)377 void RenderNodeCameraCubemap::UpdateSet1(IRenderCommandList& cmdList, const uint32_t idx)
378 {
379     // bind all radiance cubemaps
380     auto& binder = *localSets_[idx];
381     // local
382     const auto res = binder.GetDescriptorSetLayoutBindingResources();
383     const auto bindings = res.bindings;
384     const uint32_t maxCount =
385         Math::min(DefaultMaterialCameraConstants::MAX_ENVIRONMENT_COUNT, static_cast<uint32_t>(bindings.size()));
386     BindableImage bi;
387     for (uint32_t resIdx = 0U; resIdx < maxCount; ++resIdx) {
388         // filled with valid handles
389         bi.handle = currentScene_.cameraEnvRadianceHandles[resIdx];
390         bi.samplerHandle = defaultImagesAndSamplers_.cubemapSamplerHandle;
391         binder.BindImage(resIdx, bi, {});
392     }
393 }
394 
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)395 void RenderNodeCameraCubemap::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
396     const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
397 {
398     const auto scene = dataStoreScene.GetScene();
399     uint32_t cameraIdx = scene.cameraIndex;
400     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
401         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
402         currentScene_.cameraName = to_string(jsonInputs_.customCameraId);
403     } else if (!(jsonInputs_.customCameraName.empty())) {
404         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
405         currentScene_.cameraName = jsonInputs_.customCameraName;
406     }
407 
408     if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
409         // store current frame camera
410         currentScene_.camera = cameras[cameraIdx];
411     }
412     // fetch all the radiance cubemaps
413     for (uint32_t idx = 0; idx < DefaultMaterialCameraConstants::MAX_ENVIRONMENT_COUNT; ++idx) {
414         if (idx < currentScene_.camera.environmentCount) {
415             const auto& env = dataStoreCamera.GetEnvironment(currentScene_.camera.environmentIds[idx]);
416             currentScene_.cameraEnvRadianceHandles[idx] = (env.radianceCubemap)
417                                                               ? env.radianceCubemap.GetHandle()
418                                                               : defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle;
419 
420         } else {
421             currentScene_.cameraEnvRadianceHandles[idx] = defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle;
422         }
423     }
424 
425     const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
426     currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
427     currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
428     currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
429 }
430 
ProcessPostProcessConfiguration()431 void RenderNodeCameraCubemap::ProcessPostProcessConfiguration()
432 {
433     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
434         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
435         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
436             if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
437                 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
438                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
439             }
440         }
441         if (const IRenderDataStorePod* ds =
442                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
443             ds) {
444             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
445             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
446                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
447             }
448         }
449     } else if (jsonInputs_.ppName.empty()) {
450         // if trying to just use shader without post processing we enable running by default
451         ppLocalConfig_.variables.enabled = true;
452     }
453 }
454 
UpdateGlobalPostProcessUbo()455 void RenderNodeCameraCubemap::UpdateGlobalPostProcessUbo()
456 {
457     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
458     const RenderPostProcessConfiguration rppc =
459         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
460     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
461     CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
462                        sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
463     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
464         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
465         // global data
466         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
467         // local data
468         data += sizeof(GlobalPostProcessStruct);
469         CloneData(
470             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
471         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
472     }
473 }
474 
GetSceneUniformBuffers(const string_view us)475 void RenderNodeCameraCubemap::GetSceneUniformBuffers(const string_view us)
476 {
477     sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
478 
479     string camName;
480     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
481         camName = to_string(jsonInputs_.customCameraId);
482     } else if (!(jsonInputs_.customCameraName.empty())) {
483         camName = jsonInputs_.customCameraName;
484     }
485     cameraBuffers_ =
486         RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
487 }
488 
InitCreateBinders()489 void RenderNodeCameraCubemap::InitCreateBinders()
490 {
491     const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
492     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
493     {
494         DescriptorCounts dc0 = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
495         const DescriptorCounts dc1 =
496             renderNodeUtil.GetDescriptorCounts(pipelineLayout_.descriptorSetLayouts[LOCAL_POST_PROCESS_SET].bindings);
497         for (uint32_t layerIdx = 0; layerIdx < MAX_MIP_COUNT; ++layerIdx) {
498             dc0.counts.insert(dc0.counts.end(), dc1.counts.begin(), dc1.counts.end());
499         }
500         descriptorSetMgr.ResetAndReserve(dc0);
501     }
502 
503     localSets_.clear();
504     localSets_.resize(MAX_MIP_COUNT);
505     {
506         const auto& bindings = pipelineLayout_.descriptorSetLayouts[GLOBAL_POST_PROCESS_SET].bindings;
507         const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
508         globalSet0_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
509     }
510     {
511         const auto& bindings = pipelineLayout_.descriptorSetLayouts[LOCAL_POST_PROCESS_SET].bindings;
512         for (uint32_t idx = 0; idx < MAX_MIP_COUNT; ++idx) {
513             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
514             localSets_[idx] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
515         }
516     }
517 
518     if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
519         valid_ = false;
520     }
521 }
522 
ParseRenderNodeInputs()523 void RenderNodeCameraCubemap::ParseRenderNodeInputs()
524 {
525     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
526     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
527     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
528 
529     jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
530     jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
531 
532     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
533 
534 #if (CORE3D_VALIDATION_ENABLED == 1)
535     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
536         CORE_LOG_W("CORE3D_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
537             renderNodeContextMgr_->GetName().data());
538     }
539     if (jsonInputs_.ppName.empty()) {
540         CORE_LOG_W("CORE3D_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
541     }
542 #endif
543 
544     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
545     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
546     if (!shaderName.empty()) {
547         shader_ = shaderMgr.GetShaderHandle(shaderName);
548     }
549 }
550 
UpdateImageData()551 void RenderNodeCameraCubemap::UpdateImageData()
552 {
553     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
554     if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
555         builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
556     }
557     if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
558         builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
559     }
560     if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
561         builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
562     }
563     if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
564         builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
565     }
566     builtInVariables_.outputSize = Math::UVec2(1U, 1U);
567     builtInVariables_.outputMipCount = 1U;
568     if (!RenderHandleUtil::IsValid(builtInVariables_.output)) {
569         builtInVariables_.output = gpuResourceMgr.GetImageHandle(
570             stores_.dataStoreNameScene + DefaultMaterialCameraConstants::CAMERA_COLOR_PREFIX_NAME +
571             "RADIANCE_CUBEMAP_" + currentScene_.camera.name);
572     }
573     if (RenderHandleUtil::IsValid(builtInVariables_.output)) {
574         const auto& desc = gpuResourceMgr.GetImageDescriptor(builtInVariables_.output);
575         builtInVariables_.outputSize = Math::UVec2(desc.width, desc.height);
576         builtInVariables_.outputMipCount = desc.mipCount;
577     }
578 }
579 
580 // for plugin / factory interface
Create()581 IRenderNode* RenderNodeCameraCubemap::Create()
582 {
583     return new RenderNodeCameraCubemap();
584 }
585 
Destroy(IRenderNode * instance)586 void RenderNodeCameraCubemap::Destroy(IRenderNode* instance)
587 {
588     delete static_cast<RenderNodeCameraCubemap*>(instance);
589 }
590 CORE3D_END_NAMESPACE()
591