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_util.h"
17
18 #include <algorithm>
19
20 #include <render/device/intf_gpu_resource_manager.h>
21 #include <render/device/intf_shader_manager.h>
22 #include <render/device/pipeline_state_desc.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_node.h>
27 #include <render/nodecontext/intf_render_node_context_manager.h>
28 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
29 #include <render/nodecontext/intf_render_node_util.h>
30
31 #include "device/gpu_resource_handle_util.h"
32 #include "nodecontext/pipeline_descriptor_set_binder.h"
33 #include "util/log.h"
34
35 using namespace BASE_NS;
36
37 RENDER_BEGIN_NAMESPACE()
38 namespace {
GetRoutedResource(const IRenderNodeGpuResourceManager & gpuResourceMgr,const IRenderNodeGraphShareManager & rngShareMgr,const RenderDataConstants::RenderDataFixedString & name,const RenderDataConstants::RenderDataFixedString & nodeName,const RenderNodeGraphResourceLocationType resourceLocation,const uint32_t resourceIndex,const RenderHandleType handleType)39 RenderHandle GetRoutedResource(const IRenderNodeGpuResourceManager& gpuResourceMgr,
40 const IRenderNodeGraphShareManager& rngShareMgr, const RenderDataConstants::RenderDataFixedString& name,
41 const RenderDataConstants::RenderDataFixedString& nodeName,
42 const RenderNodeGraphResourceLocationType resourceLocation, const uint32_t resourceIndex,
43 const RenderHandleType handleType)
44 {
45 RenderHandle handle;
46 switch (resourceLocation) {
47 case (RenderNodeGraphResourceLocationType::DEFAULT):
48 if (handleType == RenderHandleType::GPU_BUFFER) {
49 handle = gpuResourceMgr.GetBufferHandle(name);
50 } else if (handleType == RenderHandleType::GPU_IMAGE) {
51 handle = gpuResourceMgr.GetImageHandle(name);
52 } else {
53 handle = gpuResourceMgr.GetSamplerHandle(name);
54 }
55 break;
56 case (RenderNodeGraphResourceLocationType::FROM_RENDER_GRAPH_INPUT):
57 handle = rngShareMgr.GetRenderNodeGraphInput(resourceIndex);
58 break;
59 case (RenderNodeGraphResourceLocationType::FROM_RENDER_GRAPH_OUTPUT):
60 handle = rngShareMgr.GetRenderNodeGraphOutput(resourceIndex);
61 break;
62 case (RenderNodeGraphResourceLocationType::FROM_PREVIOUS_RENDER_NODE_OUTPUT):
63 handle = rngShareMgr.GetRegisteredPrevRenderNodeOutput(resourceIndex);
64 break;
65 case (RenderNodeGraphResourceLocationType::FROM_NAMED_RENDER_NODE_OUTPUT):
66 if (!name.empty()) {
67 handle = rngShareMgr.GetRegisteredRenderNodeOutput(nodeName, name);
68 } else {
69 handle = rngShareMgr.GetRegisteredRenderNodeOutput(nodeName, resourceIndex);
70 }
71 break;
72 default:
73 break;
74 }
75 #if (RENDER_VALIDATION_ENABLED == 1)
76 if (!RenderHandleUtil::IsValid(handle)) {
77 PLUGIN_LOG_ONCE_W(string(nodeName + name),
78 "RENDER_VALIDATION: named render node GPU resource handle not found (name:%s) (type:%u)", name.c_str(),
79 static_cast<uint32_t>(handleType));
80 }
81 #endif
82 return handle;
83 }
84
SetupRenderNodeResourceHandles(const IRenderNodeGpuResourceManager & gpuResourceMgr,const IRenderNodeGraphShareManager & rngShareMgr,const RenderNodeGraphInputs::InputResources & resources,RenderNodeHandles::InputResources & res)85 void SetupRenderNodeResourceHandles(const IRenderNodeGpuResourceManager& gpuResourceMgr,
86 const IRenderNodeGraphShareManager& rngShareMgr, const RenderNodeGraphInputs::InputResources& resources,
87 RenderNodeHandles::InputResources& res)
88 {
89 const auto setHandles = [](const IRenderNodeGpuResourceManager& gpuResourceMgr,
90 const IRenderNodeGraphShareManager& rngShareMgr, const RenderHandleType handleType,
91 const auto& input, auto& output) {
92 output.reserve(input.size());
93 for (const auto& ref : input) {
94 const RenderHandle handle = GetRoutedResource(gpuResourceMgr, rngShareMgr, ref.name, ref.nodeName,
95 ref.resourceLocation, ref.resourceIndex, handleType);
96 output.emplace_back(RenderNodeResource { ref.set, ref.binding, handle, {} });
97 }
98 };
99 const auto setImageHandles = [](const IRenderNodeGpuResourceManager& gpuResourceMgr,
100 const IRenderNodeGraphShareManager& rngShareMgr,
101 vector<RenderNodeResource>& optionalSamplers, auto& input, auto& output) {
102 output.reserve(input.size());
103 for (const auto& ref : input) {
104 const RenderHandle handle = GetRoutedResource(gpuResourceMgr, rngShareMgr, ref.name, ref.nodeName,
105 ref.resourceLocation, ref.resourceIndex, RenderHandleType::GPU_IMAGE);
106 RenderHandle secondHandle;
107 for (auto sampIter = optionalSamplers.begin(); sampIter != optionalSamplers.end();) {
108 if ((sampIter->set == ref.set) && (sampIter->binding == ref.binding)) {
109 secondHandle = sampIter->handle;
110 optionalSamplers.erase(sampIter);
111 } else {
112 sampIter++;
113 }
114 }
115 output.emplace_back(RenderNodeResource { ref.set, ref.binding, handle, secondHandle });
116 }
117 };
118
119 setHandles(gpuResourceMgr, rngShareMgr, RenderHandleType::GPU_BUFFER, resources.buffers, res.buffers);
120 setHandles(gpuResourceMgr, rngShareMgr, RenderHandleType::GPU_SAMPLER, resources.samplers, res.samplers);
121 // loops through samplers for possible combined image sampler (this method is usually only called in
122 // RenderNodeInit())
123 // If found, moves the sampler handle from res.samplers to res.images.secondHandle
124 setImageHandles(gpuResourceMgr, rngShareMgr, res.samplers, resources.images, res.images);
125
126 setHandles(gpuResourceMgr, rngShareMgr, RenderHandleType::GPU_BUFFER, resources.customInputBuffers,
127 res.customInputBuffers);
128 setHandles(gpuResourceMgr, rngShareMgr, RenderHandleType::GPU_BUFFER, resources.customOutputBuffers,
129 res.customOutputBuffers);
130
131 vector<RenderNodeResource> sams;
132 setImageHandles(gpuResourceMgr, rngShareMgr, sams, resources.customInputImages, res.customInputImages);
133 setImageHandles(gpuResourceMgr, rngShareMgr, sams, resources.customOutputImages, res.customOutputImages);
134 }
135 } // namespace
136
RenderNodeUtil(IRenderNodeContextManager & renderNodeContextMgr)137 RenderNodeUtil::RenderNodeUtil(IRenderNodeContextManager& renderNodeContextMgr)
138 : renderNodeContextMgr_(renderNodeContextMgr)
139 {}
140
CreateInputRenderPass(const RenderNodeGraphInputs::InputRenderPass & renderPass) const141 RenderNodeHandles::InputRenderPass RenderNodeUtil::CreateInputRenderPass(
142 const RenderNodeGraphInputs::InputRenderPass& renderPass) const
143 {
144 RenderNodeHandles::InputRenderPass rp;
145 const auto& gpuResourceMgr = renderNodeContextMgr_.GetGpuResourceManager();
146 const auto& rngShareMgr = renderNodeContextMgr_.GetRenderNodeGraphShareManager();
147 if (!renderPass.attachments.empty()) {
148 rp.attachments.reserve(renderPass.attachments.size());
149 for (const auto& ref : renderPass.attachments) {
150 const RenderHandle handle = GetRoutedResource(gpuResourceMgr, rngShareMgr, ref.name, ref.nodeName,
151 ref.resourceLocation, ref.resourceIndex, RenderHandleType::GPU_IMAGE);
152 rp.attachments.emplace_back(RenderNodeAttachment {
153 handle, ref.loadOp, ref.storeOp, ref.stencilLoadOp, ref.stencilStoreOp, ref.clearValue });
154 }
155
156 rp.subpassIndex = renderPass.subpassIndex;
157 rp.subpassCount = renderPass.subpassCount;
158
159 rp.depthAttachmentIndex = renderPass.depthAttachmentIndex;
160 rp.depthResolveAttachmentIndex = renderPass.depthResolveAttachmentIndex;
161 rp.inputAttachmentIndices = renderPass.inputAttachmentIndices;
162 rp.colorAttachmentIndices = renderPass.colorAttachmentIndices;
163 rp.resolveAttachmentIndices = renderPass.resolveAttachmentIndices;
164 rp.depthResolveModeFlagBit = renderPass.depthResolveModeFlagBit;
165 rp.stencilResolveModeFlagBit = renderPass.stencilResolveModeFlagBit;
166 }
167
168 return rp;
169 }
170
CreateInputResources(const RenderNodeGraphInputs::InputResources & resources) const171 RenderNodeHandles::InputResources RenderNodeUtil::CreateInputResources(
172 const RenderNodeGraphInputs::InputResources& resources) const
173 {
174 RenderNodeHandles::InputResources res;
175 const auto& gpuResourceMgr = renderNodeContextMgr_.GetGpuResourceManager();
176 const auto& rngShareMgr = renderNodeContextMgr_.GetRenderNodeGraphShareManager();
177 SetupRenderNodeResourceHandles(gpuResourceMgr, rngShareMgr, resources, res);
178 return res;
179 }
180
CreatePipelineLayout(const RenderHandle & shaderHandle) const181 PipelineLayout RenderNodeUtil::CreatePipelineLayout(const RenderHandle& shaderHandle) const
182 {
183 const auto& shaderMgr = renderNodeContextMgr_.GetShaderManager();
184 RenderHandle plHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(shaderHandle);
185 if (RenderHandleUtil::IsValid(plHandle)) {
186 return shaderMgr.GetPipelineLayout(plHandle);
187 } else {
188 return shaderMgr.GetReflectionPipelineLayout(shaderHandle);
189 }
190 }
191
CreatePipelineDescriptorSetBinder(const PipelineLayout & pipelineLayout) const192 IPipelineDescriptorSetBinder::Ptr RenderNodeUtil::CreatePipelineDescriptorSetBinder(
193 const PipelineLayout& pipelineLayout) const
194 {
195 auto& descriptorSetMgr = renderNodeContextMgr_.GetDescriptorSetManager();
196 return descriptorSetMgr.CreatePipelineDescriptorSetBinder(pipelineLayout);
197 }
198
BindResourcesToBinder(const RenderNodeHandles::InputResources & resources,IPipelineDescriptorSetBinder & pipelineDescriptorSetBinder) const199 void RenderNodeUtil::BindResourcesToBinder(
200 const RenderNodeHandles::InputResources& resources, IPipelineDescriptorSetBinder& pipelineDescriptorSetBinder) const
201 {
202 pipelineDescriptorSetBinder.ClearBindings();
203 for (const auto& ref : resources.buffers) {
204 BindableBuffer bindable;
205 bindable.handle = ref.handle;
206 pipelineDescriptorSetBinder.BindBuffer(ref.set, ref.binding, bindable);
207 }
208 for (const auto& ref : resources.images) {
209 BindableImage bindable;
210 bindable.handle = ref.handle;
211 bindable.samplerHandle = ref.secondHandle; // might be combined image sampler if valid handle
212 pipelineDescriptorSetBinder.BindImage(ref.set, ref.binding, bindable);
213 }
214 for (const auto& ref : resources.samplers) {
215 BindableSampler bindable;
216 bindable.handle = ref.handle;
217 pipelineDescriptorSetBinder.BindSampler(ref.set, ref.binding, bindable);
218 }
219 }
220
GetDescriptorCounts(const PipelineLayout & pipelineLayout) const221 DescriptorCounts RenderNodeUtil::GetDescriptorCounts(const PipelineLayout& pipelineLayout) const
222 {
223 DescriptorCounts dc;
224 for (uint32_t setIdx = 0; setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++setIdx) {
225 const auto& setRef = pipelineLayout.descriptorSetLayouts[setIdx];
226 if (setRef.set == PipelineLayoutConstants::INVALID_INDEX) {
227 continue;
228 }
229 dc.counts.reserve(setRef.bindings.size());
230 for (const auto& bindingRef : setRef.bindings) {
231 dc.counts.emplace_back(
232 DescriptorCounts::TypedCount { bindingRef.descriptorType, bindingRef.descriptorCount });
233 }
234 }
235 return dc;
236 }
237
CreateRenderPass(const RenderNodeHandles::InputRenderPass & renderPass) const238 RenderPass RenderNodeUtil::CreateRenderPass(const RenderNodeHandles::InputRenderPass& renderPass) const
239 {
240 RenderPass rp;
241 RenderPassDesc& rpDesc = rp.renderPassDesc;
242
243 const uint32_t attachmentCount = (uint32_t)renderPass.attachments.size();
244 PLUGIN_ASSERT(attachmentCount <= PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT);
245 uint32_t width = ~0u;
246 uint32_t height = ~0u;
247 if (attachmentCount > 0) {
248 rp.renderPassDesc.attachmentCount = attachmentCount;
249 for (size_t idx = 0; idx < renderPass.attachments.size(); ++idx) {
250 const auto& ref = renderPass.attachments[idx];
251 rpDesc.attachments[idx] = { 0, 0, ref.loadOp, ref.storeOp, ref.stencilLoadOp, ref.stencilStoreOp,
252 ref.clearValue };
253 rpDesc.attachmentHandles[idx] = ref.handle;
254 if (idx == 0) { // optimization, width and height must match (will end in error later)
255 const GpuImageDesc desc = renderNodeContextMgr_.GetGpuResourceManager().GetImageDescriptor(ref.handle);
256 width = desc.width;
257 height = desc.height;
258 }
259 }
260
261 rpDesc.subpassCount = renderPass.subpassCount;
262 if (renderPass.subpassIndex >= renderPass.subpassCount) {
263 PLUGIN_LOG_E("Render pass subpass idx < count (%u < %u)", renderPass.subpassIndex, renderPass.subpassCount);
264 }
265 if (renderPass.subpassIndex < renderPass.subpassCount) {
266 rp.subpassStartIndex = renderPass.subpassIndex;
267 // update the one subpass described in render node graph
268 auto& spDesc = rp.subpassDesc;
269
270 spDesc.inputAttachmentCount = (uint32_t)renderPass.inputAttachmentIndices.size();
271 spDesc.colorAttachmentCount = (uint32_t)renderPass.colorAttachmentIndices.size();
272 spDesc.resolveAttachmentCount = (uint32_t)renderPass.resolveAttachmentIndices.size();
273
274 spDesc.depthAttachmentCount = (renderPass.depthAttachmentIndex != ~0u) ? 1u : 0u;
275 spDesc.depthAttachmentIndex = (spDesc.depthAttachmentCount > 0) ? renderPass.depthAttachmentIndex : 0u;
276 spDesc.depthResolveAttachmentCount = (renderPass.depthResolveAttachmentIndex != ~0u) ? 1u : 0u;
277 spDesc.depthResolveAttachmentIndex =
278 (spDesc.depthResolveAttachmentCount > 0) ? renderPass.depthResolveAttachmentIndex : 0u;
279 spDesc.depthResolveModeFlagBit = renderPass.depthResolveModeFlagBit;
280 spDesc.stencilResolveModeFlagBit = renderPass.stencilResolveModeFlagBit;
281
282 for (uint32_t idx = 0; idx < spDesc.inputAttachmentCount; ++idx) {
283 spDesc.inputAttachmentIndices[idx] = renderPass.inputAttachmentIndices[idx];
284 }
285 for (uint32_t idx = 0; idx < spDesc.colorAttachmentCount; ++idx) {
286 spDesc.colorAttachmentIndices[idx] = renderPass.colorAttachmentIndices[idx];
287 }
288 for (uint32_t idx = 0; idx < spDesc.resolveAttachmentCount; ++idx) {
289 spDesc.resolveAttachmentIndices[idx] = renderPass.resolveAttachmentIndices[idx];
290 }
291 }
292 }
293 rpDesc.renderArea = { 0, 0, width, height };
294
295 return rp;
296 }
297
CreateDefaultViewport(const RenderPass & renderPass) const298 ViewportDesc RenderNodeUtil::CreateDefaultViewport(const RenderPass& renderPass) const
299 {
300 return ViewportDesc {
301 0.0f,
302 0.0f,
303 static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth),
304 static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight),
305 0.0f,
306 1.0f,
307 };
308 }
309
CreateDefaultScissor(const RenderPass & renderPass) const310 ScissorDesc RenderNodeUtil::CreateDefaultScissor(const RenderPass& renderPass) const
311 {
312 return ScissorDesc {
313 0,
314 0,
315 renderPass.renderPassDesc.renderArea.extentWidth,
316 renderPass.renderPassDesc.renderArea.extentHeight,
317 };
318 }
319
GetRenderPostProcessConfiguration(const PostProcessConfiguration & input) const320 RenderPostProcessConfiguration RenderNodeUtil::GetRenderPostProcessConfiguration(
321 const PostProcessConfiguration& input) const
322 {
323 RenderPostProcessConfiguration output;
324 std::fill(output.factors, output.factors + PostProcessConfiguration::INDEX_FACTOR_COUNT,
325 Math::Vec4 { 0.0f, 0.0f, 0.0f, 0.0f });
326
327 output.flags = { input.enableFlags, 0, 0, 0 };
328 output.renderTimings = renderNodeContextMgr_.GetRenderNodeGraphData().renderingConfiguration.renderTimings;
329 output.factors[PostProcessConfiguration::INDEX_TONEMAP] = { input.tonemapConfiguration.exposure, 0.0f, 0.0f,
330 static_cast<float>(input.tonemapConfiguration.tonemapType) };
331 output.factors[PostProcessConfiguration::INDEX_VIGNETTE] = { input.vignetteConfiguration.coefficient,
332 input.vignetteConfiguration.power, 0.0f, 0.0f };
333 output.factors[PostProcessConfiguration::INDEX_DITHER] = { input.ditherConfiguration.amountCoefficient, 0, 0,
334 static_cast<float>(input.ditherConfiguration.ditherType) };
335 output.factors[PostProcessConfiguration::INDEX_COLOR_CONVERSION] = { 0.0f, 0.0f, 0.0f,
336 static_cast<float>(input.colorConversionConfiguration.conversionFunctionType) };
337 output.factors[PostProcessConfiguration::INDEX_COLOR_FRINGE] = { input.colorFringeConfiguration.coefficient,
338 input.colorFringeConfiguration.distanceCoefficient, 0.0f, 0.0f };
339
340 output.factors[PostProcessConfiguration::INDEX_BLUR] = { static_cast<float>(input.blurConfiguration.blurType),
341 static_cast<float>(input.blurConfiguration.blurQualityType), input.blurConfiguration.filterSize, 0 };
342 output.factors[PostProcessConfiguration::INDEX_BLOOM] = { input.bloomConfiguration.thresholdHard,
343 input.bloomConfiguration.thresholdSoft, input.bloomConfiguration.amountCoefficient,
344 input.bloomConfiguration.dirtMaskCoefficient };
345
346 output.factors[PostProcessConfiguration::INDEX_FXAA] = { static_cast<float>(input.fxaaConfiguration.sharpness),
347 static_cast<float>(input.fxaaConfiguration.quality), 0.0f, 0.0f };
348 output.factors[PostProcessConfiguration::INDEX_TAA] = { static_cast<float>(input.taaConfiguration.sharpness),
349 static_cast<float>(input.taaConfiguration.quality), 0.0f, 0.0f };
350 return output;
351 }
352
HasChangeableResources(const RenderNodeGraphInputs::InputRenderPass & renderPass) const353 bool RenderNodeUtil::HasChangeableResources(const RenderNodeGraphInputs::InputRenderPass& renderPass) const
354 {
355 bool changeable = false;
356 for (const auto& ref : renderPass.attachments) {
357 if (ref.resourceLocation != RenderNodeGraphResourceLocationType::DEFAULT) {
358 changeable = true;
359 }
360 }
361 return changeable;
362 }
363
HasChangeableResources(const RenderNodeGraphInputs::InputResources & resources) const364 bool RenderNodeUtil::HasChangeableResources(const RenderNodeGraphInputs::InputResources& resources) const
365 {
366 auto HasChangingResources = [](const auto& vec) {
367 bool changeable = false;
368 for (const auto& ref : vec) {
369 if (ref.resourceLocation != RenderNodeGraphResourceLocationType::DEFAULT) {
370 changeable = true;
371 }
372 }
373 return changeable;
374 };
375 bool changeable = false;
376 changeable = changeable || HasChangingResources(resources.buffers);
377 changeable = changeable || HasChangingResources(resources.images);
378 changeable = changeable || HasChangingResources(resources.samplers);
379 changeable = changeable || HasChangingResources(resources.customInputBuffers);
380 changeable = changeable || HasChangingResources(resources.customOutputBuffers);
381 changeable = changeable || HasChangingResources(resources.customInputImages);
382 changeable = changeable || HasChangingResources(resources.customOutputImages);
383 return changeable;
384 }
385 RENDER_END_NAMESPACE()
386