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