• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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) const;
137     DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetData(const RenderHandle& handle) const;
138     DynamicOffsetDescriptors GetDynamicOffsetDescriptors(const RenderHandle& handle) const;
139     bool HasDynamicBarrierResources(const RenderHandle& handle) const;
140     uint32_t GetDynamicOffsetDescriptorCount(const RenderHandle& handle) const;
141 
142     bool HasPlatformConversionBindings(const RenderHandle& handle) const;
143 
144     // Will mark the descriptor set write locked for this frame (no one else can write)
145     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSet(const RenderHandle& handle,
146         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue);
147     // platform
148     virtual bool UpdateDescriptorSetGpuHandle(const RenderHandle& handle) = 0;
149     virtual void UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources) = 0;
150 
151     // get all updated handles this frame
152     BASE_NS::array_view<const RenderHandle> GetUpdateDescriptorSetHandles() const;
153 
154     class LowLevelDescriptorSetData {
155     public:
156         LowLevelDescriptorSetData() = default;
157         virtual ~LowLevelDescriptorSetData() = default;
158 
159         LowLevelDescriptorSetData(const LowLevelDescriptorSetData&) = delete;
160         LowLevelDescriptorSetData& operator=(const LowLevelDescriptorSetData&) = delete;
161     };
162 
163     struct GlobalDescriptorSetData {
164         // should only be updated from a single place per frame
165         bool frameWriteLocked { false };
166         CpuDescriptorSet cpuDescriptorSet;
167         RenderHandleReference renderHandleReference;
168     };
169     struct GlobalDescriptorSetBase {
170         // handles are separated for direct array_view usage
171         BASE_NS::vector<RenderHandle> handles;
172         BASE_NS::vector<GlobalDescriptorSetData> data;
173         BASE_NS::string name;
174     };
175 
176 protected:
177     // platform
178     virtual void CreateDescriptorSets(const uint32_t arrayIndex, const uint32_t descriptorSetCount,
179         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) = 0;
180 
181     Device& device_;
182 
183     // NOTE: does not need mutuxes at the moment
184     // creation happens only in render nodes init or preexecute
185     BASE_NS::vector<BASE_NS::unique_ptr<GlobalDescriptorSetBase>> descriptorSets_;
186     BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex_;
187 
188     BASE_NS::vector<RenderHandle> availableHandles_;
189 
190     // all handles this frame which should be updated (needs to be locked when accessed)
191     BASE_NS::vector<RenderHandle> descriptorSetHandlesForUpdate_;
192 
193     // lock creation after pre execute done for render nodes
194     bool creationLocked_ { true };
195 
196     // used to lock shared data which could be accessed from multiple threads
197     mutable std::shared_mutex mutex_;
198 };
199 
200 /**
201 class NodeContextDescriptorSetManager.
202 */
203 class NodeContextDescriptorSetManager : public INodeContextDescriptorSetManager {
204 public:
205     explicit NodeContextDescriptorSetManager(Device& device);
206     ~NodeContextDescriptorSetManager() override = default;
207 
IsDynamicDescriptor(const DescriptorType descType)208     static constexpr inline bool IsDynamicDescriptor(const DescriptorType descType)
209     {
210         return ((descType == DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
211                 (descType == DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC));
212     }
213 
GetCpuDescriptorSetIndex(const RenderHandle & handle)214     static constexpr inline uint32_t GetCpuDescriptorSetIndex(const RenderHandle& handle)
215     {
216         const uint32_t addBits = RenderHandleUtil::GetAdditionalData(handle);
217         if (addBits & NodeContextDescriptorSetManager::ONE_FRAME_DESC_SET_BIT) {
218             return NodeContextDescriptorSetManager::DescriptorSetIndexType::DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME;
219         } else if (addBits & NodeContextDescriptorSetManager::GLOBAL_DESCRIPTOR_BIT) {
220             return ~0U; // invalid
221         } else {
222             return NodeContextDescriptorSetManager::DescriptorSetIndexType::DESCRIPTOR_SET_INDEX_TYPE_STATIC;
223         }
224     }
225 
226     // static helper function
227     static void IncreaseDescriptorSetCounts(const DescriptorSetLayoutBinding& refBinding,
228         LowLevelDescriptorCounts& descSetCounts, uint32_t& dynamicOffsetCount);
229 
230     void ResetAndReserve(const DescriptorCounts& descriptorCounts) override;
231     void ResetAndReserve(const BASE_NS::array_view<DescriptorCounts> descriptorCounts) override;
232 
233     virtual RenderHandle CreateDescriptorSet(
234         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
235     BASE_NS::vector<RenderHandle> CreateDescriptorSets(
236         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
237     RenderHandle CreateDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
238 
239     IDescriptorSetBinder::Ptr CreateDescriptorSetBinder(const RenderHandle handle,
240         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
241     IDescriptorSetBinder::Ptr CreateDescriptorSetBinder(
242         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
243 
244     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout) override;
245     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout,
246         const BASE_NS::array_view<const RenderHandle> handles,
247         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
248 
249     virtual RenderHandle CreateOneFrameDescriptorSet(
250         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
251     virtual BASE_NS::vector<RenderHandle> CreateOneFrameDescriptorSets(
252         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
253     virtual RenderHandle CreateOneFrameDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
254 
255     RenderHandleReference CreateGlobalDescriptorSet(const BASE_NS::string_view name,
256         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
257     BASE_NS::vector<RenderHandleReference> CreateGlobalDescriptorSets(const BASE_NS::string_view name,
258         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings,
259         const uint32_t descriptorSetCount) override;
260     RenderHandle GetGlobalDescriptorSet(const BASE_NS::string_view name) const override;
261     BASE_NS::array_view<const RenderHandle> GetGlobalDescriptorSets(const BASE_NS::string_view name) const override;
262 
263     DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetData(const RenderHandle handle) const;
264     DynamicOffsetDescriptors GetDynamicOffsetDescriptors(const RenderHandle handle) const;
265 
266     virtual void BeginFrame();
267 
268     // information for barrier creation what kind of descriptors does the descriptor set contain
269     // if returns false -> no need for barriers and/or layout changes
270     bool HasDynamicBarrierResources(const RenderHandle handle) const;
271     // count of dynamic offset needed when binding descriptor set
272     uint32_t GetDynamicOffsetDescriptorCount(const RenderHandle handle) const;
273 
274     bool HasPlatformConversionBindings(const RenderHandle handle) const;
275 
276     // update descriptor sets for cpu data (adds correct gpu queue as well)
277     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSet(const RenderHandle handle,
278         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue);
279     // call from backend before actual graphics api updateDescriptorset()
280     // advances the gpu handle to the next available descriptor set (ring buffer)
281     // if returns false, then the update should not be handled in the backend
282     virtual bool UpdateDescriptorSetGpuHandle(const RenderHandle handle) = 0;
283     // platform specific updates
284     virtual void UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources) = 0;
285 
286 #if (RENDER_VALIDATION_ENABLED == 1)
287     struct DescriptorCountValidation {
288         BASE_NS::unordered_map<uint32_t, int32_t> typeToCount;
289     };
290 #endif
291 #if ((RENDER_VALIDATION_ENABLED == 1) || (RENDER_VULKAN_VALIDATION_ENABLED == 1))
292     void SetValidationDebugName(const BASE_NS::string_view debugName);
293 #endif
294 
295     static constexpr uint32_t ONE_FRAME_DESC_SET_BIT { 1U << 0U };
296     static constexpr uint32_t GLOBAL_DESCRIPTOR_BIT { 1U << 1U };
297 
298     enum DescriptorSetIndexType : uint8_t {
299         DESCRIPTOR_SET_INDEX_TYPE_STATIC = 0,
300         DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME,
301         DESCRIPTOR_SET_INDEX_TYPE_COUNT,
302     };
303 
304 protected:
305     NodeContextDescriptorSetManager() = delete;
306     Device& device_;
307 
308     BASE_NS::vector<CpuDescriptorSet> cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_COUNT];
309 
310     uint32_t maxSets_ { 0 };
311     // indicates if there are some sets updated on CPU which have platfrom conversion bindings
312     bool hasPlatformConversionBindings_ { false };
313 
314     DescriptorSetUpdateInfoFlags UpdateCpuDescriptorSetImpl(const uint32_t index,
315         const DescriptorSetLayoutBindingResources& bindingResources, const GpuQueue& gpuQueue,
316         BASE_NS::array_view<CpuDescriptorSet> cpuDescriptorSets);
317     static DescriptorSetLayoutBindingResourcesHandler GetCpuDescriptorSetDataImpl(
318         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
319     static DynamicOffsetDescriptors GetDynamicOffsetDescriptorsImpl(
320         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
321     static bool HasDynamicBarrierResourcesImpl(
322         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
323     static uint32_t GetDynamicOffsetDescriptorCountImpl(
324         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
325     static bool HasPlatformConversionBindingsImpl(
326         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet);
327 
328     BASE_NS::string debugName_;
329     DescriptorSetManager& globalDescriptorSetMgr_;
330 
331 private:
332 #if (RENDER_VALIDATION_ENABLED == 1)
333     DescriptorCountValidation descriptorCountValidation_;
334 #endif
335 };
336 RENDER_END_NAMESPACE()
337 
338 #endif // CORE__RENDER__NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
339