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_single_post_process.h"
17
18 #include <base/math/mathf.h>
19 #include <render/datastore/intf_render_data_store_manager.h>
20 #include <render/datastore/intf_render_data_store_post_process.h>
21 #include <render/device/intf_gpu_resource_manager.h>
22 #include <render/device/intf_shader_manager.h>
23 #include <render/device/pipeline_layout_desc.h>
24 #include <render/device/pipeline_state_desc.h>
25 #include <render/namespace.h>
26 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
27 #include <render/nodecontext/intf_node_context_pso_manager.h>
28 #include <render/nodecontext/intf_render_command_list.h>
29 #include <render/nodecontext/intf_render_node_context_manager.h>
30 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
31 #include <render/nodecontext/intf_render_node_parser_util.h>
32 #include <render/nodecontext/intf_render_node_util.h>
33
34 #include "datastore/render_data_store_pod.h"
35 #include "datastore/render_data_store_post_process.h"
36 #include "default_engine_constants.h"
37 #include "device/gpu_resource_handle_util.h"
38 #include "util/log.h"
39
40 // shaders
41 #include <render/shaders/common/render_post_process_structs_common.h>
42
43 using namespace BASE_NS;
44
45 RENDER_BEGIN_NAMESPACE()
46 namespace {
47 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
48
49 constexpr uint32_t GLOBAL_POST_PROCESS_SET { 0u };
50 constexpr string_view RENDER_DATA_STORE_POD_NAME { RenderDataStorePod::TYPE_NAME };
51
52 constexpr string_view INPUT = "input";
53 constexpr string_view OUTPUT = "output";
54
55 constexpr string_view POST_PROCESS_BASE_PIPELINE_LAYOUT { "renderpipelinelayouts://post_process_common.shaderpl" };
56
57 struct DispatchResources {
58 RenderHandle buffer {};
59 RenderHandle image {};
60 };
61
GetDispatchResources(const RenderNodeHandles::InputResources & ir)62 DispatchResources GetDispatchResources(const RenderNodeHandles::InputResources& ir)
63 {
64 DispatchResources dr;
65 if (!ir.customInputBuffers.empty()) {
66 dr.buffer = ir.customInputBuffers[0].handle;
67 }
68 if (!ir.customInputImages.empty()) {
69 dr.image = ir.customInputImages[0].handle;
70 }
71 return dr;
72 }
73
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)74 RenderHandleReference CreatePostProcessDataUniformBuffer(
75 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
76 {
77 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
78 PLUGIN_STATIC_ASSERT(
79 sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
80 return gpuResourceMgr.Create(
81 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
82 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
83 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
84 sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
85 }
86
GetPostProcessFlag(const string_view ppName)87 uint32_t GetPostProcessFlag(const string_view ppName)
88 {
89 if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_FXAA]) {
90 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_FXAA_BIT;
91 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_TAA]) {
92 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_TAA_BIT;
93 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) {
94 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLOOM_BIT;
95 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR]) {
96 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_BLUR_BIT;
97 } else if (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_DOF]) {
98 return PostProcessConfiguration::PostProcessEnableFlagBits::ENABLE_DOF_BIT;
99 } else {
100 return 0;
101 }
102 }
103
NeedsShader(const string_view ppName)104 bool NeedsShader(const string_view ppName)
105 {
106 if ((ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLOOM]) ||
107 (ppName == PostProcessConstants::POST_PROCESS_NAMES[PostProcessConstants::RENDER_BLUR])) {
108 return false;
109 } else {
110 return true;
111 }
112 }
113
NeedsAutoBindingSet0(const RenderNodeHandles::InputResources & inputRes)114 bool NeedsAutoBindingSet0(const RenderNodeHandles::InputResources& inputRes)
115 {
116 uint32_t set0Bindings = 0;
117 for (const auto& res : inputRes.buffers) {
118 if (res.set == GLOBAL_POST_PROCESS_SET) {
119 set0Bindings++;
120 }
121 }
122 return (set0Bindings == 0);
123 }
124
GetBindableImage(const RenderHandle & res)125 inline BindableImage GetBindableImage(const RenderHandle& res)
126 {
127 return BindableImage { res, PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS,
128 PipelineStateConstants::GPU_IMAGE_ALL_LAYERS, ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, {} };
129 }
130 } // namespace
131
InitNode(IRenderNodeContextManager & renderNodeContextMgr)132 void RenderNodeSinglePostProcess::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
133 {
134 renderNodeContextMgr_ = &renderNodeContextMgr;
135
136 valid_ = true;
137 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
138 ubos_.postProcess = CreatePostProcessDataUniformBuffer(gpuResourceMgr, ubos_.postProcess);
139
140 ParseRenderNodeInputs();
141 UpdateImageData();
142 ProcessPostProcessConfiguration();
143 if (!RenderHandleUtil::IsValid(shader_)) {
144 shader_ = ppLocalConfig_.shader.GetHandle();
145 }
146 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
147 const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
148 if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
149 graphics_ = true;
150 } else if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
151 graphics_ = false;
152 threadGroupSize_ = shaderMgr.GetReflectionThreadGroupSize(shader_);
153 if (dispatchResources_.customInputBuffers.empty() && dispatchResources_.customInputImages.empty()) {
154 valid_ = false;
155 PLUGIN_LOG_W("RenderNodeSinglePostProcess: dispatchResources (GPU buffer or GPU image) needed");
156 }
157 }
158
159 pipelineLayout_ = renderNodeContextMgr.GetRenderNodeUtil().CreatePipelineLayout(shader_);
160
161 const bool needsShader = NeedsShader(jsonInputs_.ppName);
162 if (needsShader) {
163 if (!((handleType == RenderHandleType::SHADER_STATE_OBJECT) ||
164 (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
165 PLUGIN_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
166 }
167 const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
168 pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
169 if (graphics_) {
170 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
171 psoHandle_ = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
172 shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
173 } else {
174 psoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(shader_, pipelineLayout_, {});
175 }
176
177 // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
178 const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
179 const IShaderManager::CompatibilityFlags compatibilityFlags =
180 shaderMgr.GetCompatibilityFlags(basePlHandle, plHandle);
181 if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
182 PLUGIN_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
183 POST_PROCESS_BASE_PIPELINE_LAYOUT.data());
184 }
185 }
186 InitCreateBinders();
187
188 if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
189 valid_ = false;
190 }
191
192 // special handling for bloom and blur
193 RenderHandle output = builtInVariables_.output;
194 if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
195 ppLocalConfig_.variables.enabled) {
196 const RenderBloom::BloomInfo bloomInfo { GetBindableImage(builtInVariables_.input),
197 GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
198 ppGlobalConfig_.bloomConfiguration.useCompute };
199 renderBloom_.Init(renderNodeContextMgr, bloomInfo);
200 output = renderBloom_.GetFinalTarget();
201 } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
202 ppLocalConfig_.variables.enabled) {
203 RenderBlur::BlurInfo blurInfo { GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
204 false };
205 renderBlur_.Init(renderNodeContextMgr, blurInfo);
206 }
207 renderCopy_.Init(renderNodeContextMgr);
208 RegisterOutputs(output);
209 }
210
PreExecuteFrame()211 void RenderNodeSinglePostProcess::PreExecuteFrame()
212 {
213 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
214 if (jsonInputs_.hasChangeableResourceHandles) {
215 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
216 }
217 UpdateImageData();
218
219 ProcessPostProcessConfiguration();
220
221 // special handling for bloom and blur
222 RenderHandle output = builtInVariables_.output;
223 if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
224 ppLocalConfig_.variables.enabled) {
225 const RenderBloom::BloomInfo bloomInfo { GetBindableImage(builtInVariables_.input),
226 GetBindableImage(builtInVariables_.output), ubos_.postProcess.GetHandle(),
227 ppGlobalConfig_.bloomConfiguration.useCompute };
228 renderBloom_.PreExecute(*renderNodeContextMgr_, bloomInfo, ppGlobalConfig_);
229 output = renderBloom_.GetFinalTarget();
230 } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
231 ppLocalConfig_.variables.enabled) {
232 RenderBlur::BlurInfo blurInfo { GetBindableImage(builtInVariables_.input), ubos_.postProcess.GetHandle(),
233 false };
234 renderBlur_.PreExecute(*renderNodeContextMgr_, blurInfo);
235 }
236 {
237 renderCopy_.PreExecute();
238 }
239 RegisterOutputs(output);
240 }
241
ExecuteFrame(IRenderCommandList & cmdList)242 void RenderNodeSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
243 {
244 if ((!ppLocalConfig_.variables.enabled) &&
245 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
246 return;
247 }
248
249 if (ppLocalConfig_.variables.enabled) {
250 // ppConfig_ is already up-to-date from PreExecuteFrame
251 if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) &&
252 ppLocalConfig_.variables.enabled) {
253 renderBloom_.Execute(*renderNodeContextMgr_, cmdList, ppGlobalConfig_);
254 return;
255 } else if ((builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) &&
256 ppLocalConfig_.variables.enabled) {
257 renderBlur_.Execute(*renderNodeContextMgr_, cmdList, ppGlobalConfig_);
258 return;
259 }
260 if (valid_) {
261 ExecuteSinglePostProcess(cmdList);
262 }
263 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
264 IRenderNodeCopyUtil::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
265 GetBindableImage(builtInVariables_.output), {} };
266 renderCopy_.Execute(cmdList, copyInfo);
267 }
268 }
269
ExecuteSinglePostProcess(IRenderCommandList & cmdList)270 void RenderNodeSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
271 {
272 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
273 if (jsonInputs_.hasChangeableRenderPassHandles) {
274 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
275 }
276 if (jsonInputs_.hasChangeableResourceHandles) {
277 // input resources updated in preExecuteFrame
278 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
279 }
280 if (jsonInputs_.hasChangeableDispatchHandles) {
281 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
282 }
283 if (useAutoBindSet0_) {
284 UpdateGlobalPostProcessUbo();
285 }
286
287 RenderPass renderPass;
288 DispatchResources dispatchResources;
289 if (graphics_) {
290 renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
291 if ((renderPass.renderPassDesc.attachmentCount == 0) ||
292 !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
293 #if (RENDER_VALIDATION_ENABLED == 1)
294 PLUGIN_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(),
295 "RENDER_VALIDATION: RN: %s, invalid attachment", renderNodeContextMgr_->GetName().data());
296 #endif
297 return;
298 }
299 } else {
300 dispatchResources = GetDispatchResources(dispatchResources_);
301 if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
302 (!RenderHandleUtil::IsValid(dispatchResources.image))) {
303 return; // no way to evaluate dispatch size
304 }
305 }
306
307 const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
308 const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
309 const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
310 for (const auto refIndex : setIndices) {
311 const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
312 // handle automatic set 0 bindings
313 if ((refIndex == 0) && useAutoBindSet0_) {
314 auto& binder = *pipelineDescriptorSetBinder_;
315 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 0u, BindableBuffer { ubos_.postProcess.GetHandle() });
316 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 1u,
317 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
318 } else if (invalidBindings) {
319 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
320 BindDefaultResources(refIndex, bindings);
321 }
322 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
323 cmdList.UpdateDescriptorSet(descHandle, bindings);
324 }
325 #if (RENDER_VALIDATION_ENABLED == 1)
326 if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
327 PLUGIN_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
328 }
329 #endif
330
331 if (graphics_) {
332 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
333 }
334
335 cmdList.BindPipeline(psoHandle_);
336
337 // bind all sets
338 cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
339
340 if (graphics_) {
341 // dynamic state
342 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
343 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
344 cmdList.SetDynamicStateViewport(viewportDesc);
345 cmdList.SetDynamicStateScissor(scissorDesc);
346
347 if (pipelineLayout_.pushConstant.byteSize > 0) {
348 const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
349 const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
350 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
351 ppLocalConfig_.variables.factor };
352 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
353 }
354
355 cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
356 cmdList.EndRenderPass();
357 } else {
358 if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
359 cmdList.DispatchIndirect(dispatchResources.buffer, 0);
360 } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
361 const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
362 const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
363 const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
364 if (pipelineLayout_.pushConstant.byteSize > 0) {
365 const auto fWidth = static_cast<float>(targetSize.x);
366 const auto fHeight = static_cast<float>(targetSize.y);
367 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
368 ppLocalConfig_.variables.factor };
369 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
370 }
371
372 cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
373 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
374 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
375 }
376 }
377 }
378
RegisterOutputs(const RenderHandle output)379 void RenderNodeSinglePostProcess::RegisterOutputs(const RenderHandle output)
380 {
381 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
382 RenderHandle registerOutput;
383 if (ppLocalConfig_.variables.enabled) {
384 if (RenderHandleUtil::IsValid(output)) {
385 registerOutput = output;
386 }
387 }
388 if (!RenderHandleUtil::IsValid(registerOutput)) {
389 if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
390 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
391 RenderHandleUtil::IsValid(output)) {
392 registerOutput = output;
393 } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
394 RenderHandleUtil::IsValid(builtInVariables_.input)) {
395 registerOutput = builtInVariables_.input;
396 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
397 registerOutput = builtInVariables_.defWhiteImage;
398 } else {
399 registerOutput = builtInVariables_.defBlackImage;
400 }
401 }
402 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
403 }
404
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)405 void RenderNodeSinglePostProcess::BindDefaultResources(
406 const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
407 {
408 if (pipelineDescriptorSetBinder_) {
409 auto& binder = *pipelineDescriptorSetBinder_;
410 for (const auto& ref : bindings.buffers) {
411 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
412 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
413 }
414 }
415 for (const auto& ref : bindings.images) {
416 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
417 BindableImage bi;
418 bi.handle = builtInVariables_.defBlackImage;
419 bi.samplerHandle = builtInVariables_.defSampler;
420 binder.BindImage(set, ref.binding.binding, bi);
421 }
422 }
423 for (const auto& ref : bindings.samplers) {
424 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
425 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
426 }
427 }
428 }
429 }
430
ProcessPostProcessConfiguration()431 void RenderNodeSinglePostProcess::ProcessPostProcessConfiguration()
432 {
433 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
434 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
435 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
436 if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
437 auto* const dataStore = static_cast<const IRenderDataStorePostProcess*>(ds);
438 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
439 }
440 }
441 if (const auto* ds =
442 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
443 ds) {
444 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
445 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
446 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
447 }
448 }
449 } else if (jsonInputs_.ppName.empty()) {
450 // if trying to just use shader without post processing we enable running by default
451 ppLocalConfig_.variables.enabled = true;
452 }
453 }
454
UpdateGlobalPostProcessUbo()455 void RenderNodeSinglePostProcess::UpdateGlobalPostProcessUbo()
456 {
457 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
458 const RenderPostProcessConfiguration rppc =
459 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
460 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
461 PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
462 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
463 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
464 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
465 // global data
466 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
467 // local data
468 data += sizeof(GlobalPostProcessStruct);
469 CloneData(
470 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
471 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
472 }
473 }
474
InitCreateBinders()475 void RenderNodeSinglePostProcess::InitCreateBinders()
476 {
477 const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
478 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
479 DescriptorCounts dc;
480 if (builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLOOM_BIT) {
481 dc = RenderBloom::GetDescriptorCounts();
482 } else if (builtInVariables_.postProcessFlag & PostProcessConfiguration::ENABLE_BLUR_BIT) {
483 dc = RenderBlur::GetDescriptorCounts();
484 } else {
485 dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
486 }
487 if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
488 const DescriptorCounts copyDc = renderCopy_.GetRenderDescriptorCounts();
489 for (const auto& ref : copyDc.counts) {
490 dc.counts.push_back(ref);
491 }
492 }
493 descriptorSetMgr.ResetAndReserve(dc);
494
495 pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
496 if (pipelineDescriptorSetBinder_) {
497 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
498 if (NeedsAutoBindingSet0(inputResources_)) {
499 useAutoBindSet0_ = true;
500 }
501 } else {
502 valid_ = false;
503 }
504 }
505
ParseRenderNodeInputs()506 void RenderNodeSinglePostProcess::ParseRenderNodeInputs()
507 {
508 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
509 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
510 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
511 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
512 jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
513 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
514
515 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
516 builtInVariables_.postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
517
518 #if (RENDER_VALIDATION_ENABLED == 1)
519 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
520 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
521 renderNodeContextMgr_->GetName().data());
522 }
523 if (jsonInputs_.ppName.empty()) {
524 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
525 }
526 #endif
527
528 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
529 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
530 if (!shaderName.empty()) {
531 shader_ = shaderMgr.GetShaderHandle(shaderName);
532 }
533 const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
534 if (!defaultOutput.empty()) {
535 if (defaultOutput == "output") {
536 jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
537 } else if (defaultOutput == "input_output_copy") {
538 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
539 } else if (defaultOutput == "input") {
540 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
541 } else if (defaultOutput == "black") {
542 jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
543 } else if (defaultOutput == "white") {
544 jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
545 } else {
546 PLUGIN_LOG_W("RenderNodeSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
547 }
548 }
549
550 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
551 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
552 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
553 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
554
555 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
556 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
557 jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
558
559 // process custom resources
560 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
561 const auto& ref = jsonInputs_.resources.customInputImages[idx];
562 if (ref.usageName == INPUT) {
563 jsonInputs_.inputIdx = idx;
564 }
565 }
566 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
567 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
568 if (ref.usageName == OUTPUT) {
569 jsonInputs_.outputIdx = idx;
570 }
571 }
572 }
573
UpdateImageData()574 void RenderNodeSinglePostProcess::UpdateImageData()
575 {
576 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
577 if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
578 builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
579 }
580 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
581 builtInVariables_.defBlackImage =
582 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
583 }
584 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
585 builtInVariables_.defWhiteImage =
586 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
587 }
588 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
589 builtInVariables_.defSampler =
590 gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
591 }
592 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
593 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
594 }
595 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
596 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
597 }
598 }
599
600 // for plugin / factory interface
Create()601 IRenderNode* RenderNodeSinglePostProcess::Create()
602 {
603 return new RenderNodeSinglePostProcess();
604 }
605
Destroy(IRenderNode * instance)606 void RenderNodeSinglePostProcess::Destroy(IRenderNode* instance)
607 {
608 delete static_cast<RenderNodeSinglePostProcess*>(instance);
609 }
610 RENDER_END_NAMESPACE()
611