1 /*
2 * Copyright (c) 2022 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