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__PIPELINE_DESCRIPTOR_SET_BINDER_H
17 #define RENDER_RENDER__PIPELINE_DESCRIPTOR_SET_BINDER_H
18 
19 #include <cstdint>
20 
21 #include <base/containers/array_view.h>
22 #include <base/containers/vector.h>
23 #include <render/device/pipeline_layout_desc.h>
24 #include <render/device/pipeline_state_desc.h>
25 #include <render/namespace.h>
26 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
27 #include <render/resource_handle.h>
28 
29 #include "device/gpu_resource_handle_util.h"
30 #include "util/log.h"
31 
RENDER_BEGIN_NAMESPACE()32 RENDER_BEGIN_NAMESPACE()
33 namespace DescriptorSetBinderUtil {
34 constexpr RenderHandleType GetRenderHandleType(const DescriptorType dt)
35 {
36     if (dt == CORE_DESCRIPTOR_TYPE_SAMPLER) {
37         return RenderHandleType::GPU_SAMPLER;
38     } else if (((dt >= CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) && (dt <= CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE)) ||
39                (dt == CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
40         return RenderHandleType::GPU_IMAGE;
41     } else if (((dt >= CORE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) &&
42                 (dt <= CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) ||
43                (dt == CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE)) {
44         return RenderHandleType::GPU_BUFFER;
45     }
46     return RenderHandleType::UNDEFINED;
47 }
48 
49 constexpr PipelineStageFlags GetPipelineStageFlags(const ShaderStageFlags shaderStageFlags)
50 {
51     PipelineStageFlags pipelineStageFlags { 0 };
52     if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT) {
53         pipelineStageFlags |= PipelineStageFlagBits::CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT;
54     }
55     if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT) {
56         pipelineStageFlags |= PipelineStageFlagBits::CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
57     }
58     if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
59         pipelineStageFlags |= PipelineStageFlagBits::CORE_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
60     }
61     return pipelineStageFlags;
62 }
63 
64 constexpr AccessFlags GetAccessFlags(const DescriptorType dt)
65 {
66     if ((dt == CORE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) || (dt == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
67         (dt == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)) {
68         return CORE_ACCESS_UNIFORM_READ_BIT;
69     } else if ((dt == CORE_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) || (dt == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
70                (dt == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) || (dt == CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE)) {
71         // NOTE: could be optimized with shader reflection info
72         return (CORE_ACCESS_SHADER_READ_BIT | CORE_ACCESS_SHADER_WRITE_BIT);
73     } else if (dt == CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) {
74         return CORE_ACCESS_INPUT_ATTACHMENT_READ_BIT;
75     } else {
76         // CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
77         // CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE
78         // CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
79         // CORE_DESCRIPTOR_TYPE_SAMPLER
80         // CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE
81         return CORE_ACCESS_SHADER_READ_BIT;
82     }
83 }
84 } // namespace DescriptorSetBinderUtil
85 
86 /** DescriptorSetBinder.
87  */
88 class DescriptorSetBinder final : public IDescriptorSetBinder {
89 public:
90     DescriptorSetBinder(const RenderHandle handle,
91         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings);
92     explicit DescriptorSetBinder(
93         const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings);
94     ~DescriptorSetBinder() = default;
95 
96     void ClearBindings() override;
97     RenderHandle GetDescriptorSetHandle() const override;
98     DescriptorSetLayoutBindingResources GetDescriptorSetLayoutBindingResources() const override;
99 
100     bool GetDescriptorSetLayoutBindingValidity() const override;
101     void PrintDescriptorSetLayoutBindingValidation() const override;
102 
103     // all must call this
104     void BindBuffer(
105         const uint32_t binding, const BindableBuffer& resource, const AdditionalDescriptorFlags flags) override;
106     void BindBuffer(const uint32_t binding, const BindableBuffer& resource) override;
107     void BindBuffer(const uint32_t binding, const RenderHandle handle, const uint32_t byteOffset) override;
108     void BindBuffer(
109         const uint32_t binding, const RenderHandle handle, const uint32_t byteOffset, const uint32_t byteSize) override;
110     // for descriptor array binding
111     void BindBuffers(const uint32_t binding, const BASE_NS::array_view<const BindableBuffer> resources) override;
112 
113     // all must call this
114     void BindImage(
115         const uint32_t binding, const BindableImage& resource, const AdditionalDescriptorFlags flags) override;
116     void BindImage(const uint32_t binding, const BindableImage& resource) override;
117     void BindImage(const uint32_t binding, const RenderHandle handle) override;
118     void BindImage(const uint32_t binding, const RenderHandle handle, const RenderHandle samplerHandle) override;
119     // for descriptor array binding
120     void BindImages(const uint32_t binding, const BASE_NS::array_view<const BindableImage> resources) override;
121 
122     // all must call this
123     void BindSampler(
124         const uint32_t binding, const BindableSampler& resource, const AdditionalDescriptorFlags flags) override;
125     void BindSampler(const uint32_t binding, const BindableSampler& resource) override;
126     void BindSampler(const uint32_t binding, const RenderHandle handle) override;
127     // for descriptor array binding
128     void BindSamplers(const uint32_t binding, const BASE_NS::array_view<const BindableSampler> resources) override;
129 
130 protected:
131     void Destroy() override;
132 
133 private:
134     void Init(const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings);
135     void InitFillBindings(const BASE_NS::array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings,
136         const uint32_t bufferCount, const uint32_t imageCount, const uint32_t samplerCount);
137 
138     RenderHandle handle_;
139     BASE_NS::vector<DescriptorSetLayoutBindingResource> bindings_;
140 
141     BASE_NS::vector<BufferDescriptor> buffers_;
142     BASE_NS::vector<ImageDescriptor> images_;
143     BASE_NS::vector<SamplerDescriptor> samplers_;
144 
145     // accesses array with binding number and retuns index;
146     PLUGIN_STATIC_ASSERT(PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT == 16u);
147     uint8_t bindingToIndex_[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT] { 16, 16, 16, 16, 16, 16, 16, 16,
148         16, 16, 16, 16, 16, 16, 16, 16 };
149     uint32_t maxBindingCount_ { 0u };
150 
151     uint32_t descriptorBindingMask_ { 0 };
152     uint32_t bindingMask_ { 0 };
153 };
154 
155 /** PipelineDescriptorSetBinder.
156  */
157 class PipelineDescriptorSetBinder final : public IPipelineDescriptorSetBinder {
158 public:
159     PipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout,
160         const BASE_NS::array_view<const RenderHandle> handles,
161         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings);
162     PipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout,
163         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings);
164     ~PipelineDescriptorSetBinder() = default;
165 
166     void ClearBindings() override;
167 
168     RenderHandle GetDescriptorSetHandle(const uint32_t set) const override;
169     DescriptorSetLayoutBindingResources GetDescriptorSetLayoutBindingResources(const uint32_t set) const override;
170     bool GetPipelineDescriptorSetLayoutBindingValidity() const override;
171 
172     uint32_t GetDescriptorSetCount() const override;
173     BASE_NS::array_view<const uint32_t> GetSetIndices() const override;
174     BASE_NS::array_view<const RenderHandle> GetDescriptorSetHandles() const override;
175 
176     uint32_t GetFirstSet() const override;
177     BASE_NS::array_view<const RenderHandle> GetDescriptorSetHandles(
178         const uint32_t beginSet, const uint32_t count) const override;
179 
180     void BindBuffer(const uint32_t set, const uint32_t binding, const BindableBuffer& resource,
181         const AdditionalDescriptorFlags flags) override;
182     void BindBuffer(const uint32_t set, const uint32_t binding, const BindableBuffer& resource) override;
183     void BindBuffers(
184         const uint32_t set, const uint32_t binding, const BASE_NS::array_view<const BindableBuffer> resources) override;
185 
186     void BindImage(const uint32_t set, const uint32_t binding, const BindableImage& resource,
187         const AdditionalDescriptorFlags flags) override;
188     void BindImage(const uint32_t set, const uint32_t binding, const BindableImage& resource) override;
189     void BindImages(
190         const uint32_t set, const uint32_t binding, const BASE_NS::array_view<const BindableImage> resources) override;
191 
192     void BindSampler(const uint32_t set, const uint32_t binding, const BindableSampler& resource,
193         const AdditionalDescriptorFlags flags) override;
194     void BindSampler(const uint32_t set, const uint32_t binding, const BindableSampler& resource) override;
195     void BindSamplers(const uint32_t set, const uint32_t binding,
196         const BASE_NS::array_view<const BindableSampler> resources) override;
197 
198     void PrintPipelineDescriptorSetLayoutBindingValidation() const override;
199 
200 protected:
201     void Destroy() override;
202 
203 private:
204     // binder can be created without valid handles
205     void Init(const PipelineLayout& pipelineLayout, const BASE_NS::array_view<const RenderHandle> handles,
206         const BASE_NS::array_view<const DescriptorSetLayoutBindings> descriptorSetsLayoutBindings, bool validHandles);
207 
208     // set -> actual vector index
209     uint32_t setToBinderIndex_[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT] { ~0u, ~0u, ~0u, ~0u };
210 
211     BASE_NS::vector<DescriptorSetBinder> descriptorSetBinders_;
212 
213     BASE_NS::vector<uint32_t> setIndices_;
214     BASE_NS::vector<RenderHandle> descriptorSetHandles_;
215 };
216 RENDER_END_NAMESPACE()
217 
218 #endif // CORE__RENDER__PIPELINE_DESCRIPTOR_SET_BINDER_H
219