1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "render_node_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 RegisterOutputs();
240 }
241
PreExecuteFrame()242 void RenderNodeCameraSinglePostProcess::PreExecuteFrame()
243 {
244 {
245 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
246 const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
247 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
248 const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
249 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
250 const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
251 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
252 const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight;
253 if (validRenderDataStore) {
254 UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
255 }
256 }
257
258 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
259 if (jsonInputs_.hasChangeableResourceHandles) {
260 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
261 }
262 UpdateImageData();
263 ProcessPostProcessConfiguration();
264 RegisterOutputs();
265 }
266
ExecuteFrame(IRenderCommandList & cmdList)267 void RenderNodeCameraSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
268 {
269 if ((!ppLocalConfig_.variables.enabled) &&
270 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
271 return;
272 }
273
274 if (ppLocalConfig_.variables.enabled && valid_) {
275 ExecuteSinglePostProcess(cmdList);
276 }
277 }
278
ExecuteSinglePostProcess(IRenderCommandList & cmdList)279 void RenderNodeCameraSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
280 {
281 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
282 if (jsonInputs_.hasChangeableRenderPassHandles) {
283 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
284 }
285 if (jsonInputs_.hasChangeableResourceHandles) {
286 // input resources updated in preExecuteFrame
287 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
288 }
289 if (jsonInputs_.hasChangeableDispatchHandles) {
290 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
291 }
292 if (useAutoBindSet0_) {
293 UpdateGlobalPostProcessUbo();
294 }
295
296 RenderPass renderPass;
297 DispatchResources dispatchResources;
298 if (graphics_) {
299 renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
300 if ((renderPass.renderPassDesc.attachmentCount == 0) ||
301 !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
302 #if (CORE3D_VALIDATION_ENABLED == 1)
303 CORE_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(), "RN: %s, invalid attachment",
304 renderNodeContextMgr_->GetName().data());
305 #endif
306 return;
307 }
308 } else {
309 dispatchResources = GetDispatchResources(dispatchResources_);
310 if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
311 (!RenderHandleUtil::IsValid(dispatchResources.image))) {
312 return; // no way to evaluate dispatch size
313 }
314 }
315
316 const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
317 const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
318 const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
319 for (const auto refIndex : setIndices) {
320 const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
321 // handle automatic set 0 bindings
322 if ((refIndex == 0) && useAutoBindSet0_) {
323 UpdateSet0(cmdList);
324 } else if (invalidBindings) {
325 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
326 BindDefaultResources(refIndex, bindings);
327 }
328 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
329 cmdList.UpdateDescriptorSet(descHandle, bindings);
330 }
331 #if (CORE3D_VALIDATION_ENABLED == 1)
332 if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
333 CORE_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
334 }
335 #endif
336
337 if (graphics_) {
338 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
339 }
340
341 cmdList.BindPipeline(psoHandle_);
342
343 // bind all sets
344 cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
345
346 if (graphics_) {
347 // dynamic state
348 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
349 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
350 cmdList.SetDynamicStateViewport(viewportDesc);
351 cmdList.SetDynamicStateScissor(scissorDesc);
352 // push constants
353 if (pipelineLayout_.pushConstant.byteSize > 0) {
354 const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
355 const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
356 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
357 ppLocalConfig_.variables.factor };
358 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
359 }
360
361 cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
362 cmdList.EndRenderPass();
363 } else {
364 if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
365 cmdList.DispatchIndirect(dispatchResources.buffer, 0);
366 } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
367 const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
368 const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
369 const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
370 if (pipelineLayout_.pushConstant.byteSize > 0) {
371 const float fWidth = static_cast<float>(targetSize.x);
372 const float fHeight = static_cast<float>(targetSize.y);
373 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
374 ppLocalConfig_.variables.factor };
375 cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
376 }
377
378 cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
379 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
380 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
381 }
382 }
383 }
384
RegisterOutputs()385 void RenderNodeCameraSinglePostProcess::RegisterOutputs()
386 {
387 const RenderHandle output = builtInVariables_.output;
388 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
389 RenderHandle registerOutput;
390 if (ppLocalConfig_.variables.enabled) {
391 if (RenderHandleUtil::IsValid(output)) {
392 registerOutput = output;
393 }
394 }
395 if (!RenderHandleUtil::IsValid(registerOutput)) {
396 if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
397 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
398 RenderHandleUtil::IsValid(output)) {
399 registerOutput = output;
400 } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
401 RenderHandleUtil::IsValid(builtInVariables_.input)) {
402 registerOutput = builtInVariables_.input;
403 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
404 registerOutput = builtInVariables_.defWhiteImage;
405 } else {
406 registerOutput = builtInVariables_.defBlackImage;
407 }
408 }
409 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
410 }
411
UpdateSet0(IRenderCommandList & cmdList)412 void RenderNodeCameraSinglePostProcess::UpdateSet0(IRenderCommandList& cmdList)
413 {
414 const RenderHandle radianceCubemap = currentScene_.cameraEnvRadianceHandle;
415 const RenderHandle colorPrePass = RenderHandleUtil::IsValid(currentScene_.prePassColorTarget)
416 ? currentScene_.prePassColorTarget
417 : defaultImagesAndSamplers_.colorPrePassHandle;
418
419 auto& binder = *pipelineDescriptorSetBinder_;
420 uint32_t bindingIndex = 0;
421 // global
422 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, BindableBuffer { ubos_.postProcess.GetHandle() });
423 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++,
424 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
425
426 // scene and camera global
427 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { sceneBuffers_.camera });
428 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.generalData });
429
430 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.environment });
431 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.fog });
432 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.light });
433 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.postProcess });
434 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, bindingIndex++, { cameraBuffers_.lightCluster });
435
436 // scene and camera global images
437 BindableImage bi;
438 bi.handle = colorPrePass;
439 bi.samplerHandle = defaultImagesAndSamplers_.linearMipHandle;
440 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
441 bi.handle = shadowBuffers_.vsmColorHandle;
442 bi.samplerHandle = shadowBuffers_.vsmSamplerHandle;
443 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
444 bi.handle = shadowBuffers_.pcfDepthHandle;
445 bi.samplerHandle = shadowBuffers_.pcfSamplerHandle;
446 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
447 bi.handle = radianceCubemap;
448 bi.samplerHandle = defaultImagesAndSamplers_.cubemapHandle;
449 binder.BindImage(GLOBAL_POST_PROCESS_SET, bindingIndex++, bi, CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT);
450
451 // NOTE: UpdateDescriptorSets is done when called
452 }
453
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)454 void RenderNodeCameraSinglePostProcess::BindDefaultResources(
455 const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
456 {
457 if (pipelineDescriptorSetBinder_) {
458 auto& binder = *pipelineDescriptorSetBinder_;
459 for (const auto& ref : bindings.buffers) {
460 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
461 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
462 }
463 }
464 for (const auto& ref : bindings.images) {
465 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
466 BindableImage bi;
467 bi.handle = builtInVariables_.defBlackImage;
468 bi.samplerHandle = builtInVariables_.defSampler;
469 binder.BindImage(set, ref.binding.binding, bi);
470 }
471 }
472 for (const auto& ref : bindings.samplers) {
473 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
474 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
475 }
476 }
477 }
478 }
479
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)480 void RenderNodeCameraSinglePostProcess::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
481 const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
482 {
483 const auto scene = dataStoreScene.GetScene();
484 uint32_t cameraIdx = scene.cameraIndex;
485 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
486 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
487 } else if (!(jsonInputs_.customCameraName.empty())) {
488 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
489 }
490
491 if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
492 // store current frame camera
493 currentScene_.camera = cameras[cameraIdx];
494 }
495 const auto camHandles = RenderNodeSceneUtil::GetSceneCameraImageHandles(
496 *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
497 currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
498
499 const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
500 currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
501 currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
502 currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
503 }
504
ProcessPostProcessConfiguration()505 void RenderNodeCameraSinglePostProcess::ProcessPostProcessConfiguration()
506 {
507 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
508 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
509 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
510 if (jsonInputs_.renderDataStore.typeName == RENDER_DATA_STORE_POST_PROCESS_NAME) {
511 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
512 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
513 }
514 }
515 if (const IRenderDataStorePod* ds =
516 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
517 ds) {
518 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
519 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
520 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
521 }
522 }
523 } else if (jsonInputs_.ppName.empty()) {
524 // if trying to just use shader without post processing we enable running by default
525 ppLocalConfig_.variables.enabled = true;
526 }
527 }
528
UpdateGlobalPostProcessUbo()529 void RenderNodeCameraSinglePostProcess::UpdateGlobalPostProcessUbo()
530 {
531 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
532 const RenderPostProcessConfiguration rppc =
533 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
534 CORE_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
535 CORE_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
536 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
537 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
538 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
539 // global data
540 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
541 // local data
542 data += sizeof(GlobalPostProcessStruct);
543 CloneData(
544 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
545 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
546 }
547 }
548
GetSceneUniformBuffers(const string_view us)549 void RenderNodeCameraSinglePostProcess::GetSceneUniformBuffers(const string_view us)
550 {
551 sceneBuffers_ = RenderNodeSceneUtil::GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
552
553 string camName;
554 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
555 camName = to_string(jsonInputs_.customCameraId);
556 } else if (!(jsonInputs_.customCameraName.empty())) {
557 camName = jsonInputs_.customCameraName;
558 }
559 cameraBuffers_ =
560 RenderNodeSceneUtil::GetSceneCameraBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
561 }
562
InitCreateBinders()563 void RenderNodeCameraSinglePostProcess::InitCreateBinders()
564 {
565 const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
566 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
567 {
568 DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
569 descriptorSetMgr.ResetAndReserve(dc);
570 }
571
572 pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
573 if (pipelineDescriptorSetBinder_) {
574 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
575 if (NeedsAutoBindingSet0(inputResources_)) {
576 useAutoBindSet0_ = true;
577 }
578 } else {
579 valid_ = false;
580 }
581 if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
582 valid_ = false;
583 }
584 }
585
ParseRenderNodeInputs()586 void RenderNodeCameraSinglePostProcess::ParseRenderNodeInputs()
587 {
588 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
589 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
590 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
591 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
592 jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
593 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
594
595 jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
596 jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
597
598 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
599
600 #if (CORE3D_VALIDATION_ENABLED == 1)
601 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
602 CORE_LOG_W("CORE3D_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
603 renderNodeContextMgr_->GetName().data());
604 }
605 if (jsonInputs_.ppName.empty()) {
606 CORE_LOG_W("CORE3D_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
607 }
608 #endif
609
610 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
611 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
612 if (!shaderName.empty()) {
613 shader_ = shaderMgr.GetShaderHandle(shaderName);
614 }
615 const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
616 if (!defaultOutput.empty()) {
617 if (defaultOutput == "output") {
618 jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
619 } else if (defaultOutput == "input_output_copy") {
620 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
621 } else if (defaultOutput == "input") {
622 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
623 } else if (defaultOutput == "black") {
624 jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
625 } else if (defaultOutput == "white") {
626 jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
627 } else {
628 CORE_LOG_W(
629 "RenderNodeCameraSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
630 }
631 }
632
633 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
634 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
635 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
636 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
637
638 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
639 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
640 jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
641
642 // process custom resources
643 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
644 const auto& ref = jsonInputs_.resources.customInputImages[idx];
645 if (ref.usageName == INPUT) {
646 jsonInputs_.inputIdx = idx;
647 }
648 }
649 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
650 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
651 if (ref.usageName == OUTPUT) {
652 jsonInputs_.outputIdx = idx;
653 }
654 }
655 }
656
UpdateImageData()657 void RenderNodeCameraSinglePostProcess::UpdateImageData()
658 {
659 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
660 if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
661 builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
662 }
663 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
664 builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
665 }
666 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
667 builtInVariables_.defWhiteImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_WHITE);
668 }
669 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
670 builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
671 }
672 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
673 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
674 }
675 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
676 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
677 }
678 }
679
680 // for plugin / factory interface
Create()681 IRenderNode* RenderNodeCameraSinglePostProcess::Create()
682 {
683 return new RenderNodeCameraSinglePostProcess();
684 }
685
Destroy(IRenderNode * instance)686 void RenderNodeCameraSinglePostProcess::Destroy(IRenderNode* instance)
687 {
688 delete static_cast<RenderNodeCameraSinglePostProcess*>(instance);
689 }
690 CORE3D_END_NAMESPACE()
691