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_camera_single_post_process.h"
17
18 #include <3d/render/intf_render_data_store_default_camera.h>
19 #include <3d/render/intf_render_data_store_default_light.h>
20 #include <3d/render/intf_render_data_store_default_scene.h>
21 #include <base/math/mathf.h>
22 #include <core/log.h>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/intf_render_data_store_post_process.h>
26 #include <render/datastore/render_data_store_render_pods.h>
27 #include <render/device/intf_gpu_resource_manager.h>
28 #include <render/device/intf_shader_manager.h>
29 #include <render/device/pipeline_layout_desc.h>
30 #include <render/device/pipeline_state_desc.h>
31 #include <render/namespace.h>
32 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
33 #include <render/nodecontext/intf_node_context_pso_manager.h>
34 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
35 #include <render/nodecontext/intf_render_command_list.h>
36 #include <render/nodecontext/intf_render_node_context_manager.h>
37 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
38 #include <render/nodecontext/intf_render_node_parser_util.h>
39 #include <render/nodecontext/intf_render_node_util.h>
40
41 // shaders
42 #include <render/shaders/common/render_post_process_structs_common.h>
43
44 using namespace BASE_NS;
45 using namespace RENDER_NS;
46
47 CORE3D_BEGIN_NAMESPACE()
48 namespace {
49 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
50
51 constexpr uint32_t GLOBAL_POST_PROCESS_SET { 0u };
52 constexpr string_view RENDER_DATA_STORE_POD_NAME { "RenderDataStorePod" };
53 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_NAME { "RenderDataStorePostProcess" };
54
55 constexpr string_view CORE_DEFAULT_GPU_IMAGE_BLACK { "CORE_DEFAULT_GPU_IMAGE" };
56 constexpr string_view CORE_DEFAULT_GPU_IMAGE_WHITE { "CORE_DEFAULT_GPU_IMAGE_WHITE" };
57
58 constexpr string_view INPUT = "input";
59 constexpr string_view OUTPUT = "output";
60 #if (CORE3D_VALIDATION_ENABLED == 1)
61 constexpr string_view POST_PROCESS_BASE_PIPELINE_LAYOUT { "renderpipelinelayouts://post_process_common.shaderpl" };
62 #endif
63 constexpr string_view POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT { "3dpipelinelayouts://core3d_post_process.shaderpl" };
64
65 #if (CORE3D_VALIDATION_ENABLED == 1)
GetPostProcessFlag(const string_view ppName)66 uint32_t GetPostProcessFlag(const string_view ppName)
67 {
68 // get built-in flags
69 if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_FXAA]) {
70 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
71 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_TAA]) {
72 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT;
73 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) {
74 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT;
75 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR]) {
76 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT;
77 } else {
78 return 0;
79 }
80 }
81 #endif
82
GetShadowBufferNodeData(const IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view sceneName)83 RenderNodeCameraSinglePostProcess::ShadowBuffers GetShadowBufferNodeData(
84 const IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view sceneName)
85 {
86 RenderNodeCameraSinglePostProcess::ShadowBuffers sb;
87 sb.vsmSamplerHandle =
88 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER);
89 sb.pcfSamplerHandle =
90 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER);
91
92 sb.pcfDepthHandle =
93 gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_DEPTH_BUFFER_NAME);
94 sb.vsmColorHandle =
95 gpuResourceMgr.GetImageHandle(sceneName + DefaultMaterialLightingConstants::SHADOW_VSM_COLOR_BUFFER_NAME);
96 if (!RenderHandleUtil::IsValid(sb.pcfDepthHandle)) {
97 sb.pcfDepthHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
98 }
99 if (!RenderHandleUtil::IsValid(sb.vsmColorHandle)) {
100 sb.vsmColorHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
101 }
102
103 return sb;
104 }
105
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)106 RenderHandleReference CreatePostProcessDataUniformBuffer(
107 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
108 {
109 CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
110 CORE_STATIC_ASSERT(
111 sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
112 return gpuResourceMgr.Create(
113 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
114 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
115 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
116 sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
117 }
118
NeedsAutoBindingSet0(const RenderNodeHandles::InputResources & inputRes)119 bool NeedsAutoBindingSet0(const RenderNodeHandles::InputResources& inputRes)
120 {
121 uint32_t set0Bindings = 0;
122 for (const auto& res : inputRes.buffers) {
123 if (res.set == GLOBAL_POST_PROCESS_SET) {
124 set0Bindings++;
125 }
126 }
127 return (set0Bindings == 0);
128 }
129
GetDefaultImagesAndSamplers(const IRenderNodeGpuResourceManager & gpuResourceMgr)130 RenderNodeCameraSinglePostProcess::DefaultImagesAndSamplers GetDefaultImagesAndSamplers(
131 const IRenderNodeGpuResourceManager& gpuResourceMgr)
132 {
133 RenderNodeCameraSinglePostProcess::DefaultImagesAndSamplers dias;
134 dias.cubemapHandle =
135 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
136 dias.linearHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
137 dias.nearestHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
138 dias.linearMipHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
139 dias.colorPrePassHandle = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
140 return dias;
141 }
142
143 struct DispatchResources {
144 RenderHandle buffer {};
145 RenderHandle image {};
146 };
147
GetDispatchResources(const RenderNodeHandles::InputResources & ir)148 DispatchResources GetDispatchResources(const RenderNodeHandles::InputResources& ir)
149 {
150 DispatchResources dr;
151 if (!ir.customInputBuffers.empty()) {
152 dr.buffer = ir.customInputBuffers[0].handle;
153 }
154 if (!ir.customInputImages.empty()) {
155 dr.image = ir.customInputImages[0].handle;
156 }
157 return dr;
158 }
159 } // namespace
160
InitNode(IRenderNodeContextManager & renderNodeContextMgr)161 void RenderNodeCameraSinglePostProcess::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
162 {
163 renderNodeContextMgr_ = &renderNodeContextMgr;
164
165 valid_ = true;
166 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
167 ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
168
169 ParseRenderNodeInputs();
170 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
171 stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
172 renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
173 currentScene_ = {};
174
175 shadowBuffers_ = GetShadowBufferNodeData(gpuResourceMgr, stores_.dataStoreNameScene);
176 defaultImagesAndSamplers_ = GetDefaultImagesAndSamplers(gpuResourceMgr);
177
178 UpdateImageData();
179 ProcessPostProcessConfiguration();
180 GetSceneUniformBuffers(stores_.dataStoreNameScene);
181 if (!RenderHandleUtil::IsValid(shader_)) {
182 shader_ = ppLocalConfig_.shader.GetHandle();
183 }
184
185 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
186 const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
187 const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
188 pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
189 if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
190 graphics_ = true;
191 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
192 psoHandle_ = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
193 shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
194 } else if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
195 graphics_ = false;
196 psoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(shader_, pipelineLayout_, {});
197 threadGroupSize_ = shaderMgr.GetReflectionThreadGroupSize(shader_);
198 if (dispatchResources_.customInputBuffers.empty() && dispatchResources_.customInputImages.empty()) {
199 valid_ = false;
200 CORE_LOG_W("RenderNodeCameraSinglePostProcess: dispatchResources (GPU buffer or GPU image) needed");
201 }
202 } else {
203 CORE_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
204 }
205 {
206 // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
207 const RenderHandle baseCamPlHandle =
208 shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT);
209 // when validation enabled compare to render post process pipeline layout as well
210 #if (CORE3D_VALIDATION_ENABLED == 1)
211 {
212 const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
213 const IShaderManager::CompatibilityFlags compatibilityFlags =
214 shaderMgr.GetCompatibilityFlags(baseCamPlHandle, basePlHandle);
215 if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
216 CORE_LOG_E("RN:%s uncompatible render vs 3D pipeline layout (%s)",
217 renderNodeContextMgr_->GetName().data(), POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
218 }
219 }
220 #endif
221 const IShaderManager::CompatibilityFlags compatibilityFlags =
222 shaderMgr.GetCompatibilityFlags(baseCamPlHandle, plHandle);
223 if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
224 CORE_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
225 POST_PROCESS_CAMERA_BASE_PIPELINE_LAYOUT.data());
226 }
227 }
228
229 #if (CORE3D_VALIDATION_ENABLED == 1)
230 // 3d does not operate on render built-in post processes
231 const uint32_t postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
232 if (postProcessFlag != 0) {
233 valid_ = false;
234 CORE_LOG_W("RN:%s does not execute render built-in post processes.", renderNodeContextMgr_->GetName().data());
235 }
236 #endif
237 InitCreateBinders();
238
239 renderCopy_.Init(renderNodeContextMgr, {});
240
241 RegisterOutputs();
242 }
243
PreExecuteFrame()244 void RenderNodeCameraSinglePostProcess::PreExecuteFrame()
245 {
246 {
247 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
248 const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
249 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
250 const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
251 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
252 const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
253 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
254 const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
255 if (validRenderDataStore) {
256 UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
257 }
258 }
259
260 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
261 if (jsonInputs_.hasChangeableResourceHandles) {
262 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
263 }
264 UpdateImageData();
265 ProcessPostProcessConfiguration();
266 RegisterOutputs();
267 }
268
ExecuteFrame(IRenderCommandList & cmdList)269 void RenderNodeCameraSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
270 {
271 if ((!ppLocalConfig_.variables.enabled) &&
272 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
273 return;
274 }
275
276 if (ppLocalConfig_.variables.enabled && valid_) {
277 ExecuteSinglePostProcess(cmdList);
278 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
279 renderCopy_.Execute(*renderNodeContextMgr_, cmdList);
280 }
281 }
282
ExecuteSinglePostProcess(IRenderCommandList & cmdList)283 void RenderNodeCameraSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
284 {
285 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
286 if (jsonInputs_.hasChangeableRenderPassHandles) {
287 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
288 }
289 if (jsonInputs_.hasChangeableResourceHandles) {
290 // input resources updated in preExecuteFrame
291 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
292 }
293 if (jsonInputs_.hasChangeableDispatchHandles) {
294 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
295 }
296 if (useAutoBindSet0_) {
297 UpdateGlobalPostProcessUbo();
298 }
299
300 RenderPass renderPass;
301 DispatchResources dispatchResources;
302 if (graphics_) {
303 renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
304 if ((renderPass.renderPassDesc.attachmentCount == 0) ||
305 !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
306 #if (CORE3D_VALIDATION_ENABLED == 1)
307 CORE_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(), "RN: %s, invalid attachment",
308 renderNodeContextMgr_->GetName().data());
309 #endif
310 return;
311 }
312 } else {
313 dispatchResources = GetDispatchResources(dispatchResources_);
314 if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
315 (!RenderHandleUtil::IsValid(dispatchResources.image))) {
316 return; // no way to evaluate dispatch size
317 }
318 }
319
320 const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
321 const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
322 const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
323 for (const auto refIndex : setIndices) {
324 const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
325 // handle automatic set 0 bindings
326 if ((refIndex == 0) && useAutoBindSet0_) {
327 UpdateSet0(cmdList);
328 } else if (invalidBindings) {
329 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
330 BindDefaultResources(refIndex, bindings);
331 }
332 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
333 cmdList.UpdateDescriptorSet(descHandle, bindings);
334 }
335 #if (CORE3D_VALIDATION_ENABLED == 1)
336 if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
337 CORE_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
338 }
339 #endif
340
341 if (graphics_) {
342 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
343 }
344
345 cmdList.BindPipeline(psoHandle_);
346
347 // bind all sets
348 cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
349
350 if (graphics_) {
351 // dynamic state
352 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
353 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
354 cmdList.SetDynamicStateViewport(viewportDesc);
355 cmdList.SetDynamicStateScissor(scissorDesc);
356 // push constants
357 if (pipelineLayout_.pushConstant.byteSize > 0) {
358 const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
359 const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
360 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
361 ppLocalConfig_.variables.factor };
362 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
363 }
364
365 cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
366 cmdList.EndRenderPass();
367 } else {
368 if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
369 cmdList.DispatchIndirect(dispatchResources.buffer, 0);
370 } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
371 const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
372 const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
373 const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
374 if (pipelineLayout_.pushConstant.byteSize > 0) {
375 const float fWidth = static_cast<float>(targetSize.x);
376 const float fHeight = static_cast<float>(targetSize.y);
377 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
378 ppLocalConfig_.variables.factor };
379 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
380 }
381
382 cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
383 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
384 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
385 }
386 }
387 }
388
RegisterOutputs()389 void RenderNodeCameraSinglePostProcess::RegisterOutputs()
390 {
391 const RenderHandle output = builtInVariables_.output;
392 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
393 RenderHandle registerOutput;
394 if (ppLocalConfig_.variables.enabled) {
395 if (RenderHandleUtil::IsValid(output)) {
396 registerOutput = output;
397 }
398 }
399 if (!RenderHandleUtil::IsValid(registerOutput)) {
400 if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
401 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
402 RenderHandleUtil::IsValid(output)) {
403 registerOutput = output;
404 } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
405 RenderHandleUtil::IsValid(builtInVariables_.input)) {
406 registerOutput = builtInVariables_.input;
407 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
408 registerOutput = builtInVariables_.defWhiteImage;
409 } else {
410 registerOutput = builtInVariables_.defBlackImage;
411 }
412 }
413 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
414 }
415
UpdateSet0(IRenderCommandList & cmdList)416 void RenderNodeCameraSinglePostProcess::UpdateSet0(IRenderCommandList& cmdList)
417 {
418 const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
419 const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
420 ? currentScene_.prePassColorTarget
421 : defaultImagesAndSamplers_.colorPrePassHandle;
422
423 auto& binder = *pipelineDescriptorSetBinder_;
424 uint32_t bindingIndex = 0;
425 // global
426 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
427 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++,
428 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
429
430 // scene and camera global
431 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { sceneBuffers_.camera });
432 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.generalData });
433
434 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.environment });
435 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.fog });
436 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.light });
437 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.postProcess });
438 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.lightCluster });
439
440 // scene and camera global images
441 BindableImage bi;
442 bi.handle = colorPrePass;
443 bi.samplerHandle = defaultImagesAndSamplers_.linearMipHandle;
444 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
445 bi.handle = shadowBuffers_.vsmColorHandle;
446 bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
447 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
448 bi.handle = shadowBuffers_.pcfDepthHandle;
449 bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
450 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
451 bi.handle = radianceCubemap;
452 bi.samplerHandle = defaultImagesAndSamplers_.cubemapHandle;
453 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
454
455 // NOTE: UpdateDescriptorSets is done when called
456 }
457
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)458 void RenderNodeCameraSinglePostProcess::BindDefaultResources(
459 const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
460 {
461 if (pipelineDescriptorSetBinder_) {
462 auto& binder = *pipelineDescriptorSetBinder_;
463 for (const auto& ref : bindings.buffers) {
464 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
465 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
466 }
467 }
468 for (const auto& ref : bindings.images) {
469 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
470 BindableImage bi;
471 bi.handle = builtInVariables_.defBlackImage;
472 bi.samplerHandle = builtInVariables_.defSampler;
473 binder.BindImage(set, ref.binding.binding, bi);
474 }
475 }
476 for (const auto& ref : bindings.samplers) {
477 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
478 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
479 }
480 }
481 }
482 }
483
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)484 void RenderNodeCameraSinglePostProcess::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
485 const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
486 {
487 const auto scene = dataStoreScene.GetScene();
488 uint32_t cameraIdx = scene.cameraIndex;
489 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
490 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
491 } else if (!(jsonInputs_.customCameraName.empty())) {
492 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
493 }
494
495 if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
496 // store current frame camera
497 currentScene_.camera = cameras[cameraIdx];
498 }
499 const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
500 *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
501 currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
502
503 const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
504 currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
505 currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
506 currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
507 }
508
ProcessPostProcessConfiguration()509 void RenderNodeCameraSinglePostProcess::ProcessPostProcessConfiguration()
510 {
511 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
512 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
513 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
514 if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
515 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
516 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
517 }
518 }
519 if (const IRenderDataStorePod* ds =
520 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
521 ds) {
522 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
523 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
524 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
525 }
526 }
527 } else if (jsonInputs_.ppName.empty()) {
528 // if trying to just use shader without post processing we enable running by default
529 ppLocalConfig_.variables.enabled = true;
530 }
531 }
532
UpdateGlobalPostProcessUbo()533 void RenderNodeCameraSinglePostProcess::UpdateGlobalPostProcessUbo()
534 {
535 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
536 const RenderPostProcessConfiguration rppc =
537 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
538 CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
539 CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
540 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
541 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
542 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
543 // global data
544 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
545 // local data
546 data += sizeof(GlobalPostProcessStruct);
547 CloneData(
548 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
549 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
550 }
551 }
552
GetSceneUniformBuffers(const string_view us)553 void RenderNodeCameraSinglePostProcess::GetSceneUniformBuffers(const string_view us)
554 {
555 sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
556
557 string camName;
558 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
559 camName = to_string(jsonInputs_.customCameraId);
560 } else if (!(jsonInputs_.customCameraName.empty())) {
561 camName = jsonInputs_.customCameraName;
562 }
563 cameraBuffers_ =
564 RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
565 }
566
InitCreateBinders()567 void RenderNodeCameraSinglePostProcess::InitCreateBinders()
568 {
569 const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
570 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
571 {
572 DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
573 if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
574 const DescriptorCounts copyDc = renderCopy_.GetDescriptorCounts();
575 for (const auto& ref : copyDc.counts) {
576 dc.counts.push_back(ref);
577 }
578 }
579 descriptorSetMgr.ResetAndReserve(dc);
580 }
581
582 pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
583 if (pipelineDescriptorSetBinder_) {
584 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
585 if (NeedsAutoBindingSet0(inputResources_)) {
586 useAutoBindSet0_ = true;
587 }
588 } else {
589 valid_ = false;
590 }
591 if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
592 valid_ = false;
593 }
594 }
595
ParseRenderNodeInputs()596 void RenderNodeCameraSinglePostProcess::ParseRenderNodeInputs()
597 {
598 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
599 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
600 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
601 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
602 jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
603 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
604
605 jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
606 jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
607
608 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
609
610 #if (CORE3D_VALIDATION_ENABLED == 1)
611 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
612 CORE_LOG_W("CORE3D_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
613 renderNodeContextMgr_->GetName().data());
614 }
615 if (jsonInputs_.ppName.empty()) {
616 CORE_LOG_W("CORE3D_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
617 }
618 #endif
619
620 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
621 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
622 if (!shaderName.empty()) {
623 shader_ = shaderMgr.GetShaderHandle(shaderName);
624 }
625 const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
626 if (!defaultOutput.empty()) {
627 if (defaultOutput == "output") {
628 jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
629 } else if (defaultOutput == "input_output_copy") {
630 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
631 } else if (defaultOutput == "input") {
632 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
633 } else if (defaultOutput == "black") {
634 jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
635 } else if (defaultOutput == "white") {
636 jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
637 } else {
638 CORE_LOG_W(
639 "RenderNodeCameraSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
640 }
641 }
642
643 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
644 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
645 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
646 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
647
648 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
649 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
650 jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
651
652 // process custom resources
653 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
654 const auto& ref = jsonInputs_.resources.customInputImages[idx];
655 if (ref.usageName == INPUT) {
656 jsonInputs_.inputIdx = idx;
657 }
658 }
659 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
660 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
661 if (ref.usageName == OUTPUT) {
662 jsonInputs_.outputIdx = idx;
663 }
664 }
665 }
666
UpdateImageData()667 void RenderNodeCameraSinglePostProcess::UpdateImageData()
668 {
669 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
670 if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
671 builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
672 }
673 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
674 builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
675 }
676 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
677 builtInVariables_.defWhiteImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
678 }
679 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
680 builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
681 }
682 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
683 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
684 }
685 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
686 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
687 }
688 }
689
690 // for plugin / factory interface
Create()691 IRenderNode* RenderNodeCameraSinglePostProcess::Create()
692 {
693 return new RenderNodeCameraSinglePostProcess();
694 }
695
Destroy(IRenderNode * instance)696 void RenderNodeCameraSinglePostProcess::Destroy(IRenderNode* instance)
697 {
698 delete static_cast<RenderNodeCameraSinglePostProcess*>(instance);
699 }
700 CORE3D_END_NAMESPACE()
701