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_bloom.h"
17
18 #include <base/math/vector.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/namespace.h>
24 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
25 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
26 #include <render/nodecontext/intf_render_command_list.h>
27 #include <render/nodecontext/intf_render_node_context_manager.h>
28 #include <render/nodecontext/intf_render_node_parser_util.h>
29 #include <render/nodecontext/intf_render_node_util.h>
30
31 #include "datastore/render_data_store_pod.h"
32 #include "util/log.h"
33
34 // shaders
35 #include <render/shaders/common/render_post_process_structs_common.h>
36
37 using namespace BASE_NS;
38
39 RENDER_BEGIN_NAMESPACE()
40 namespace {
41 constexpr uint32_t UBO_OFFSET_ALIGNMENT { PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE };
42
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)43 RenderHandleReference CreatePostProcessDataUniformBuffer(
44 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
45 {
46 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
47 PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) == UBO_OFFSET_ALIGNMENT);
48 return gpuResourceMgr.Create(
49 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
50 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
51 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
52 sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
53 }
54
GetBindableImage(const RenderNodeResource & res)55 inline BindableImage GetBindableImage(const RenderNodeResource& res)
56 {
57 return BindableImage { res.handle, res.mip, res.layer, ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, res.secondHandle };
58 }
59 } // namespace
60
InitNode(IRenderNodeContextManager & renderNodeContextMgr)61 void RenderNodeBloom::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
62 {
63 valid_ = true;
64
65 renderNodeContextMgr_ = &renderNodeContextMgr;
66 ParseRenderNodeInputs();
67
68 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
69 PLUGIN_LOG_E("RenderNodeBloom: render data store configuration not set in render node graph");
70 }
71 if (jsonInputs_.renderDataStore.typeName != RenderDataStorePod::TYPE_NAME) {
72 PLUGIN_LOG_E("RenderNodeBloom: render data store type name not supported (%s != %s)",
73 jsonInputs_.renderDataStore.typeName.data(), RenderDataStorePod::TYPE_NAME);
74 valid_ = false;
75 }
76
77 postProcessUbo_ =
78 CreatePostProcessDataUniformBuffer(renderNodeContextMgr_->GetGpuResourceManager(), postProcessUbo_);
79
80 ProcessPostProcessConfiguration(renderNodeContextMgr_->GetRenderDataStoreManager());
81 renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(renderBloom_.GetDescriptorCounts());
82 const RenderBloom::BloomInfo info { GetBindableImage(inputResources_.customInputImages[0]),
83 GetBindableImage(inputResources_.customOutputImages[0]), postProcessUbo_.GetHandle(),
84 ppConfig_.bloomConfiguration.useCompute };
85 renderBloom_.Init(renderNodeContextMgr, info);
86 }
87
PreExecuteFrame()88 void RenderNodeBloom::PreExecuteFrame()
89 {
90 if (!valid_) {
91 return;
92 }
93
94 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
95 if (jsonInputs_.hasChangeableResourceHandles) {
96 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
97 }
98 ProcessPostProcessConfiguration(renderNodeContextMgr_->GetRenderDataStoreManager());
99 UpdatePostProcessData(ppConfig_);
100
101 const RenderBloom::BloomInfo info { GetBindableImage(inputResources_.customInputImages[0]),
102 GetBindableImage(inputResources_.customOutputImages[0]), postProcessUbo_.GetHandle(),
103 ppConfig_.bloomConfiguration.useCompute };
104 renderBloom_.PreExecute(*renderNodeContextMgr_, info, ppConfig_);
105 }
106
ExecuteFrame(IRenderCommandList & cmdList)107 void RenderNodeBloom::ExecuteFrame(IRenderCommandList& cmdList)
108 {
109 if (!valid_) {
110 return;
111 }
112
113 renderBloom_.Execute(*renderNodeContextMgr_, cmdList, ppConfig_);
114 }
115
GetExecuteFlags() const116 IRenderNode::ExecuteFlags RenderNodeBloom::GetExecuteFlags() const
117 {
118 // At the moment bloom needs typically copy even though it would not be in use
119 return ExecuteFlagBits::EXECUTE_FLAG_BITS_DEFAULT;
120 }
121
ProcessPostProcessConfiguration(const IRenderNodeRenderDataStoreManager & dataStoreMgr)122 void RenderNodeBloom::ProcessPostProcessConfiguration(const IRenderNodeRenderDataStoreManager& dataStoreMgr)
123 {
124 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
125 if (const IRenderDataStore* ds = dataStoreMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName);
126 ds) {
127 if (jsonInputs_.renderDataStore.typeName == RenderDataStorePod::TYPE_NAME) {
128 auto const dataStore = static_cast<IRenderDataStorePod const*>(ds);
129 auto const dataView = dataStore->Get(jsonInputs_.renderDataStore.configurationName);
130 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
131 ppConfig_ = *((const PostProcessConfiguration*)dataView.data());
132 }
133 }
134 }
135 }
136 }
137
ParseRenderNodeInputs()138 void RenderNodeBloom::ParseRenderNodeInputs()
139 {
140 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
141 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
142 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
143 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
144
145 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
146 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
147 }
148
UpdatePostProcessData(const PostProcessConfiguration & postProcessConfiguration)149 void RenderNodeBloom::UpdatePostProcessData(const PostProcessConfiguration& postProcessConfiguration)
150 {
151 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
152 const RenderPostProcessConfiguration rppc =
153 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(postProcessConfiguration);
154 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
155 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(postProcessUbo_.GetHandle())); data) {
156 const auto* dataEnd = data + sizeof(RenderPostProcessConfiguration);
157 if (!CloneData(data, size_t(dataEnd - data), &rppc, sizeof(RenderPostProcessConfiguration))) {
158 PLUGIN_LOG_E("post process ubo copying failed.");
159 }
160 gpuResourceMgr.UnmapBuffer(postProcessUbo_.GetHandle());
161 }
162 }
163
164 // for plugin / factory interface
Create()165 IRenderNode* RenderNodeBloom::Create()
166 {
167 return new RenderNodeBloom();
168 }
169
Destroy(IRenderNode * instance)170 void RenderNodeBloom::Destroy(IRenderNode* instance)
171 {
172 delete static_cast<RenderNodeBloom*>(instance);
173 }
174 RENDER_END_NAMESPACE()
175