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