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