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