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