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