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_RENDER__NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
17 #define RENDER_RENDER__NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
18 
19 #include <cstdint>
20 
21 #include <base/containers/string.h>
22 #include <base/containers/unordered_map.h>
23 #include <base/containers/vector.h>
24 #include <render/device/pipeline_layout_desc.h>
25 #include <render/namespace.h>
26 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
27 #include <render/resource_handle.h>
28 
29 #include "device/gpu_resource_handle_util.h"
30 
31 RENDER_BEGIN_NAMESPACE()
32 class Device;
33 class IDescriptorSetBinder;
34 class IPipelineDescriptorSetBinder;
35 
36 struct DynamicOffsetDescriptors {
37     BASE_NS::array_view<const RenderHandle> resources;
38 };
39 
40 /**
41 class NodeContextDescriptorSetManager.
42 */
43 class NodeContextDescriptorSetManager : public INodeContextDescriptorSetManager {
44 public:
45     ~NodeContextDescriptorSetManager() override = default;
46 
IsDynamicDescriptor(const DescriptorType descType)47     static constexpr inline bool IsDynamicDescriptor(const DescriptorType descType)
48     {
49         return ((descType == DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
50                 (descType == DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC));
51     }
52 
53     void ResetAndReserve(const DescriptorCounts& descriptorCounts) override;
54     void ResetAndReserve(const BASE_NS::array_view<DescriptorCounts> descriptorCounts) override;
55 
56     virtual RenderHandle CreateDescriptorSet(
57         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
58     BASE_NS::vector<RenderHandle> CreateDescriptorSets(
59         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
60     RenderHandle CreateDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
61 
62     IDescriptorSetBinder::Ptr CreateDescriptorSetBinder(const RenderHandle handle,
63         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override;
64 
65     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout) override;
66     IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout,
67         const BASE_NS::array_view<const RenderHandle> handles,
68         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
69 
70     virtual RenderHandle CreateOneFrameDescriptorSet(
71         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings) override = 0;
72     virtual BASE_NS::vector<RenderHandle> CreateOneFrameDescriptorSets(
73         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings) override;
74     virtual RenderHandle CreateOneFrameDescriptorSet(const uint32_t set, const PipelineLayout& pipelineLayout) override;
75 
76     DescriptorSetLayoutBindingResources GetCpuDescriptorSetData(const RenderHandle handle) const;
77     DynamicOffsetDescriptors GetDynamicOffsetDescriptors(const RenderHandle handle) const;
78 
79     virtual void BeginFrame();
80 
81     // information for barrier creation what kind of descriptors does the descriptor set contain
82     // if returns false -> no need for barriers and/or layout changes
83     bool HasDynamicBarrierResources(const RenderHandle handle) const;
84     // count of dynamic offset needed when binding descriptor set
85     uint32_t GetDynamicOffsetDescriptorCount(const RenderHandle handle) const;
86 
87     // information that this descriptor has a special platform hwbuffer resources bound
88     // they might need some special platform specific handling
89     bool HasPlatformBufferBindings(const RenderHandle handle) const;
90 
91     // update descriptor sets for cpu data (adds correct gpu queue as well)
92     bool UpdateCpuDescriptorSet(const RenderHandle handle, const DescriptorSetLayoutBindingResources& bindingResources,
93         const GpuQueue& gpuQueue);
94     // call from backend before actual graphics api updateDescriptorset()
95     // advances the gpu handle to the next available descriptor set (ring buffer)
96     virtual void UpdateDescriptorSetGpuHandle(const RenderHandle handle) = 0;
97     // platform specific updates
98     virtual void UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources) = 0;
99 
100     struct CpuDescriptorSet {
101         uint32_t currentGpuBufferingIndex { 0 };
102         bool gpuDescriptorSetCreated { false };
103         bool isDirty { false };
104         bool hasDynamicBarrierResources { false };
105         bool hasPlatformConversionBindings { false }; // e.g. hwbuffers with ycbcr / OES
106         bool hasImmutableSamplers { false };
107 
108         BASE_NS::vector<DescriptorSetLayoutBindingResource> bindings;
109 
110         BASE_NS::vector<BufferDescriptor> buffers;
111         BASE_NS::vector<ImageDescriptor> images;
112         BASE_NS::vector<SamplerDescriptor> samplers;
113 
114         // gpu buffers with dynamic offsets
115         BASE_NS::vector<RenderHandle> dynamicOffsetDescriptors;
116     };
117 
118 #if (RENDER_VALIDATION_ENABLED == 1)
119     struct DescriptorCountValidation {
120         BASE_NS::unordered_map<uint32_t, int32_t> typeToCount;
121     };
122 #endif
123 #if ((RENDER_VALIDATION_ENABLED == 1) || (RENDER_VULKAN_VALIDATION_ENABLED == 1))
124     void SetValidationDebugName(const BASE_NS::string_view debugName);
125 #endif
126 protected:
127     static constexpr uint32_t ONE_FRAME_DESC_SET_BIT { 1u };
128     enum DescriptorSetIndexType : uint8_t {
129         DESCRIPTOR_SET_INDEX_TYPE_STATIC = 0,
130         DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME,
131         DESCRIPTOR_SET_INDEX_TYPE_COUNT,
132     };
133 
134     NodeContextDescriptorSetManager() = default;
135     BASE_NS::vector<CpuDescriptorSet> cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_COUNT];
136 
137     uint32_t maxSets_ { 0 };
138     // indicates if there are some sets updated on CPU which have platfrom conversion bindings
139     bool hasPlatformConversionBindings_ { false };
140 
141     bool UpdateCpuDescriptorSetImpl(const uint32_t index, const DescriptorSetLayoutBindingResources& bindingResources,
142         const GpuQueue& gpuQueue, BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSets);
143     DescriptorSetLayoutBindingResources GetCpuDescriptorSetDataImpl(
144         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet) const;
145     DynamicOffsetDescriptors GetDynamicOffsetDescriptorsImpl(
146         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet) const;
147     bool HasDynamicBarrierResourcesImpl(
148         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet) const;
149     uint32_t GetDynamicOffsetDescriptorCountImpl(
150         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet) const;
151     bool HasPlatformBufferBindingsImpl(
152         const uint32_t index, const BASE_NS::vector<CpuDescriptorSet>& cpuDescriptorSet) const;
153 
154 #if ((RENDER_VALIDATION_ENABLED == 1) || (RENDER_VULKAN_VALIDATION_ENABLED == 1))
155     BASE_NS::string debugName_;
156 #endif
157 private:
158 #if (RENDER_VALIDATION_ENABLED == 1)
159     DescriptorCountValidation descriptorCountValidation_;
160 #endif
161 };
162 RENDER_END_NAMESPACE()
163 
164 #endif // CORE__RENDER__NODE_CONTEXT_DESCRIPTOR_SET_MANAGER_H
165