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