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_shadow_render_slot.h"
17
18 #include <3d/render/default_material_constants.h>
19 #include <3d/render/intf_render_data_store_default_camera.h>
20 #include <3d/render/intf_render_data_store_default_light.h>
21 #include <3d/render/intf_render_data_store_default_material.h>
22 #include <3d/render/intf_render_data_store_default_scene.h>
23 #include <base/containers/vector.h>
24 #include <base/math/mathf.h>
25 #include <base/math/matrix_util.h>
26 #include <base/math/vector_util.h>
27 #include <core/log.h>
28 #include <core/namespace.h>
29 #include <render/datastore/intf_render_data_store.h>
30 #include <render/datastore/intf_render_data_store_manager.h>
31 #include <render/device/intf_gpu_resource_manager.h>
32 #include <render/device/intf_shader_manager.h>
33 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
34 #include <render/nodecontext/intf_node_context_pso_manager.h>
35 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
36 #include <render/nodecontext/intf_render_command_list.h>
37 #include <render/nodecontext/intf_render_node_context_manager.h>
38 #include <render/nodecontext/intf_render_node_parser_util.h>
39 #include <render/nodecontext/intf_render_node_util.h>
40 #include <render/resource_handle.h>
41
42 #include "render/default_constants.h"
43 #include "render/render_node_scene_util.h"
44
45 namespace {
46 #include <3d/shaders/common/3d_dm_structures_common.h>
47 } // namespace
48
49 CORE3D_BEGIN_NAMESPACE()
50 using namespace BASE_NS;
51 using namespace RENDER_NS;
52
53 namespace {
54 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
55
56 static constexpr uint32_t UBO_OFFSET_ALIGNMENT { 256u };
57 static constexpr uint32_t MAX_SHADOW_ATLAS_WIDTH { 8192u };
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
GetDepthBufferDesc(const RenderNodeDefaultShadowRenderSlot::ShadowBuffers & shadowBuffers)66 GpuImageDesc GetDepthBufferDesc(const RenderNodeDefaultShadowRenderSlot::ShadowBuffers& shadowBuffers)
67 {
68 constexpr ImageUsageFlags usage = ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
69 ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT;
70 constexpr MemoryPropertyFlags memPropertyFlags = CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
71 return GpuImageDesc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
72 Format::BASE_FORMAT_D16_UNORM, ImageTiling::CORE_IMAGE_TILING_OPTIMAL, usage, memPropertyFlags, 0,
73 EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, shadowBuffers.width,
74 shadowBuffers.height, 1, 1, 1, SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
75 }
76
GetColorBufferDesc(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderNodeDefaultShadowRenderSlot::ShadowBuffers & shadowBuffers)77 GpuImageDesc GetColorBufferDesc(const IRenderNodeGpuResourceManager& gpuResourceMgr,
78 const RenderNodeDefaultShadowRenderSlot::ShadowBuffers& shadowBuffers)
79 {
80 const EngineImageCreationFlags engineImageCreateFlags =
81 EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS;
82
83 const ImageUsageFlags usage =
84 ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT;
85 const MemoryPropertyFlags memPropertyFlags = CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
86 Format format = Format::BASE_FORMAT_R16G16_UNORM;
87 const auto formatProperties = gpuResourceMgr.GetFormatProperties(format);
88 if ((formatProperties.optimalTilingFeatures & CORE_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0) {
89 format = Format::BASE_FORMAT_R16G16_SFLOAT;
90 }
91 return GpuImageDesc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D, format,
92 ImageTiling::CORE_IMAGE_TILING_OPTIMAL, usage, memPropertyFlags, 0, engineImageCreateFlags, shadowBuffers.width,
93 shadowBuffers.height, 1u, 1u, 1u, SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
94 }
95
IsInverseWinding(const RenderSubmeshFlags submeshFlags)96 inline bool IsInverseWinding(const RenderSubmeshFlags submeshFlags)
97 {
98 return ((submeshFlags & RenderSubmeshFlagBits::RENDER_SUBMESH_INVERSE_WINDING_BIT) > 0);
99 }
100
CreateGeneralDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr)101 inline RenderHandleReference CreateGeneralDataUniformBuffer(IRenderNodeGpuResourceManager& gpuResourceMgr)
102 {
103 return gpuResourceMgr.Create(GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
104 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
105 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
106 UBO_OFFSET_ALIGNMENT * DefaultMaterialLightingConstants::MAX_SHADOW_COUNT });
107 }
108
109 template<typename RenderDataStoreType>
GetRenderDataStore(const IRenderNodeRenderDataStoreManager & renderDataStoreManager,const string_view name)110 RenderDataStoreType* GetRenderDataStore(
111 const IRenderNodeRenderDataStoreManager& renderDataStoreManager, const string_view name)
112 {
113 return static_cast<RenderDataStoreType*>(renderDataStoreManager.GetRenderDataStore(name));
114 }
115
UpdateResourceCount(uint32_t & oldCount,const uint32_t newValue,const uint32_t overCommitDivisor)116 inline bool UpdateResourceCount(uint32_t& oldCount, const uint32_t newValue, const uint32_t overCommitDivisor)
117 {
118 if (oldCount < newValue) {
119 oldCount = newValue + (newValue / overCommitDivisor);
120 return true;
121 }
122 return false;
123 }
124
125 struct FrameGlobalDescriptorSets {
126 RenderHandle set1;
127 RenderHandle set2Default;
128 array_view<const RenderHandle> set2;
129 bool valid = false;
130 };
131
GetFrameGlobalDescriptorSets(IRenderNodeContextManager * rncm,const SceneRenderDataStores & stores)132 FrameGlobalDescriptorSets GetFrameGlobalDescriptorSets(
133 IRenderNodeContextManager* rncm, const SceneRenderDataStores& stores)
134 {
135 FrameGlobalDescriptorSets fgds;
136 if (rncm) {
137 // re-fetch global descriptor sets every frame
138 const INodeContextDescriptorSetManager& dsMgr = rncm->GetDescriptorSetManager();
139 const string_view us = stores.dataStoreNameScene;
140 fgds.set1 = dsMgr.GetGlobalDescriptorSet(
141 us + DefaultMaterialMaterialConstants::MATERIAL_SET1_GLOBAL_DESCRIPTOR_SET_NAME);
142 fgds.set2 = dsMgr.GetGlobalDescriptorSets(
143 us + DefaultMaterialMaterialConstants::MATERIAL_RESOURCES_GLOBAL_DESCRIPTOR_SET_NAME);
144 fgds.set2Default = dsMgr.GetGlobalDescriptorSet(
145 us + DefaultMaterialMaterialConstants::MATERIAL_DEFAULT_RESOURCE_GLOBAL_DESCRIPTOR_SET_NAME);
146 #if (CORE3D_VALIDATION_ENABLED == 1)
147 if (fgds.set2.empty()) {
148 CORE_LOG_ONCE_W("core3d_global_descriptor_set_render_slot_issues",
149 "CORE3D_VALIDATION: Global descriptor set for default material env not found");
150 }
151 #endif
152 fgds.valid = RenderHandleUtil::IsValid(fgds.set1) && RenderHandleUtil::IsValid(fgds.set2Default);
153 if (!fgds.valid) {
154 CORE_LOG_ONCE_E("core3d_global_descriptor_set_shadow_all_issues",
155 "Global descriptor set 1/2 for default material not found (RenderNodeDefaultCameraController needed)");
156 }
157 }
158 return fgds;
159 }
160 } // namespace
161
InitNode(IRenderNodeContextManager & renderNodeContextMgr)162 void RenderNodeDefaultShadowRenderSlot::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
163 {
164 renderNodeContextMgr_ = &renderNodeContextMgr;
165 ParseRenderNodeInputs();
166
167 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
168 stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
169 renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
170
171 auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
172 {
173 shadowBuffers_.depthName =
174 stores_.dataStoreNameScene + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME;
175 shadowBuffers_.vsmColorName =
176 stores_.dataStoreNameScene + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME;
177 shadowBuffers_.depthHandle =
178 gpuResourceMgr.Create(shadowBuffers_.depthName, GetDepthBufferDesc(shadowBuffers_));
179 shadowBuffers_.vsmColorHandle =
180 gpuResourceMgr.Create(shadowBuffers_.vsmColorName, GetColorBufferDesc(gpuResourceMgr, shadowBuffers_));
181 }
182
183 // reset
184 validShadowNode_ = false;
185 currentScene_ = {};
186 allShaderData_ = {};
187 allDescriptorSets_ = {};
188
189 CreateDefaultShaderData();
190
191 uboHandles_.generalData = CreateGeneralDataUniformBuffer(gpuResourceMgr);
192 sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
193 if (RenderHandleUtil::IsValid(sceneBuffers_.camera)) {
194 validShadowNode_ = true;
195 }
196 }
197
PreExecuteFrame()198 void RenderNodeDefaultShadowRenderSlot::PreExecuteFrame()
199 {
200 shadowCount_ = 0U;
201 if (!validShadowNode_) {
202 return;
203 }
204
205 ProcessBuffersAndDescriptors();
206
207 const auto& dataMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
208 const auto* dataStoreMaterial =
209 GetRenderDataStore<IRenderDataStoreDefaultMaterial>(dataMgr, stores_.dataStoreNameMaterial);
210 auto* dataStoreLight = GetRenderDataStore<IRenderDataStoreDefaultLight>(dataMgr, stores_.dataStoreNameLight);
211 auto* dataStoreCamera = GetRenderDataStore<IRenderDataStoreDefaultCamera>(dataMgr, stores_.dataStoreNameCamera);
212 auto* dataStoreScene = GetRenderDataStore<IRenderDataStoreDefaultScene>(dataMgr, stores_.dataStoreNameScene);
213
214 if ((!dataStoreMaterial) || (!dataStoreLight) || (!dataStoreCamera) || (!dataStoreScene)) {
215 return;
216 }
217 const auto scene = dataStoreScene->GetScene();
218 const auto lightCounts = dataStoreLight->GetLightCounts();
219 shadowCount_ = lightCounts.shadowCount;
220
221 const Math::UVec2 res = dataStoreLight->GetShadowQualityResolution();
222 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
223 const IRenderDataStoreDefaultLight::ShadowTypes shadowTypes = dataStoreLight->GetShadowTypes();
224 if (shadowCount_ > 0) {
225 const uint32_t xWidth = Math::min(res.x * shadowCount_, MAX_SHADOW_ATLAS_WIDTH);
226 const uint32_t yHeight = res.y;
227 const bool xChanged = (xWidth != shadowBuffers_.width);
228 const bool yChanged = (yHeight != shadowBuffers_.height);
229 const bool shadowTypeChanged = (shadowTypes.shadowType != shadowBuffers_.shadowTypes.shadowType);
230
231 if (xChanged || yChanged || shadowTypeChanged) {
232 shadowBuffers_.shadowTypes = shadowTypes;
233 shadowBuffers_.width = xWidth;
234 shadowBuffers_.height = yHeight;
235
236 shadowBuffers_.depthHandle =
237 gpuResourceMgr.Create(shadowBuffers_.depthName, GetDepthBufferDesc(shadowBuffers_));
238 if (shadowBuffers_.shadowTypes.shadowType == IRenderDataStoreDefaultLight::ShadowType::VSM) {
239 shadowBuffers_.vsmColorHandle = gpuResourceMgr.Create(
240 shadowBuffers_.vsmColorName, GetColorBufferDesc(gpuResourceMgr, shadowBuffers_));
241 } else {
242 }
243 }
244 }
245 }
246
GetExecuteFlags() const247 IRenderNode::ExecuteFlags RenderNodeDefaultShadowRenderSlot::GetExecuteFlags() const
248 {
249 // NOTE: shadow buffers should not be read
250 // we can leave there old data without clearing if shadow count goes to zero
251 if (validShadowNode_ && (shadowCount_ > 0U)) {
252 return 0U;
253 } else {
254 return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
255 }
256 }
257
ExecuteFrame(IRenderCommandList & cmdList)258 void RenderNodeDefaultShadowRenderSlot::ExecuteFrame(IRenderCommandList& cmdList)
259 {
260 if ((!validShadowNode_) || (shadowCount_ == 0U)) {
261 return;
262 }
263
264 const auto& dataMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
265 auto* storeScene = GetRenderDataStore<IRenderDataStoreDefaultScene>(dataMgr, stores_.dataStoreNameScene);
266 auto* storeMaterial = GetRenderDataStore<IRenderDataStoreDefaultMaterial>(dataMgr, stores_.dataStoreNameMaterial);
267 auto* storeCamera = GetRenderDataStore<IRenderDataStoreDefaultCamera>(dataMgr, stores_.dataStoreNameCamera);
268 auto* storeLight = GetRenderDataStore<IRenderDataStoreDefaultLight>(dataMgr, stores_.dataStoreNameLight);
269
270 if (storeScene && storeMaterial && storeCamera && storeLight && allShaderData_.slotHasShaders) {
271 const auto scene = storeScene->GetScene();
272 const auto lightCounts = storeLight->GetLightCounts();
273 const uint32_t shadowCounts = lightCounts.shadowCount;
274 CORE_ASSERT(shadowCounts == shadowCount_);
275 if (shadowCounts == 0) {
276 return; // early out
277 }
278
279 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "3DShadows", DefaultDebugConstants::DEFAULT_DEBUG_COLOR);
280
281 UpdateCurrentScene(*storeScene, *storeLight);
282 UpdateGeneralDataUniformBuffers(*storeLight);
283
284 const auto cameras = storeCamera->GetCameras();
285 const auto lights = storeLight->GetLights();
286
287 // write all shadows in a single render pass
288 renderPass_ = CreateRenderPass(shadowBuffers_);
289 cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
290
291 uint32_t shadowPassIdx = 0;
292 for (const auto& light : lights) {
293 if ((light.lightUsageFlags & RenderLight::LIGHT_USAGE_SHADOW_LIGHT_BIT) == 0) {
294 continue;
295 }
296 #if (CORE3D_VALIDATION_ENABLED == 1)
297 if (light.shadowCameraIndex >= static_cast<uint32_t>(cameras.size())) {
298 const string onceName = string(renderNodeContextMgr_->GetName().data()) + "_too_many_cam";
299 CORE_LOG_ONCE_W(onceName,
300 "CORE3D_VALIDATION: RN: %s, shadow cameras dropped, too many cameras in scene",
301 renderNodeContextMgr_->GetName().data());
302 }
303 #endif
304 if (light.shadowCameraIndex < static_cast<uint32_t>(cameras.size())) {
305 const auto& camera = cameras[light.shadowCameraIndex];
306 // sort slot data to be accessible
307 ProcessSlotSubmeshes(*storeCamera, *storeMaterial, light.shadowCameraIndex);
308 if (!sortedSlotSubmeshes_.empty()) {
309 RenderSubmeshes(
310 cmdList, *storeMaterial, shadowBuffers_.shadowTypes.shadowType, camera, light, shadowPassIdx);
311 }
312 }
313
314 shadowPassIdx++;
315 }
316
317 cmdList.EndRenderPass();
318 }
319 }
320
RenderSubmeshes(IRenderCommandList & cmdList,const IRenderDataStoreDefaultMaterial & dataStoreMaterial,const IRenderDataStoreDefaultLight::ShadowType shadowType,const RenderCamera & camera,const RenderLight & light,const uint32_t shadowPassIdx)321 void RenderNodeDefaultShadowRenderSlot::RenderSubmeshes(IRenderCommandList& cmdList,
322 const IRenderDataStoreDefaultMaterial& dataStoreMaterial, const IRenderDataStoreDefaultLight::ShadowType shadowType,
323 const RenderCamera& camera, const RenderLight& light, const uint32_t shadowPassIdx)
324 {
325 const size_t submeshCount = sortedSlotSubmeshes_.size();
326
327 // re-fetch global descriptor sets every frame
328 const FrameGlobalDescriptorSets fgds = GetFrameGlobalDescriptorSets(renderNodeContextMgr_, stores_);
329 if (!fgds.valid) {
330 return; // cannot continue
331 }
332
333 // dynamic state
334 {
335 const int32_t xOffset = static_cast<int32_t>(light.shadowIndex * currentScene_.res.x);
336 ViewportDesc vd = currentScene_.viewportDesc;
337 vd.x = static_cast<float>(xOffset);
338 ScissorDesc sd = currentScene_.scissorDesc;
339 sd.offsetX = xOffset;
340 cmdList.SetDynamicStateViewport(vd);
341 cmdList.SetDynamicStateScissor(sd);
342 }
343
344 // set 0, update camera
345 UpdateSet0(cmdList, shadowPassIdx);
346
347 const uint64_t camLayerMask = camera.layerMask;
348 RenderHandle boundPsoHandle = {};
349 uint64_t boundShaderHash = 0;
350 uint32_t currMaterialIndex = ~0u;
351 bool initialBindDone = false; // cannot be checked from the idx
352 bool hasSet2ImageData = false;
353 const auto& selectableShaders =
354 (shadowType == IRenderDataStoreDefaultLight::ShadowType::VSM) ? vsmShaders_ : pcfShaders_;
355
356 const auto& submeshMaterialFlags = dataStoreMaterial.GetSubmeshMaterialFlags();
357 const auto& submeshes = dataStoreMaterial.GetSubmeshes();
358 for (size_t idx = 0; idx < submeshCount; ++idx) {
359 // NOTE: submesh index is used to index into already updated descriptor set 2 slot
360 // if the alpha shadow version is used
361 const uint32_t submeshIndex = sortedSlotSubmeshes_[idx].submeshIndex;
362 const auto& currSubmesh = submeshes[submeshIndex];
363
364 // sorted slot submeshes should already have removed layers if default sorting was used
365 if ((camLayerMask & currSubmesh.layers.layerMask) == 0) {
366 continue;
367 }
368 auto currMaterialFlags = submeshMaterialFlags[submeshIndex];
369 // get shader and graphics state and start hashing
370 const auto& ssp = sortedSlotSubmeshes_[idx];
371 ShaderStateData ssd { ssp.shaderHandle, ssp.gfxStateHandle, 0, selectableShaders.basic,
372 selectableShaders.basicState };
373 ssd.hash = (ssd.shader.id << 32U) | (ssd.gfxState.id & 0xFFFFffff);
374 HashCombine(ssd.hash, ((ssd.defaultShader.id << 32U) | (ssd.defaultShaderState.id & 0xFFFFffff)));
375 ssd.hash = HashShaderAndSubmesh(ssd.hash, currMaterialFlags.renderDepthHash);
376 if (ssd.hash != boundShaderHash) {
377 const PsoCreationValue psoVal = GetSubmeshPso(ssd, currMaterialFlags, currSubmesh.submeshFlags);
378 if (psoVal.psoHandle.id != boundPsoHandle.id) {
379 boundShaderHash = ssd.hash;
380 boundPsoHandle = psoVal.psoHandle;
381 hasSet2ImageData = psoVal.hasImageData;
382 cmdList.BindPipeline(boundPsoHandle);
383 }
384 }
385
386 // bind first set only the first time
387 if (!initialBindDone) {
388 const RenderHandle descriptorSetHandle = allDescriptorSets_.set0[shadowPassIdx]->GetDescriptorSetHandle();
389 cmdList.BindDescriptorSets(0u, { &descriptorSetHandle, 1u });
390 }
391
392 // set 1 (material, mesh matrix and skin matrices)
393 const uint32_t currMatOffset =
394 currSubmesh.indices.materialFrameOffset * CORE_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT;
395 const uint32_t currMeshMatrixOffset = currSubmesh.indices.meshIndex * CORE_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT;
396 uint32_t currJointMatrixOffset = 0u;
397 if (currSubmesh.submeshFlags & RenderSubmeshFlagBits::RENDER_SUBMESH_SKIN_BIT) {
398 currJointMatrixOffset =
399 currSubmesh.indices.skinJointIndex * static_cast<uint32_t>(sizeof(DefaultMaterialSkinStruct));
400 }
401 const uint32_t dynamicOffsets[] = { currMeshMatrixOffset, currJointMatrixOffset, currMatOffset, currMatOffset,
402 currMatOffset };
403 // set to bind, handle to resource, offsets for dynamic descs
404 IRenderCommandList::BindDescriptorSetData bindSets[2U] {};
405 uint32_t bindSetCount = 0U;
406 bindSets[bindSetCount++] = { fgds.set1, dynamicOffsets };
407
408 // update material descriptor set
409 if ((!initialBindDone) || ((currMaterialIndex != currSubmesh.indices.materialIndex) && hasSet2ImageData)) {
410 currMaterialIndex = currSubmesh.indices.materialIndex;
411 // safety check for global material sets
412 const RenderHandle set2Handle =
413 (currMaterialIndex < fgds.set2.size()) ? fgds.set2[currMaterialIndex] : fgds.set2Default;
414 bindSets[bindSetCount++] = { set2Handle, {} };
415 }
416
417 // bind sets 1 and possibly 2
418 cmdList.BindDescriptorSets(1U, { bindSets, bindSetCount });
419
420 initialBindDone = true;
421
422 // vertex buffers and draw
423 if (currSubmesh.buffers.vertexBufferCount > 0) {
424 cmdList.BindVertexBuffers({ currSubmesh.buffers.vertexBuffers, currSubmesh.buffers.vertexBufferCount });
425 }
426 const auto& dc = currSubmesh.drawCommand;
427 const VertexBuffer& iArgs = currSubmesh.buffers.indirectArgsBuffer;
428 const bool indirectDraw = RenderHandleUtil::IsValid(iArgs.bufferHandle);
429 if ((currSubmesh.buffers.indexBuffer.byteSize > 0U) &&
430 RenderHandleUtil::IsValid(currSubmesh.buffers.indexBuffer.bufferHandle)) {
431 cmdList.BindIndexBuffer(currSubmesh.buffers.indexBuffer);
432 if (indirectDraw) {
433 cmdList.DrawIndexedIndirect(
434 iArgs.bufferHandle, iArgs.bufferOffset, dc.drawCountIndirect, dc.strideIndirect);
435 } else {
436 cmdList.DrawIndexed(dc.indexCount, dc.instanceCount, 0, 0, 0);
437 }
438 } else {
439 if (indirectDraw) {
440 cmdList.DrawIndirect(iArgs.bufferHandle, iArgs.bufferOffset, dc.drawCountIndirect, dc.strideIndirect);
441 } else {
442 cmdList.Draw(dc.vertexCount, dc.instanceCount, 0, 0);
443 }
444 }
445 }
446 }
447
UpdateSet0(IRenderCommandList & cmdList,const uint32_t shadowPassIdx)448 void RenderNodeDefaultShadowRenderSlot::UpdateSet0(IRenderCommandList& cmdList, const uint32_t shadowPassIdx)
449 {
450 auto& binder = *allDescriptorSets_.set0[shadowPassIdx];
451 uint32_t bindingIndex = 0;
452 binder.BindBuffer(bindingIndex++, sceneBuffers_.camera, 0u);
453 binder.BindBuffer(bindingIndex++, uboHandles_.generalData.GetHandle(), UBO_OFFSET_ALIGNMENT * shadowPassIdx);
454 cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
455 }
456
CreateDefaultShaderData()457 void RenderNodeDefaultShadowRenderSlot::CreateDefaultShaderData()
458 {
459 allShaderData_ = {};
460
461 const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
462 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
463 // default viewport from sizes. camera will update later (if needed)
464 currentScene_.viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass_);
465 currentScene_.scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass_);
466
467 allShaderData_.defaultPlHandle =
468 shaderMgr.GetPipelineLayoutHandle(DefaultMaterialShaderConstants::PIPELINE_LAYOUT_DEPTH);
469 allShaderData_.defaultPipelineLayout = shaderMgr.GetPipelineLayout(allShaderData_.defaultPlHandle);
470 allShaderData_.defaultVidHandle =
471 shaderMgr.GetVertexInputDeclarationHandle(DefaultMaterialShaderConstants::VERTEX_INPUT_DECLARATION_DEPTH);
472
473 // pcf
474 {
475 const IShaderManager::RenderSlotData rsd = shaderMgr.GetRenderSlotData(jsonInputs_.renderSlotId);
476 pcfShaders_.basic = rsd.shader.GetHandle();
477 pcfShaders_.basicState = rsd.graphicsState.GetHandle();
478 if (shaderMgr.IsShader(pcfShaders_.basic)) {
479 allShaderData_.slotHasShaders = true;
480 const ShaderSpecializationConstantView& sscv = shaderMgr.GetReflectionSpecialization(pcfShaders_.basic);
481 allShaderData_.defaultSpecilizationConstants.resize(sscv.constants.size());
482 for (uint32_t idx = 0; idx < (uint32_t)allShaderData_.defaultSpecilizationConstants.size(); ++idx) {
483 allShaderData_.defaultSpecilizationConstants[idx] = sscv.constants[idx];
484 }
485 }
486 }
487 // vsm
488 {
489 const IShaderManager::RenderSlotData rsd = shaderMgr.GetRenderSlotData(jsonInputs_.renderSlotVsmId);
490 vsmShaders_.basic = rsd.shader.GetHandle();
491 vsmShaders_.basicState = rsd.graphicsState.GetHandle();
492 }
493
494 // GPU resources
495 {
496 IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
497 allShaderData_.defaultBaseColor.handle =
498 gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_BASE_COLOR);
499 allShaderData_.defaultBaseColor.samplerHandle =
500 gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_REPEAT");
501 }
502 }
503
CreateNewPso(const ShaderStateData & ssd,const ShaderSpecializationConstantDataView & specialization,const RenderSubmeshFlags submeshFlags)504 RenderNodeDefaultShadowRenderSlot::PsoCreationValue RenderNodeDefaultShadowRenderSlot::CreateNewPso(
505 const ShaderStateData& ssd, const ShaderSpecializationConstantDataView& specialization,
506 const RenderSubmeshFlags submeshFlags)
507 {
508 const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
509 RenderHandle currShader;
510 RenderHandle currPl;
511 RenderHandle currVid;
512 RenderHandle currState;
513 // first try to find matching shader
514 if (RenderHandleUtil::GetHandleType(ssd.shader) == RenderHandleType::SHADER_STATE_OBJECT) {
515 currShader = ssd.shader; // force given shader
516 const RenderHandle slotShader = shaderMgr.GetShaderHandle(ssd.shader, currentScene_.renderSlotId);
517 if (RenderHandleUtil::IsValid(slotShader)) {
518 currShader = slotShader; // override with render slot variant
519 }
520 // if not explicit gfx state given, check if shader has graphics state for this slot
521 if (!RenderHandleUtil::IsValid(ssd.gfxState)) {
522 const auto gfxStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(currShader);
523 if (shaderMgr.GetRenderSlotId(gfxStateHandle) == currentScene_.renderSlotId) {
524 currState = gfxStateHandle;
525 }
526 }
527 currVid = shaderMgr.GetVertexInputDeclarationHandleByShaderHandle(currShader);
528 currPl = shaderMgr.GetPipelineLayoutHandleByShaderHandle(currShader);
529 }
530 if (RenderHandleUtil::GetHandleType(ssd.gfxState) == RenderHandleType::GRAPHICS_STATE) {
531 const RenderHandle slotState = shaderMgr.GetGraphicsStateHandle(ssd.gfxState, currentScene_.renderSlotId);
532 if (RenderHandleUtil::IsValid(slotState)) {
533 currState = slotState;
534 }
535 }
536
537 // fallback to defaults if needed
538 currShader = RenderHandleUtil::IsValid(currShader) ? currShader : ssd.defaultShader;
539 currPl = RenderHandleUtil::IsValid(currPl) ? currPl : allShaderData_.defaultPlHandle;
540 currVid = RenderHandleUtil::IsValid(currVid) ? currVid : allShaderData_.defaultVidHandle;
541 currState = RenderHandleUtil::IsValid(currState) ? currState : ssd.defaultShaderState;
542
543 auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
544 RenderHandle psoHandle;
545 // ATM pipeline layout setup to shader is not forced. Use default if not an extra set.
546 if (IsInverseWinding(submeshFlags)) {
547 // we create a new graphics state with inverse winding
548 GraphicsState gfxState = shaderMgr.GetGraphicsState(currState);
549 gfxState.rasterizationState.frontFace = FrontFace::CORE_FRONT_FACE_CLOCKWISE;
550 const PipelineLayout& pl = shaderMgr.GetPipelineLayout(currPl);
551 const VertexInputDeclarationView vidv = shaderMgr.GetVertexInputDeclarationView(currVid);
552 psoHandle = psoMgr.GetGraphicsPsoHandle(
553 currShader, gfxState, pl, vidv, specialization, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
554 } else {
555 psoHandle = psoMgr.GetGraphicsPsoHandle(
556 currShader, currState, currPl, currVid, specialization, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
557 }
558
559 const PipelineLayout& shaderPl = shaderMgr.GetReflectionPipelineLayout(currShader);
560 const bool hasSet2Images = (shaderPl.descriptorSetLayouts[2U].bindings.size() > 0);
561
562 allShaderData_.perShaderData.push_back(PerShaderData { currShader, psoHandle, currState, hasSet2Images });
563 allShaderData_.shaderIdToData[ssd.hash] = (uint32_t)allShaderData_.perShaderData.size() - 1;
564 return { psoHandle, hasSet2Images };
565 }
566
GetSubmeshPso(const ShaderStateData & ssd,const RenderDataDefaultMaterial::SubmeshMaterialFlags & submeshMaterialFlags,const RenderSubmeshFlags submeshFlags)567 RenderNodeDefaultShadowRenderSlot::PsoCreationValue RenderNodeDefaultShadowRenderSlot::GetSubmeshPso(
568 const ShaderStateData& ssd, const RenderDataDefaultMaterial::SubmeshMaterialFlags& submeshMaterialFlags,
569 const RenderSubmeshFlags submeshFlags)
570 {
571 if (const auto dataIter = allShaderData_.shaderIdToData.find(ssd.hash);
572 dataIter != allShaderData_.shaderIdToData.cend()) {
573 const auto& data = allShaderData_.perShaderData[dataIter->second];
574 return { data.psoHandle, data.hasSet2Images };
575 }
576 // specialization for not found hash
577 constexpr size_t maxSpecializationFlagCount { 8u };
578 uint32_t specializationFlags[maxSpecializationFlagCount];
579 const size_t maxSpecializations =
580 Math::min(maxSpecializationFlagCount, allShaderData_.defaultSpecilizationConstants.size());
581 for (size_t idx = 0; idx < maxSpecializations; ++idx) {
582 const auto& ref = allShaderData_.defaultSpecilizationConstants[idx];
583 if (ref.shaderStage != ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT) {
584 continue;
585 }
586 const uint32_t constantId = ref.offset / sizeof(uint32_t);
587 switch (ref.id) {
588 case 0u:
589 specializationFlags[constantId] = submeshFlags & RenderDataDefaultMaterial::RENDER_SUBMESH_DEPTH_FLAGS;
590 break;
591 case 1u:
592 specializationFlags[constantId] =
593 submeshMaterialFlags.renderMaterialFlags & RenderDataDefaultMaterial::RENDER_MATERIAL_DEPTH_FLAGS;
594 break;
595 default:
596 break;
597 }
598 }
599
600 const ShaderSpecializationConstantDataView spec { { allShaderData_.defaultSpecilizationConstants.data(),
601 maxSpecializations },
602 { specializationFlags, maxSpecializations } };
603
604 return CreateNewPso(ssd, spec, submeshFlags);
605 }
606
CreateRenderPass(const ShadowBuffers & buffers)607 RenderPass RenderNodeDefaultShadowRenderSlot::CreateRenderPass(const ShadowBuffers& buffers)
608 {
609 // NOTE: the depth buffer needs to be samplable (optimmally with VSM it could be discarded)
610 const bool isPcf = (buffers.shadowTypes.shadowType == IRenderDataStoreDefaultLight::ShadowType::PCF);
611 RenderPass renderPass;
612 renderPass.renderPassDesc.renderArea = { 0, 0, buffers.width, buffers.height };
613 renderPass.renderPassDesc.subpassCount = 1;
614 renderPass.subpassStartIndex = 0;
615 auto& subpass = renderPass.subpassDesc;
616 subpass.depthAttachmentCount = 1u;
617 subpass.depthAttachmentIndex = 0u;
618 renderPass.renderPassDesc.attachmentCount = 1u;
619 renderPass.renderPassDesc.attachmentHandles[0] = buffers.depthHandle.GetHandle();
620 renderPass.renderPassDesc.attachments[0] = {
621 0,
622 0,
623 AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR,
624 AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE,
625 AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE,
626 AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_DONT_CARE,
627 ClearValue { ClearDepthStencilValue { 1.0f, 0u } },
628 };
629
630 if (!isPcf) {
631 subpass.colorAttachmentCount = 1;
632 subpass.colorAttachmentIndices[0] = 1u;
633 renderPass.renderPassDesc.attachmentCount++;
634 renderPass.renderPassDesc.attachmentHandles[1] = buffers.vsmColorHandle.GetHandle();
635 renderPass.renderPassDesc.attachments[1] = {
636 0,
637 0,
638 AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR,
639 AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE,
640 AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE,
641 AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_DONT_CARE,
642 ClearValue { ClearColorValue { 1.0f, 1.0f, 0.0f, 0.0f } },
643 };
644 }
645
646 return renderPass;
647 }
648
ProcessBuffersAndDescriptors()649 void RenderNodeDefaultShadowRenderSlot::ProcessBuffersAndDescriptors()
650 {
651 if (!allDescriptorSets_.set0[0U]) {
652 auto& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
653 const DescriptorCounts dc { {
654 // camera and general data
655 { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2U * DefaultMaterialLightingConstants::MAX_SHADOW_COUNT },
656 } };
657 descriptorSetMgr.ResetAndReserve(dc);
658
659 for (uint32_t idx = 0; idx < DefaultMaterialLightingConstants::MAX_SHADOW_COUNT; ++idx) {
660 {
661 constexpr uint32_t setIdx = 0u;
662 const RenderHandle descriptorSetHandle =
663 descriptorSetMgr.CreateDescriptorSet(setIdx, allShaderData_.defaultPipelineLayout);
664 allDescriptorSets_.set0[idx] = descriptorSetMgr.CreateDescriptorSetBinder(
665 descriptorSetHandle, allShaderData_.defaultPipelineLayout.descriptorSetLayouts[setIdx].bindings);
666 }
667 }
668 }
669 }
670
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultLight & dataStoreLight)671 void RenderNodeDefaultShadowRenderSlot::UpdateCurrentScene(
672 const IRenderDataStoreDefaultScene& dataStoreScene, const IRenderDataStoreDefaultLight& dataStoreLight)
673 {
674 const auto scene = dataStoreScene.GetScene();
675 currentScene_.res = dataStoreLight.GetShadowQualityResolution();
676 currentScene_.viewportDesc = { 0.0f, 0.0f, static_cast<float>(currentScene_.res.x),
677 static_cast<float>(currentScene_.res.y), 0.0f, 1.0f };
678 currentScene_.scissorDesc = { 0, 0, currentScene_.res.x, currentScene_.res.y };
679 currentScene_.sceneTimingData = { scene.sceneDeltaTime, scene.deltaTime, scene.totalTime,
680 *reinterpret_cast<const float*>(&scene.frameIndex) };
681
682 currentScene_.renderSlotId =
683 (shadowBuffers_.shadowTypes.shadowType == IRenderDataStoreDefaultLight::ShadowType::VSM)
684 ? jsonInputs_.renderSlotVsmId
685 : jsonInputs_.renderSlotId;
686 }
687
UpdateGeneralDataUniformBuffers(const IRenderDataStoreDefaultLight & dataStoreLight)688 void RenderNodeDefaultShadowRenderSlot::UpdateGeneralDataUniformBuffers(
689 const IRenderDataStoreDefaultLight& dataStoreLight)
690 {
691 IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
692 const Math::Vec2 viewportSize = { static_cast<float>(currentScene_.viewportDesc.width),
693 static_cast<float>(currentScene_.viewportDesc.height) };
694 const Math::Vec4 viewportSizeInvSize = { viewportSize.x, viewportSize.y, 1.0f / viewportSize.x,
695 1.0f / viewportSize.y };
696 DefaultMaterialGeneralDataStruct dataStruct {
697 { 0, 0, 0u, 0u }, // NOTE: shadow camera id to both
698 viewportSizeInvSize,
699 currentScene_.sceneTimingData,
700 };
701 auto* data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(uboHandles_.generalData.GetHandle()));
702 if (!data) {
703 return;
704 }
705 const auto* dataEnd = data + UBO_OFFSET_ALIGNMENT * DefaultMaterialLightingConstants::MAX_SHADOW_COUNT;
706 const auto lights = dataStoreLight.GetLights();
707 uint32_t shadowPassIndex = 0;
708 for (uint32_t lightIdx = 0; lightIdx < lights.size(); ++lightIdx) {
709 const auto& light = lights[lightIdx];
710 if ((light.lightUsageFlags & RenderLight::LIGHT_USAGE_SHADOW_LIGHT_BIT) == 0) {
711 continue;
712 }
713 if (light.shadowCameraIndex != ~0u) {
714 dataStruct.indices = { light.shadowCameraIndex, 0u, 0u, 0u };
715 auto* currData = data + UBO_OFFSET_ALIGNMENT * shadowPassIndex;
716 if (!CloneData(
717 currData, size_t(dataEnd - currData), &dataStruct, sizeof(DefaultMaterialGeneralDataStruct))) {
718 CORE_LOG_E("generalData ubo copying failed.");
719 }
720 }
721 shadowPassIndex++;
722 }
723 gpuResourceMgr.UnmapBuffer(uboHandles_.generalData.GetHandle());
724 }
725
ProcessSlotSubmeshes(const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultMaterial & dataStoreMaterial,const uint32_t shadowCameraIdx)726 void RenderNodeDefaultShadowRenderSlot::ProcessSlotSubmeshes(const IRenderDataStoreDefaultCamera& dataStoreCamera,
727 const IRenderDataStoreDefaultMaterial& dataStoreMaterial, const uint32_t shadowCameraIdx)
728 {
729 const uint32_t cameraIndex = shadowCameraIdx;
730 const IRenderNodeSceneUtil::RenderSlotInfo rsi { currentScene_.renderSlotId, jsonInputs_.sortType,
731 jsonInputs_.cullType, 0 };
732 RenderNodeSceneUtil::GetRenderSlotSubmeshes(
733 dataStoreCamera, dataStoreMaterial, cameraIndex, {}, rsi, sortedSlotSubmeshes_);
734 }
735
ParseRenderNodeInputs()736 void RenderNodeDefaultShadowRenderSlot::ParseRenderNodeInputs()
737 {
738 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
739 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
740
741 jsonInputs_.sortType = parserUtil.GetRenderSlotSortType(jsonVal, "renderSlotSortType");
742 jsonInputs_.cullType = parserUtil.GetRenderSlotCullType(jsonVal, "renderSlotCullType");
743 jsonInputs_.nodeFlags = static_cast<uint32_t>(parserUtil.GetUintValue(jsonVal, "nodeFlags"));
744 if (jsonInputs_.nodeFlags == ~0u) {
745 jsonInputs_.nodeFlags = 0;
746 }
747
748 jsonInputs_.renderSlotId =
749 renderNodeContextMgr_->GetShaderManager().GetRenderSlotId(parserUtil.GetStringValue(jsonVal, "renderSlot"));
750 jsonInputs_.renderSlotVsmId =
751 renderNodeContextMgr_->GetShaderManager().GetRenderSlotId(parserUtil.GetStringValue(jsonVal, "renderSlotVsm"));
752 if (jsonInputs_.renderSlotVsmId == ~0u) {
753 jsonInputs_.renderSlotVsmId = jsonInputs_.renderSlotId;
754 #if (CORE3D_VALIDATION_ENABLED == 1)
755 CORE_LOG_I("RN (%s), VSM render slot not given (renderSlotVsm)", renderNodeContextMgr_->GetName().data());
756 #endif
757 }
758 }
759
760 // for plugin / factory interface
Create()761 RENDER_NS::IRenderNode* RenderNodeDefaultShadowRenderSlot::Create()
762 {
763 return new RenderNodeDefaultShadowRenderSlot();
764 }
765
Destroy(IRenderNode * instance)766 void RenderNodeDefaultShadowRenderSlot::Destroy(IRenderNode* instance)
767 {
768 delete static_cast<RenderNodeDefaultShadowRenderSlot*>(instance);
769 }
770 CORE3D_END_NAMESPACE()
771