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_material_deferred_shading.h"
17
18 #include <algorithm>
19
20 #include <3d/render/default_material_constants.h>
21 #include <3d/render/intf_render_data_store_default_camera.h>
22 #include <3d/render/intf_render_data_store_default_light.h>
23 #include <3d/render/intf_render_data_store_default_scene.h>
24 #include <3d/render/render_data_defines_3d.h>
25 #include <base/containers/string.h>
26 #include <base/math/matrix.h>
27 #include <base/math/matrix_util.h>
28 #include <core/log.h>
29 #include <core/namespace.h>
30 #include <render/datastore/intf_render_data_store.h>
31 #include <render/datastore/intf_render_data_store_manager.h>
32 #include <render/datastore/intf_render_data_store_pod.h>
33 #include <render/datastore/render_data_store_render_pods.h>
34 #include <render/device/intf_gpu_resource_manager.h>
35 #include <render/device/intf_shader_manager.h>
36 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
37 #include <render/nodecontext/intf_node_context_pso_manager.h>
38 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
39 #include <render/nodecontext/intf_render_command_list.h>
40 #include <render/nodecontext/intf_render_node_context_manager.h>
41 #include <render/nodecontext/intf_render_node_parser_util.h>
42 #include <render/nodecontext/intf_render_node_util.h>
43
44 #include "render/render_node_scene_util.h"
45
46 namespace {
47 #include <3d/shaders/common/3d_dm_structures_common.h>
48 #include <render/shaders/common/render_post_process_structs_common.h>
49 } // namespace
50 CORE3D_BEGIN_NAMESPACE()
51 using namespace BASE_NS;
52 using namespace RENDER_NS;
53
54 namespace {
55 constexpr string_view RENDER_DATA_STORE_POD_NAME { "RenderDataStorePod" };
56 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_NAME { "RenderDataStorePostProcess" };
57 constexpr uint32_t BUILT_IN_SETS_COUNT { 2u };
58 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
59
GetShadowBufferNodeData(IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view sceneName)60 RenderNodeDefaultMaterialDeferredShading::ShadowBuffers GetShadowBufferNodeData(
61 IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view sceneName)
62 {
63 RenderNodeDefaultMaterialDeferredShading::ShadowBuffers sb;
64 sb.vsmSamplerHandle =
65 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER);
66 sb.pcfSamplerHandle =
67 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER);
68
69 sb.pcfDepthHandle =
70 gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME);
71 sb.vsmColorHandle =
72 gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME);
73 if (!RenderHandleUtil::IsValid(sb.pcfDepthHandle)) {
74 sb.pcfDepthHandle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE_WHITE");
75 }
76 if (!RenderHandleUtil::IsValid(sb.vsmColorHandle)) {
77 sb.vsmColorHandle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
78 }
79
80 return sb;
81 }
82
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)83 RenderHandleReference CreatePostProcessDataUniformBuffer(
84 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
85 {
86 CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
87 CORE_STATIC_ASSERT(
88 sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
89 return gpuResourceMgr.Create(
90 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
91 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
92 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
93 sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
94 }
95 } // namespace
96
InitNode(IRenderNodeContextManager & renderNodeContextMgr)97 void RenderNodeDefaultMaterialDeferredShading::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
98 {
99 renderNodeContextMgr_ = &renderNodeContextMgr;
100 allShaderData_ = {};
101 ParseRenderNodeInputs();
102
103 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
104 stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
105 renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
106
107 allDescriptorSets_ = {};
108 currentScene_ = {};
109 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
110 ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
111
112 if ((jsonInputs_.nodeFlags & RenderSceneFlagBits::RENDER_SCENE_DIRECT_POST_PROCESS_BIT) &&
113 jsonInputs_.renderDataStore.dataStoreName.empty()) {
114 CORE_LOG_V("%s: render data store post process configuration not set in render node graph",
115 renderNodeContextMgr_->GetName().data());
116 }
117
118 GetSceneUniformBuffers(stores_.dataStoreNameScene);
119 shadowBuffers_ = GetShadowBufferNodeData(gpuResourceMgr, stores_.dataStoreNameScene);
120
121 renderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
122
123 samplerHandles_.cubemap =
124 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
125 samplerHandles_.linear = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
126 samplerHandles_.nearest = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
127 samplerHandles_.linearMip = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
128
129 defaultColorPrePassHandle_ = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
130 allShaderData_.shaderHandle = shader_;
131 CreateDefaultShaderData();
132 CreateDescriptorSets();
133 }
134
PreExecuteFrame()135 void RenderNodeDefaultMaterialDeferredShading::PreExecuteFrame()
136 {
137 // re-create needed gpu resources
138 }
139
ExecuteFrame(IRenderCommandList & cmdList)140 void RenderNodeDefaultMaterialDeferredShading::ExecuteFrame(IRenderCommandList& cmdList)
141 {
142 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
143 const auto* dataStoreScene =
144 static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
145 const auto* dataStoreCamera =
146 static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
147 const auto* dataStoreLight =
148 static_cast<IRenderDataStoreDefaultLight*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
149
150 const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
151 if (validRenderDataStore) {
152 UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
153 UpdatePostProcessConfiguration();
154 UpdateGlobalPostProcessUbo();
155 }
156 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
157 if (jsonInputs_.hasChangeableResourceHandles) {
158 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
159 renderNodeUtil.BindResourcesToBinder(inputResources_, *allDescriptorSets_.pipelineDescriptorSetBinder);
160 }
161
162 cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
163 if (validRenderDataStore) {
164 RenderData(cmdList);
165 }
166 cmdList.EndRenderPass();
167 }
168
RenderData(IRenderCommandList & cmdList)169 void RenderNodeDefaultMaterialDeferredShading::RenderData(IRenderCommandList& cmdList)
170 {
171 if (!valid_) {
172 return;
173 }
174 const RenderHandle psoHandle = GetPsoHandle();
175 if (!RenderHandleUtil::IsValid(psoHandle)) {
176 return; // early out
177 }
178 cmdList.BindPipeline(psoHandle);
179
180 // set 0, update camera, general data, and lighting
181 // set 1, update input attachments
182 UpdateSet01(cmdList);
183 // set 2-3, update user bindings
184 UpdateUserSets(cmdList);
185
186 // dynamic state
187 cmdList.SetDynamicStateViewport(currentScene_.viewportDesc);
188 cmdList.SetDynamicStateScissor(currentScene_.scissorDesc);
189
190 // bind all sets
191 {
192 RenderHandle descriptorSets[4U] = {
193 allDescriptorSets_.set0->GetDescriptorSetHandle(),
194 allDescriptorSets_.set1->GetDescriptorSetHandle(),
195 {},
196 {},
197 };
198 uint32_t setCount = BUILT_IN_SETS_COUNT;
199 if (allDescriptorSets_.hasUserSet2 && allDescriptorSets_.pipelineDescriptorSetBinder) {
200 descriptorSets[setCount] = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(setCount);
201 setCount++;
202 }
203 if (allDescriptorSets_.hasUserSet3 && allDescriptorSets_.pipelineDescriptorSetBinder) {
204 descriptorSets[setCount] = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(setCount);
205 setCount++;
206 }
207 cmdList.BindDescriptorSets(0u, { descriptorSets, setCount });
208 }
209
210 // push constants
211 if (pipelineLayout_.pushConstant.byteSize > 0) {
212 const float fWidth = static_cast<float>(renderPass_.renderPassDesc.renderArea.extentWidth);
213 const float fHeight = static_cast<float>(renderPass_.renderPassDesc.renderArea.extentHeight);
214 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
215 ppLocalConfig_.variables.factor };
216 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
217 }
218
219 cmdList.Draw(3u, 1u, 0u, 0u);
220 }
221
UpdateSet01(IRenderCommandList & cmdList)222 void RenderNodeDefaultMaterialDeferredShading::UpdateSet01(IRenderCommandList& cmdList)
223 {
224 auto& binder0 = *allDescriptorSets_.set0;
225 auto& binder1 = *allDescriptorSets_.set1;
226 {
227 uint32_t bindingIndex = 0;
228 // global
229 binder0.BindBuffer(bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
230 binder0.BindBuffer(
231 bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
232
233 // scene and camera global
234 binder0.BindBuffer(bindingIndex++, sceneBuffers_.camera, 0u);
235 binder0.BindBuffer(bindingIndex++, cameraBuffers_.generalData, 0u);
236
237 const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
238 const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
239 ? currentScene_.prePassColorTarget
240 : defaultColorPrePassHandle_;
241
242 binder0.BindBuffer(bindingIndex++, cameraBuffers_.environment, 0u);
243 binder0.BindBuffer(bindingIndex++, cameraBuffers_.fog, 0u);
244 binder0.BindBuffer(bindingIndex++, cameraBuffers_.light, 0u);
245 binder0.BindBuffer(bindingIndex++, cameraBuffers_.postProcess, 0u);
246 binder0.BindBuffer(bindingIndex++, cameraBuffers_.lightCluster, 0u);
247
248 // use immutable samplers for all set 0 samplers
249 BindableImage bi;
250 bi.handle = colorPrePass;
251 bi.samplerHandle = samplerHandles_.linearMip;
252 binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
253 bi.handle = shadowBuffers_.vsmColorHandle;
254 bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
255 binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
256 bi.handle = shadowBuffers_.pcfDepthHandle;
257 bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
258 binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
259 bi.handle = radianceCubemap;
260 bi.samplerHandle = samplerHandles_.cubemap;
261 binder0.BindImage(bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
262 }
263 {
264 const auto& renderPassDesc = renderPass_.renderPassDesc;
265 const auto& subpassDesc = renderPass_.subpassDesc;
266 for (uint32_t bindingIdx = 0; bindingIdx < subpassDesc.inputAttachmentCount; ++bindingIdx) {
267 binder1.BindImage(
268 bindingIdx, renderPassDesc.attachmentHandles[subpassDesc.inputAttachmentIndices[bindingIdx]]);
269 }
270 }
271
272 const RenderHandle handles[] { binder0.GetDescriptorSetHandle(), binder1.GetDescriptorSetHandle() };
273 const DescriptorSetLayoutBindingResources resources[] { binder0.GetDescriptorSetLayoutBindingResources(),
274 binder1.GetDescriptorSetLayoutBindingResources() };
275 cmdList.UpdateDescriptorSets(handles, resources);
276 }
277
UpdateUserSets(IRenderCommandList & cmdList)278 void RenderNodeDefaultMaterialDeferredShading::UpdateUserSets(IRenderCommandList& cmdList)
279 {
280 if (allDescriptorSets_.hasUserSet2 && allDescriptorSets_.pipelineDescriptorSetBinder) {
281 uint32_t set = BUILT_IN_SETS_COUNT;
282 const auto descHandle = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(set);
283 const auto bindings =
284 allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(set);
285 if (RenderHandleUtil::IsValid(descHandle) && (!bindings.bindings.empty())) {
286 cmdList.UpdateDescriptorSet(descHandle, bindings);
287 }
288 }
289 if (allDescriptorSets_.hasUserSet3 && allDescriptorSets_.pipelineDescriptorSetBinder) {
290 uint32_t set = BUILT_IN_SETS_COUNT + 1u;
291 const auto descHandle = allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetHandle(set);
292 const auto bindings =
293 allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(set);
294 if (RenderHandleUtil::IsValid(descHandle) && (!bindings.bindings.empty())) {
295 cmdList.UpdateDescriptorSet(descHandle, bindings);
296 }
297 }
298 }
299
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)300 void RenderNodeDefaultMaterialDeferredShading::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
301 const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
302 {
303 if (jsonInputs_.hasChangeableRenderPassHandles) {
304 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
305 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
306 renderPass_ = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
307 }
308
309 const auto scene = dataStoreScene.GetScene();
310 bool hasCustomCamera = false;
311 bool isNamedCamera = false; // NOTE: legacy support will be removed
312 uint32_t cameraIdx = scene.cameraIndex;
313 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
314 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
315 hasCustomCamera = true;
316 } else if (!(jsonInputs_.customCameraName.empty())) {
317 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
318 hasCustomCamera = true;
319 isNamedCamera = true;
320 }
321
322 if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
323 // store current frame camera
324 currentScene_.camera = cameras[cameraIdx];
325 }
326 const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
327 *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
328 currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
329
330 // renderpass needs to be valid (created in init)
331 if (hasCustomCamera) {
332 // uses camera based clear-setup
333 RenderNodeSceneUtil::UpdateRenderPassFromCustomCamera(currentScene_.camera, isNamedCamera, renderPass_);
334 } else {
335 RenderNodeSceneUtil::UpdateRenderPassFromCamera(currentScene_.camera, renderPass_);
336 }
337 currentScene_.viewportDesc = RenderNodeSceneUtil::CreateViewportFromCamera(currentScene_.camera);
338 currentScene_.scissorDesc = RenderNodeSceneUtil::CreateScissorFromCamera(currentScene_.camera);
339 currentScene_.viewportDesc.minDepth = 1.0f;
340 currentScene_.viewportDesc.maxDepth = 1.0f;
341
342 const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
343 currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
344 currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
345 currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
346 currentScene_.cameraShaderFlags = currentScene_.camera.shaderFlags;
347 // remove fog explicitly if render node graph input and/or default render slot usage states so
348 if (jsonInputs_.nodeFlags & RenderSceneFlagBits::RENDER_SCENE_DISABLE_FOG_BIT) {
349 currentScene_.cameraShaderFlags &= (~RenderCamera::ShaderFlagBits::CAMERA_SHADER_FOG_BIT);
350 }
351 }
352
GetPsoHandle()353 RenderHandle RenderNodeDefaultMaterialDeferredShading::GetPsoHandle()
354 {
355 uint64_t hash = 0;
356 BASE_NS::HashCombine(hash, currentScene_.lightingFlags);
357 if ((!RenderHandleUtil::IsValid(allShaderData_.psoHandle)) || (hash != allShaderData_.psoHash)) {
358 // only lighting flags can currently change dynamically
359 allShaderData_.psoHash = hash;
360
361 constexpr size_t maxFlagCount { 16u };
362 uint32_t specializationFlags[maxFlagCount];
363 const size_t maxSpecializations = Math::min(maxFlagCount, allShaderData_.defaultSpecilizationConstants.size());
364 for (size_t idx = 0; idx < maxSpecializations; ++idx) {
365 const auto& ref = allShaderData_.defaultSpecilizationConstants[idx];
366 const uint32_t constantId = ref.offset / sizeof(uint32_t);
367
368 if (ref.shaderStage == ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT) {
369 if (ref.id == 0u) {
370 specializationFlags[constantId] = currentRenderPPConfiguration_.flags.x;
371 } else if (ref.id == 1u) {
372 specializationFlags[constantId] = 0;
373 } else if (ref.id == 2u) {
374 specializationFlags[constantId] = currentScene_.lightingFlags;
375 } else if (ref.id == 4u) {
376 specializationFlags[constantId] = currentScene_.cameraShaderFlags;
377 }
378 }
379 }
380
381 const ShaderSpecializationConstantDataView specialization { allShaderData_.defaultSpecilizationConstants,
382 specializationFlags };
383 allShaderData_.psoHandle = renderNodeContextMgr_->GetPsoManager().GetGraphicsPsoHandle(
384 allShaderData_.shaderHandle, allShaderData_.stateHandle, allShaderData_.plHandle, {}, specialization,
385 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
386 }
387 return allShaderData_.psoHandle;
388 }
389
CreateDefaultShaderData()390 void RenderNodeDefaultMaterialDeferredShading::CreateDefaultShaderData()
391 {
392 // shader cannot be cleared
393 allShaderData_.defaultSpecilizationConstants = {};
394 allShaderData_.stateHandle = {};
395 allShaderData_.plHandle = {};
396 allShaderData_.psoHandle = {};
397 allShaderData_.psoHash = 0;
398
399 const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
400 if (shaderMgr.IsComputeShader(allShaderData_.shaderHandle) || shaderMgr.IsShader(allShaderData_.shaderHandle)) {
401 allShaderData_.plHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(allShaderData_.shaderHandle);
402 allShaderData_.stateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(allShaderData_.shaderHandle);
403 const ShaderSpecializationConstantView& sscv =
404 shaderMgr.GetReflectionSpecialization(allShaderData_.shaderHandle);
405 allShaderData_.defaultSpecilizationConstants.resize(sscv.constants.size());
406 for (uint32_t idx = 0; idx < (uint32_t)allShaderData_.defaultSpecilizationConstants.size(); ++idx) {
407 allShaderData_.defaultSpecilizationConstants[idx] = sscv.constants[idx];
408 }
409 } else {
410 CORE_LOG_W("RenderNode: %s, invalid shader given", renderNodeContextMgr_->GetName().data());
411 }
412 }
413
CreateDescriptorSets()414 void RenderNodeDefaultMaterialDeferredShading::CreateDescriptorSets()
415 {
416 auto& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
417
418 const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
419 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
420 const RenderHandle plDefHandle =
421 shaderMgr.GetPipelineLayoutHandle("3dpipelinelayouts://core3d_dm_fullscreen_deferred_shading.shaderpl");
422 const PipelineLayout plDef = shaderMgr.GetPipelineLayout(plDefHandle);
423 const RenderHandle plShaderHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(allShaderData_.shaderHandle);
424 pipelineLayout_ = shaderMgr.GetPipelineLayout(plShaderHandle);
425
426 const IShaderManager::CompatibilityFlags compatibilityFlags =
427 shaderMgr.GetCompatibilityFlags(plDefHandle, plShaderHandle);
428 if (compatibilityFlags != 0) {
429 valid_ = true;
430 } else {
431 CORE_LOG_W("RN: %s incompatible pipeline layout for given shader", renderNodeContextMgr_->GetName().data());
432 }
433
434 // currently we allocate just in case based on both layouts to make sure that we have enough descriptors
435 // we create pipeline descriptor set binder for convenience for user sets
436 DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
437 // double the sets for pipeline descriptor binder usage
438 for (auto& dcRef : dc.counts) {
439 dcRef.count *= 2u;
440 }
441 // add built-in set from the first set (if user set was missing something)
442 dc.counts.reserve(dc.counts.size() + plDef.descriptorSetLayouts[0U].bindings.size());
443 for (const auto& bindingRef : plDef.descriptorSetLayouts[0U].bindings) {
444 dc.counts.push_back(DescriptorCounts::TypedCount { bindingRef.descriptorType, bindingRef.descriptorCount });
445 }
446 descriptorSetMgr.ResetAndReserve(dc);
447
448 {
449 // set 0 descriptors are fixed at the moment
450 constexpr uint32_t set { 0u };
451 const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, plDef);
452 allDescriptorSets_.set0 =
453 descriptorSetMgr.CreateDescriptorSetBinder(descriptorSetHandle, plDef.descriptorSetLayouts[set].bindings);
454 }
455 {
456 // input attachment count is allowed to change, so we need to create the descriptor set based on shader
457 constexpr uint32_t set { 1u };
458 const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, pipelineLayout_);
459 allDescriptorSets_.set1 = descriptorSetMgr.CreateDescriptorSetBinder(
460 descriptorSetHandle, pipelineLayout_.descriptorSetLayouts[set].bindings);
461 }
462
463 // pipeline descriptor set binder for user sets
464 allDescriptorSets_.pipelineDescriptorSetBinder = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
465 if (allDescriptorSets_.pipelineDescriptorSetBinder) {
466 renderNodeUtil.BindResourcesToBinder(inputResources_, *allDescriptorSets_.pipelineDescriptorSetBinder);
467 #if (CORE3D_VALIDATION_ENABLED == 1)
468 auto CheckBindingValidity = [](const auto builtInBindings, const auto& resources) {
469 for (const auto& res : resources) {
470 if (res.set < builtInBindings) {
471 return false;
472 }
473 }
474 return true;
475 };
476 bool valid = CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.buffers);
477 valid = valid && CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.images);
478 valid = valid && CheckBindingValidity(BUILT_IN_SETS_COUNT, inputResources_.samplers);
479 if (!valid) {
480 CORE_LOG_W("RN: %s does not support user bindings for sets <= %u", renderNodeContextMgr_->GetName().data(),
481 BUILT_IN_SETS_COUNT);
482 }
483 allDescriptorSets_.hasUserSet2 = !(
484 allDescriptorSets_.pipelineDescriptorSetBinder->GetDescriptorSetLayoutBindingResources(BUILT_IN_SETS_COUNT)
485 .bindings.empty());
486 allDescriptorSets_.hasUserSet3 = !(allDescriptorSets_.pipelineDescriptorSetBinder
487 ->GetDescriptorSetLayoutBindingResources(BUILT_IN_SETS_COUNT + 1u)
488 .bindings.empty());
489 #endif
490 }
491 }
492
GetSceneUniformBuffers(const string_view us)493 void RenderNodeDefaultMaterialDeferredShading::GetSceneUniformBuffers(const string_view us)
494 {
495 sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
496
497 string camName;
498 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
499 camName = to_string(jsonInputs_.customCameraId);
500 } else if (!(jsonInputs_.customCameraName.empty())) {
501 camName = jsonInputs_.customCameraName;
502 }
503 cameraBuffers_ =
504 RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
505 }
506
UpdatePostProcessConfiguration()507 void RenderNodeDefaultMaterialDeferredShading::UpdatePostProcessConfiguration()
508 {
509 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
510 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
511 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
512 if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
513 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
514 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
515 }
516 }
517 if (const IRenderDataStorePod* ds =
518 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
519 ds) {
520 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
521 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
522 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
523 }
524 }
525 }
526 }
527
UpdateGlobalPostProcessUbo()528 void RenderNodeDefaultMaterialDeferredShading::UpdateGlobalPostProcessUbo()
529 {
530 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
531 const RenderPostProcessConfiguration rppc =
532 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
533 CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
534 CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
535 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
536 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
537 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
538 // global data
539 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
540 // local data
541 data += sizeof(GlobalPostProcessStruct);
542 CloneData(
543 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
544 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
545 }
546 }
547
ParseRenderNodeInputs()548 void RenderNodeDefaultMaterialDeferredShading::ParseRenderNodeInputs()
549 {
550 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
551 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
552 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
553 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
554 jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
555 jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
556 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
557
558 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
559
560 jsonInputs_.nodeFlags = static_cast<uint32_t>(parserUtil.GetUintValue(jsonVal, "nodeFlags"));
561 if (jsonInputs_.nodeFlags == ~0u) {
562 jsonInputs_.nodeFlags = 0;
563 }
564
565 const string renderSlot = parserUtil.GetStringValue(jsonVal, "renderSlot");
566 jsonInputs_.renderSlotId = renderNodeContextMgr_->GetShaderManager().GetRenderSlotId(renderSlot);
567
568 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
569 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
570 shader_ = shaderMgr.GetShaderHandle(shaderName);
571
572 EvaluateFogBits();
573
574 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
575 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
576 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
577 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
578 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
579 }
580
EvaluateFogBits()581 void RenderNodeDefaultMaterialDeferredShading::EvaluateFogBits()
582 {
583 // if no explicit bits set we check default render slot usages
584 if ((jsonInputs_.nodeFlags & (RENDER_SCENE_ENABLE_FOG_BIT | RENDER_SCENE_DISABLE_FOG_BIT)) == 0) {
585 jsonInputs_.nodeFlags |= RenderSceneFlagBits::RENDER_SCENE_ENABLE_FOG_BIT;
586 }
587 }
588
589 // for plugin / factory interface
Create()590 RENDER_NS::IRenderNode* RenderNodeDefaultMaterialDeferredShading::Create()
591 {
592 return new RenderNodeDefaultMaterialDeferredShading();
593 }
594
Destroy(IRenderNode * instance)595 void RenderNodeDefaultMaterialDeferredShading::Destroy(IRenderNode* instance)
596 {
597 delete static_cast<RenderNodeDefaultMaterialDeferredShading*>(instance);
598 }
599 CORE3D_END_NAMESPACE()
600