1 /*
2 * Copyright (c) 2022 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 RenderHandle output = builtInVariables_.output;
193 renderCopy_.Init(renderNodeContextMgr);
194 RegisterOutputs(output);
195 }
196
PreExecuteFrame()197 void RenderNodeSinglePostProcess::PreExecuteFrame()
198 {
199 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
200 if (jsonInputs_.hasChangeableResourceHandles) {
201 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
202 }
203 UpdateImageData();
204
205 ProcessPostProcessConfiguration();
206
207 RenderHandle output = builtInVariables_.output;
208 renderCopy_.PreExecute();
209 RegisterOutputs(output);
210 }
211
ExecuteFrame(IRenderCommandList & cmdList)212 void RenderNodeSinglePostProcess::ExecuteFrame(IRenderCommandList& cmdList)
213 {
214 if ((!ppLocalConfig_.variables.enabled) &&
215 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
216 return;
217 }
218
219 if (ppLocalConfig_.variables.enabled) {
220 // ppConfig_ is already up-to-date from PreExecuteFrame
221 if (valid_) {
222 ExecuteSinglePostProcess(cmdList);
223 }
224 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
225 IRenderNodeCopyUtil::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
226 GetBindableImage(builtInVariables_.output), {} };
227 renderCopy_.Execute(cmdList, copyInfo);
228 }
229 }
230
ExecuteSinglePostProcess(IRenderCommandList & cmdList)231 void RenderNodeSinglePostProcess::ExecuteSinglePostProcess(IRenderCommandList& cmdList)
232 {
233 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
234 if (jsonInputs_.hasChangeableRenderPassHandles) {
235 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
236 }
237 if (jsonInputs_.hasChangeableResourceHandles) {
238 // input resources updated in preExecuteFrame
239 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
240 }
241 if (jsonInputs_.hasChangeableDispatchHandles) {
242 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
243 }
244 if (useAutoBindSet0_) {
245 UpdateGlobalPostProcessUbo();
246 }
247
248 RenderPass renderPass;
249 DispatchResources dispatchResources;
250 if (graphics_) {
251 renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
252 if ((renderPass.renderPassDesc.attachmentCount == 0) ||
253 !RenderHandleUtil::IsValid(renderPass.renderPassDesc.attachmentHandles[0])) {
254 #if (RENDER_VALIDATION_ENABLED == 1)
255 PLUGIN_LOG_ONCE_W("rp_missing_" + renderNodeContextMgr_->GetName(),
256 "RENDER_VALIDATION: RN: %s, invalid attachment", renderNodeContextMgr_->GetName().data());
257 #endif
258 return;
259 }
260 } else {
261 dispatchResources = GetDispatchResources(dispatchResources_);
262 if ((!RenderHandleUtil::IsValid(dispatchResources.buffer)) &&
263 (!RenderHandleUtil::IsValid(dispatchResources.image))) {
264 return; // no way to evaluate dispatch size
265 }
266 }
267
268 const bool invalidBindings = (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity());
269 const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
270 const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
271 for (const auto refIndex : setIndices) {
272 const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
273 // handle automatic set 0 bindings
274 if ((refIndex == 0) && useAutoBindSet0_) {
275 auto& binder = *pipelineDescriptorSetBinder_;
276 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 0u, BindableBuffer { ubos_.postProcess.GetHandle() });
277 binder.BindBuffer(GLOBAL_POST_PROCESS_SET, 1u,
278 BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
279 } else if (invalidBindings) {
280 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
281 BindDefaultResources(refIndex, bindings);
282 }
283 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
284 cmdList.UpdateDescriptorSet(descHandle, bindings);
285 }
286 #if (RENDER_VALIDATION_ENABLED == 1)
287 if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
288 PLUGIN_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
289 }
290 #endif
291
292 if (graphics_) {
293 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
294 }
295
296 cmdList.BindPipeline(psoHandle_);
297
298 // bind all sets
299 cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
300
301 if (graphics_) {
302 // dynamic state
303 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
304 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
305 cmdList.SetDynamicStateViewport(viewportDesc);
306 cmdList.SetDynamicStateScissor(scissorDesc);
307
308 if (pipelineLayout_.pushConstant.byteSize > 0) {
309 const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
310 const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
311 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
312 ppLocalConfig_.variables.factor };
313 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
314 }
315
316 cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
317 cmdList.EndRenderPass();
318 } else {
319 if (RenderHandleUtil::IsValid(dispatchResources.buffer)) {
320 cmdList.DispatchIndirect(dispatchResources.buffer, 0);
321 } else if (RenderHandleUtil::IsValid(dispatchResources.image)) {
322 const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
323 const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dispatchResources.image);
324 const Math::UVec3 targetSize = { desc.width, desc.height, desc.depth };
325 if (pipelineLayout_.pushConstant.byteSize > 0) {
326 const auto fWidth = static_cast<float>(targetSize.x);
327 const auto fHeight = static_cast<float>(targetSize.y);
328 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
329 ppLocalConfig_.variables.factor };
330 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(pc));
331 }
332
333 cmdList.Dispatch((targetSize.x + threadGroupSize_.x - 1u) / threadGroupSize_.x,
334 (targetSize.y + threadGroupSize_.y - 1u) / threadGroupSize_.y,
335 (targetSize.z + threadGroupSize_.z - 1u) / threadGroupSize_.z);
336 }
337 }
338 }
339
RegisterOutputs(const RenderHandle output)340 void RenderNodeSinglePostProcess::RegisterOutputs(const RenderHandle output)
341 {
342 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
343 RenderHandle registerOutput;
344 if (ppLocalConfig_.variables.enabled) {
345 if (RenderHandleUtil::IsValid(output)) {
346 registerOutput = output;
347 }
348 }
349 if (!RenderHandleUtil::IsValid(registerOutput)) {
350 if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
351 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
352 RenderHandleUtil::IsValid(output)) {
353 registerOutput = output;
354 } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
355 RenderHandleUtil::IsValid(builtInVariables_.input)) {
356 registerOutput = builtInVariables_.input;
357 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
358 registerOutput = builtInVariables_.defWhiteImage;
359 } else {
360 registerOutput = builtInVariables_.defBlackImage;
361 }
362 }
363 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
364 }
365
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)366 void RenderNodeSinglePostProcess::BindDefaultResources(
367 const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
368 {
369 if (pipelineDescriptorSetBinder_) {
370 auto& binder = *pipelineDescriptorSetBinder_;
371 for (const auto& ref : bindings.buffers) {
372 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
373 binder.BindBuffer(set, ref.binding.binding, BindableBuffer { builtInVariables_.defBuffer });
374 }
375 }
376 for (const auto& ref : bindings.images) {
377 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
378 BindableImage bi;
379 bi.handle = builtInVariables_.defBlackImage;
380 bi.samplerHandle = builtInVariables_.defSampler;
381 binder.BindImage(set, ref.binding.binding, bi);
382 }
383 }
384 for (const auto& ref : bindings.samplers) {
385 if (!RenderHandleUtil::IsValid(ref.resource.handle)) {
386 binder.BindSampler(set, ref.binding.binding, BindableSampler { builtInVariables_.defSampler });
387 }
388 }
389 }
390 }
391
ProcessPostProcessConfiguration()392 void RenderNodeSinglePostProcess::ProcessPostProcessConfiguration()
393 {
394 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
395 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
396 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName); ds) {
397 if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
398 auto* const dataStore = static_cast<const IRenderDataStorePostProcess*>(ds);
399 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
400 }
401 }
402 if (const auto* ds =
403 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
404 ds) {
405 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
406 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
407 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
408 }
409 }
410 } else if (jsonInputs_.ppName.empty()) {
411 // if trying to just use shader without post processing we enable running by default
412 ppLocalConfig_.variables.enabled = true;
413 }
414 }
415
UpdateGlobalPostProcessUbo()416 void RenderNodeSinglePostProcess::UpdateGlobalPostProcessUbo()
417 {
418 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
419 const RenderPostProcessConfiguration rppc =
420 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
421 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
422 PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
423 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
424 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
425 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
426 // global data
427 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
428 // local data
429 data += sizeof(GlobalPostProcessStruct);
430 CloneData(
431 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
432 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
433 }
434 }
435
InitCreateBinders()436 void RenderNodeSinglePostProcess::InitCreateBinders()
437 {
438 const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
439 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
440 DescriptorCounts dc;
441
442 dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
443
444 if (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY) {
445 const DescriptorCounts copyDc = renderCopy_.GetRenderDescriptorCounts();
446 for (const auto& ref : copyDc.counts) {
447 dc.counts.push_back(ref);
448 }
449 }
450 descriptorSetMgr.ResetAndReserve(dc);
451
452 pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
453 if (pipelineDescriptorSetBinder_) {
454 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
455 if (NeedsAutoBindingSet0(inputResources_)) {
456 useAutoBindSet0_ = true;
457 }
458 } else {
459 valid_ = false;
460 }
461 }
462
ParseRenderNodeInputs()463 void RenderNodeSinglePostProcess::ParseRenderNodeInputs()
464 {
465 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
466 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
467 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
468 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
469 jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
470 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
471
472 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
473 builtInVariables_.postProcessFlag = GetPostProcessFlag(jsonInputs_.ppName);
474
475 #if (RENDER_VALIDATION_ENABLED == 1)
476 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
477 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
478 renderNodeContextMgr_->GetName().data());
479 }
480 if (jsonInputs_.ppName.empty()) {
481 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
482 }
483 #endif
484
485 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
486 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
487 if (!shaderName.empty()) {
488 shader_ = shaderMgr.GetShaderHandle(shaderName);
489 }
490 const auto defaultOutput = parserUtil.GetStringValue(jsonVal, "defaultOutputImage");
491 if (!defaultOutput.empty()) {
492 if (defaultOutput == "output") {
493 jsonInputs_.defaultOutputImage = DefaultOutputImage::OUTPUT;
494 } else if (defaultOutput == "input_output_copy") {
495 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT_OUTPUT_COPY;
496 } else if (defaultOutput == "input") {
497 jsonInputs_.defaultOutputImage = DefaultOutputImage::INPUT;
498 } else if (defaultOutput == "black") {
499 jsonInputs_.defaultOutputImage = DefaultOutputImage::BLACK;
500 } else if (defaultOutput == "white") {
501 jsonInputs_.defaultOutputImage = DefaultOutputImage::WHITE;
502 } else {
503 PLUGIN_LOG_W("RenderNodeSinglePostProcess default output image not supported (%s)", defaultOutput.c_str());
504 }
505 }
506
507 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
508 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
509 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
510 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
511
512 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
513 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
514 jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
515
516 // process custom resources
517 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
518 const auto& ref = jsonInputs_.resources.customInputImages[idx];
519 if (ref.usageName == INPUT) {
520 jsonInputs_.inputIdx = idx;
521 }
522 }
523 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
524 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
525 if (ref.usageName == OUTPUT) {
526 jsonInputs_.outputIdx = idx;
527 }
528 }
529 }
530
UpdateImageData()531 void RenderNodeSinglePostProcess::UpdateImageData()
532 {
533 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
534 if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
535 builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
536 }
537 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
538 builtInVariables_.defBlackImage =
539 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
540 }
541 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
542 builtInVariables_.defWhiteImage =
543 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
544 }
545 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
546 builtInVariables_.defSampler =
547 gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
548 }
549 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
550 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
551 }
552 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
553 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
554 }
555 }
556
557 // for plugin / factory interface
Create()558 IRenderNode* RenderNodeSinglePostProcess::Create()
559 {
560 return new RenderNodeSinglePostProcess();
561 }
562
Destroy(IRenderNode * instance)563 void RenderNodeSinglePostProcess::Destroy(IRenderNode* instance)
564 {
565 delete static_cast<RenderNodeSinglePostProcess*>(instance);
566 }
567 RENDER_END_NAMESPACE()
568