• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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