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_default_material_deferred_shading.h"
17 
18 #include <algorithm>
19 
20 #include <3d/render/default_material_constants.h>
21 #include <3d/render/intf_render_data_store_default_camera.h>
22 #include <3d/render/intf_render_data_store_default_light.h>
23 #include <3d/render/intf_render_data_store_default_scene.h>
24 #include <3d/render/render_data_defines_3d.h>
25 #include <base/containers/string.h>
26 #include <base/math/matrix.h>
27 #include <base/math/matrix_util.h>
28 #include <core/log.h>
29 #include <core/namespace.h>
30 #include <render/datastore/intf_render_data_store.h>
31 #include <render/datastore/intf_render_data_store_manager.h>
32 #include <render/datastore/intf_render_data_store_pod.h>
33 #include <render/datastore/render_data_store_render_pods.h>
34 #include <render/device/intf_gpu_resource_manager.h>
35 #include <render/device/intf_shader_manager.h>
36 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
37 #include <render/nodecontext/intf_node_context_pso_manager.h>
38 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
39 #include <render/nodecontext/intf_render_command_list.h>
40 #include <render/nodecontext/intf_render_node_context_manager.h>
41 #include <render/nodecontext/intf_render_node_parser_util.h>
42 #include <render/nodecontext/intf_render_node_util.h>
43 
44 #include "render/render_node_scene_util.h"
45 
46 namespace {
47 #include <3d/shaders/common/3d_dm_structures_common.h>
48 #include <render/shaders/common/render_post_process_structs_common.h>
49 } // namespace
50 CORE3D_BEGIN_NAMESPACE()
51 using namespace BASE_NS;
52 using namespace RENDER_NS;
53 
54 namespace {
55 constexpr string_view RENDER_DATA_STORE_POD_NAME { "RenderDataStorePod" };
56 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_NAME { "RenderDataStorePostProcess" };
57 constexpr uint32_t BUILT_IN_SETS_COUNT { 2u };
58 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
59 
GetShadowBufferNodeData(IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view sceneName)60 RenderNodeDefaultMaterialDeferredShading::ShadowBuffers GetShadowBufferNodeData(
61     IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view sceneName)
62 {
63     RenderNodeDefaultMaterialDeferredShading::ShadowBuffers sb;
64     sb.vsmSamplerHandle =
65         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER);
66     sb.pcfSamplerHandle =
67         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER);
68 
69     sb.pcfDepthHandle =
70         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME);
71     sb.vsmColorHandle =
72         gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME);
73     if (!RenderHandleUtil::IsValid(sb.pcfDepthHandle)) {
74         sb.pcfDepthHandle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE_WHITE");
75     }
76     if (!RenderHandleUtil::IsValid(sb.vsmColorHandle)) {
77         sb.vsmColorHandle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
78     }
79 
80     return sb;
81 }
82 
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)83 RenderHandleReference CreatePostProcessDataUniformBuffer(
84     IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
85 {
86     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
87     CORE_STATIC_ASSERT(
88         sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
89     return gpuResourceMgr.Create(
90         handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
91                     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
92                     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
93                     sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
94 }
95 } // namespace
96 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)97 void RenderNodeDefaultMaterialDeferredShading::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
98 {
99     renderNodeContextMgr_ = &renderNodeContextMgr;
100     allShaderData_ = {};
101     ParseRenderNodeInputs();
102 
103     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
104     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
105         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
106 
107     allDescriptorSets_ = {};
108     currentScene_ = {};
109     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
110     ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
111 
112     if ((jsonInputs_.nodeFlags & RenderSceneFlagBits::RENDER_SCENE_DIRECT_POST_PROCESS_BIT) &&
113         jsonInputs_.renderDataStore.dataStoreName.empty()) {
114         CORE_LOG_V("%s: render data store post process configuration not set in render node graph",
115             renderNodeContextMgr_->GetName().data());
116     }
117 
118     GetSceneUniformBuffers(stores_.dataStoreNameScene);
119     shadowBuffers_ = GetShadowBufferNodeData(gpuResourceMgr, stores_.dataStoreNameScene);
120 
121     renderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
122 
123     samplerHandles_.cubemap =
124         gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
125     samplerHandles_.linear = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
126     samplerHandles_.nearest = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
127     samplerHandles_.linearMip = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
128 
129     defaultColorPrePassHandle_ = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
130     allShaderData_.shaderHandle = shader_;
131     CreateDefaultShaderData();
132     CreateDescriptorSets();
133 }
134 
PreExecuteFrame()135 void RenderNodeDefaultMaterialDeferredShading::PreExecuteFrame()
136 {
137     // re-create needed gpu resources
138 }
139 
ExecuteFrame(IRenderCommandList & cmdList)140 void RenderNodeDefaultMaterialDeferredShading::ExecuteFrame(IRenderCommandList& cmdList)
141 {
142     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
143     const auto* dataStoreScene =
144         static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
145     const auto* dataStoreCamera =
146         static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
147     const auto* dataStoreLight =
148         static_cast<IRenderDataStoreDefaultLight*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
149 
150     const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
151     if (validRenderDataStore) {
152         UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
153         UpdatePostProcessConfiguration();
154         UpdateGlobalPostProcessUbo();
155     }
156     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
157     if (jsonInputs_.hasChangeableResourceHandles) {
158         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
159         renderNodeUtil.BindResourcesToBinder(inputResources_, *allDescriptorSets_.pipelineDescriptorSetBinder);
160     }
161 
162     cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
163     if (validRenderDataStore) {
164         RenderData(cmdList);
165     }
166     cmdList.EndRenderPass();
167 }
168 
RenderData(IRenderCommandList & cmdList)169 void RenderNodeDefaultMaterialDeferredShading::RenderData(IRenderCommandList& cmdList)
170 {
171     if (!valid_) {
172         return;
173     }
174     const RenderHandle psoHandle = GetPsoHandle();
175     if (!RenderHandleUtil::IsValid(psoHandle)) {
176         return; // early out
177     }
178     cmdList.BindPipeline(psoHandle);
179 
180     // set 0, update camera, general data, and lighting
181     // set 1, update input attachments
182     UpdateSet01(cmdList);
183     // set 2-3, update user bindings
184     UpdateUserSets(cmdList);
185 
186     // dynamic state
187     cmdList.SetDynamicStateViewport(currentScene_.viewportDesc);
188     cmdList.SetDynamicStateScissor(currentScene_.scissorDesc);
189 
190     // bind all sets
191     {
192         RenderHandle descriptorSets[4U] = {
193             allDescriptorSets_.set0->GetDescriptorSetHandle(),
194             allDescriptorSets_.set1->GetDescriptorSetHandle(),
195             {},
196             {},
197         };
198         uint32_t setCount = BUILT_IN_SETS_COUNT;
199         if (allDescriptorSets_.hasUserSet2 && allDescriptorSets_.pipelineDescriptorSetBinder) {
200             descriptorSets[setCount] = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(setCount);
201             setCount++;
202         }
203         if (allDescriptorSets_.hasUserSet3 && allDescriptorSets_.pipelineDescriptorSetBinder) {
204             descriptorSets[setCount] = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(setCount);
205             setCount++;
206         }
207         cmdList.BindDescriptorSets(0u, { descriptorSets, setCount });
208     }
209 
210     // push constants
211     if (pipelineLayout_.pushConstant.byteSize > 0) {
212         const float fWidth = static_cast<float>(renderPass_.renderPassDesc.renderArea.extentWidth);
213         const float fHeight = static_cast<float>(renderPass_.renderPassDesc.renderArea.extentHeight);
214         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
215             ppLocalConfig_.variables.factor };
216         cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
217     }
218 
219     cmdList.Draw(3u, 1u, 0u, 0u);
220 }
221 
UpdateSet01(IRenderCommandList & cmdList)222 void RenderNodeDefaultMaterialDeferredShading::UpdateSet01(IRenderCommandList& cmdList)
223 {
224     auto& binder0 = *allDescriptorSets_.set0;
225     auto& binder1 = *allDescriptorSets_.set1;
226     {
227         uint32_t bindingIndex = 0;
228         // global
229         binder0.BindBuffer(bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
230         binder0.BindBuffer(
231             bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
232 
233         // scene and camera global
234         binder0.BindBuffer(bindingIndex++, sceneBuffers_.camera, 0u);
235         binder0.BindBuffer(bindingIndex++, cameraBuffers_.generalData, 0u);
236 
237         const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
238         const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
239                                               ? currentScene_.prePassColorTarget
240                                               : defaultColorPrePassHandle_;
241 
242         binder0.BindBuffer(bindingIndex++, cameraBuffers_.environment, 0u);
243         binder0.BindBuffer(bindingIndex++, cameraBuffers_.fog, 0u);
244         binder0.BindBuffer(bindingIndex++, cameraBuffers_.light, 0u);
245         binder0.BindBuffer(bindingIndex++, cameraBuffers_.postProcess, 0u);
246         binder0.BindBuffer(bindingIndex++, cameraBuffers_.lightCluster, 0u);
247 
248         // use immutable samplers for all set 0 samplers
249         BindableImage bi;
250         bi.handle = colorPrePass;
251         bi.samplerHandle = samplerHandles_.linearMip;
252         binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
253         bi.handle = shadowBuffers_.vsmColorHandle;
254         bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
255         binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
256         bi.handle = shadowBuffers_.pcfDepthHandle;
257         bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
258         binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
259         bi.handle = radianceCubemap;
260         bi.samplerHandle = samplerHandles_.cubemap;
261         binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
262     }
263     {
264         const auto& renderPassDesc = renderPass_.renderPassDesc;
265         const auto& subpassDesc = renderPass_.subpassDesc;
266         for (uint32_t bindingIdx = 0; bindingIdx < subpassDesc.inputAttachmentCount; ++bindingIdx) {
267             binder1.BindImage(
268                 bindingIdx, renderPassDesc.attachmentHandles[subpassDesc.inputAttachmentIndices[bindingIdx]]);
269         }
270     }
271 
272     const RenderHandle handles[] { binder0.GetDescriptorSetHandle(), binder1.GetDescriptorSetHandle() };
273     const DescriptorSetLayoutBindingResources resources[] { binder0.GetDescriptorSetLayoutBindingResources(),
274         binder1.GetDescriptorSetLayoutBindingResources() };
275     cmdList.UpdateDescriptorSets(handles, resources);
276 }
277 
UpdateUserSets(IRenderCommandList & cmdList)278 void RenderNodeDefaultMaterialDeferredShading::UpdateUserSets(IRenderCommandList& cmdList)
279 {
280     if (allDescriptorSets_.hasUserSet2 && allDescriptorSets_.pipelineDescriptorSetBinder) {
281         uint32_t set = BUILT_IN_SETS_COUNT;
282         const auto descHandle = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(set);
283         const auto bindings =
284             allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(set);
285         if (RenderHandleUtil::IsValid(descHandle) && (!bindings.bindings.empty())) {
286             cmdList.UpdateDescriptorSet(descHandle, bindings);
287         }
288     }
289     if (allDescriptorSets_.hasUserSet3 && allDescriptorSets_.pipelineDescriptorSetBinder) {
290         uint32_t set = BUILT_IN_SETS_COUNT + 1u;
291         const auto descHandle = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(set);
292         const auto bindings =
293             allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(set);
294         if (RenderHandleUtil::IsValid(descHandle) && (!bindings.bindings.empty())) {
295             cmdList.UpdateDescriptorSet(descHandle, bindings);
296         }
297     }
298 }
299 
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)300 void RenderNodeDefaultMaterialDeferredShading::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
301     const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
302 {
303     if (jsonInputs_.hasChangeableRenderPassHandles) {
304         const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
305         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
306         renderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
307     }
308 
309     const auto scene = dataStoreScene.GetScene();
310     bool hasCustomCamera = false;
311     bool isNamedCamera = false; // NOTE: legacy support will be removed
312     uint32_t cameraIdx = scene.cameraIndex;
313     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
314         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
315         hasCustomCamera = true;
316     } else if (!(jsonInputs_.customCameraName.empty())) {
317         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
318         hasCustomCamera = true;
319         isNamedCamera = true;
320     }
321 
322     if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
323         // store current frame camera
324         currentScene_.camera = cameras[cameraIdx];
325     }
326     const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
327         *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
328     currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
329 
330     // renderpass needs to be valid (created in init)
331     if (hasCustomCamera) {
332         // uses camera based clear-setup
333         RenderNodeSceneUtil::UpdateRenderPassFromCustomCamera(currentScene_.camera, isNamedCamera, renderPass_);
334     } else {
335         RenderNodeSceneUtil::UpdateRenderPassFromCamera(currentScene_.camera, renderPass_);
336     }
337     currentScene_.viewportDesc = RenderNodeSceneUtil::CreateViewportFromCamera(currentScene_.camera);
338     currentScene_.scissorDesc = RenderNodeSceneUtil::CreateScissorFromCamera(currentScene_.camera);
339     currentScene_.viewportDesc.minDepth = 1.0f;
340     currentScene_.viewportDesc.maxDepth = 1.0f;
341 
342     const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
343     currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
344     currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
345     currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
346     currentScene_.cameraShaderFlags = currentScene_.camera.shaderFlags;
347     // remove fog explicitly if render node graph input and/or default render slot usage states so
348     if (jsonInputs_.nodeFlags & RenderSceneFlagBits::RENDER_SCENE_DISABLE_FOG_BIT) {
349         currentScene_.cameraShaderFlags &= (~RenderCamera::ShaderFlagBits::CAMERA_SHADER_FOG_BIT);
350     }
351 }
352 
GetPsoHandle()353 RenderHandle RenderNodeDefaultMaterialDeferredShading::GetPsoHandle()
354 {
355     uint64_t hash = 0;
356     BASE_NS::HashCombine(hash, currentScene_.lightingFlags);
357     if ((!RenderHandleUtil::IsValid(allShaderData_.psoHandle)) || (hash != allShaderData_.psoHash)) {
358         // only lighting flags can currently change dynamically
359         allShaderData_.psoHash = hash;
360 
361         constexpr size_t maxFlagCount { 16u };
362         uint32_t specializationFlags[maxFlagCount];
363         const size_t maxSpecializations = Math::min(maxFlagCount, allShaderData_.defaultSpecilizationConstants.size());
364         for (size_t idx = 0; idx < maxSpecializations; ++idx) {
365             const auto& ref = allShaderData_.defaultSpecilizationConstants[idx];
366             const uint32_t constantId = ref.offset / sizeof(uint32_t);
367 
368             if (ref.shaderStage == ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT) {
369                 if (ref.id == 0u) {
370                     specializationFlags[constantId] = currentRenderPPConfiguration_.flags.x;
371                 } else if (ref.id == 1u) {
372                     specializationFlags[constantId] = 0;
373                 } else if (ref.id == 2u) {
374                     specializationFlags[constantId] = currentScene_.lightingFlags;
375                 } else if (ref.id == 4u) {
376                     specializationFlags[constantId] = currentScene_.cameraShaderFlags;
377                 }
378             }
379         }
380 
381         const ShaderSpecializationConstantDataView specialization { allShaderData_.defaultSpecilizationConstants,
382             specializationFlags };
383         allShaderData_.psoHandle = renderNodeContextMgr_->GetPsoManager().GetGraphicsPsoHandle(
384             allShaderData_.shaderHandle, allShaderData_.stateHandle, allShaderData_.plHandle, {}, specialization,
385             { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
386     }
387     return allShaderData_.psoHandle;
388 }
389 
CreateDefaultShaderData()390 void RenderNodeDefaultMaterialDeferredShading::CreateDefaultShaderData()
391 {
392     // shader cannot be cleared
393     allShaderData_.defaultSpecilizationConstants = {};
394     allShaderData_.stateHandle = {};
395     allShaderData_.plHandle = {};
396     allShaderData_.psoHandle = {};
397     allShaderData_.psoHash = 0;
398 
399     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
400     if (shaderMgr.IsComputeShader(allShaderData_.shaderHandle) || shaderMgr.IsShader(allShaderData_.shaderHandle)) {
401         allShaderData_.plHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(allShaderData_.shaderHandle);
402         allShaderData_.stateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(allShaderData_.shaderHandle);
403         const ShaderSpecializationConstantView& sscv =
404             shaderMgr.GetReflectionSpecialization(allShaderData_.shaderHandle);
405         allShaderData_.defaultSpecilizationConstants.resize(sscv.constants.size());
406         for (uint32_t idx = 0; idx < (uint32_t)allShaderData_.defaultSpecilizationConstants.size(); ++idx) {
407             allShaderData_.defaultSpecilizationConstants[idx] = sscv.constants[idx];
408         }
409     } else {
410         CORE_LOG_W("RenderNode: %s, invalid shader given", renderNodeContextMgr_->GetName().data());
411     }
412 }
413 
CreateDescriptorSets()414 void RenderNodeDefaultMaterialDeferredShading::CreateDescriptorSets()
415 {
416     auto& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
417 
418     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
419     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
420     const RenderHandle plDefHandle =
421         shaderMgr.GetPipelineLayoutHandle("3dpipelinelayouts://core3d_dm_fullscreen_deferred_shading.shaderpl");
422     const PipelineLayout plDef = shaderMgr.GetPipelineLayout(plDefHandle);
423     const RenderHandle plShaderHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(allShaderData_.shaderHandle);
424     pipelineLayout_ = shaderMgr.GetPipelineLayout(plShaderHandle);
425 
426     const IShaderManager::CompatibilityFlags compatibilityFlags =
427         shaderMgr.GetCompatibilityFlags(plDefHandle, plShaderHandle);
428     if (compatibilityFlags != 0) {
429         valid_ = true;
430     } else {
431         CORE_LOG_W("RN: %s incompatible pipeline layout for given shader", renderNodeContextMgr_->GetName().data());
432     }
433 
434     // currently we allocate just in case based on both layouts to make sure that we have enough descriptors
435     // we create pipeline descriptor set binder for convenience for user sets
436     DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
437     // double the sets for pipeline descriptor binder usage
438     for (auto& dcRef : dc.counts) {
439         dcRef.count *= 2u;
440     }
441     // add built-in set from the first set (if user set was missing something)
442     dc.counts.reserve(dc.counts.size() + plDef.descriptorSetLayouts[0U].bindings.size());
443     for (const auto& bindingRef : plDef.descriptorSetLayouts[0U].bindings) {
444         dc.counts.push_back(DescriptorCounts::TypedCount { bindingRef.descriptorType, bindingRef.descriptorCount });
445     }
446     descriptorSetMgr.ResetAndReserve(dc);
447 
448     {
449         // set 0 descriptors are fixed at the moment
450         constexpr uint32_t set { 0u };
451         const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, plDef);
452         allDescriptorSets_.set0 =
453             descriptorSetMgr.CreateDescriptorSetBinder(descriptorSetHandle, plDef.descriptorSetLayouts[set].bindings);
454     }
455     {
456         // input attachment count is allowed to change, so we need to create the descriptor set based on shader
457         constexpr uint32_t set { 1u };
458         const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, pipelineLayout_);
459         allDescriptorSets_.set1 = descriptorSetMgr.CreateDescriptorSetBinder(
460             descriptorSetHandle, pipelineLayout_.descriptorSetLayouts[set].bindings);
461     }
462 
463     // pipeline descriptor set binder for user sets
464     allDescriptorSets_.pipelineDescriptorSetBinder = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
465     if (allDescriptorSets_.pipelineDescriptorSetBinder) {
466         renderNodeUtil.BindResourcesToBinder(inputResources_, *allDescriptorSets_.pipelineDescriptorSetBinder);
467 #if (CORE3D_VALIDATION_ENABLED == 1)
468         auto CheckBindingValidity = [](const auto builtInBindings, const auto& resources) {
469             for (const auto& res : resources) {
470                 if (res.set < builtInBindings) {
471                     return false;
472                 }
473             }
474             return true;
475         };
476         bool valid = CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.buffers);
477         valid = valid && CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.images);
478         valid = valid && CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.samplers);
479         if (!valid) {
480             CORE_LOG_W("RN: %s does not support user bindings for sets <= %u", renderNodeContextMgr_->GetName().data(),
481                 BUILT_IN_SETS_COUNT);
482         }
483         allDescriptorSets_.hasUserSet2 = !(
484             allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(BUILT_IN_SETS_COUNT)
485                 .bindings.empty());
486         allDescriptorSets_.hasUserSet3 = !(allDescriptorSets_.pipelineDescriptorSetBinder
487                                                ->GetDescriptorSetLayoutBindingResources(BUILT_IN_SETS_COUNT + 1u)
488                                                .bindings.empty());
489 #endif
490     }
491 }
492 
GetSceneUniformBuffers(const string_view us)493 void RenderNodeDefaultMaterialDeferredShading::GetSceneUniformBuffers(const string_view us)
494 {
495     sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
496 
497     string camName;
498     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
499         camName = to_string(jsonInputs_.customCameraId);
500     } else if (!(jsonInputs_.customCameraName.empty())) {
501         camName = jsonInputs_.customCameraName;
502     }
503     cameraBuffers_ =
504         RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
505 }
506 
UpdatePostProcessConfiguration()507 void RenderNodeDefaultMaterialDeferredShading::UpdatePostProcessConfiguration()
508 {
509     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
510         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
511         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
512             if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
513                 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
514                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
515             }
516         }
517         if (const IRenderDataStorePod* ds =
518                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
519             ds) {
520             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
521             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
522                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
523             }
524         }
525     }
526 }
527 
UpdateGlobalPostProcessUbo()528 void RenderNodeDefaultMaterialDeferredShading::UpdateGlobalPostProcessUbo()
529 {
530     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
531     const RenderPostProcessConfiguration rppc =
532         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
533     CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
534     CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
535                        sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
536     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
537         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
538         // global data
539         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
540         // local data
541         data += sizeof(GlobalPostProcessStruct);
542         CloneData(
543             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
544         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
545     }
546 }
547 
ParseRenderNodeInputs()548 void RenderNodeDefaultMaterialDeferredShading::ParseRenderNodeInputs()
549 {
550     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
551     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
552     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
553     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
554     jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
555     jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
556     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
557 
558     jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
559 
560     jsonInputs_.nodeFlags = static_cast<uint32_t>(parserUtil.GetUintValue(jsonVal, "nodeFlags"));
561     if (jsonInputs_.nodeFlags == ~0u) {
562         jsonInputs_.nodeFlags = 0;
563     }
564 
565     const string renderSlot = parserUtil.GetStringValue(jsonVal, "renderSlot");
566     jsonInputs_.renderSlotId = renderNodeContextMgr_->GetShaderManager().GetRenderSlotId(renderSlot);
567 
568     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
569     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
570     shader_ = shaderMgr.GetShaderHandle(shaderName);
571 
572     EvaluateFogBits();
573 
574     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
575     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
576     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
577     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
578     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
579 }
580 
EvaluateFogBits()581 void RenderNodeDefaultMaterialDeferredShading::EvaluateFogBits()
582 {
583     // if no explicit bits set we check default render slot usages
584     if ((jsonInputs_.nodeFlags & (RENDER_SCENE_ENABLE_FOG_BIT | RENDER_SCENE_DISABLE_FOG_BIT)) == 0) {
585         jsonInputs_.nodeFlags |= RenderSceneFlagBits::RENDER_SCENE_ENABLE_FOG_BIT;
586     }
587 }
588 
589 // for plugin / factory interface
Create()590 RENDER_NS::IRenderNode* RenderNodeDefaultMaterialDeferredShading::Create()
591 {
592     return new RenderNodeDefaultMaterialDeferredShading();
593 }
594 
Destroy(IRenderNode * instance)595 void RenderNodeDefaultMaterialDeferredShading::Destroy(IRenderNode* instance)
596 {
597     delete static_cast<RenderNodeDefaultMaterialDeferredShading*>(instance);
598 }
599 CORE3D_END_NAMESPACE()
600