• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_node_default_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