• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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_flare.h"
44 #include "util/log.h"
45 
46 // shaders
47 #include <render/shaders/common/render_post_process_layout_common.h>
48 #include <render/shaders/common/render_post_process_structs_common.h>
49 
50 using namespace BASE_NS;
51 using namespace CORE_NS;
52 
53 RENDER_BEGIN_NAMESPACE()
54 namespace {
55 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
56 
57 constexpr uint32_t UBO_OFFSET_ALIGNMENT { PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE };
58 constexpr uint32_t MAX_POST_PROCESS_EFFECT_COUNT { 8 };
59 constexpr uint32_t POST_PROCESS_UBO_BYTE_SIZE { sizeof(GlobalPostProcessStruct) +
60                                                 sizeof(LocalPostProcessStruct) * MAX_POST_PROCESS_EFFECT_COUNT };
61 
62 constexpr uint32_t GL_LAYER_CANNOT_OPT_FLAGS =
63     PostProcessConfiguration::ENABLE_BLOOM_BIT | PostProcessConfiguration::ENABLE_TAA_BIT;
64 
65 constexpr string_view INPUT_COLOR = "color";
66 constexpr string_view INPUT_DEPTH = "depth";
67 constexpr string_view INPUT_VELOCITY = "velocity";
68 constexpr string_view INPUT_HISTORY = "history";
69 constexpr string_view INPUT_HISTORY_NEXT = "history_next";
70 
71 constexpr string_view COMBINED_SHADER_NAME = "rendershaders://shader/fullscreen_combined_post_process.shader";
72 constexpr string_view COMBINED_LAYER_SHADER_NAME =
73     "rendershaders://shader/fullscreen_combined_post_process_layer.shader";
74 constexpr string_view FXAA_SHADER_NAME = "rendershaders://shader/fullscreen_fxaa.shader";
75 constexpr string_view TAA_SHADER_NAME = "rendershaders://shader/fullscreen_taa.shader";
76 constexpr string_view DOF_BLUR_SHADER_NAME = "rendershaders://shader/depth_of_field_blur.shader";
77 constexpr string_view DOF_SHADER_NAME = "rendershaders://shader/depth_of_field.shader";
78 constexpr string_view COPY_SHADER_NAME = "rendershaders://shader/fullscreen_copy.shader";
79 
CreateRenderPass(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle input)80 RenderPass CreateRenderPass(const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle input)
81 {
82     const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(input);
83     RenderPass rp;
84     rp.renderPassDesc.attachmentCount = 1u;
85     rp.renderPassDesc.attachmentHandles[0u] = input;
86     rp.renderPassDesc.attachments[0u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
87     rp.renderPassDesc.attachments[0u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
88     rp.renderPassDesc.renderArea = { 0, 0, desc.width, desc.height };
89 
90     rp.renderPassDesc.subpassCount = 1u;
91     rp.subpassDesc.colorAttachmentCount = 1u;
92     rp.subpassDesc.colorAttachmentIndices[0u] = 0u;
93     rp.subpassStartIndex = 0u;
94     return rp;
95 }
96 
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)97 RenderHandleReference CreatePostProcessDataUniformBuffer(
98     IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
99 {
100     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
101     PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) == UBO_OFFSET_ALIGNMENT);
102     return gpuResourceMgr.Create(
103         handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
104                     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
105                     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, POST_PROCESS_UBO_BYTE_SIZE });
106 }
107 
FillTmpImageDesc(GpuImageDesc & desc)108 void FillTmpImageDesc(GpuImageDesc& desc)
109 {
110     desc.imageType = CORE_IMAGE_TYPE_2D;
111     desc.imageViewType = CORE_IMAGE_VIEW_TYPE_2D;
112     desc.engineCreationFlags = EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS |
113                                EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS;
114     desc.usageFlags =
115         ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT;
116     // don't want this multisampled even if the final output would be.
117     desc.sampleCountFlags = SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT;
118     desc.layerCount = 1U;
119     desc.mipCount = 1U;
120 }
121 
IsValidHandle(const BindableImage & img)122 inline bool IsValidHandle(const BindableImage& img)
123 {
124     return RenderHandleUtil::IsValid(img.handle);
125 }
126 } // namespace
127 
Init(IRenderNodeContextManager & renderNodeContextMgr,const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)128 void RenderNodePostProcessUtil::Init(
129     IRenderNodeContextManager& renderNodeContextMgr, const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
130 {
131     renderNodeContextMgr_ = &renderNodeContextMgr;
132     postProcessInfo_ = postProcessInfo;
133     CreatePostProcessInterfaces();
134     ParseRenderNodeInputs();
135     UpdateImageData();
136 
137     deviceBackendType_ = renderNodeContextMgr_->GetRenderContext().GetDevice().GetBackendType();
138 
139     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
140     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
141     samplers_.nearest =
142         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP);
143     samplers_.linear =
144         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
145     samplers_.mipLinear =
146         gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP);
147     ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
148 
149     InitCreateShaderResources();
150 
151     if ((!IsValidHandle(images_.input)) || (!IsValidHandle(images_.output))) {
152         validInputs_ = false;
153         PLUGIN_LOG_E("RN: %s, expects custom input and output image", renderNodeContextMgr_->GetName().data());
154     }
155 
156     if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
157         PLUGIN_LOG_W("RenderNodeCombinedPostProcess: render data store configuration not set in render node graph");
158     }
159     if (jsonInputs_.renderDataStore.typeName != RenderDataStorePod::TYPE_NAME) {
160         PLUGIN_LOG_E("RenderNodeCombinedPostProcess: render data store type name not supported (%s != %s)",
161             jsonInputs_.renderDataStore.typeName.data(), RenderDataStorePod::TYPE_NAME);
162         validInputs_ = false;
163     }
164 
165     {
166         vector<DescriptorCounts> descriptorCounts;
167         descriptorCounts.reserve(16U);
168         // pre-set custom descriptor sets
169         descriptorCounts.push_back(DescriptorCounts { {
170             { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 8u },
171             { CORE_DESCRIPTOR_TYPE_SAMPLER, 8u },
172             { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8u },
173         } });
174         descriptorCounts.push_back(renderBloom_.GetDescriptorCounts());
175         descriptorCounts.push_back(renderBlur_.GetDescriptorCounts());
176         descriptorCounts.push_back(renderBloom_.GetDescriptorCounts());
177         descriptorCounts.push_back(renderMotionBlur_.GetDescriptorCounts());
178         descriptorCounts.push_back(renderCopy_.GetRenderDescriptorCounts());
179         descriptorCounts.push_back(renderCopyLayer_.GetRenderDescriptorCounts());
180         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(combineData_.sd.pipelineLayoutData));
181         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(combineDataLayer_.sd.pipelineLayoutData));
182         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(fxaaData_.sd.pipelineLayoutData));
183         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(taaData_.sd.pipelineLayoutData));
184         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(dofBlurData_.sd.pipelineLayoutData));
185         descriptorCounts.push_back(renderNearBlur_.GetDescriptorCounts());
186         descriptorCounts.push_back(renderFarBlur_.GetDescriptorCounts());
187         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(dofData_.sd.pipelineLayoutData));
188         descriptorCounts.push_back(renderNodeUtil.GetDescriptorCounts(copyData_.sd.pipelineLayoutData));
189         renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(descriptorCounts);
190     }
191     // bloom does not do combine, and does not render to output with this combined post process
192     ProcessPostProcessConfiguration();
193     {
194         const RenderBloom::BloomInfo bloomInfo { images_.input, {}, ubos_.postProcess.GetHandle(),
195             ppConfig_.bloomConfiguration.useCompute };
196         renderBloom_.Init(renderNodeContextMgr, bloomInfo);
197     }
198     {
199         RenderBlur::BlurInfo blurInfo { images_.output, ubos_.postProcess.GetHandle(), false,
200             CORE_BLUR_TYPE_DOWNSCALE_RGBA, CORE_BLUR_TYPE_RGBA_DOF };
201         renderBlur_.Init(renderNodeContextMgr, blurInfo);
202         renderNearBlur_.Init(renderNodeContextMgr, blurInfo);
203         renderFarBlur_.Init(renderNodeContextMgr, blurInfo);
204     }
205     {
206         RenderMotionBlur::MotionBlurInfo motionBlurInfo {};
207         renderMotionBlur_.Init(renderNodeContextMgr, motionBlurInfo);
208     }
209     renderCopy_.Init(renderNodeContextMgr);
210     if (deviceBackendType_ != DeviceBackendType::VULKAN) {
211         // prepare for possible layer copy
212         renderCopyLayer_.Init(renderNodeContextMgr);
213     }
214 
215     if (ppLensFlareInterface_.postProcessNode) {
216         ppLensFlareInterface_.postProcessNode->Init(ppLensFlareInterface_.postProcess, *renderNodeContextMgr_);
217     }
218 
219     InitCreateBinders();
220 
221     if ((!jsonInputs_.resources.customOutputImages.empty()) && (!inputResources_.customOutputImages.empty()) &&
222         (RenderHandleUtil::IsValid(inputResources_.customOutputImages[0].handle))) {
223         IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
224         shrMgr.RegisterRenderNodeOutput(
225             jsonInputs_.resources.customOutputImages[0u].name, inputResources_.customOutputImages[0u].handle);
226     }
227 }
228 
PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)229 void RenderNodePostProcessUtil::PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
230 {
231     postProcessInfo_ = postProcessInfo;
232     if (!validInputs_) {
233         return;
234     }
235 
236     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
237     if (jsonInputs_.hasChangeableResourceHandles) {
238         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
239     }
240     UpdateImageData();
241 
242     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
243     const GpuImageDesc inputDesc = gpuResourceMgr.GetImageDescriptor(images_.input.handle);
244     const GpuImageDesc outputDesc = gpuResourceMgr.GetImageDescriptor(images_.output.handle);
245     outputSize_ = { outputDesc.width, outputDesc.height };
246 #if (RENDER_VALIDATION_ENABLED == 1)
247     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT) &&
248         (!validInputsForTaa_)) {
249         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_taa_depth_vel",
250             "RENDER_VALIDATION: Default TAA post process needs output depth, velocity, and history.");
251     }
252     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT) &&
253         (!validInputsForDof_)) {
254         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_dof_depth",
255             "RENDER_VALIDATION: Default DOF post process needs output depth.");
256     }
257     if ((ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT) &&
258         (!validInputsForMb_)) {
259         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName() + "_mb_vel",
260             "RENDER_VALIDATION: Default motion blur post process needs output (samplable) velocity.");
261     }
262 #endif
263 
264     // process this frame's enabled post processes here
265     // bloom might need target updates, no further processing is needed
266     ProcessPostProcessConfiguration();
267 
268     // post process
269     const bool fxaaEnabled =
270         ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
271     const bool motionBlurEnabled =
272         validInputsForMb_ &&
273         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT);
274     const bool dofEnabled =
275         validInputsForDof_ &&
276         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT);
277 
278     ti_.idx = 0;
279     const bool basicImagesNeeded = fxaaEnabled || motionBlurEnabled || dofEnabled;
280     const bool mipImageNeeded = dofEnabled;
281     const auto nearMips = static_cast<uint32_t>(Math::ceilToInt(ppConfig_.dofConfiguration.nearBlur));
282     const auto farMips = static_cast<uint32_t>(Math::ceilToInt(ppConfig_.dofConfiguration.farBlur));
283     const bool mipCountChanged = (nearMips != ti_.mipCount[0U]) || (farMips != ti_.mipCount[1U]);
284     const bool sizeChanged = (ti_.targetSize.x != static_cast<float>(outputSize_.x)) ||
285                              (ti_.targetSize.y != static_cast<float>(outputSize_.y));
286     if (sizeChanged) {
287         ti_.targetSize.x = Math::max(1.0f, static_cast<float>(outputSize_.x));
288         ti_.targetSize.y = Math::max(1.0f, static_cast<float>(outputSize_.y));
289         ti_.targetSize.z = 1.f / ti_.targetSize.x;
290         ti_.targetSize.w = 1.f / ti_.targetSize.y;
291     }
292     if (basicImagesNeeded) {
293         if ((!ti_.images[0U]) || sizeChanged) {
294 #if (RENDER_VALIDATION_ENABLED == 1)
295             PLUGIN_LOG_I("RENDER_VALIDATION: post process temporary images re-created (size:%ux%u)", outputSize_.x,
296                 outputSize_.y);
297 #endif
298             GpuImageDesc tmpDesc = outputDesc;
299             FillTmpImageDesc(tmpDesc);
300             ti_.images[0U] = gpuResourceMgr.Create(ti_.images[0U], tmpDesc);
301             ti_.images[1U] = gpuResourceMgr.Create(ti_.images[1U], tmpDesc);
302             ti_.imageCount = 2U;
303         }
304     } else {
305         ti_.images[0U] = {};
306         ti_.images[1U] = {};
307     }
308     if (mipImageNeeded) {
309         if ((!ti_.mipImages[0U]) || sizeChanged || mipCountChanged) {
310 #if (RENDER_VALIDATION_ENABLED == 1)
311             PLUGIN_LOG_I("RENDER_VALIDATION: post process temporary mip image re-created (size:%ux%u)", outputSize_.x,
312                 outputSize_.y);
313 #endif
314             GpuImageDesc tmpDesc = outputDesc;
315             FillTmpImageDesc(tmpDesc);
316             tmpDesc.mipCount = nearMips;
317             ti_.mipImages[0] = gpuResourceMgr.Create(ti_.mipImages[0U], tmpDesc);
318             tmpDesc.mipCount = farMips;
319             ti_.mipImages[1] = gpuResourceMgr.Create(ti_.mipImages[1U], tmpDesc);
320             ti_.mipImageCount = 2U;
321             ti_.mipCount[0U] = nearMips;
322             ti_.mipCount[1U] = farMips;
323         }
324     } else {
325         ti_.mipImages[0U] = {};
326         ti_.mipImages[1U] = {};
327     }
328     if ((!basicImagesNeeded) && (!mipImageNeeded)) {
329         ti_ = {};
330     }
331 
332     BindableImage postTaaBloomInput = images_.input;
333     // prepare for possible layer copy
334     glOptimizedLayerCopyEnabled_ = false;
335     if ((deviceBackendType_ != DeviceBackendType::VULKAN) &&
336         (images_.input.layer != PipelineStateConstants::GPU_IMAGE_ALL_LAYERS)) {
337         if ((ppConfig_.enableFlags & GL_LAYER_CANNOT_OPT_FLAGS) == 0U) {
338             // optimize with combine
339             glOptimizedLayerCopyEnabled_ = true;
340         } else {
341             if (sizeChanged || (!ti_.layerCopyImage)) {
342                 GpuImageDesc tmpDesc = inputDesc; // NOTE: input desc
343                 FillTmpImageDesc(tmpDesc);
344                 ti_.layerCopyImage = gpuResourceMgr.Create(ti_.layerCopyImage, tmpDesc);
345             }
346 
347             BindableImage layerCopyOutput;
348             layerCopyOutput.handle = ti_.layerCopyImage.GetHandle();
349             renderCopyLayer_.PreExecute();
350 
351             // postTaa bloom input
352             postTaaBloomInput = layerCopyOutput;
353         }
354     }
355 
356     if (validInputsForTaa_ &&
357         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT)) {
358         postTaaBloomInput = images_.historyNext;
359     }
360 
361     // NOTE: separate flare with new post process interface
362     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_LENS_FLARE_BIT) {
363         if (ppLensFlareInterface_.postProcessNode && ppLensFlareInterface_.postProcess) {
364             // copy properties to new property post process
365             IPropertyHandle* props = ppLensFlareInterface_.postProcess->GetProperties();
366             CORE_NS::SetPropertyValue(props, "flarePos", ppConfig_.lensFlareConfiguration.flarePosition);
367             CORE_NS::SetPropertyValue(props, "intensity", ppConfig_.lensFlareConfiguration.intensity);
368 
369             auto& ppNode = *ppLensFlareInterface_.postProcessNode;
370             CORE_NS::SetPropertyValue(ppNode.GetRenderInputProperties(), "input", postTaaBloomInput);
371             ppNode.PreExecute();
372         }
373     }
374 
375     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT) {
376         const RenderBloom::BloomInfo bloomInfo { postTaaBloomInput, {}, ubos_.postProcess.GetHandle(),
377             ppConfig_.bloomConfiguration.useCompute };
378         renderBloom_.PreExecute(*renderNodeContextMgr_, bloomInfo, ppConfig_);
379     }
380 
381     // needs to evaluate what is the final effect, where we will use the final target
382     // the final target (output) might a swapchain which cannot be sampled
383     framePostProcessInOut_.clear();
384     // after bloom or TAA
385     BindableImage input = postTaaBloomInput;
386     const bool postProcessNeeded = (ppConfig_.enableFlags != 0);
387     const bool sameInputOutput = (images_.input.handle == images_.output.handle);
388     // combine
389     if (postProcessNeeded && (!sameInputOutput)) {
390         const BindableImage output =
391             (basicImagesNeeded || mipImageNeeded) ? GetIntermediateImage(input.handle) : images_.output;
392         framePostProcessInOut_.push_back({ input, output });
393         input = framePostProcessInOut_.back().output;
394     }
395     if (fxaaEnabled) {
396         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
397         input = framePostProcessInOut_.back().output;
398     }
399     if (motionBlurEnabled) {
400         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
401         input = framePostProcessInOut_.back().output;
402     }
403     if (dofEnabled) {
404         framePostProcessInOut_.push_back({ input, GetIntermediateImage(input.handle) });
405         input = framePostProcessInOut_.back().output;
406     }
407     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
408         framePostProcessInOut_.push_back({ input, input });
409         input = framePostProcessInOut_.back().output;
410     }
411     // finalize
412     if (!framePostProcessInOut_.empty()) {
413         framePostProcessInOut_.back().output = images_.output;
414     }
415 
416     uint32_t ppIdx = 0U;
417     if (postProcessNeeded && (!sameInputOutput)) {
418         ppIdx++;
419     }
420     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT) {
421         ppIdx++;
422     }
423     if (motionBlurEnabled) {
424         const auto& inOut = framePostProcessInOut_[ppIdx++];
425         const RenderMotionBlur::MotionBlurInfo info { inOut.input.handle, inOut.output.handle, images_.velocity.handle,
426             images_.depth.handle, ubos_.postProcess.GetHandle(),
427             sizeof(GlobalPostProcessStruct) + PP_MB_IDX * UBO_OFFSET_ALIGNMENT, outputSize_ };
428         renderMotionBlur_.PreExecute(*renderNodeContextMgr_, info, ppConfig_);
429     }
430 
431     if (dofEnabled) {
432         auto nearMip = GetMipImage(input.handle);
433         RenderBlur::BlurInfo blurInfo { nearMip, ubos_.postProcess.GetHandle(), false, CORE_BLUR_TYPE_DOWNSCALE_RGBA,
434             CORE_BLUR_TYPE_RGBA_DOF };
435         renderNearBlur_.PreExecute(*renderNodeContextMgr_, blurInfo);
436 
437         blurInfo.blurTarget = GetMipImage(nearMip.handle);
438         renderFarBlur_.PreExecute(*renderNodeContextMgr_, blurInfo);
439         ppIdx++;
440     }
441 
442     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
443         const auto& inOut = framePostProcessInOut_[ppIdx++];
444         RenderBlur::BlurInfo blurInfo { inOut.output, ubos_.postProcess.GetHandle(), false };
445         renderBlur_.PreExecute(*renderNodeContextMgr_, blurInfo);
446     }
447 
448     PLUGIN_ASSERT(ppIdx == framePostProcessInOut_.size());
449 
450     if ((!jsonInputs_.resources.customOutputImages.empty()) && (!inputResources_.customOutputImages.empty()) &&
451         (RenderHandleUtil::IsValid(inputResources_.customOutputImages[0].handle))) {
452         IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
453         shrMgr.RegisterRenderNodeOutput(
454             jsonInputs_.resources.customOutputImages[0u].name, inputResources_.customOutputImages[0u].handle);
455     }
456 }
457 
Execute(IRenderCommandList & cmdList)458 void RenderNodePostProcessUtil::Execute(IRenderCommandList& cmdList)
459 {
460     if (!validInputs_) {
461         return;
462     }
463 
464     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderPostProcess", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
465 
466     UpdatePostProcessData(ppConfig_);
467 
468     // prepare for possible layer copy if not using optimized paths for layers
469     if ((deviceBackendType_ != DeviceBackendType::VULKAN) &&
470         (images_.input.layer != PipelineStateConstants::GPU_IMAGE_ALL_LAYERS) && (!glOptimizedLayerCopyEnabled_)) {
471         BindableImage layerCopyOutput;
472         layerCopyOutput.handle = ti_.layerCopyImage.GetHandle();
473         IRenderNodeCopyUtil::CopyInfo layerCopyInfo;
474         layerCopyInfo.input = images_.input;
475         layerCopyInfo.output = layerCopyOutput;
476         layerCopyInfo.copyType = IRenderNodeCopyUtil::CopyType::LAYER_COPY;
477         renderCopyLayer_.Execute(cmdList, layerCopyInfo);
478     }
479 
480     if (validInputsForTaa_ &&
481         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT)) {
482         ExecuteTAA(cmdList, { images_.input, images_.historyNext });
483     }
484 
485     // NOTE: separate flare with new post process interface
486     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_LENS_FLARE_BIT) {
487         if (ppLensFlareInterface_.postProcessNode) {
488             auto& ppNode = *ppLensFlareInterface_.postProcessNode;
489             // inputs set in pre-execute
490             ppNode.Execute(cmdList);
491         }
492     }
493 
494     // ppConfig_ is already up-to-date from PreExecuteFrame
495     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT) {
496         renderBloom_.Execute(*renderNodeContextMgr_, cmdList, ppConfig_);
497     }
498 
499     // post process
500     const bool fxaaEnabled =
501         ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
502     const bool motionBlurEnabled =
503         validInputsForMb_ &&
504         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_MOTION_BLUR_BIT);
505     const bool dofEnabled =
506         validInputsForDof_ &&
507         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT);
508 
509     // after bloom or TAA
510     const bool postProcessNeeded = (ppConfig_.enableFlags != 0);
511     const bool sameInputOutput = (images_.input.handle == images_.output.handle);
512 
513 #if (RENDER_VALIDATION_ENABLED == 1)
514     if (postProcessNeeded && sameInputOutput) {
515         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName().data(),
516             "%s: combined post process shader not supported for same input/output ATM.",
517             renderNodeContextMgr_->GetName().data());
518     }
519 #endif
520     uint32_t ppIdx = 0U;
521     if (postProcessNeeded && (!sameInputOutput)) {
522         ExecuteCombine(cmdList, framePostProcessInOut_[ppIdx++]);
523     }
524 
525     if (fxaaEnabled) {
526         ExecuteFXAA(cmdList, framePostProcessInOut_[ppIdx++]);
527     }
528 
529     if (motionBlurEnabled) {
530         const auto& inOut = framePostProcessInOut_[ppIdx++];
531         RenderMotionBlur::MotionBlurInfo info { inOut.input.handle, inOut.output.handle, images_.velocity.handle,
532             images_.depth.handle, ubos_.postProcess.GetHandle(),
533             sizeof(GlobalPostProcessStruct) + PP_MB_IDX * UBO_OFFSET_ALIGNMENT, outputSize_ };
534         renderMotionBlur_.Execute(*renderNodeContextMgr_, cmdList, info, ppConfig_);
535     }
536     if (dofEnabled) {
537         const auto& inOut = framePostProcessInOut_[ppIdx++];
538         ExecuteDof(cmdList, inOut);
539     }
540 
541     // post blur
542     if (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT) {
543         ppIdx++;
544         // NOTE: add ppConfig
545         renderBlur_.Execute(*renderNodeContextMgr_, cmdList, ppConfig_);
546     }
547 
548     PLUGIN_ASSERT(ppIdx == framePostProcessInOut_.size());
549 
550     // if all flags are zero and output is different than input
551     // we need to execute a copy
552     if ((!postProcessNeeded) && (!sameInputOutput)) {
553         ExecuteBlit(cmdList, { images_.input, images_.output });
554     }
555 }
556 
ExecuteCombine(IRenderCommandList & cmdList,const InputOutput & inOut)557 void RenderNodePostProcessUtil::ExecuteCombine(IRenderCommandList& cmdList, const InputOutput& inOut)
558 {
559     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderCombine", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
560 
561     const RenderHandle bloomImage =
562         (ppConfig_.enableFlags & PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT)
563             ? renderBloom_.GetFinalTarget()
564             : aimg_.black;
565 
566     auto& effect = glOptimizedLayerCopyEnabled_ ? combineDataLayer_ : combineData_;
567     const RenderPass renderPass = CreateRenderPass(renderNodeContextMgr_->GetGpuResourceManager(), inOut.output.handle);
568     if (!RenderHandleUtil::IsValid(effect.pso)) {
569         auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
570         const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
571         const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(effect.sd.shader);
572         effect.pso = psoMgr.GetGraphicsPsoHandle(effect.sd.shader, graphicsStateHandle, effect.sd.pipelineLayout, {},
573             {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
574     }
575 
576     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
577     cmdList.BindPipeline(effect.pso);
578 
579     {
580         RenderHandle sets[2U] {};
581         DescriptorSetLayoutBindingResources resources[2U] {};
582         {
583             const RenderHandle ubo = ubos_.postProcess.GetHandle();
584             PLUGIN_ASSERT(binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_COMBINED_IDX]);
585             auto& binder = *binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_COMBINED_IDX];
586             binder.ClearBindings();
587             uint32_t binding = 0u;
588             binder.BindBuffer(binding, ubo, 0);
589             binder.BindBuffer(++binding, ubo, sizeof(GlobalPostProcessStruct) + PP_COMBINED_IDX * UBO_OFFSET_ALIGNMENT);
590             sets[0U] = binder.GetDescriptorSetHandle();
591             resources[0U] = binder.GetDescriptorSetLayoutBindingResources();
592         }
593         {
594             auto& binder = *binders_.combineBinder;
595             binder.ClearBindings();
596             uint32_t binding = 0u;
597             BindableImage mainInput = inOut.input;
598             mainInput.samplerHandle = samplers_.linear;
599             binder.BindImage(binding++, mainInput);
600             binder.BindImage(binding++, bloomImage, samplers_.linear);
601             binder.BindImage(binding++, images_.dirtMask, samplers_.linear);
602             sets[1U] = binder.GetDescriptorSetHandle();
603             resources[1U] = binder.GetDescriptorSetLayoutBindingResources();
604         }
605         cmdList.UpdateDescriptorSets(sets, resources);
606         cmdList.BindDescriptorSets(0u, sets);
607     }
608 
609     // dynamic state
610     cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass));
611     cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass));
612 
613     if (effect.sd.pipelineLayoutData.pushConstant.byteSize > 0U) {
614         const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
615         const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
616         const float layer = glOptimizedLayerCopyEnabled_ ? float(inOut.input.layer) : 0.0f;
617         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
618             { layer, 0.0f, 0.0f, 0.0f } };
619         cmdList.PushConstantData(effect.sd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
620     }
621 
622     cmdList.Draw(3u, 1u, 0u, 0u);
623     cmdList.EndRenderPass();
624 }
625 
ExecuteFXAA(IRenderCommandList & cmdList,const InputOutput & inOut)626 void RenderNodePostProcessUtil::ExecuteFXAA(IRenderCommandList& cmdList, const InputOutput& inOut)
627 {
628     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderFXAA", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
629 
630     auto renderPass = CreateRenderPass(renderNodeContextMgr_->GetGpuResourceManager(), inOut.output.handle);
631     if (!RenderHandleUtil::IsValid(fxaaData_.pso)) {
632         auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
633         const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
634         const RenderHandle gfxHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(fxaaData_.sd.shader);
635         fxaaData_.pso = psoMgr.GetGraphicsPsoHandle(fxaaData_.sd.shader, gfxHandle, fxaaData_.sd.pipelineLayout, {}, {},
636             { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
637     }
638 
639     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
640     cmdList.BindPipeline(fxaaData_.pso);
641 
642     {
643         RenderHandle sets[2U] {};
644         DescriptorSetLayoutBindingResources resources[2U] {};
645         {
646             const RenderHandle ubo = ubos_.postProcess.GetHandle();
647             PLUGIN_ASSERT(binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_FXAA_IDX]);
648             auto& binder = *binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_FXAA_IDX];
649             binder.ClearBindings();
650             uint32_t binding = 0u;
651             binder.BindBuffer(binding, ubo, 0u);
652             binder.BindBuffer(++binding, ubo, sizeof(GlobalPostProcessStruct) + PP_FXAA_IDX * UBO_OFFSET_ALIGNMENT);
653             sets[0U] = binder.GetDescriptorSetHandle();
654             resources[0U] = binder.GetDescriptorSetLayoutBindingResources();
655         }
656         {
657             auto& binder = *binders_.fxaaBinder;
658             binder.ClearBindings();
659             uint32_t binding = 0u;
660             binder.BindImage(binding, inOut.input);
661             binder.BindSampler(++binding, samplers_.linear);
662             sets[1U] = binder.GetDescriptorSetHandle();
663             resources[1U] = binder.GetDescriptorSetLayoutBindingResources();
664         }
665         cmdList.UpdateDescriptorSets(sets, resources);
666         cmdList.BindDescriptorSets(0u, sets);
667     }
668 
669     if (fxaaData_.sd.pipelineLayoutData.pushConstant.byteSize > 0U) {
670         const LocalPostProcessPushConstantStruct pc { ti_.targetSize,
671             PostProcessConversionHelper::GetFactorFxaa(ppConfig_) };
672         cmdList.PushConstantData(fxaaData_.sd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
673     }
674 
675     // dynamic state
676     cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass));
677     cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass));
678 
679     cmdList.Draw(3u, 1u, 0u, 0u);
680     cmdList.EndRenderPass();
681 }
682 
ExecuteTAA(IRenderCommandList & cmdList,const InputOutput & inOut)683 void RenderNodePostProcessUtil::ExecuteTAA(IRenderCommandList& cmdList, const InputOutput& inOut)
684 {
685     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderTAA", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
686 
687     auto renderPass = CreateRenderPass(renderNodeContextMgr_->GetGpuResourceManager(), inOut.output.handle);
688     if (!RenderHandleUtil::IsValid(taaData_.pso)) {
689         const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
690         auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
691         const RenderHandle gfxHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(taaData_.sd.shader);
692         taaData_.pso = psoMgr.GetGraphicsPsoHandle(taaData_.sd.shader, gfxHandle, taaData_.sd.pipelineLayout, {}, {},
693             { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
694     }
695 
696     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
697     cmdList.BindPipeline(taaData_.pso);
698 
699     {
700         RenderHandle sets[2U] {};
701         DescriptorSetLayoutBindingResources resources[2U] {};
702         {
703             const RenderHandle ubo = ubos_.postProcess.GetHandle();
704             PLUGIN_ASSERT(binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_TAA_IDX]);
705             auto& binder = *binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_TAA_IDX];
706             binder.ClearBindings();
707             uint32_t binding = 0u;
708             binder.BindBuffer(binding++, ubo, 0u);
709             binder.BindBuffer(binding++, ubo, sizeof(GlobalPostProcessStruct) + PP_TAA_IDX * UBO_OFFSET_ALIGNMENT);
710             sets[0U] = binder.GetDescriptorSetHandle();
711             resources[0U] = binder.GetDescriptorSetLayoutBindingResources();
712         }
713         {
714             auto& binder = *binders_.taaBinder;
715             binder.ClearBindings();
716             uint32_t binding = 0u;
717             binder.BindImage(binding, images_.depth.handle);
718             binder.BindImage(++binding, inOut.input.handle);
719             binder.BindImage(++binding, images_.velocity.handle);
720             binder.BindImage(++binding, images_.history.handle);
721             binder.BindSampler(++binding, samplers_.linear);
722             sets[1U] = binder.GetDescriptorSetHandle();
723             resources[1U] = binder.GetDescriptorSetLayoutBindingResources();
724         }
725         cmdList.UpdateDescriptorSets(sets, resources);
726         cmdList.BindDescriptorSets(0U, sets);
727     }
728 
729     if (taaData_.sd.pipelineLayoutData.pushConstant.byteSize > 0U) {
730         const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
731         const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
732         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
733             PostProcessConversionHelper::GetFactorTaa(ppConfig_) };
734         cmdList.PushConstantData(taaData_.sd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
735     }
736 
737     // dynamic state
738     cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass));
739     cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass));
740 
741     cmdList.Draw(3u, 1u, 0u, 0u);
742     cmdList.EndRenderPass();
743 }
744 
ExecuteDofBlur(IRenderCommandList & cmdList,const InputOutput & inOut)745 void RenderNodePostProcessUtil::ExecuteDofBlur(IRenderCommandList& cmdList, const InputOutput& inOut)
746 {
747     RenderPass rp;
748     {
749         const GpuImageDesc desc =
750             renderNodeContextMgr_->GetGpuResourceManager().GetImageDescriptor(ti_.mipImages[0U].GetHandle());
751         rp.renderPassDesc.attachmentCount = 2u;
752         rp.renderPassDesc.attachmentHandles[0u] = ti_.mipImages[0U].GetHandle();
753         rp.renderPassDesc.attachments[0u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
754         rp.renderPassDesc.attachments[0u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
755         rp.renderPassDesc.attachmentHandles[1u] = ti_.mipImages[1U].GetHandle();
756         rp.renderPassDesc.attachments[1u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
757         rp.renderPassDesc.attachments[1u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
758         rp.renderPassDesc.renderArea = { 0, 0, desc.width, desc.height };
759 
760         rp.renderPassDesc.subpassCount = 1u;
761         rp.subpassDesc.colorAttachmentCount = 2u;
762         rp.subpassDesc.colorAttachmentIndices[0u] = 0u;
763         rp.subpassDesc.colorAttachmentIndices[1u] = 1u;
764         rp.subpassStartIndex = 0u;
765     }
766     if (!RenderHandleUtil::IsValid(dofBlurData_.pso)) {
767         auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
768         const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
769         const RenderHandle gfxHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(dofBlurData_.sd.shader);
770         dofBlurData_.pso = psoMgr.GetGraphicsPsoHandle(dofBlurData_.sd.shader, gfxHandle,
771             dofBlurData_.sd.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
772     }
773     cmdList.BeginRenderPass(rp.renderPassDesc, rp.subpassStartIndex, rp.subpassDesc);
774     cmdList.BindPipeline(dofBlurData_.pso);
775 
776     {
777         RenderHandle sets[2U] {};
778         DescriptorSetLayoutBindingResources resources[2U] {};
779         {
780             // NOTE: this updated descriptor set is used in dof
781             const RenderHandle ubo = ubos_.postProcess.GetHandle();
782             PLUGIN_ASSERT(binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_DOF_IDX]);
783             auto& binder = *binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_DOF_IDX];
784             binder.ClearBindings();
785             uint32_t binding = 0u;
786             binder.BindBuffer(binding, ubo, 0u);
787             binder.BindBuffer(++binding, ubo, sizeof(GlobalPostProcessStruct) + PP_DOF_IDX * UBO_OFFSET_ALIGNMENT);
788             sets[0U] = binder.GetDescriptorSetHandle();
789             resources[0U] = binder.GetDescriptorSetLayoutBindingResources();
790         }
791         {
792             auto& binder = *binders_.dofBlurBinder;
793             binder.ClearBindings();
794             uint32_t binding = 0u;
795             BindableImage input = inOut.input;
796             input.samplerHandle = samplers_.mipLinear;
797             binder.BindImage(binding, input);
798             BindableImage depth = images_.depth;
799             depth.samplerHandle = samplers_.nearest;
800             binder.BindImage(++binding, depth);
801             sets[1U] = binder.GetDescriptorSetHandle();
802             resources[1U] = binder.GetDescriptorSetLayoutBindingResources();
803         }
804         cmdList.UpdateDescriptorSets(sets, resources);
805         cmdList.BindDescriptorSets(0U, sets);
806     }
807 
808     {
809         const float fWidth = static_cast<float>(rp.renderPassDesc.renderArea.extentWidth);
810         const float fHeight = static_cast<float>(rp.renderPassDesc.renderArea.extentHeight);
811         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
812         cmdList.PushConstantData(dofBlurData_.sd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
813     }
814 
815     // dynamic state
816     cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(rp));
817     cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(rp));
818 
819     cmdList.Draw(3u, 1u, 0u, 0u);
820     cmdList.EndRenderPass();
821     const auto maxMipLevel = ppConfig_.blurConfiguration.maxMipLevel;
822     ppConfig_.blurConfiguration.maxMipLevel = static_cast<uint32_t>(Math::round(ppConfig_.dofConfiguration.nearBlur));
823     renderNearBlur_.Execute(*renderNodeContextMgr_, cmdList, ppConfig_);
824     ppConfig_.blurConfiguration.maxMipLevel = static_cast<uint32_t>(Math::round(ppConfig_.dofConfiguration.farBlur));
825     renderFarBlur_.Execute(*renderNodeContextMgr_, cmdList, ppConfig_);
826     ppConfig_.blurConfiguration.maxMipLevel = maxMipLevel;
827 }
828 
ExecuteDof(IRenderCommandList & cmdList,const InputOutput & inOut)829 void RenderNodePostProcessUtil::ExecuteDof(IRenderCommandList& cmdList, const InputOutput& inOut)
830 {
831     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderDoF", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
832 
833     // NOTE: updates set 0 for dof
834     ExecuteDofBlur(cmdList, inOut);
835 
836     auto renderPass = CreateRenderPass(renderNodeContextMgr_->GetGpuResourceManager(), inOut.output.handle);
837     if (!RenderHandleUtil::IsValid(dofData_.pso)) {
838         auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
839         const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
840         const RenderHandle gfxHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(dofData_.sd.shader);
841         dofData_.pso = psoMgr.GetGraphicsPsoHandle(dofData_.sd.shader, gfxHandle, dofData_.sd.pipelineLayout, {}, {},
842             { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
843     }
844 
845     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
846     cmdList.BindPipeline(dofData_.pso);
847 
848     RenderHandle sets[2u] {};
849     {
850         // NOTE: descriptor set updated by DOF blur
851         PLUGIN_ASSERT(binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_DOF_IDX]);
852         auto& binder = *binders_.globalSet0[POST_PROCESS_UBO_INDICES::PP_DOF_IDX];
853         sets[0u] = binder.GetDescriptorSetHandle();
854     }
855     {
856         auto& binder = *binders_.dofBinder;
857         binder.ClearBindings();
858         uint32_t binding = 0u;
859         BindableImage input = inOut.input;
860         input.samplerHandle = samplers_.mipLinear;
861         binder.BindImage(binding, input);
862         binder.BindImage(++binding, ti_.mipImages[0U].GetHandle(), samplers_.mipLinear);
863         binder.BindImage(++binding, ti_.mipImages[1U].GetHandle(), samplers_.mipLinear);
864         BindableImage depth = images_.depth;
865         depth.samplerHandle = samplers_.nearest;
866         binder.BindImage(++binding, depth);
867 
868         cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
869         sets[1u] = binder.GetDescriptorSetHandle();
870     }
871     cmdList.BindDescriptorSets(0u, sets);
872 
873     if (dofData_.sd.pipelineLayoutData.pushConstant.byteSize > 0U) {
874         const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
875         const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
876         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
877         cmdList.PushConstantData(dofData_.sd.pipelineLayoutData.pushConstant, arrayviewU8(pc));
878     }
879 
880     // dynamic state
881     cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass));
882     cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass));
883 
884     cmdList.Draw(3u, 1u, 0u, 0u);
885     cmdList.EndRenderPass();
886 }
887 
ExecuteBlit(IRenderCommandList & cmdList,const InputOutput & inOut)888 void RenderNodePostProcessUtil::ExecuteBlit(IRenderCommandList& cmdList, const InputOutput& inOut)
889 {
890     // extra blit from input to ouput
891     if (RenderHandleUtil::IsGpuImage(inOut.input.handle) && RenderHandleUtil::IsGpuImage(inOut.output.handle)) {
892 #if (RENDER_VALIDATION_ENABLED == 1)
893         PLUGIN_LOG_ONCE_W(renderNodeContextMgr_->GetName().data(),
894             "RENDER_PERFORMANCE_VALIDATION: Extra blit from input to output (RN: %s)",
895             renderNodeContextMgr_->GetName().data());
896 #endif
897         RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderBlit", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
898 
899         auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
900 
901         RenderPass renderPass = CreateRenderPass(gpuResourceMgr, inOut.output.handle);
902         auto& effect = copyData_;
903         if (!RenderHandleUtil::IsValid(effect.pso)) {
904             auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
905             const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
906             const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(effect.sd.shader);
907             effect.pso = psoMgr.GetGraphicsPsoHandle(effect.sd.shader, graphicsStateHandle, effect.sd.pipelineLayout,
908                 {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
909         }
910 
911         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
912         cmdList.BindPipeline(effect.pso);
913 
914         {
915             auto& binder = *binders_.copyBinder;
916             binder.ClearBindings();
917             uint32_t binding = 0u;
918             binder.BindSampler(binding, samplers_.linear);
919             binder.BindImage(++binding, inOut.input);
920             cmdList.UpdateDescriptorSet(
921                 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
922             cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
923         }
924 
925         // dynamic state
926         const ViewportDesc viewportDesc = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass);
927         const ScissorDesc scissorDesc = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass);
928         cmdList.SetDynamicStateViewport(viewportDesc);
929         cmdList.SetDynamicStateScissor(scissorDesc);
930 
931         cmdList.Draw(3u, 1u, 0u, 0u);
932         cmdList.EndRenderPass();
933     }
934 }
935 
UpdatePostProcessData(const PostProcessConfiguration & postProcessConfiguration)936 void RenderNodePostProcessUtil::UpdatePostProcessData(const PostProcessConfiguration& postProcessConfiguration)
937 {
938     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
939     const RenderPostProcessConfiguration rppc =
940         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(postProcessConfiguration);
941     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
942     if (auto* const data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
943         const auto* dataEnd = data + POST_PROCESS_UBO_BYTE_SIZE;
944         if (!CloneData(data, size_t(dataEnd - data), &rppc, sizeof(RenderPostProcessConfiguration))) {
945             PLUGIN_LOG_E("post process ubo copying failed.");
946         }
947         {
948             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_TAA_IDX * UBO_OFFSET_ALIGNMENT);
949             auto factor = PostProcessConversionHelper::GetFactorTaa(postProcessConfiguration);
950             CloneData(localData, size_t(dataEnd - localData), &factor, sizeof(factor));
951         }
952         {
953             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_BLOOM_IDX * UBO_OFFSET_ALIGNMENT);
954             auto factor = PostProcessConversionHelper::GetFactorBloom(postProcessConfiguration);
955             CloneData(localData, size_t(dataEnd - localData), &factor, sizeof(factor));
956         }
957         {
958             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_BLUR_IDX * UBO_OFFSET_ALIGNMENT);
959             auto factor = PostProcessConversionHelper::GetFactorBlur(postProcessConfiguration);
960             CloneData(localData, size_t(dataEnd - localData), &factor, sizeof(factor));
961         }
962         {
963             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_FXAA_IDX * UBO_OFFSET_ALIGNMENT);
964             auto factor = PostProcessConversionHelper::GetFactorFxaa(postProcessConfiguration);
965             CloneData(localData, size_t(dataEnd - localData), &factor, sizeof(factor));
966         }
967         {
968             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_DOF_IDX * UBO_OFFSET_ALIGNMENT);
969             auto factors = PostProcessConversionHelper::GetFactorDof(postProcessConfiguration);
970             CloneData(localData, size_t(dataEnd - localData), &factors, sizeof(factors));
971             localData += sizeof(factors);
972             factors = PostProcessConversionHelper::GetFactorDof2(postProcessConfiguration);
973             CloneData(localData, size_t(dataEnd - localData), &factors, sizeof(factors));
974         }
975         {
976             auto* localData = data + (sizeof(RenderPostProcessConfiguration) + PP_MB_IDX * UBO_OFFSET_ALIGNMENT);
977             auto factor = PostProcessConversionHelper::GetFactorMotionBlur(postProcessConfiguration);
978             CloneData(localData, size_t(dataEnd - localData), &factor, sizeof(factor));
979         }
980 
981         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
982     }
983 }
984 
ProcessPostProcessConfiguration()985 void RenderNodePostProcessUtil::ProcessPostProcessConfiguration()
986 {
987     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
988         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
989         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
990             if (jsonInputs_.renderDataStore.typeName == RenderDataStorePod::TYPE_NAME) {
991                 auto const dataStore = static_cast<const IRenderDataStorePod*>(ds);
992                 auto const dataView = dataStore->Get(jsonInputs_.renderDataStore.configurationName);
993                 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
994                     ppConfig_ = *((const PostProcessConfiguration*)dataView.data());
995                     if (RenderHandleUtil::IsValid(ppConfig_.bloomConfiguration.dirtMaskImage)) {
996                         images_.dirtMask = ppConfig_.bloomConfiguration.dirtMaskImage;
997                     } else {
998                         images_.dirtMask = aimg_.black;
999                     }
1000                 }
1001             }
1002         }
1003     }
1004 }
1005 
InitCreateShaderResources()1006 void RenderNodePostProcessUtil::InitCreateShaderResources()
1007 {
1008     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
1009 
1010     combineData_ = {};
1011     combineDataLayer_ = {};
1012     copyData_ = {};
1013     fxaaData_ = {};
1014     taaData_ = {};
1015     dofData_ = {};
1016     dofBlurData_ = {};
1017 
1018     combineData_.sd = shaderMgr.GetShaderDataByShaderName(COMBINED_SHADER_NAME);
1019     combineDataLayer_.sd = shaderMgr.GetShaderDataByShaderName(COMBINED_LAYER_SHADER_NAME);
1020     copyData_.sd = shaderMgr.GetShaderDataByShaderName(COPY_SHADER_NAME);
1021     fxaaData_.sd = shaderMgr.GetShaderDataByShaderName(FXAA_SHADER_NAME);
1022     taaData_.sd = shaderMgr.GetShaderDataByShaderName(TAA_SHADER_NAME);
1023     dofData_.sd = shaderMgr.GetShaderDataByShaderName(DOF_SHADER_NAME);
1024     dofBlurData_.sd = shaderMgr.GetShaderDataByShaderName(DOF_BLUR_SHADER_NAME);
1025 }
1026 
InitCreateBinders()1027 void RenderNodePostProcessUtil::InitCreateBinders()
1028 {
1029     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
1030     {
1031         constexpr uint32_t globalSetIdx = 0u;
1032         constexpr uint32_t localSetIdx = 1u;
1033 
1034         for (uint32_t idx = 0; idx < POST_PROCESS_UBO_INDICES::PP_COUNT_IDX; ++idx) {
1035             binders_.globalSet0[idx] = descriptorSetMgr.CreateDescriptorSetBinder(
1036                 descriptorSetMgr.CreateDescriptorSet(globalSetIdx, combineData_.sd.pipelineLayoutData),
1037                 combineData_.sd.pipelineLayoutData.descriptorSetLayouts[globalSetIdx].bindings);
1038         }
1039 
1040         binders_.combineBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1041             descriptorSetMgr.CreateDescriptorSet(localSetIdx, combineData_.sd.pipelineLayoutData),
1042             combineData_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1043         binders_.combineLayerBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1044             descriptorSetMgr.CreateDescriptorSet(localSetIdx, combineDataLayer_.sd.pipelineLayoutData),
1045             combineDataLayer_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1046 
1047         binders_.fxaaBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1048             descriptorSetMgr.CreateDescriptorSet(localSetIdx, fxaaData_.sd.pipelineLayoutData),
1049             fxaaData_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1050         binders_.taaBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1051             descriptorSetMgr.CreateDescriptorSet(localSetIdx, taaData_.sd.pipelineLayoutData),
1052             taaData_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1053 
1054         binders_.dofBlurBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1055             descriptorSetMgr.CreateDescriptorSet(localSetIdx, dofBlurData_.sd.pipelineLayoutData),
1056             dofBlurData_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1057         binders_.dofBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1058             descriptorSetMgr.CreateDescriptorSet(localSetIdx, dofData_.sd.pipelineLayoutData),
1059             dofData_.sd.pipelineLayoutData.descriptorSetLayouts[localSetIdx].bindings);
1060     }
1061     binders_.copyBinder = descriptorSetMgr.CreateDescriptorSetBinder(
1062         descriptorSetMgr.CreateDescriptorSet(0u, copyData_.sd.pipelineLayoutData),
1063         copyData_.sd.pipelineLayoutData.descriptorSetLayouts[0u].bindings);
1064 }
1065 
ParseRenderNodeInputs()1066 void RenderNodePostProcessUtil::ParseRenderNodeInputs()
1067 {
1068     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
1069     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
1070     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
1071     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
1072 
1073     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
1074     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
1075     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
1076 
1077     // process custom inputs
1078     for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
1079         const auto& ref = jsonInputs_.resources.customInputImages[idx];
1080         if (ref.usageName == INPUT_COLOR) {
1081             jsonInputs_.colorIndex = idx;
1082         } else if (ref.usageName == INPUT_DEPTH) {
1083             jsonInputs_.depthIndex = idx;
1084         } else if (ref.usageName == INPUT_VELOCITY) {
1085             jsonInputs_.velocityIndex = idx;
1086         } else if (ref.usageName == INPUT_HISTORY) {
1087             jsonInputs_.historyIndex = idx;
1088         } else if (ref.usageName == INPUT_HISTORY_NEXT) {
1089             jsonInputs_.historyNextIndex = idx;
1090         }
1091     }
1092 }
1093 
UpdateImageData()1094 void RenderNodePostProcessUtil::UpdateImageData()
1095 {
1096     if ((!RenderHandleUtil::IsValid(aimg_.black)) || (!RenderHandleUtil::IsValid(aimg_.white))) {
1097         auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
1098         aimg_.black = gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
1099         aimg_.white = gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
1100     }
1101 
1102     if (postProcessInfo_.parseRenderNodeInputs) {
1103         if (inputResources_.customInputImages.empty() || inputResources_.customOutputImages.empty()) {
1104             return; // early out
1105         }
1106 
1107         images_.input.handle = inputResources_.customInputImages[0].handle;
1108         images_.output.handle = inputResources_.customOutputImages[0].handle;
1109         if (jsonInputs_.depthIndex < inputResources_.customInputImages.size()) {
1110             images_.depth.handle = inputResources_.customInputImages[jsonInputs_.depthIndex].handle;
1111         }
1112         if (jsonInputs_.velocityIndex < inputResources_.customInputImages.size()) {
1113             images_.velocity.handle = inputResources_.customInputImages[jsonInputs_.velocityIndex].handle;
1114         }
1115         if (jsonInputs_.historyIndex < inputResources_.customInputImages.size()) {
1116             images_.history.handle = inputResources_.customInputImages[jsonInputs_.historyIndex].handle;
1117         }
1118         if (jsonInputs_.historyNextIndex < inputResources_.customInputImages.size()) {
1119             images_.historyNext.handle = inputResources_.customInputImages[jsonInputs_.historyNextIndex].handle;
1120         }
1121     } else {
1122         images_.input = postProcessInfo_.imageData.input;
1123         images_.output = postProcessInfo_.imageData.output;
1124         images_.depth = postProcessInfo_.imageData.depth;
1125         images_.velocity = postProcessInfo_.imageData.velocity;
1126         images_.history = postProcessInfo_.imageData.history;
1127         images_.historyNext = postProcessInfo_.imageData.historyNext;
1128     }
1129 
1130     validInputsForTaa_ = false;
1131     validInputsForDof_ = false;
1132     validInputsForMb_ = false;
1133     bool validDepth = false;
1134     bool validHistory = false;
1135     bool validVelocity = false;
1136     if (IsValidHandle(images_.depth) && (images_.depth.handle != aimg_.white)) {
1137         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
1138         const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(images_.depth.handle);
1139         if (desc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
1140             validDepth = true;
1141         }
1142     } else {
1143         images_.depth.handle = aimg_.white; // default depth
1144     }
1145     if (IsValidHandle(images_.velocity) && (images_.velocity.handle != aimg_.black)) {
1146         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
1147         const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(images_.velocity.handle);
1148         if (desc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
1149             validVelocity = true;
1150         }
1151     } else {
1152         images_.velocity.handle = aimg_.black; // default velocity
1153     }
1154     if (IsValidHandle(images_.history) && IsValidHandle(images_.historyNext)) {
1155         const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
1156         const GpuImageDesc& velDesc = gpuResourceMgr.GetImageDescriptor(images_.velocity.handle);
1157         if (velDesc.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT) {
1158             validHistory = true;
1159         }
1160     }
1161     if (!RenderHandleUtil::IsValid(images_.dirtMask)) {
1162         images_.dirtMask = aimg_.black; // default dirt mask
1163     }
1164 
1165     validInputsForDof_ = validDepth;
1166     validInputsForTaa_ = validDepth && validHistory; // TAA can be used without velocities
1167     validInputsForMb_ = validVelocity;
1168 }
1169 
CreatePostProcessInterfaces()1170 void RenderNodePostProcessUtil::CreatePostProcessInterfaces()
1171 {
1172     auto* renderClassFactory = renderNodeContextMgr_->GetRenderContext().GetInterface<IClassFactory>();
1173     if (renderClassFactory) {
1174         ppLensFlareInterface_.postProcess =
1175             CreateInstance<IRenderPostProcess>(*renderClassFactory, RenderPostProcessFlare::UID);
1176         if (ppLensFlareInterface_.postProcess) {
1177             ppLensFlareInterface_.postProcessNode = CreateInstance<IRenderPostProcessNode>(
1178                 *renderClassFactory, ppLensFlareInterface_.postProcess->GetRenderPostProcessNodeUid());
1179         }
1180     }
1181 }
1182 
1183 ///////////////////////////////////////////////////////////////////////////////////////////////////
1184 
Init(IRenderNodeContextManager & renderNodeContextMgr,const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)1185 void RenderNodePostProcessUtilImpl::Init(
1186     IRenderNodeContextManager& renderNodeContextMgr, const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
1187 {
1188     rn_.Init(renderNodeContextMgr, postProcessInfo);
1189 }
1190 
PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo & postProcessInfo)1191 void RenderNodePostProcessUtilImpl::PreExecute(const IRenderNodePostProcessUtil::PostProcessInfo& postProcessInfo)
1192 {
1193     rn_.PreExecute(postProcessInfo);
1194 }
1195 
Execute(IRenderCommandList & cmdList)1196 void RenderNodePostProcessUtilImpl::Execute(IRenderCommandList& cmdList)
1197 {
1198     rn_.Execute(cmdList);
1199 }
1200 
GetInterface(const Uid & uid) const1201 const IInterface* RenderNodePostProcessUtilImpl::GetInterface(const Uid& uid) const
1202 {
1203     if ((uid == IRenderNodePostProcessUtil::UID) || (uid == IInterface::UID)) {
1204         return this;
1205     }
1206     return nullptr;
1207 }
1208 
GetInterface(const Uid & uid)1209 IInterface* RenderNodePostProcessUtilImpl::GetInterface(const Uid& uid)
1210 {
1211     if ((uid == IRenderNodePostProcessUtil::UID) || (uid == IInterface::UID)) {
1212         return this;
1213     }
1214     return nullptr;
1215 }
1216 
Ref()1217 void RenderNodePostProcessUtilImpl::Ref()
1218 {
1219     refCount_++;
1220 }
1221 
Unref()1222 void RenderNodePostProcessUtilImpl::Unref()
1223 {
1224     if (--refCount_ == 0) {
1225         delete this;
1226     }
1227 }
1228 RENDER_END_NAMESPACE()
1229