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