1 /*
2 * Copyright (C) 2023 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_back_buffer.h"
17
18 #include <base/containers/string.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/device/intf_shader_manager.h>
24 #include <render/device/pipeline_layout_desc.h>
25 #include <render/device/pipeline_state_desc.h>
26 #include <render/namespace.h>
27 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
28 #include <render/nodecontext/intf_node_context_pso_manager.h>
29 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
30 #include <render/nodecontext/intf_render_command_list.h>
31 #include <render/nodecontext/intf_render_node_context_manager.h>
32 #include <render/nodecontext/intf_render_node_parser_util.h>
33 #include <render/nodecontext/intf_render_node_util.h>
34 #include <render/render_data_structures.h>
35 #include <render/resource_handle.h>
36
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 RENDER_BEGIN_NAMESPACE()
44 namespace {
FillPushConstant(const GpuImageDesc & dstImageDesc,const RenderPostProcessConfiguration & currentRenderPostProcessConfiguration_)45 PostProcessTonemapStruct FillPushConstant(
46 const GpuImageDesc& dstImageDesc, const RenderPostProcessConfiguration& currentRenderPostProcessConfiguration_)
47 {
48 PostProcessTonemapStruct pushData;
49
50 const float fWidth = static_cast<float>(dstImageDesc.width);
51 const float fHeight = static_cast<float>(dstImageDesc.height);
52
53 pushData.texSizeInvTexSize[0u] = fWidth;
54 pushData.texSizeInvTexSize[1u] = fHeight;
55 pushData.texSizeInvTexSize[2u] = 1.0f / fWidth;
56 pushData.texSizeInvTexSize[3u] = 1.0f / fHeight;
57 pushData.flags = currentRenderPostProcessConfiguration_.flags;
58 pushData.tonemap = currentRenderPostProcessConfiguration_.factors[PostProcessConfiguration::INDEX_TONEMAP];
59 pushData.vignette = currentRenderPostProcessConfiguration_.factors[PostProcessConfiguration::INDEX_VIGNETTE];
60 pushData.colorFringe = currentRenderPostProcessConfiguration_.factors[PostProcessConfiguration::INDEX_COLOR_FRINGE];
61 pushData.dither = currentRenderPostProcessConfiguration_.factors[PostProcessConfiguration::INDEX_DITHER];
62 return pushData;
63 }
64 } // namespace
65
InitNode(IRenderNodeContextManager & renderNodeContextMgr)66 void RenderNodeBackBuffer::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
67 {
68 renderNodeContextMgr_ = &renderNodeContextMgr;
69 ParseRenderNodeInputs();
70
71 psoHandle_ = {};
72
73 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
74 PLUGIN_LOG_V("RenderNodeBackBuffer: render data store configuration not set in render node graph");
75 }
76
77 const auto& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil();
78 renderPass_ = renderNodeUtil.CreateRenderPass(inputRenderPass_);
79
80 pipelineLayout_ = renderNodeUtil.CreatePipelineLayout(shader_);
81 {
82 const DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
83 renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(dc);
84 }
85
86 pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
87 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
88 }
89
ExecuteFrame(IRenderCommandList & cmdList)90 void RenderNodeBackBuffer::ExecuteFrame(IRenderCommandList& cmdList)
91 {
92 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
93 const PostProcessConfiguration ppConfig = GetPostProcessConfiguration(renderDataStoreMgr);
94
95 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
96 if (jsonInputs_.hasChangeableRenderPassHandles) {
97 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
98 }
99 if (jsonInputs_.hasChangeableResourceHandles) {
100 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
101 renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
102 }
103
104 // Size update mut be done before specialization
105 const RenderHandle dstImageHandle = UpdateColorAttachmentSize();
106
107 CheckForPsoSpecilization(ppConfig);
108
109 for (auto refIndex : pipelineDescriptorSetBinder_->GetSetIndices()) {
110 const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
111 const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
112 cmdList.UpdateDescriptorSet(descHandle, bindings);
113 }
114
115 cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
116 cmdList.BindPipeline(psoHandle_);
117
118 // bind all sets
119 cmdList.BindDescriptorSets(0, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
120
121 // dynamic state
122 cmdList.SetDynamicStateViewport(currentViewportDesc_);
123 cmdList.SetDynamicStateScissor(currentScissorDesc_);
124
125 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
126 const GpuImageDesc dstImageDesc = gpuResourceMgr.GetImageDescriptor(dstImageHandle);
127
128 if (pipelineLayout_.pushConstant.byteSize > 0) {
129 const PostProcessTonemapStruct pushData =
130 FillPushConstant(dstImageDesc, currentRenderPostProcessConfiguration_);
131 cmdList.PushConstant(pipelineLayout_.pushConstant, reinterpret_cast<const uint8_t*>(&pushData));
132 }
133
134 cmdList.Draw(3u, 1u, 0u, 0u); // vertexCount 3, drawing one triangle
135 cmdList.EndRenderPass();
136 }
137
CheckForPsoSpecilization(const PostProcessConfiguration & postProcessConfiguration)138 void RenderNodeBackBuffer::CheckForPsoSpecilization(const PostProcessConfiguration& postProcessConfiguration)
139 {
140 const RenderPostProcessConfiguration renderPostProcessConfiguration =
141 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(postProcessConfiguration);
142 if (!RenderHandleUtil::IsValid(psoHandle_)) {
143 auto& psoMgr = renderNodeContextMgr_->GetPsoManager();
144 const DynamicStateFlags dynamicStateFlags =
145 DynamicStateFlagBits::CORE_DYNAMIC_STATE_VIEWPORT | DynamicStateFlagBits::CORE_DYNAMIC_STATE_SCISSOR;
146 const RenderHandle graphicsState =
147 renderNodeContextMgr_->GetShaderManager().GetGraphicsStateHandleByShaderHandle(shader_);
148 psoHandle_ = psoMgr.GetGraphicsPsoHandle(shader_, graphicsState, pipelineLayout_, {}, {}, dynamicStateFlags);
149 }
150
151 // store new values
152 currentRenderPostProcessConfiguration_ = renderPostProcessConfiguration;
153 }
154
GetPostProcessConfiguration(const IRenderNodeRenderDataStoreManager & dataStoreMgr)155 PostProcessConfiguration RenderNodeBackBuffer::GetPostProcessConfiguration(
156 const IRenderNodeRenderDataStoreManager& dataStoreMgr)
157 {
158 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
159 auto const dataStore = static_cast<IRenderDataStorePod const*>(
160 dataStoreMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName));
161 if (dataStore) {
162 auto const dataView = dataStore->Get(jsonInputs_.renderDataStore.configurationName);
163 const PostProcessConfiguration* data = (const PostProcessConfiguration*)dataView.data();
164 if (data) {
165 return *data;
166 }
167 }
168 }
169 return {};
170 }
171
UpdateColorAttachmentSize()172 RenderHandle RenderNodeBackBuffer::UpdateColorAttachmentSize()
173 {
174 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
175 RenderHandle dstImageHandle;
176 if (!inputRenderPass_.attachments.empty()) {
177 dstImageHandle = inputRenderPass_.attachments[0].handle;
178
179 const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(inputRenderPass_.attachments[0].handle);
180 if (desc.width != currentBackBuffer_.width || desc.height != currentBackBuffer_.height ||
181 desc.format != currentBackBuffer_.format) {
182 currentBackBuffer_.width = desc.width;
183 currentBackBuffer_.height = desc.height;
184 currentBackBuffer_.format = desc.format;
185
186 // re-create render pass (swapchain/backbuffer size may have changed)
187 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
188 renderPass_ = renderNodeUtil.CreateRenderPass(inputRenderPass_);
189
190 currentViewportDesc_.x = 0.0f;
191 currentViewportDesc_.y = 0.0f;
192 currentViewportDesc_.width = static_cast<float>(currentBackBuffer_.width);
193 currentViewportDesc_.height = static_cast<float>(currentBackBuffer_.height);
194
195 currentScissorDesc_.offsetX = 0;
196 currentScissorDesc_.offsetY = 0;
197 currentScissorDesc_.extentWidth = currentBackBuffer_.width;
198 currentScissorDesc_.extentHeight = currentBackBuffer_.height;
199 }
200 }
201 return dstImageHandle;
202 }
203
ParseRenderNodeInputs()204 void RenderNodeBackBuffer::ParseRenderNodeInputs()
205 {
206 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
207 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
208 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
209 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
210 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
211
212 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
213 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
214 shader_ = shaderMgr.GetShaderHandle(shaderName);
215
216 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
217 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
218 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
219
220 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
221 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
222 }
223
224 // for plugin / factory interface
Create()225 IRenderNode* RenderNodeBackBuffer::Create()
226 {
227 return new RenderNodeBackBuffer();
228 }
229
Destroy(IRenderNode * instance)230 void RenderNodeBackBuffer::Destroy(IRenderNode* instance)
231 {
232 delete static_cast<RenderNodeBackBuffer*>(instance);
233 }
234 RENDER_END_NAMESPACE()
235