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