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