• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_post_process_util.h"
17 
18 #include <core/property/property_handle_util.h>
19 #include <render/datastore/intf_render_data_store_manager.h>
20 #include <render/datastore/intf_render_data_store_pod.h>
21 #include <render/datastore/render_data_store_render_pods.h>
22 #include <render/device/intf_gpu_resource_manager.h>
23 #include <render/device/intf_shader_manager.h>
24 #include <render/device/pipeline_state_desc.h>
25 #include <render/intf_render_context.h>
26 #include <render/namespace.h>
27 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
28 #include <render/nodecontext/intf_node_context_pso_manager.h>
29 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
30 #include <render/nodecontext/intf_render_command_list.h>
31 #include <render/nodecontext/intf_render_node.h>
32 #include <render/nodecontext/intf_render_node_context_manager.h>
33 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
34 #include <render/nodecontext/intf_render_node_parser_util.h>
35 #include <render/nodecontext/intf_render_node_util.h>
36 #include <render/property/property_types.h>
37 
38 #include "datastore/render_data_store_pod.h"
39 #include "datastore/render_data_store_post_process.h"
40 #include "default_engine_constants.h"
41 #include "device/gpu_resource_handle_util.h"
42 #include "nodecontext/pipeline_descriptor_set_binder.h"
43 #include "postprocesses/render_post_process_bloom.h"
44 #include "postprocesses/render_post_process_blur.h"
45 #include "postprocesses/render_post_process_combined.h"
46 #include "postprocesses/render_post_process_dof.h"
47 #include "postprocesses/render_post_process_flare.h"
48 #include "postprocesses/render_post_process_fxaa.h"
49 #include "postprocesses/render_post_process_motion_blur.h"
50 #include "postprocesses/render_post_process_taa.h"
51 #include "postprocesses/render_post_process_upscale.h"
52 #include "util/log.h"
53 
54 // shaders
55 #include <render/shaders/common/render_post_process_layout_common.h>
56 #include <render/shaders/common/render_post_process_structs_common.h>
57 
58 using namespace BASE_NS;
59 using namespace CORE_NS;
60 
61 RENDER_BEGIN_NAMESPACE()
62 namespace {
63 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
64 constexpr uint32_t GL_LAYER_CANNOT_OPT_FLAGS = PostProcessConfiguration::ENABLE_BLOOM_BIT |
65                                                PostProcessConfiguration::ENABLE_TAA_BIT |
66                                                PostProcessConfiguration::ENABLE_DOF_BIT;
67 
68 constexpr string_view INPUT_COLOR = "color";
69 constexpr string_view INPUT_DEPTH = "depth";
70 constexpr string_view INPUT_VELOCITY = "velocity";
71 constexpr string_view INPUT_HISTORY = "history";
72 constexpr string_view INPUT_HISTORY_NEXT = "history_next";
73 
74 constexpr string_view COPY_SHADER_NAME = "rendershaders://shader/fullscreen_copy.shader";
75 
76 const bool ENABLE_UPSCALER = false;
77 
CreateRenderPass(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle input)78 RenderPass CreateRenderPass(const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle input)
79 {
80     const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(input);
81     RenderPass rp;
82     rp.renderPassDesc.attachmentCount = 1u;
83     rp.renderPassDesc.attachmentHandles[0u] = input;
84     rp.renderPassDesc.attachments[0u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
85     rp.renderPassDesc.attachments[0u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
86     rp.renderPassDesc.renderArea = { 0, 0, desc.width, desc.height };
87 
88     rp.renderPassDesc.subpassCount = 1u;
89     rp.subpassDesc.colorAttachmentCount = 1u;
90     rp.subpassDesc.colorAttachmentIndices[0u] = 0u;
91     rp.subpassStartIndex = 0u;
92     return rp;
93 }
94 
FillTmpImageDesc(GpuImageDesc & desc)95 void FillTmpImageDesc(GpuImageDesc& desc)
96 {
97     desc.imageType = CORE_IMAGE_TYPE_2D;
98     desc.imageViewType = CORE_IMAGE_VIEW_TYPE_2D;
99     desc.engineCreationFlags = EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS |
100                                EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS;
101     desc.usageFlags =
102         ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT;
103     // don't want this multisampled even if the final output would be.
104     desc.sampleCountFlags = SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT;
105     desc.layerCount = 1U;
106     desc.mipCount = 1U;
107 }
108 
IsValidHandle(const BindableImage & img)109 inline bool IsValidHandle(const BindableImage& img)
110 {
111     return RenderHandleUtil::IsValid(img.handle);
112 }
113 } // namespace
114 
Init(IRenderNodeContextManager & renderNodeContextMgr,const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)115 void RenderNodePostProcessUtil::Init(
116     IRenderNodeContextManager& renderNodeContextMgr, const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
117 {
118     renderNodeContextMgr_ = &renderNodeContextMgr;
119     postProcessInfo_ = postProcessInfo;
120     CreatePostProcessInterfaces();
121     ParseRenderNodeInputs();
122     UpdateImageData();
123 
124     deviceBackendType_ = renderNodeContextMgr_->GetRenderContext().GetDevice().GetBackendType();
125 
126     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
127     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
128     samplers_.nearest =
129         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP);
130     samplers_.linear =
131         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
132     samplers_.mipLinear =
133         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP);
134 
135     InitCreateShaderResources();
136 
137     if ((!IsValidHandle(images_.input)) || (!IsValidHandle(images_.output))) {
138         validInputs_ = false;
139         PLUGIN_LOG_E("RN: %s, expects custom input and output image", renderNodeContextMgr_->GetName().data());
140     }
141 
142     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
143         PLUGIN_LOG_W("RenderNodeCombinedPostProcess: render data store configuration not set in render node graph");
144     }
145     if (jsonInputs_.renderDataStore.typeName != RenderDataStorePod::TYPE_NAME) {
146         PLUGIN_LOG_E("RenderNodeCombinedPostProcess: render data store type name not supported (%s != %s)",
147             jsonInputs_.renderDataStore.typeName.data(), RenderDataStorePod::TYPE_NAME);
148         validInputs_ = false;
149     }
150 
151     // call post process interface inits before descriptor set allocation
152     {
153         if (ppLensFlareInterface_.postProcessNode) {
154             ppLensFlareInterface_.postProcessNode->Init(ppLensFlareInterface_.postProcess, *renderNodeContextMgr_);
155         }
156         if (ENABLE_UPSCALER) {
157             if (ppRenderUpscaleInterface_.postProcessNode) {
158                 ppRenderUpscaleInterface_.postProcessNode->Init(
159                     ppRenderUpscaleInterface_.postProcess, *renderNodeContextMgr_);
160             }
161         }
162         if (ppRenderBlurInterface_.postProcessNode) {
163             ppRenderBlurInterface_.postProcessNode->Init(ppRenderBlurInterface_.postProcess, *renderNodeContextMgr_);
164         }
165         if (ppRenderTaaInterface_.postProcessNode) {
166             ppRenderTaaInterface_.postProcessNode->Init(ppRenderTaaInterface_.postProcess, *renderNodeContextMgr_);
167         }
168         if (ppRenderFxaaInterface_.postProcessNode) {
169             ppRenderFxaaInterface_.postProcessNode->Init(ppRenderFxaaInterface_.postProcess, *renderNodeContextMgr_);
170         }
171         if (ppRenderDofInterface_.postProcessNode) {
172             ppRenderDofInterface_.postProcessNode->Init(ppRenderDofInterface_.postProcess, *renderNodeContextMgr_);
173         }
174         if (ppRenderMotionBlurInterface_.postProcessNode) {
175             ppRenderMotionBlurInterface_.postProcessNode->Init(
176                 ppRenderMotionBlurInterface_.postProcess, *renderNodeContextMgr_);
177         }
178         if (ppRenderBloomInterface_.postProcessNode) {
179             ppRenderBloomInterface_.postProcessNode->Init(ppRenderBloomInterface_.postProcess, *renderNodeContextMgr_);
180         }
181         if (ppRenderCombinedInterface_.postProcessNode) {
182             ppRenderCombinedInterface_.postProcessNode->Init(
183                 ppRenderCombinedInterface_.postProcess, *renderNodeContextMgr_);
184         }
185     }
186     {
187         vector<DescriptorCounts> descriptorCounts;
188         descriptorCounts.reserve(16U);
189         // pre-set custom descriptor sets
190         descriptorCounts.push_back(DescriptorCounts { {
191             { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 8u },
192             { CORE_DESCRIPTOR_TYPE_SAMPLER, 8u },
193             { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8u },
194         } });
195         descriptorCounts.push_back(renderCopyLayer_.GetRenderDescriptorCounts());
196         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(copyData_.sd.pipelineLayoutData));
197         // interfaces
198         if (ppRenderBlurInterface_.postProcessNode) {
199             descriptorCounts.push_back(ppRenderBlurInterface_.postProcessNode->GetRenderDescriptorCounts());
200         }
201         if (ppRenderTaaInterface_.postProcessNode) {
202             descriptorCounts.push_back(ppRenderTaaInterface_.postProcessNode->GetRenderDescriptorCounts());
203         }
204         if (ppRenderFxaaInterface_.postProcessNode) {
205             descriptorCounts.push_back(ppRenderFxaaInterface_.postProcessNode->GetRenderDescriptorCounts());
206         }
207         if (ppRenderDofInterface_.postProcessNode) {
208             descriptorCounts.push_back(ppRenderDofInterface_.postProcessNode->GetRenderDescriptorCounts());
209         }
210         if (ppRenderMotionBlurInterface_.postProcessNode) {
211             descriptorCounts.push_back(ppRenderMotionBlurInterface_.postProcessNode->GetRenderDescriptorCounts());
212         }
213         if (ppRenderBloomInterface_.postProcessNode) {
214             descriptorCounts.push_back(ppRenderBloomInterface_.postProcessNode->GetRenderDescriptorCounts());
215         }
216         if (ppRenderCombinedInterface_.postProcess) {
217             descriptorCounts.push_back(ppRenderCombinedInterface_.postProcessNode->GetRenderDescriptorCounts());
218         }
219         if (ppRenderUpscaleInterface_.postProcess && ENABLE_UPSCALER) {
220             descriptorCounts.push_back(ppRenderUpscaleInterface_.postProcessNode->GetRenderDescriptorCounts());
221         }
222         renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(descriptorCounts);
223     }
224 
225     ProcessPostProcessConfiguration();
226 
227     if (deviceBackendType_ != DeviceBackendType::VULKAN) {
228         // prepare for possible layer copy
229         renderCopyLayer_.Init(renderNodeContextMgr);
230     }
231 
232     InitCreateBinders();
233 
234     if ((!jsonInputs_.resources.customOutputImages.empty()) && (!inputResources_.customOutputImages.empty()) &&
235         (RenderHandleUtil::IsValid(inputResources_.customOutputImages[0].handle))) {
236         IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
237         shrMgr.RegisterRenderNodeOutput(
238             jsonInputs_.resources.customOutputImages[0u].name, inputResources_.customOutputImages[0u].handle);
239     }
240 }
241 
PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)242 void RenderNodePostProcessUtil::PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
243 {
244     postProcessInfo_ = postProcessInfo;
245     if (!validInputs_) {
246         return;
247     }
248 
249     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
250     if (jsonInputs_.hasChangeableResourceHandles) {
251         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
252     }
253     UpdateImageData();
254 
255     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
256     const GpuImageDesc inputDesc = gpuResourceMgr.GetImageDescriptor(images_.input.handle);
257     const GpuImageDesc outputDesc = gpuResourceMgr.GetImageDescriptor(images_.output.handle);
258     outputSize_ = { outputDesc.width, outputDesc.height };
259 #if (RENDER_VALIDATION_ENABLED == 1)
260     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT) &&
261         (!validInputsForTaa_)) {
262         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_taa_depth_vel",
263             "RENDER_VALIDATION: Default TAA post process needs output depth, velocity, and history.");
264     }
265     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT) &&
266         (!validInputsForDof_)) {
267         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_dof_depth",
268             "RENDER_VALIDATION: Default DOF post process needs output depth.");
269     }
270     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT) &&
271         (!validInputsForMb_)) {
272         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_mb_vel",
273             "RENDER_VALIDATION: Default motion blur post process needs output (samplable) velocity.");
274     }
275 #endif
276 
277     // process this frame's enabled post processes here
278     // bloom might need target updates, no further processing is needed
279     ProcessPostProcessConfiguration();
280 
281     // post process
282     const bool fxaaEnabled =
283         ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
284     const bool motionBlurEnabled =
285         validInputsForMb_ &&
286         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT);
287     const bool dofEnabled =
288         validInputsForDof_ &&
289         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT);
290 
291     ti_.idx = 0;
292     const bool basicImagesNeeded = fxaaEnabled || motionBlurEnabled || dofEnabled;
293     const bool mipImageNeeded = dofEnabled;
294     const auto nearMips = static_cast<uint32_t>(Math::ceilToInt(ppConfig_.dofConfiguration.nearBlur));
295     const auto farMips = static_cast<uint32_t>(Math::ceilToInt(ppConfig_.dofConfiguration.farBlur));
296     const bool mipCountChanged = (nearMips != ti_.mipCount[0U]) || (farMips != ti_.mipCount[1U]);
297     const bool sizeChanged = (ti_.targetSize.x != static_cast<float>(outputSize_.x)) ||
298                              (ti_.targetSize.y != static_cast<float>(outputSize_.y));
299     if (sizeChanged) {
300         ti_.targetSize.x = Math::max(1.0f, static_cast<float>(outputSize_.x));
301         ti_.targetSize.y = Math::max(1.0f, static_cast<float>(outputSize_.y));
302         ti_.targetSize.z = 1.f / ti_.targetSize.x;
303         ti_.targetSize.w = 1.f / ti_.targetSize.y;
304     }
305     if (basicImagesNeeded) {
306         if ((!ti_.images[0U]) || sizeChanged) {
307 #if (RENDER_VALIDATION_ENABLED == 1)
308             PLUGIN_LOG_I("RENDER_VALIDATION: post process temporary images re-created (size:%ux%u)", outputSize_.x,
309                 outputSize_.y);
310 #endif
311             GpuImageDesc tmpDesc = outputDesc;
312             FillTmpImageDesc(tmpDesc);
313             ti_.images[0U] = gpuResourceMgr.Create(ti_.images[0U], tmpDesc);
314             ti_.images[1U] = gpuResourceMgr.Create(ti_.images[1U], tmpDesc);
315             ti_.imageCount = 2U;
316         }
317     } else {
318         ti_.images[0U] = {};
319         ti_.images[1U] = {};
320     }
321     if (mipImageNeeded) {
322         if ((!ti_.mipImages[0U]) || sizeChanged || mipCountChanged) {
323 #if (RENDER_VALIDATION_ENABLED == 1)
324             PLUGIN_LOG_I("RENDER_VALIDATION: post process temporary mip image re-created (size:%ux%u)", outputSize_.x,
325                 outputSize_.y);
326 #endif
327             GpuImageDesc tmpDesc = outputDesc;
328             FillTmpImageDesc(tmpDesc);
329             tmpDesc.mipCount = nearMips;
330             ti_.mipImages[0] = gpuResourceMgr.Create(ti_.mipImages[0U], tmpDesc);
331             tmpDesc.mipCount = farMips;
332             ti_.mipImages[1] = gpuResourceMgr.Create(ti_.mipImages[1U], tmpDesc);
333             ti_.mipImageCount = 2U;
334             ti_.mipCount[0U] = nearMips;
335             ti_.mipCount[1U] = farMips;
336         }
337     } else {
338         ti_.mipImages[0U] = {};
339         ti_.mipImages[1U] = {};
340     }
341     if ((!basicImagesNeeded) && (!mipImageNeeded)) {
342         ti_ = {};
343     }
344 
345     BindableImage postTaaBloomInput = images_.input;
346     // prepare for possible layer copy
347     glOptimizedLayerCopyEnabled_ = false;
348     if ((deviceBackendType_ != DeviceBackendType::VULKAN) &&
349         (images_.input.layer != PipelineStateConstants::GPU_IMAGE_ALL_LAYERS)) {
350         if ((ppConfig_.enableFlags & GL_LAYER_CANNOT_OPT_FLAGS) == 0U) {
351             // optimize with combine
352             glOptimizedLayerCopyEnabled_ = true;
353         } else {
354             if (sizeChanged || (!ti_.layerCopyImage)) {
355                 GpuImageDesc tmpDesc = inputDesc; // NOTE: input desc
356                 FillTmpImageDesc(tmpDesc);
357                 ti_.layerCopyImage = gpuResourceMgr.Create(ti_.layerCopyImage, tmpDesc);
358             }
359 
360             BindableImage layerCopyOutput;
361             layerCopyOutput.handle = ti_.layerCopyImage.GetHandle();
362             renderCopyLayer_.PreExecute();
363 
364             // postTaa bloom input
365             postTaaBloomInput = layerCopyOutput;
366         }
367     }
368 
369     if (validInputsForTaa_ &&
370         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT)) {
371         postTaaBloomInput = images_.historyNext;
372         if (ppRenderTaaInterface_.postProcessNode && ppRenderTaaInterface_.postProcess) {
373             // copy properties to new property post process
374             RenderPostProcessTaa& pp = static_cast<RenderPostProcessTaa&>(*ppRenderTaaInterface_.postProcess);
375             pp.propertiesData.enabled = true;
376             pp.propertiesData.taaConfiguration = ppConfig_.taaConfiguration;
377 
378             RenderPostProcessTaaNode& ppNode =
379                 static_cast<RenderPostProcessTaaNode&>(*ppRenderTaaInterface_.postProcessNode);
380             ppNode.nodeInputsData.input = images_.input;
381             ppNode.nodeOutputsData.output = images_.historyNext;
382             ppNode.nodeInputsData.depth = images_.depth;
383             ppNode.nodeInputsData.velocity = images_.velocity;
384             ppNode.nodeInputsData.history = images_.history;
385             ppNode.PreExecute();
386         }
387     }
388 
389     if (ENABLE_UPSCALER) {
390         if (ppRenderUpscaleInterface_.postProcessNode && ppRenderUpscaleInterface_.postProcess) {
391             RenderPostProcessUpscale& pp =
392                 static_cast<RenderPostProcessUpscale&>(*ppRenderUpscaleInterface_.postProcess);
393 
394             pp.propertiesData.enabled = true;
395             pp.propertiesData.ratio = 1.0f;
396 
397             RenderPostProcessUpscaleNode& ppNode =
398                 static_cast<RenderPostProcessUpscaleNode&>(*ppRenderUpscaleInterface_.postProcessNode);
399 
400             ppNode.nodeInputsData.input = postTaaBloomInput;
401             ppNode.nodeInputsData.depth = images_.depth;
402             ppNode.nodeInputsData.velocity = images_.velocity;
403             ppNode.PreExecute();
404         }
405     }
406     // NOTE: separate flare with new post process interface
407     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_LENS_FLARE_BIT) {
408         if (ppLensFlareInterface_.postProcessNode && ppLensFlareInterface_.postProcess) {
409             // copy properties to new property post process
410             RenderPostProcessFlare& pp = static_cast<RenderPostProcessFlare&>(*ppLensFlareInterface_.postProcess);
411             pp.propertiesData.enabled = true;
412             pp.propertiesData.flarePos = ppConfig_.lensFlareConfiguration.flarePosition;
413             pp.propertiesData.intensity = ppConfig_.lensFlareConfiguration.intensity;
414 
415             RenderPostProcessFlareNode& ppNode =
416                 static_cast<RenderPostProcessFlareNode&>(*ppLensFlareInterface_.postProcessNode);
417             ppNode.nodeInputsData.input = postTaaBloomInput;
418             ppNode.PreExecute();
419         }
420     }
421 
422     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT) {
423         if (ppRenderBloomInterface_.postProcessNode && ppRenderBloomInterface_.postProcess) {
424             // copy properties to new property post process
425             RenderPostProcessBloom& pp = static_cast<RenderPostProcessBloom&>(*ppRenderBloomInterface_.postProcess);
426             pp.propertiesData.enabled = true;
427             pp.propertiesData.bloomConfiguration = ppConfig_.bloomConfiguration;
428 
429             RenderPostProcessBloomNode& ppNode =
430                 static_cast<RenderPostProcessBloomNode&>(*ppRenderBloomInterface_.postProcessNode);
431             ppNode.nodeInputsData.input = postTaaBloomInput;
432             ppNode.PreExecute();
433         }
434     }
435 
436     // needs to evaluate what is the final effect, where we will use the final target
437     // the final target (output) might be a swapchain which cannot be sampled
438     framePostProcessInOut_.clear();
439     // after bloom or TAA
440     BindableImage input = postTaaBloomInput;
441     const bool postProcessNeeded = (ppConfig_.enableFlags != 0);
442     const bool sameInputOutput = (images_.input.handle == images_.output.handle);
443     // combine
444     if (postProcessNeeded && (!sameInputOutput)) {
445         const BindableImage output =
446             (basicImagesNeeded || mipImageNeeded) ? GetIntermediateImage(input.handle) : images_.output;
447         framePostProcessInOut_.push_back({ input, output });
448         input = framePostProcessInOut_.back().output;
449     }
450     if (fxaaEnabled) {
451         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
452         input = framePostProcessInOut_.back().output;
453     }
454     if (motionBlurEnabled) {
455         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
456         input = framePostProcessInOut_.back().output;
457     }
458     if (dofEnabled) {
459         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
460         input = framePostProcessInOut_.back().output;
461     }
462     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
463         framePostProcessInOut_.push_back({ input, input });
464         input = framePostProcessInOut_.back().output;
465     }
466     // finalize
467     if (!framePostProcessInOut_.empty()) {
468         framePostProcessInOut_.back().output = images_.output;
469     }
470 
471     uint32_t ppIdx = 0U;
472     if (postProcessNeeded && (!sameInputOutput)) {
473         if (ppRenderCombinedInterface_.postProcessNode && ppRenderCombinedInterface_.postProcess) {
474             RenderPostProcessCombined& pp =
475                 static_cast<RenderPostProcessCombined&>(*ppRenderCombinedInterface_.postProcess);
476             pp.propertiesData.enabled = true;
477             pp.propertiesData.postProcessConfiguration = ppConfig_;
478             pp.propertiesData.glOptimizedLayerCopyEnabled = glOptimizedLayerCopyEnabled_;
479 
480             RenderPostProcessCombinedNode& ppNode =
481                 static_cast<RenderPostProcessCombinedNode&>(*ppRenderCombinedInterface_.postProcessNode);
482             ppNode.nodeInputsData.input = framePostProcessInOut_[ppIdx].input;
483             ppNode.nodeOutputsData.output = framePostProcessInOut_[ppIdx].output;
484             ppNode.nodeInputsData.dirtMask.handle = images_.dirtMask;
485             RenderHandle bloomImage = aimg_.black;
486             if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT) &&
487                 ppRenderBloomInterface_.postProcessNode) {
488                 bloomImage = static_cast<RenderPostProcessBloomNode*>(ppRenderBloomInterface_.postProcessNode.get())
489                                  ->GetFinalTarget();
490             }
491             ppNode.nodeInputsData.bloomFinalTarget.handle = bloomImage;
492             ppNode.PreExecute();
493         }
494         ppIdx++;
495     }
496     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT) {
497         if (ppRenderFxaaInterface_.postProcessNode && ppRenderFxaaInterface_.postProcess) {
498             // copy properties to new property post process
499             RenderPostProcessFxaa& pp = static_cast<RenderPostProcessFxaa&>(*ppRenderFxaaInterface_.postProcess);
500             pp.propertiesData.enabled = true;
501             pp.propertiesData.fxaaConfiguration = ppConfig_.fxaaConfiguration;
502             pp.propertiesData.targetSize = ti_.targetSize;
503 
504             RenderPostProcessFxaaNode& ppNode =
505                 static_cast<RenderPostProcessFxaaNode&>(*ppRenderFxaaInterface_.postProcessNode);
506             ppNode.nodeInputsData.input = framePostProcessInOut_[ppIdx].input;
507             ppNode.nodeOutputsData.output = framePostProcessInOut_[ppIdx].output;
508             ppNode.PreExecute();
509         }
510         ppIdx++;
511     }
512     if (motionBlurEnabled) {
513         if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT) {
514             if (ppRenderMotionBlurInterface_.postProcessNode && ppRenderMotionBlurInterface_.postProcess) {
515                 RenderPostProcessMotionBlur& pp =
516                     static_cast<RenderPostProcessMotionBlur&>(*ppRenderMotionBlurInterface_.postProcess);
517                 pp.propertiesData.enabled = true;
518                 pp.propertiesData.motionBlurConfiguration = ppConfig_.motionBlurConfiguration;
519                 pp.propertiesData.size = outputSize_;
520 
521                 RenderPostProcessMotionBlurNode& ppNode =
522                     static_cast<RenderPostProcessMotionBlurNode&>(*ppRenderMotionBlurInterface_.postProcessNode);
523                 ppNode.nodeInputsData.input = framePostProcessInOut_[ppIdx].input;
524                 ppNode.nodeOutputsData.output = framePostProcessInOut_[ppIdx].output;
525                 ppNode.nodeInputsData.velocity = images_.velocity;
526                 ppNode.nodeInputsData.depth = images_.depth;
527 
528                 ppNode.PreExecute();
529             }
530         }
531         ppIdx++;
532     }
533 
534     if (dofEnabled) {
535         auto nearMip = GetMipImage(input.handle);
536         auto farMip = GetMipImage(nearMip.handle);
537         if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT) {
538             if (ppRenderDofInterface_.postProcessNode && ppRenderDofInterface_.postProcess) {
539                 // copy properties to new property post process
540                 RenderPostProcessDof& pp = static_cast<RenderPostProcessDof&>(*ppRenderDofInterface_.postProcess);
541                 pp.propertiesData.enabled = true;
542                 pp.propertiesData.dofConfiguration = ppConfig_.dofConfiguration;
543                 pp.propertiesData.mipImages[0] = ti_.mipImages[0];
544                 pp.propertiesData.mipImages[1] = ti_.mipImages[1];
545                 pp.propertiesData.nearMip = nearMip;
546                 pp.propertiesData.farMip = farMip;
547 
548                 RenderPostProcessDofNode& ppNode =
549                     static_cast<RenderPostProcessDofNode&>(*ppRenderDofInterface_.postProcessNode);
550                 ppNode.nodeInputsData.input = framePostProcessInOut_[ppIdx].input;
551                 ppNode.nodeOutputsData.output = framePostProcessInOut_[ppIdx].output;
552                 ppNode.nodeInputsData.depth = images_.depth;
553 
554                 ppNode.PreExecute();
555             }
556         }
557         ppIdx++;
558     }
559 
560     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
561         const auto& inOut = framePostProcessInOut_[ppIdx++];
562         if (ppRenderBlurInterface_.postProcessNode && ppRenderBlurInterface_.postProcess) {
563             // copy properties to new property post process
564             RenderPostProcessBlur& pp = static_cast<RenderPostProcessBlur&>(*ppRenderBlurInterface_.postProcess);
565             pp.propertiesData.enabled = true;
566             pp.propertiesData.blurConfiguration = ppConfig_.blurConfiguration;
567 
568             RenderPostProcessBlurNode& ppNode =
569                 static_cast<RenderPostProcessBlurNode&>(*ppRenderBlurInterface_.postProcessNode);
570             ppNode.nodeInputsData.input = inOut.output;
571             ppNode.PreExecute();
572         }
573     }
574 
575     PLUGIN_ASSERT(ppIdx == framePostProcessInOut_.size());
576 
577     if ((!jsonInputs_.resources.customOutputImages.empty()) && (!inputResources_.customOutputImages.empty()) &&
578         (RenderHandleUtil::IsValid(inputResources_.customOutputImages[0].handle))) {
579         IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
580         shrMgr.RegisterRenderNodeOutput(
581             jsonInputs_.resources.customOutputImages[0u].name, inputResources_.customOutputImages[0u].handle);
582     }
583 }
584 
Execute(IRenderCommandList & cmdList)585 void RenderNodePostProcessUtil::Execute(IRenderCommandList& cmdList)
586 {
587     if (!validInputs_) {
588         return;
589     }
590 
591     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderPostProcess", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
592 
593     // prepare for possible layer copy if not using optimized paths for layers
594     if ((deviceBackendType_ != DeviceBackendType::VULKAN) &&
595         (images_.input.layer != PipelineStateConstants::GPU_IMAGE_ALL_LAYERS) && (!glOptimizedLayerCopyEnabled_)) {
596         BindableImage layerCopyOutput;
597         layerCopyOutput.handle = ti_.layerCopyImage.GetHandle();
598         IRenderNodeCopyUtil::CopyInfo layerCopyInfo;
599         layerCopyInfo.input = images_.input;
600         layerCopyInfo.output = layerCopyOutput;
601         layerCopyInfo.copyType = IRenderNodeCopyUtil::CopyType::LAYER_COPY;
602         renderCopyLayer_.Execute(cmdList, layerCopyInfo);
603     }
604 
605     if (validInputsForTaa_ &&
606         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT)) {
607         if (ppRenderTaaInterface_.postProcessNode && ppRenderTaaInterface_.postProcess) {
608             // inputs set in pre-execute
609             ppRenderTaaInterface_.postProcessNode->Execute(cmdList);
610         }
611     }
612 
613     if (validInputsForUpscale_ && ENABLE_UPSCALER) {
614         ppRenderUpscaleInterface_.postProcessNode->Execute(cmdList);
615     }
616 
617     // NOTE: separate flare with new post process interface
618     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_LENS_FLARE_BIT) {
619         if (ppLensFlareInterface_.postProcessNode) {
620             // inputs set in pre-execute
621             ppLensFlareInterface_.postProcessNode->Execute(cmdList);
622         }
623     }
624 
625     // ppConfig_ is already up-to-date from PreExecuteFrame
626     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT) {
627         if (ppRenderBloomInterface_.postProcessNode && ppRenderBloomInterface_.postProcess) {
628             // inputs set in pre-execute
629             ppRenderBloomInterface_.postProcessNode->Execute(cmdList);
630         }
631     }
632 
633     // post process
634     const bool fxaaEnabled =
635         ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
636     const bool motionBlurEnabled =
637         validInputsForMb_ &&
638         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT);
639     const bool dofEnabled =
640         validInputsForDof_ &&
641         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT);
642 
643     // after bloom or TAA
644     const bool postProcessNeeded = (ppConfig_.enableFlags != 0);
645     const bool sameInputOutput = (images_.input.handle == images_.output.handle);
646 
647 #if (RENDER_VALIDATION_ENABLED == 1)
648     if (postProcessNeeded && sameInputOutput) {
649         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName().data(),
650             "%s: combined post process shader not supported for same input/output ATM.",
651             renderNodeContextMgr_->GetName().data());
652     }
653 #endif
654     uint32_t ppIdx = 0U;
655     if (postProcessNeeded && (!sameInputOutput)) {
656         if (ppRenderCombinedInterface_.postProcessNode && ppRenderCombinedInterface_.postProcess) {
657             ppRenderCombinedInterface_.postProcessNode->Execute(cmdList);
658             ppIdx++;
659         }
660     }
661 
662     if (fxaaEnabled) {
663         if (ppRenderFxaaInterface_.postProcessNode && ppRenderFxaaInterface_.postProcess) {
664             ppRenderFxaaInterface_.postProcessNode->Execute(cmdList);
665             ppIdx++;
666         }
667     }
668 
669     if (motionBlurEnabled) {
670         ppIdx++;
671         if (ppRenderMotionBlurInterface_.postProcessNode && ppRenderMotionBlurInterface_.postProcess) {
672             ppRenderMotionBlurInterface_.postProcessNode->Execute(cmdList);
673         }
674     }
675     if (dofEnabled) {
676         ppIdx++;
677         if (ppRenderDofInterface_.postProcessNode && ppRenderDofInterface_.postProcess) {
678             ppRenderDofInterface_.postProcessNode->Execute(cmdList);
679         }
680     }
681 
682     // post blur
683     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
684         ppIdx++;
685         if (ppRenderBlurInterface_.postProcessNode && ppRenderBlurInterface_.postProcess) {
686             ppRenderBlurInterface_.postProcessNode->Execute(cmdList);
687         }
688     }
689 
690     PLUGIN_ASSERT(ppIdx == framePostProcessInOut_.size());
691 
692     // if all flags are zero and output is different than input
693     // we need to execute a copy
694     if ((!postProcessNeeded) && (!sameInputOutput)) {
695         ExecuteBlit(cmdList, { images_.input, images_.output });
696     }
697 }
698 
ExecuteBlit(IRenderCommandList & cmdList,const InputOutput & inOut)699 void RenderNodePostProcessUtil::ExecuteBlit(IRenderCommandList& cmdList, const InputOutput& inOut)
700 {
701     // extra blit from input to ouput
702     if (RenderHandleUtil::IsGpuImage(inOut.input.handle) && RenderHandleUtil::IsGpuImage(inOut.output.handle)) {
703 #if (RENDER_VALIDATION_ENABLED == 1)
704         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName().data(),
705             "RENDER_PERFORMANCE_VALIDATION: Extra blit from input to output (RN: %s)",
706             renderNodeContextMgr_->GetName().data());
707 #endif
708         RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderBlit", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
709 
710         auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
711 
712         RenderPass renderPass = CreateRenderPass(gpuResourceMgr, inOut.output.handle);
713         auto& effect = copyData_;
714         if (!RenderHandleUtil::IsValid(effect.pso)) {
715             auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
716             const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
717             const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(effect.sd.shader);
718             effect.pso = psoMgr.GetGraphicsPsoHandle(effect.sd.shader, graphicsStateHandle, effect.sd.pipelineLayout,
719                 {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
720         }
721 
722         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
723         cmdList.BindPipeline(effect.pso);
724 
725         {
726             auto& binder = *binders_.copyBinder;
727             binder.ClearBindings();
728             uint32_t binding = 0u;
729             binder.BindSampler(binding, samplers_.linear);
730             binder.BindImage(++binding, inOut.input);
731             cmdList.UpdateDescriptorSet(
732                 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
733             cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
734         }
735 
736         // dynamic state
737         const ViewportDesc viewportDesc = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass);
738         const ScissorDesc scissorDesc = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass);
739         cmdList.SetDynamicStateViewport(viewportDesc);
740         cmdList.SetDynamicStateScissor(scissorDesc);
741 
742         cmdList.Draw(3u, 1u, 0u, 0u);
743         cmdList.EndRenderPass();
744     }
745 }
746 
ProcessPostProcessConfiguration()747 void RenderNodePostProcessUtil::ProcessPostProcessConfiguration()
748 {
749     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
750         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
751         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
752             if (jsonInputs_.renderDataStore.typeName == RenderDataStorePod::TYPE_NAME) {
753                 auto const dataStore = static_cast<const IRenderDataStorePod*>(ds);
754                 auto const dataView = dataStore->Get(jsonInputs_.renderDataStore.configurationName);
755                 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
756                     ppConfig_ = *((const PostProcessConfiguration*)dataView.data());
757                     if (RenderHandleUtil::IsValid(ppConfig_.bloomConfiguration.dirtMaskImage)) {
758                         images_.dirtMask = ppConfig_.bloomConfiguration.dirtMaskImage;
759                     } else {
760                         images_.dirtMask = aimg_.black;
761                     }
762                 }
763             }
764         }
765     }
766 }
767 
InitCreateShaderResources()768 void RenderNodePostProcessUtil::InitCreateShaderResources()
769 {
770     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
771     copyData_ = {};
772 
773     copyData_.sd = shaderMgr.GetShaderDataByShaderName(COPY_SHADER_NAME);
774 }
775 
InitCreateBinders()776 void RenderNodePostProcessUtil::InitCreateBinders()
777 {
778     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
779 
780     binders_.copyBinder = descriptorSetMgr.CreateDescriptorSetBinder(
781         descriptorSetMgr.CreateDescriptorSet(0u, copyData_.sd.pipelineLayoutData),
782         copyData_.sd.pipelineLayoutData.descriptorSetLayouts[0u].bindings);
783 }
784 
ParseRenderNodeInputs()785 void RenderNodePostProcessUtil::ParseRenderNodeInputs()
786 {
787     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
788     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
789     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
790     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
791 
792     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
793     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
794     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
795 
796     // process custom inputs
797     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
798         const auto& ref = jsonInputs_.resources.customInputImages[idx];
799         if (ref.usageName == INPUT_COLOR) {
800             jsonInputs_.colorIndex = idx;
801         } else if (ref.usageName == INPUT_DEPTH) {
802             jsonInputs_.depthIndex = idx;
803         } else if (ref.usageName == INPUT_VELOCITY) {
804             jsonInputs_.velocityIndex = idx;
805         } else if (ref.usageName == INPUT_HISTORY) {
806             jsonInputs_.historyIndex = idx;
807         } else if (ref.usageName == INPUT_HISTORY_NEXT) {
808             jsonInputs_.historyNextIndex = idx;
809         }
810     }
811 }
812 
UpdateImageData()813 void RenderNodePostProcessUtil::UpdateImageData()
814 {
815     if ((!RenderHandleUtil::IsValid(aimg_.black)) || (!RenderHandleUtil::IsValid(aimg_.white))) {
816         auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
817         aimg_.black = gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
818         aimg_.white = gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
819     }
820 
821     if (postProcessInfo_.parseRenderNodeInputs) {
822         if (inputResources_.customInputImages.empty() || inputResources_.customOutputImages.empty()) {
823             return; // early out
824         }
825 
826         images_.input.handle = inputResources_.customInputImages[0].handle;
827         images_.output.handle = inputResources_.customOutputImages[0].handle;
828         if (jsonInputs_.depthIndex < inputResources_.customInputImages.size()) {
829             images_.depth.handle = inputResources_.customInputImages[jsonInputs_.depthIndex].handle;
830         }
831         if (jsonInputs_.velocityIndex < inputResources_.customInputImages.size()) {
832             images_.velocity.handle = inputResources_.customInputImages[jsonInputs_.velocityIndex].handle;
833         }
834         if (jsonInputs_.historyIndex < inputResources_.customInputImages.size()) {
835             images_.history.handle = inputResources_.customInputImages[jsonInputs_.historyIndex].handle;
836         }
837         if (jsonInputs_.historyNextIndex < inputResources_.customInputImages.size()) {
838             images_.historyNext.handle = inputResources_.customInputImages[jsonInputs_.historyNextIndex].handle;
839         }
840     } else {
841         images_.input = postProcessInfo_.imageData.input;
842         images_.output = postProcessInfo_.imageData.output;
843         images_.depth = postProcessInfo_.imageData.depth;
844         images_.velocity = postProcessInfo_.imageData.velocity;
845         images_.history = postProcessInfo_.imageData.history;
846         images_.historyNext = postProcessInfo_.imageData.historyNext;
847     }
848 
849     validInputsForTaa_ = false;
850     validInputsForDof_ = false;
851     validInputsForMb_ = false;
852     bool validDepth = false;
853     bool validHistory = false;
854     bool validVelocity = false;
855     if (IsValidHandle(images_.depth) && (images_.depth.handle != aimg_.white)) {
856         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
857         const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(images_.depth.handle);
858         if (desc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
859             validDepth = true;
860         }
861     } else {
862         images_.depth.handle = aimg_.white; // default depth
863     }
864     if (IsValidHandle(images_.velocity) && (images_.velocity.handle != aimg_.black)) {
865         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
866         const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(images_.velocity.handle);
867         if (desc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
868             validVelocity = true;
869         }
870     } else {
871         images_.velocity.handle = aimg_.black; // default velocity
872     }
873     if (IsValidHandle(images_.history) && IsValidHandle(images_.historyNext)) {
874         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
875         const GpuImageDesc& velDesc = gpuResourceMgr.GetImageDescriptor(images_.velocity.handle);
876         if (velDesc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
877             validHistory = true;
878         }
879     }
880     if (!RenderHandleUtil::IsValid(images_.dirtMask)) {
881         images_.dirtMask = aimg_.black; // default dirt mask
882     }
883 
884     validInputsForTaa_ = validDepth && validHistory; // TAA can be used without velocities
885     validInputsForDof_ = validDepth;
886     validInputsForMb_ = validVelocity;
887     validInputsForUpscale_ = validDepth && validVelocity;
888 }
889 
CreatePostProcessInterfaces()890 void RenderNodePostProcessUtil::CreatePostProcessInterfaces()
891 {
892     auto* renderClassFactory = renderNodeContextMgr_->GetRenderContext().GetInterface<IClassFactory>();
893     if (renderClassFactory) {
894         auto CreatePostProcessInterface = [&](const auto uid, auto& pp, auto& ppNode) {
895             if (pp = CreateInstance<IRenderPostProcess>(*renderClassFactory, uid); pp) {
896                 ppNode = CreateInstance<IRenderPostProcessNode>(*renderClassFactory, pp->GetRenderPostProcessNodeUid());
897             }
898         };
899 
900         CreatePostProcessInterface(
901             RenderPostProcessFlare::UID, ppLensFlareInterface_.postProcess, ppLensFlareInterface_.postProcessNode);
902         if (ENABLE_UPSCALER) {
903             CreatePostProcessInterface(RenderPostProcessUpscale::UID, ppRenderUpscaleInterface_.postProcess,
904                 ppRenderUpscaleInterface_.postProcessNode);
905         }
906         CreatePostProcessInterface(
907             RenderPostProcessBlur::UID, ppRenderBlurInterface_.postProcess, ppRenderBlurInterface_.postProcessNode);
908 
909         CreatePostProcessInterface(
910             RenderPostProcessBloom::UID, ppRenderBloomInterface_.postProcess, ppRenderBloomInterface_.postProcessNode);
911 
912         CreatePostProcessInterface(
913             RenderPostProcessTaa::UID, ppRenderTaaInterface_.postProcess, ppRenderTaaInterface_.postProcessNode);
914 
915         CreatePostProcessInterface(
916             RenderPostProcessFxaa::UID, ppRenderFxaaInterface_.postProcess, ppRenderFxaaInterface_.postProcessNode);
917 
918         CreatePostProcessInterface(
919             RenderPostProcessDof::UID, ppRenderDofInterface_.postProcess, ppRenderDofInterface_.postProcessNode);
920 
921         CreatePostProcessInterface(RenderPostProcessMotionBlur::UID, ppRenderMotionBlurInterface_.postProcess,
922             ppRenderMotionBlurInterface_.postProcessNode);
923 
924         CreatePostProcessInterface(RenderPostProcessCombined::UID, ppRenderCombinedInterface_.postProcess,
925             ppRenderCombinedInterface_.postProcessNode);
926     }
927 }
928 
929 ///////////////////////////////////////////////////////////////////////////////////////////////////
930 
Init(IRenderNodeContextManager & renderNodeContextMgr,const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)931 void RenderNodePostProcessUtilImpl::Init(
932     IRenderNodeContextManager& renderNodeContextMgr, const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
933 {
934     rn_.Init(renderNodeContextMgr, postProcessInfo);
935 }
936 
PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)937 void RenderNodePostProcessUtilImpl::PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
938 {
939     rn_.PreExecute(postProcessInfo);
940 }
941 
Execute(IRenderCommandList & cmdList)942 void RenderNodePostProcessUtilImpl::Execute(IRenderCommandList& cmdList)
943 {
944     rn_.Execute(cmdList);
945 }
946 
GetInterface(const Uid & uid) const947 const IInterface* RenderNodePostProcessUtilImpl::GetInterface(const Uid& uid) const
948 {
949     if ((uid == IRenderNodePostProcessUtil::UID) || (uid == IInterface::UID)) {
950         return this;
951     }
952     return nullptr;
953 }
954 
GetInterface(const Uid & uid)955 IInterface* RenderNodePostProcessUtilImpl::GetInterface(const Uid& uid)
956 {
957     if ((uid == IRenderNodePostProcessUtil::UID) || (uid == IInterface::UID)) {
958         return this;
959     }
960     return nullptr;
961 }
962 
Ref()963 void RenderNodePostProcessUtilImpl::Ref()
964 {
965     refCount_++;
966 }
967 
Unref()968 void RenderNodePostProcessUtilImpl::Unref()
969 {
970     if (--refCount_ == 0) {
971         delete this;
972     }
973 }
974 RENDER_END_NAMESPACE()
975