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