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