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