• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef RENDER_NODECONTEXT_NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
17 #define RENDER_NODECONTEXT_NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
18 
19 #include <cstdint>
20 #include <shared_mutex>
21 
22 #include <base/containers/string.h>
23 #include <base/containers/unordered_map.h>
24 #include <base/containers/vector.h>
25 #include <render/device/pipeline_layout_desc.h>
26 #include <render/namespace.h>
27 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
28 #include <render/resource_handle.h>
29 
30 #include "device/gpu_resource_handle_util.h"
31 
32 RENDER_BEGIN_NAMESPACE()
33 class Device;
34 class IDescriptorSetBinder;
35 class IPipelineDescriptorSetBinder;
36 
37 struct DynamicOffsetDescriptors {
38     BASE_NS::array_view<const RenderHandle> resources;
39 };
40 
41 struct BufferDescriptorHandler {
42     BufferDescriptor desc;
43     // fetched and compared for possibly needed changes
44     EngineResourceHandle handle;
45 };
46 
47 struct ImageDescriptorHandler {
48     ImageDescriptor desc;
49     // fetched and compared for possibly needed changes
50     EngineResourceHandle handle;
51     EngineResourceHandle samplerHandle;
52 };
53 
54 struct SamplerDescriptorHandler {
55     SamplerDescriptor desc;
56     // fetched and compared for possibly needed changes
57     EngineResourceHandle handle;
58 };
59 
60 /** Descriptor set layout binding resources */
61 struct DescriptorSetLayoutBindingResourcesHandler {
62     /** Bindings */
63     BASE_NS::array_view<const DescriptorSetLayoutBindingResource> bindings;
64 
65     /** Buffer descriptors */
66     BASE_NS::array_view<const BufferDescriptorHandler> buffers;
67     /** Image descriptors */
68     BASE_NS::array_view<const ImageDescriptorHandler> images;
69     /** Sampler descriptors */
70     BASE_NS::array_view<const SamplerDescriptorHandler> samplers;
71 
72     /** Mask of bindings in the descriptor set. Max uint is value which means that not set */
73     uint32_t descriptorSetBindingMask { ~0u };
74     /** Current binding mask. Max uint is value which means that not set */
75     uint32_t bindingMask { ~0u };
76 };
77 
78 struct CpuDescriptorSet {
79     uint32_t currentGpuBufferingIndex { 0 };
80     bool gpuDescriptorSetCreated { false };
81     bool isDirty { false };
82     bool hasDynamicBarrierResources { false };
83     bool hasPlatformConversionBindings { false }; // e.g. hwbuffers with ycbcr / OES
84     bool hasImmutableSamplers { false };
85 
86     BASE_NS::vector<DescriptorSetLayoutBindingResource> bindings;
87 
88     BASE_NS::vector<BufferDescriptorHandler> buffers;
89     BASE_NS::vector<ImageDescriptorHandler> images;
90     BASE_NS::vector<SamplerDescriptorHandler> samplers;
91 
92     // gpu buffers with dynamic offsets
93     BASE_NS::vector<RenderHandle> dynamicOffsetDescriptors;
94 };
95 
96 // storage counts
97 struct LowLevelDescriptorCounts {
98     uint32_t writeDescriptorCount { 0u };
99     uint32_t bufferCount { 0u };
100     uint32_t imageCount { 0u };
101     uint32_t samplerCount { 0u };
102     uint32_t accelCount { 0u };
103 };
104 
105 enum DescriptorSetUpdateInfoFlagBits {
106     // invalid handles etc.
107     DESCRIPTOR_SET_UPDATE_INFO_INVALID_BIT = (1 << 0),
108     // new handles -> needs real update
109     DESCRIPTOR_SET_UPDATE_INFO_NEW_BIT = (1 << 1),
110 };
111 using DescriptorSetUpdateInfoFlags = uint32_t;
112 
113 /**
114  * Global descriptor set manager
115  * NOTE: The global descriptor sets are still updated through different NodeContextDescriptorSetManager s
116  */
117 class DescriptorSetManager {
118 public:
119     explicit DescriptorSetManager(Device& device);
120     virtual ~DescriptorSetManager() = default;
121 
122     virtual void BeginFrame();
123 
124     void LockFrameCreation();
125 
126     BASE_NS::vector<RenderHandleReference> CreateDescriptorSets(const BASE_NS::string_view name,
127         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings, const uint32_t count);
128     RenderHandleReference CreateDescriptorSet(const BASE_NS::string_view name,
129         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings);
130 
131     // get one
132     RenderHandle GetDescriptorSetHandle(const BASE_NS::string_view name) const;
133     // get all descriptor sets defined with this name
134     BASE_NS::array_view<const RenderHandle> GetDescriptorSetHandles(const BASE_NS::string_view name) const;
135 
136     CpuDescriptorSet* GetCpuDescriptorSet(const RenderHandle& handle);
137     DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetData(const RenderHandle& handle);
138     DynamicOffsetDescriptors GetDynamicOffsetDescriptors(const RenderHandle& handle);
139     bool HasDynamicBarrierResources(const RenderHandle& handle);
140     uint32_t GetDynamicOffsetDescriptorCount(const RenderHandle& handle);
141 
142     // Will mark the descriptor set write locked for this frame (no one else can write)
143     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSet(const RenderHandle& handle,
144         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue);
145     // platform
146     virtual void UpdateDescriptorSetGpuHandle(const RenderHandle& handle) = 0;
147     virtual void UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources) = 0;
148 
149     // get all updated handles this frame
150     BASE_NS::array_view<const RenderHandle> GetUpdateDescriptorSetHandles() const;
151 
152     class LowLevelDescriptorSetData {
153     public:
154         LowLevelDescriptorSetData() = default;
155         virtual ~LowLevelDescriptorSetData() = default;
156 
157         LowLevelDescriptorSetData(const LowLevelDescriptorSetData&) = delete;
158         LowLevelDescriptorSetData& operator=(const LowLevelDescriptorSetData&) = delete;
159     };
160 
161     struct GlobalDescriptorSetData {
162         // should only be updated from a single place per frame
163         bool frameWriteLocked { false };
164         CpuDescriptorSet cpuDescriptorSet;
165         RenderHandleReference renderHandleReference;
166     };
167     struct GlobalDescriptorSetBase {
168         // handles are separated for direct array_view usage
169         BASE_NS::vector<RenderHandle> handles;
170         BASE_NS::vector<GlobalDescriptorSetData> data;
171         BASE_NS::string name;
172     };
173 
174 protected:
175     // platform
176     virtual void CreateDescriptorSets(const uint32_t arrayIndex, const uint32_t descriptorSetCount,
177         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) = 0;
178 
179     Device& device_;
180 
181     // NOTE: does not need mutuxes at the moment
182     // creation happens only in render nodes init or preexecute
183     BASE_NS::vector<BASE_NS::unique_ptr<GlobalDescriptorSetBase>> descriptorSets_;
184     BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex_;
185 
186     BASE_NS::vector<RenderHandle> availableHandles_;
187 
188     // all handles this frame which should be updated (needs to be locked when accessed)
189     BASE_NS::vector<RenderHandle> descriptorSetHandlesForUpdate_;
190 
191     // lock creation after pre execute done for render nodes
192     bool creationLocked_ { true };
193 
194     // used to lock shared data which could be accessed from multiple threads
195     mutable std::shared_mutex mutex_;
196 };
197 
198 /**
199 class NodeContextDescriptorSetManager.
200 */
201 class NodeContextDescriptorSetManager : public INodeContextDescriptorSetManager {
202 public:
203     explicit NodeContextDescriptorSetManager(Device& device);
204     ~NodeContextDescriptorSetManager() override = default;
205 
IsDynamicDescriptor(const DescriptorType descType)206     static constexpr inline bool IsDynamicDescriptor(const DescriptorType descType)
207     {
208         return ((descType == DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
209                 (descType == DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC));
210     }
211 
GetCpuDescriptorSetIndex(const RenderHandle & handle)212     static constexpr inline uint32_t GetCpuDescriptorSetIndex(const RenderHandle& handle)
213     {
214         const uint32_t addBits = RenderHandleUtil::GetAdditionalData(handle);
215         if (addBits & NodeContextDescriptorSetManager::ONE_FRAME_DESC_SET_BIT) {
216             return NodeContextDescriptorSetManager::DescriptorSetIndexType::DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME;
217         } else if (addBits & NodeContextDescriptorSetManager::GLOBAL_DESCRIPTOR_BIT) {
218             return ~0U; // invalid
219         } else {
220             return NodeContextDescriptorSetManager::DescriptorSetIndexType::DESCRIPTOR_SET_INDEX_TYPE_STATIC;
221         }
222     }
223 
224     // static helper function
225     static void IncreaseDescriptorSetCounts(const DescriptorSetLayoutBinding& refBinding,
226         LowLevelDescriptorCounts& descSetCounts, uint32_t& dynamicOffsetCount);
227 
228     void ResetAndReserve(const DescriptorCounts& descriptorCounts) override;
229     void ResetAndReserve(const BASE_NS::array_view<DescriptorCounts> descriptorCounts) override;
230 
231     virtual RenderHandle CreateDescriptorSet(
232         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
233     BASE_NS::vector<RenderHandle> CreateDescriptorSets(
234         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
235     RenderHandle CreateDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
236 
237     IDescriptorSetBinder::Ptr CreateDescriptorSetBinder(const RenderHandle handle,
238         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
239     IDescriptorSetBinder::Ptr CreateDescriptorSetBinder(
240         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
241 
242     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout) override;
243     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout,
244         const BASE_NS::array_view<const RenderHandle> handles,
245         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
246 
247     virtual RenderHandle CreateOneFrameDescriptorSet(
248         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
249     virtual BASE_NS::vector<RenderHandle> CreateOneFrameDescriptorSets(
250         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
251     virtual RenderHandle CreateOneFrameDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
252 
253     RenderHandleReference CreateGlobalDescriptorSet(const BASE_NS::string_view name,
254         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
255     BASE_NS::vector<RenderHandleReference> CreateGlobalDescriptorSets(const BASE_NS::string_view name,
256         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings,
257         const uint32_t descriptorSetCount) override;
258     RenderHandle GetGlobalDescriptorSet(const BASE_NS::string_view name) const override;
259     BASE_NS::array_view<const RenderHandle> GetGlobalDescriptorSets(const BASE_NS::string_view name) const override;
260 
261     DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetData(const RenderHandle handle) const;
262     DynamicOffsetDescriptors GetDynamicOffsetDescriptors(const RenderHandle handle) const;
263 
264     virtual void BeginFrame();
265 
266     // information for barrier creation what kind of descriptors does the descriptor set contain
267     // if returns false -> no need for barriers and/or layout changes
268     bool HasDynamicBarrierResources(const RenderHandle handle) const;
269     // count of dynamic offset needed when binding descriptor set
270     uint32_t GetDynamicOffsetDescriptorCount(const RenderHandle handle) const;
271 
272     // update descriptor sets for cpu data (adds correct gpu queue as well)
273     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSet(const RenderHandle handle,
274         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue);
275     // call from backend before actual graphics api updateDescriptorset()
276     // advances the gpu handle to the next available descriptor set (ring buffer)
277     virtual void UpdateDescriptorSetGpuHandle(const RenderHandle handle) = 0;
278     // platform specific updates
279     virtual void UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources) = 0;
280 
281 #if (RENDER_VALIDATION_ENABLED == 1)
282     struct DescriptorCountValidation {
283         BASE_NS::unordered_map<uint32_t, int32_t> typeToCount;
284     };
285 #endif
286 #if ((RENDER_VALIDATION_ENABLED == 1) || (RENDER_VULKAN_VALIDATION_ENABLED == 1))
287     void SetValidationDebugName(const BASE_NS::string_view debugName);
288 #endif
289 
290     static constexpr uint32_t ONE_FRAME_DESC_SET_BIT { 1U << 0U };
291     static constexpr uint32_t GLOBAL_DESCRIPTOR_BIT { 1U << 1U };
292 
293     enum DescriptorSetIndexType : uint8_t {
294         DESCRIPTOR_SET_INDEX_TYPE_STATIC = 0,
295         DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME,
296         DESCRIPTOR_SET_INDEX_TYPE_COUNT,
297     };
298 
299 protected:
300     NodeContextDescriptorSetManager() = delete;
301     Device& device_;
302 
303     BASE_NS::vector<CpuDescriptorSet> cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_COUNT];
304 
305     uint32_t maxSets_ { 0 };
306     // indicates if there are some sets updated on CPU which have platfrom conversion bindings
307     bool hasPlatformConversionBindings_ { false };
308 
309     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSetImpl(const uint32_t index,
310         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue,
311         BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSets);
312     static DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetDataImpl(
313         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
314     static DynamicOffsetDescriptors GetDynamicOffsetDescriptorsImpl(
315         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
316     static bool HasDynamicBarrierResourcesImpl(
317         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
318     static uint32_t GetDynamicOffsetDescriptorCountImpl(
319         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
320 
321     BASE_NS::string debugName_;
322     DescriptorSetManager& globalDescriptorSetMgr_;
323 
324 private:
325 #if (RENDER_VALIDATION_ENABLED == 1)
326     DescriptorCountValidation descriptorCountValidation_;
327 #endif
328 };
329 RENDER_END_NAMESPACE()
330 
331 #endif // CORE__RENDER__NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
332