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