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_depth_render_slot.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_material.h>
23 #include <3d/render/intf_render_data_store_default_scene.h>
24 #include <base/math/matrix_util.h>
25 #include <base/math/vector.h>
26 #include <core/log.h>
27 #include <core/namespace.h>
28 #include <render/datastore/intf_render_data_store.h>
29 #include <render/datastore/intf_render_data_store_manager.h>
30 #include <render/device/intf_gpu_resource_manager.h>
31 #include <render/device/intf_shader_manager.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_parser_util.h>
38 #include <render/nodecontext/intf_render_node_util.h>
39 #include <render/resource_handle.h>
40 
41 #include "render/render_node_scene_util.h"
42 
43 #if (CORE3D_DEV_ENABLED == 1)
44 #include "render/datastore/render_data_store_default_material.h"
45 #endif
46 
47 namespace {
48 #include <3d/shaders/common/3d_dm_structures_common.h>
49 } // namespace
50 
51 CORE3D_BEGIN_NAMESPACE()
52 using namespace BASE_NS;
53 using namespace RENDER_NS;
54 
55 namespace {
56 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
57 constexpr uint32_t UBO_BIND_OFFSET_ALIGNMENT { PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE };
58 
HashShaderAndSubmesh(const uint64_t shaderDataHash,const uint32_t renderHash)59 inline uint64_t HashShaderAndSubmesh(const uint64_t shaderDataHash, const uint32_t renderHash)
60 {
61     uint64_t hash = (uint64_t)renderHash;
62     HashCombine(hash, shaderDataHash);
63     return hash;
64 }
65 
IsInverseWinding(const RenderSubmeshFlags submeshFlags,const RenderSceneFlags sceneRenderingFlags,const RenderCamera::Flags cameraRenderingFlags)66 inline bool IsInverseWinding(const RenderSubmeshFlags submeshFlags, const RenderSceneFlags sceneRenderingFlags,
67     const RenderCamera::Flags cameraRenderingFlags)
68 {
69     const bool flipWinding = (sceneRenderingFlags & RENDER_SCENE_FLIP_WINDING_BIT) |
70                              (cameraRenderingFlags & RenderCamera::CAMERA_FLAG_INVERSE_WINDING_BIT);
71     const bool isNegative = flipWinding
72                                 ? !((submeshFlags & RenderSubmeshFlagBits::RENDER_SUBMESH_INVERSE_WINDING_BIT) > 0)
73                                 : ((submeshFlags & RenderSubmeshFlagBits::RENDER_SUBMESH_INVERSE_WINDING_BIT) > 0);
74     return isNegative;
75 }
76 } // namespace
77 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)78 void RenderNodeDefaultDepthRenderSlot::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
79 {
80     renderNodeContextMgr_ = &renderNodeContextMgr;
81     ParseRenderNodeInputs();
82 
83     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
84     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
85         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
86 
87     // reset
88     currentScene_ = {};
89     allShaderData_ = {};
90     objectCounts_ = {};
91 
92     rngRenderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
93     CreateDefaultShaderData();
94 
95     auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
96     buffers_.defaultBuffer = gpuResourceMgr.GetBufferHandle("CORE_DEFAULT_GPU_BUFFER");
97     GetSceneUniformBuffers(stores_.dataStoreNameScene);
98     GetCameraUniformBuffers(stores_.dataStoreNameScene);
99 }
100 
PreExecuteFrame()101 void RenderNodeDefaultDepthRenderSlot::PreExecuteFrame()
102 {
103     // re-create needed gpu resources
104     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
105     const IRenderDataStoreDefaultMaterial* dataStoreMaterial = static_cast<IRenderDataStoreDefaultMaterial*>(
106         renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameMaterial));
107     // we need to have all buffers created (reason to have at least 1u)
108     if (dataStoreMaterial) {
109         const auto dsOc = dataStoreMaterial->GetSlotObjectCounts(jsonInputs_.renderSlotId);
110         const ObjectCounts oc {
111             Math::max(dsOc.meshCount, 1u),
112             Math::max(dsOc.submeshCount, 1u),
113             Math::max(dsOc.skinCount, 1u),
114         };
115         ProcessBuffersAndDescriptors(oc);
116     } else if (objectCounts_.maxSlotMeshCount == 0) {
117         ProcessBuffersAndDescriptors({ 1u, 1u, 1u });
118     }
119 }
120 
ExecuteFrame(IRenderCommandList & cmdList)121 void RenderNodeDefaultDepthRenderSlot::ExecuteFrame(IRenderCommandList& cmdList)
122 {
123     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
124     const auto* dataStoreScene =
125         static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
126     const auto* dataStoreMaterial = static_cast<IRenderDataStoreDefaultMaterial*>(
127         renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameMaterial));
128     const auto* dataStoreCamera =
129         static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
130 
131     const bool validRenderDataStore = dataStoreScene && dataStoreMaterial && dataStoreCamera;
132     if (validRenderDataStore) {
133         UpdateCurrentScene(*dataStoreScene, *dataStoreCamera);
134     } else {
135         CORE_LOG_E("invalid render data stores in RenderNodeDefaultDepthRenderSlot");
136     }
137 
138     cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
139 
140     if (validRenderDataStore) {
141         const auto cameras = dataStoreCamera->GetCameras();
142         const auto scene = dataStoreScene->GetScene();
143 
144         const bool hasShaders = allShaderData_.slotHasShaders;
145         const bool hasCamera =
146             (!cameras.empty() && (currentScene_.cameraIdx < (uint32_t)cameras.size())) ? true : false;
147 
148         ProcessSlotSubmeshes(*dataStoreCamera, *dataStoreMaterial);
149         const bool hasSubmeshes = (!sortedSlotSubmeshes_.empty());
150         if (hasShaders && hasCamera && hasSubmeshes) {
151             RenderSubmeshes(cmdList, *dataStoreMaterial, *dataStoreCamera);
152         }
153     }
154 
155     cmdList.EndRenderPass();
156 }
157 
RenderSubmeshes(IRenderCommandList & cmdList,const IRenderDataStoreDefaultMaterial & dataStoreMaterial,const IRenderDataStoreDefaultCamera & dataStoreCamera)158 void RenderNodeDefaultDepthRenderSlot::RenderSubmeshes(IRenderCommandList& cmdList,
159     const IRenderDataStoreDefaultMaterial& dataStoreMaterial, const IRenderDataStoreDefaultCamera& dataStoreCamera)
160 {
161     const size_t submeshCount = sortedSlotSubmeshes_.size();
162     CORE_ASSERT(submeshCount <= objectCounts_.maxSlotSubmeshCount);
163 
164     // dynamic state
165     cmdList.SetDynamicStateViewport(currentScene_.viewportDesc);
166     cmdList.SetDynamicStateScissor(currentScene_.scissorDesc);
167 
168     // set 0, update camera, general data
169     // set 1, update mesh matrices, material data, and skinning data (uses dynamic offset)
170     UpdateSet01(cmdList);
171 
172     // first two sets are only bound for the first submesh (inside for loop)
173     // no bindless, we need to update images per object
174     RenderHandle boundPsoHandle = {};
175     uint64_t boundShaderHash = 0;
176     bool initialBindDone = false; // cannot be checked from the idx
177 
178     const auto& submeshMaterialFlags = dataStoreMaterial.GetSubmeshMaterialFlags();
179     const auto& submeshes = dataStoreMaterial.GetSubmeshes();
180     const uint64_t camLayerMask = currentScene_.camera.layerMask;
181     for (size_t idx = 0; idx < submeshCount; ++idx) {
182         const auto& ssp = sortedSlotSubmeshes_[idx];
183         const uint32_t submeshIndex = ssp.submeshIndex;
184         const auto& currSubmesh = submeshes[submeshIndex];
185         const RenderSubmeshFlags submeshFlags = currSubmesh.submeshFlags | jsonInputs_.nodeSubmeshExtraFlags;
186         auto currMaterialFlags = submeshMaterialFlags[submeshIndex];
187 
188         // sorted slot submeshes should already have removed layers if default sorting was used
189         if (((camLayerMask & currSubmesh.layerMask) == 0) ||
190             ((jsonInputs_.nodeFlags & RENDER_SCENE_DISCARD_MATERIAL_BIT) &&
191                 (currMaterialFlags.extraMaterialRenderingFlags &
192                     RenderExtraRenderingFlagBits::RENDER_EXTRA_RENDERING_DISCARD_BIT))) {
193             continue;
194         }
195 
196         const uint32_t renderHash = currMaterialFlags.renderHash;
197         // get shader and graphics state and start hashing
198         ShaderStateData ssd { ssp.shaderHandle, ssp.gfxStateHandle, 0 };
199         ssd.hash = (ssd.shader.id << 32U) | (ssd.gfxState.id & 0xFFFFffff);
200         // current shader state is fetched for build-in and custom shaders (decision is made later)
201         ssd.hash = HashShaderAndSubmesh(ssd.hash, renderHash);
202         if (ssd.hash != boundShaderHash) {
203             const RenderHandle pso = GetSubmeshPso(ssd, currMaterialFlags, submeshFlags);
204             if (pso.id != boundPsoHandle.id) {
205                 boundShaderHash = ssd.hash;
206                 boundPsoHandle = pso;
207                 cmdList.BindPipeline(boundPsoHandle);
208             }
209         }
210 
211         // bind first set only the first time
212         if (!initialBindDone) {
213             RenderHandle setResourceHandles[2u] { allDescriptorSets_.set01[0u]->GetDescriptorSetHandle(),
214                 allDescriptorSets_.set01[1u]->GetDescriptorSetHandle() };
215             cmdList.BindDescriptorSets(0, { setResourceHandles, 2u });
216         }
217 
218         // set 1 (mesh matrix, skin matrices, material, material user data)
219         const uint32_t currMeshMatrixOffset = currSubmesh.meshIndex * UBO_BIND_OFFSET_ALIGNMENT;
220         uint32_t currJointMatrixOffset = 0u;
221         if (submeshFlags & RenderSubmeshFlagBits::RENDER_SUBMESH_SKIN_BIT) {
222             currJointMatrixOffset =
223                 currSubmesh.skinJointIndex * static_cast<uint32_t>(sizeof(DefaultMaterialSkinStruct));
224         }
225         const uint32_t dynamicOffsets[] = { currMeshMatrixOffset, currJointMatrixOffset };
226         // set to bind, handle to resource, offsets for dynamic descs
227         cmdList.BindDescriptorSet(1u, allDescriptorSets_.set01[1u]->GetDescriptorSetHandle(), dynamicOffsets);
228 
229         initialBindDone = true;
230 
231         // vertex buffers and draw
232         if (currSubmesh.vertexBufferCount > 0) {
233             VertexBuffer vbs[RENDER_NS::PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT];
234             for (uint32_t vbIdx = 0; vbIdx < currSubmesh.vertexBufferCount; ++vbIdx) {
235                 vbs[vbIdx] = ConvertVertexBuffer(currSubmesh.vertexBuffers[vbIdx]);
236             }
237             cmdList.BindVertexBuffers({ vbs, currSubmesh.vertexBufferCount });
238         }
239         const auto& dc = currSubmesh.drawCommand;
240         const RenderVertexBuffer& iArgs = currSubmesh.indirectArgsBuffer;
241         const bool indirectDraw = iArgs.bufferHandle ? true : false;
242         if (currSubmesh.indexBuffer.byteSize > 0U) {
243             cmdList.BindIndexBuffer(ConvertIndexBuffer(currSubmesh.indexBuffer));
244             if (indirectDraw) {
245                 cmdList.DrawIndexedIndirect(iArgs.bufferHandle.GetHandle(), iArgs.bufferOffset, 1u, 0u);
246             } else {
247                 cmdList.DrawIndexed(dc.indexCount, dc.instanceCount, 0, 0, 0);
248             }
249         } else {
250             if (indirectDraw) {
251                 cmdList.DrawIndirect(iArgs.bufferHandle.GetHandle(), iArgs.bufferOffset, 1u, 0u);
252             } else {
253                 cmdList.Draw(dc.vertexCount, dc.instanceCount, 0, 0);
254             }
255         }
256     }
257 }
258 
UpdateSet01(IRenderCommandList & cmdList)259 void RenderNodeDefaultDepthRenderSlot::UpdateSet01(IRenderCommandList& cmdList)
260 {
261     auto& binder0 = *allDescriptorSets_.set01[0u];
262     auto& binder1 = *allDescriptorSets_.set01[1u];
263     {
264         uint32_t bindingIndex = 0;
265         binder0.BindBuffer(bindingIndex++, buffers_.camera, 0u);
266         binder0.BindBuffer(bindingIndex++, buffers_.generalData, 0u);
267     }
268     {
269         // NOTE: should be PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE or current size
270         constexpr uint32_t skinSize = sizeof(DefaultMaterialSkinStruct);
271 
272         uint32_t bindingIdx = 0u;
273         binder1.BindBuffer(bindingIdx++, buffers_.mesh, 0u, PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
274         binder1.BindBuffer(bindingIdx++, buffers_.skinJoint, 0u, skinSize);
275     }
276     const RenderHandle handles[] { binder0.GetDescriptorSetHandle(), binder1.GetDescriptorSetHandle() };
277     const DescriptorSetLayoutBindingResources resources[] { binder0.GetDescriptorSetLayoutBindingResources(),
278         binder1.GetDescriptorSetLayoutBindingResources() };
279     cmdList.UpdateDescriptorSets(handles, resources);
280 }
281 
GetSubmeshPso(const ShaderStateData & ssd,const RenderDataDefaultMaterial::SubmeshMaterialFlags & submeshMaterialFlags,const RenderSubmeshFlags submeshFlags)282 RenderHandle RenderNodeDefaultDepthRenderSlot::GetSubmeshPso(const ShaderStateData& ssd,
283     const RenderDataDefaultMaterial::SubmeshMaterialFlags& submeshMaterialFlags, const RenderSubmeshFlags submeshFlags)
284 {
285     if (const auto dataIter = allShaderData_.shaderIdToData.find(ssd.hash);
286         dataIter != allShaderData_.shaderIdToData.cend()) {
287         const auto& ref = allShaderData_.perShaderData[dataIter->second];
288         return ref.psoHandle;
289     }
290     return CreateNewPso(ssd, submeshMaterialFlags, submeshFlags);
291 }
292 
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera)293 void RenderNodeDefaultDepthRenderSlot::UpdateCurrentScene(
294     const IRenderDataStoreDefaultScene& dataStoreScene, const IRenderDataStoreDefaultCamera& dataStoreCamera)
295 {
296     if (jsonInputs_.hasChangeableRenderPassHandles) {
297         const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
298         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
299         rngRenderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
300     }
301     // get default RNG based render pass setup
302     renderPass_ = rngRenderPass_;
303 
304     const auto scene = dataStoreScene.GetScene();
305     bool hasCustomCamera = false;
306     bool isNamedCamera = false; // NOTE: legacy support will be removed
307     uint32_t cameraIdx = scene.cameraIndex;
308     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
309         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
310         hasCustomCamera = true;
311     } else if (!(jsonInputs_.customCameraName.empty())) {
312         cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
313         hasCustomCamera = true;
314         isNamedCamera = true;
315     }
316 
317     if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
318         // store current frame camera
319         currentScene_.camera = cameras[cameraIdx];
320     }
321 
322     // renderpass needs to be valid (created in init)
323     if (hasCustomCamera) {
324         // uses camera based loadOp clear override if given
325         RenderNodeSceneUtil::UpdateRenderPassFromCustomCamera(currentScene_.camera, isNamedCamera, renderPass_);
326     } else {
327         RenderNodeSceneUtil::UpdateRenderPassFromCamera(currentScene_.camera, renderPass_);
328     }
329     currentScene_.viewportDesc = RenderNodeSceneUtil::CreateViewportFromCamera(currentScene_.camera);
330     currentScene_.scissorDesc = RenderNodeSceneUtil::CreateScissorFromCamera(currentScene_.camera);
331     currentScene_.cameraIdx = cameraIdx;
332 }
333 
CreateDefaultShaderData()334 void RenderNodeDefaultDepthRenderSlot::CreateDefaultShaderData()
335 {
336     allShaderData_ = {};
337 
338     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
339     allShaderData_.defaultPlHandle =
340         shaderMgr.GetPipelineLayoutHandle(DefaultMaterialShaderConstants::PIPELINE_LAYOUT_DEPTH);
341     allShaderData_.defaultPipelineLayout = shaderMgr.GetPipelineLayout(allShaderData_.defaultPlHandle);
342     allShaderData_.defaultVidHandle =
343         shaderMgr.GetVertexInputDeclarationHandle(DefaultMaterialShaderConstants::VERTEX_INPUT_DECLARATION_DEPTH);
344 
345     {
346         // get the default material shader and default shader state
347         const IShaderManager::RenderSlotData shaderRsd = shaderMgr.GetRenderSlotData(jsonInputs_.shaderRenderSlotId);
348         allShaderData_.defaultShaderHandle = shaderRsd.shader.GetHandle();
349         allShaderData_.defaultStateHandle = shaderRsd.graphicsState.GetHandle();
350         if (shaderMgr.IsShader(allShaderData_.defaultShaderHandle)) {
351             allShaderData_.slotHasShaders = true;
352             const ShaderSpecializationConstantView& sscv =
353                 shaderMgr.GetReflectionSpecialization(allShaderData_.defaultShaderHandle);
354             allShaderData_.defaultSpecilizationConstants.resize(sscv.constants.size());
355             for (uint32_t idx = 0; idx < (uint32_t)allShaderData_.defaultSpecilizationConstants.size(); ++idx) {
356                 allShaderData_.defaultSpecilizationConstants[idx] = sscv.constants[idx];
357             }
358             specializationData_.maxSpecializationCount =
359                 Math::min(static_cast<uint32_t>(allShaderData_.defaultSpecilizationConstants.size()),
360                     SpecializationData::MAX_FLAG_COUNT);
361         } else {
362             CORE_LOG_I("RenderNode: %s, no default shaders for render slot id %u",
363                 renderNodeContextMgr_->GetName().data(), jsonInputs_.shaderRenderSlotId);
364         }
365         if (jsonInputs_.shaderRenderSlotId != jsonInputs_.stateRenderSlotId) {
366             const IShaderManager::RenderSlotData stateRsd = shaderMgr.GetRenderSlotData(jsonInputs_.stateRenderSlotId);
367             if (stateRsd.graphicsState) {
368                 allShaderData_.defaultStateHandle = stateRsd.graphicsState.GetHandle();
369             } else {
370                 CORE_LOG_I("RenderNode: %s, no default state for render slot id %u",
371                     renderNodeContextMgr_->GetName().data(), jsonInputs_.stateRenderSlotId);
372             }
373         }
374     }
375 }
376 
GetSceneUniformBuffers(const string_view us)377 void RenderNodeDefaultDepthRenderSlot::GetSceneUniformBuffers(const string_view us)
378 {
379     const auto& gpuMgr = renderNodeContextMgr_->GetGpuResourceManager();
380     buffers_.camera = gpuMgr.GetBufferHandle(us + DefaultMaterialCameraConstants::CAMERA_DATA_BUFFER_NAME);
381     buffers_.mesh = gpuMgr.GetBufferHandle(us + DefaultMaterialMaterialConstants::MESH_DATA_BUFFER_NAME);
382     buffers_.skinJoint = gpuMgr.GetBufferHandle(us + DefaultMaterialMaterialConstants::SKIN_DATA_BUFFER_NAME);
383 
384     auto checkValidity = [](const RenderHandle defaultBuffer, bool& valid, RenderHandle& buffer) {
385         if (!RenderHandleUtil::IsValid(buffer)) {
386             valid = false;
387             buffer = defaultBuffer;
388         }
389     };
390     bool valid = true;
391     checkValidity(buffers_.defaultBuffer, valid, buffers_.camera);
392     checkValidity(buffers_.defaultBuffer, valid, buffers_.mesh);
393     checkValidity(buffers_.defaultBuffer, valid, buffers_.skinJoint);
394     if (!valid) {
395         CORE_LOG_E(
396             "RN: %s, invalid configuration, not all scene buffers not found.", renderNodeContextMgr_->GetName().data());
397     }
398 }
399 
GetCameraUniformBuffers(const string_view us)400 void RenderNodeDefaultDepthRenderSlot::GetCameraUniformBuffers(const string_view us)
401 {
402     string camName;
403     if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
404         camName = to_string(jsonInputs_.customCameraId);
405     } else if (!(jsonInputs_.customCameraName.empty())) {
406         camName = jsonInputs_.customCameraName;
407     }
408     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
409     buffers_.generalData = gpuResourceMgr.GetBufferHandle(
410         us + DefaultMaterialCameraConstants::CAMERA_GENERAL_BUFFER_PREFIX_NAME + camName);
411 
412     auto checkValidity = [](const RenderHandle defaultBuffer, bool& valid, RenderHandle& buffer) {
413         if (!RenderHandleUtil::IsValid(buffer)) {
414             valid = false;
415             buffer = defaultBuffer;
416         }
417     };
418     bool valid = true;
419     checkValidity(buffers_.defaultBuffer, valid, buffers_.generalData);
420     if (!valid) {
421         CORE_LOG_E(
422             "RN: %s, invalid configuration, not all camera buffers found.", renderNodeContextMgr_->GetName().data());
423     }
424 }
425 
CreateNewPso(const ShaderStateData & ssd,const RenderDataDefaultMaterial::SubmeshMaterialFlags & submeshMaterialFlags,const RenderSubmeshFlags submeshFlags)426 RenderHandle RenderNodeDefaultDepthRenderSlot::CreateNewPso(const ShaderStateData& ssd,
427     const RenderDataDefaultMaterial::SubmeshMaterialFlags& submeshMaterialFlags, const RenderSubmeshFlags submeshFlags)
428 {
429     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
430     // NOTE: The easiest route would be to input shader and graphics state to material component
431     RenderHandle currShader;
432     RenderHandle currPl;
433     RenderHandle currVid;
434     RenderHandle currState;
435     // first try to find matching shader
436     if (RenderHandleUtil::GetHandleType(ssd.shader) == RenderHandleType::SHADER_STATE_OBJECT) {
437         // we force the given shader if explicit shader render slot is not given
438         if (!jsonInputs_.explicitShader) {
439             currShader = ssd.shader;
440         }
441         const RenderHandle slotShader = shaderMgr.GetShaderHandle(ssd.shader, jsonInputs_.shaderRenderSlotId);
442         if (RenderHandleUtil::IsValid(slotShader)) {
443             currShader = slotShader; // override with render slot variant
444         }
445         // if not explicit gfx state given, check if shader has graphics state for this slot
446         if (!RenderHandleUtil::IsValid(ssd.gfxState)) {
447             const auto gfxStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(currShader);
448             if (shaderMgr.GetRenderSlotId(gfxStateHandle) == jsonInputs_.stateRenderSlotId) {
449                 currState = gfxStateHandle;
450             }
451         }
452         currVid = shaderMgr.GetVertexInputDeclarationHandleByShaderHandle(currShader);
453         currPl = shaderMgr.GetPipelineLayoutHandleByShaderHandle(currShader);
454     }
455     if (RenderHandleUtil::GetHandleType(ssd.gfxState) == RenderHandleType::GRAPHICS_STATE) {
456         const RenderHandle slotState = shaderMgr.GetGraphicsStateHandle(ssd.gfxState, jsonInputs_.stateRenderSlotId);
457         if (RenderHandleUtil::IsValid(slotState)) {
458             currState = slotState;
459         }
460     }
461 
462     // NOTE: the pipeline layout compatibility should be checked
463 
464     // fallback to defaults if needed
465     currShader = RenderHandleUtil::IsValid(currShader) ? currShader : allShaderData_.defaultShaderHandle;
466     currPl = RenderHandleUtil::IsValid(currPl) ? currPl : allShaderData_.defaultPlHandle;
467     currVid = RenderHandleUtil::IsValid(currVid) ? currVid : allShaderData_.defaultVidHandle;
468     currState = RenderHandleUtil::IsValid(currState) ? currState : allShaderData_.defaultStateHandle;
469 
470     auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
471     RenderHandle psoHandle;
472     constexpr array_view<const DynamicStateEnum> dynamicStatesView { DYNAMIC_STATES, countof(DYNAMIC_STATES) };
473     if (IsInverseWinding(submeshFlags, jsonInputs_.nodeFlags, currentScene_.camera.flags)) {
474         // we create a new graphics state with inverse winding
475         GraphicsState gfxState = shaderMgr.GetGraphicsState(currState);
476         gfxState.rasterizationState.frontFace = FrontFace::CORE_FRONT_FACE_CLOCKWISE;
477         const auto spec = GetShaderSpecializationView(gfxState, submeshMaterialFlags, submeshFlags);
478         psoHandle = psoMgr.GetGraphicsPsoHandle(currShader, gfxState, shaderMgr.GetPipelineLayout(currPl),
479             shaderMgr.GetVertexInputDeclarationView(currVid), spec, dynamicStatesView);
480     } else {
481         const GraphicsState& gfxState = shaderMgr.GetGraphicsState(currState);
482         const auto spec = GetShaderSpecializationView(gfxState, submeshMaterialFlags, submeshFlags);
483         psoHandle = psoMgr.GetGraphicsPsoHandle(currShader, currState, currPl, currVid, spec, dynamicStatesView);
484     }
485 
486     allShaderData_.perShaderData.push_back(PerShaderData { currShader, psoHandle, currState });
487     allShaderData_.shaderIdToData[ssd.hash] = (uint32_t)allShaderData_.perShaderData.size() - 1;
488     return psoHandle;
489 }
490 
GetShaderSpecializationView(const RENDER_NS::GraphicsState & gfxState,const RenderDataDefaultMaterial::SubmeshMaterialFlags & submeshMaterialFlags,const RenderSubmeshFlags submeshFlags)491 ShaderSpecializationConstantDataView RenderNodeDefaultDepthRenderSlot::GetShaderSpecializationView(
492     const RENDER_NS::GraphicsState& gfxState,
493     const RenderDataDefaultMaterial::SubmeshMaterialFlags& submeshMaterialFlags, const RenderSubmeshFlags submeshFlags)
494 {
495     for (uint32_t idx = 0; idx < specializationData_.maxSpecializationCount; ++idx) {
496         const auto& ref = allShaderData_.defaultSpecilizationConstants[idx];
497         const uint32_t constantId = ref.offset / sizeof(uint32_t);
498 
499         if (ref.shaderStage == ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT) {
500             if (ref.id == 0u) {
501                 specializationData_.flags[constantId] = submeshFlags;
502             } else if (ref.id == 1u) {
503                 specializationData_.flags[constantId] = submeshMaterialFlags.renderMaterialFlags;
504             }
505         } else if (ref.shaderStage == ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT) {
506             if (ref.id == 0u) {
507                 specializationData_.flags[constantId] = static_cast<uint32_t>(submeshMaterialFlags.materialType);
508             }
509         }
510     }
511 
512     return { { allShaderData_.defaultSpecilizationConstants.data(), specializationData_.maxSpecializationCount },
513         { specializationData_.flags, specializationData_.maxSpecializationCount } };
514 }
515 
ProcessBuffersAndDescriptors(const ObjectCounts & objectCounts)516 void RenderNodeDefaultDepthRenderSlot::ProcessBuffersAndDescriptors(const ObjectCounts& objectCounts)
517 {
518     constexpr uint32_t overEstimate { 16u };
519     bool updateDescriptorSets = false;
520     if (objectCounts_.maxSlotMeshCount < objectCounts.maxSlotMeshCount) {
521         updateDescriptorSets = true;
522         objectCounts_.maxSlotMeshCount = objectCounts.maxSlotMeshCount + (objectCounts.maxSlotMeshCount / overEstimate);
523     }
524     if (objectCounts_.maxSlotSkinCount < objectCounts.maxSlotSkinCount) {
525         updateDescriptorSets = true;
526         objectCounts_.maxSlotSkinCount = objectCounts.maxSlotSkinCount + (objectCounts.maxSlotSkinCount / overEstimate);
527     }
528     if (objectCounts_.maxSlotSubmeshCount < objectCounts.maxSlotSubmeshCount) {
529         updateDescriptorSets = true;
530         objectCounts_.maxSlotSubmeshCount =
531             objectCounts.maxSlotSubmeshCount + (objectCounts.maxSlotSubmeshCount / overEstimate);
532     }
533 
534     if (updateDescriptorSets) {
535         ResetAndUpdateDescriptorSets();
536     }
537 }
538 
ResetAndUpdateDescriptorSets()539 void RenderNodeDefaultDepthRenderSlot::ResetAndUpdateDescriptorSets()
540 {
541     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
542     // known and calculated (could run through descriptorsets and calculate automatically as well)
543     const DescriptorCounts dc { {
544         // camera + general data
545         { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u },
546         // mesh and skin data
547         { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2u },
548     } };
549     descriptorSetMgr.ResetAndReserve(dc);
550 
551     for (uint32_t setIdx = 0; setIdx < AllDescriptorSets::SINGLE_SET_COUNT; ++setIdx) {
552         const RenderHandle descriptorSetHandle =
553             descriptorSetMgr.CreateDescriptorSet(setIdx, allShaderData_.defaultPipelineLayout);
554         allDescriptorSets_.set01[setIdx] = descriptorSetMgr.CreateDescriptorSetBinder(
555             descriptorSetHandle, allShaderData_.defaultPipelineLayout.descriptorSetLayouts[setIdx].bindings);
556     }
557 }
558 
ProcessSlotSubmeshes(const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultMaterial & dataStoreMaterial)559 void RenderNodeDefaultDepthRenderSlot::ProcessSlotSubmeshes(
560     const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
561 {
562     // currentScene has been updated prior, has the correct camera (scene camera or custom camera)
563     const IRenderNodeSceneUtil::RenderSlotInfo rsi { jsonInputs_.renderSlotId, jsonInputs_.sortType,
564         jsonInputs_.cullType, jsonInputs_.nodeMaterialDiscardFlags };
565     RenderNodeSceneUtil::GetRenderSlotSubmeshes(
566         dataStoreCamera, dataStoreMaterial, currentScene_.cameraIdx, rsi, sortedSlotSubmeshes_);
567 }
568 
ParseRenderNodeInputs()569 void RenderNodeDefaultDepthRenderSlot::ParseRenderNodeInputs()
570 {
571     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
572     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
573     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
574     jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
575     jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
576     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
577 
578     jsonInputs_.sortType = parserUtil.GetRenderSlotSortType(jsonVal, "renderSlotSortType");
579     jsonInputs_.cullType = parserUtil.GetRenderSlotCullType(jsonVal, "renderSlotCullType");
580     jsonInputs_.nodeFlags = static_cast<uint32_t>(parserUtil.GetUintValue(jsonVal, "nodeFlags"));
581     if (jsonInputs_.nodeFlags == ~0u) {
582         jsonInputs_.nodeFlags = 0;
583     }
584     jsonInputs_.nodeMaterialDiscardFlags =
585         static_cast<uint32_t>(parserUtil.GetUintValue(jsonVal, "nodeMaterialDiscardFlags"));
586     if (jsonInputs_.nodeMaterialDiscardFlags == ~0u) {
587         jsonInputs_.nodeMaterialDiscardFlags = 0;
588     }
589     // automatic default material velocity named target based parsing to add velocity calculations bit
590     for (const auto& ref : jsonInputs_.renderPass.attachments) {
591         if (ref.name == DefaultMaterialRenderNodeConstants::CORE_DM_CAMERA_VELOCITY_NORMAL) {
592             jsonInputs_.nodeSubmeshExtraFlags |= RenderSubmeshFlagBits::RENDER_SUBMESH_VELOCITY_BIT;
593         }
594     }
595 
596     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
597     const string renderSlot = parserUtil.GetStringValue(jsonVal, "renderSlot");
598     jsonInputs_.renderSlotId = shaderMgr.GetRenderSlotId(renderSlot);
599     jsonInputs_.shaderRenderSlotId = jsonInputs_.renderSlotId;
600     jsonInputs_.stateRenderSlotId = jsonInputs_.renderSlotId;
601     const string shaderRenderSlot = parserUtil.GetStringValue(jsonVal, "shaderRenderSlot");
602     if (!shaderRenderSlot.empty()) {
603         const uint32_t renderSlotId = shaderMgr.GetRenderSlotId(shaderRenderSlot);
604         if (renderSlotId != ~0U) {
605             jsonInputs_.shaderRenderSlotId = renderSlotId;
606             jsonInputs_.explicitShader = true;
607         }
608     }
609     const string stateRenderSlot = parserUtil.GetStringValue(jsonVal, "stateRenderSlot");
610     if (!stateRenderSlot.empty()) {
611         const uint32_t renderSlotId = shaderMgr.GetRenderSlotId(stateRenderSlot);
612         jsonInputs_.stateRenderSlotId = (renderSlotId != ~0U) ? renderSlotId : jsonInputs_.renderSlotId;
613     }
614 
615     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
616     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
617     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
618 }
619 
620 // for plugin / factory interface
Create()621 RENDER_NS::IRenderNode* RenderNodeDefaultDepthRenderSlot::Create()
622 {
623     return new RenderNodeDefaultDepthRenderSlot();
624 }
625 
Destroy(IRenderNode * instance)626 void RenderNodeDefaultDepthRenderSlot::Destroy(IRenderNode* instance)
627 {
628     delete static_cast<RenderNodeDefaultDepthRenderSlot*>(instance);
629 }
630 CORE3D_END_NAMESPACE()
631