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 API_RENDER_RESOURCE_HANDLE_H
17 #define API_RENDER_RESOURCE_HANDLE_H
18 
19 #include <cstdint>
20 
21 #include <base/containers/generic_iterator.h>
22 #include <base/containers/refcnt_ptr.h>
23 #include <core/property/property.h>
24 #include <render/namespace.h>
25 
RENDER_BEGIN_NAMESPACE()26 RENDER_BEGIN_NAMESPACE()
27 /** \addtogroup group_resourcehandle
28  *  @{
29  */
30 constexpr const uint64_t INVALID_RESOURCE_HANDLE { 0xFFFFFFFFffffffff };
31 
32 /** Render handle (used for various renderer and rendering related handles) */
33 struct RenderHandle {
34     /** ID */
35     uint64_t id { INVALID_RESOURCE_HANDLE };
36 };
37 /** @} */
38 
39 /** Render handle equals comparison */
40 inline bool operator==(const RenderHandle& lhs, const RenderHandle& rhs) noexcept
41 {
42     return (lhs.id == rhs.id);
43 }
44 
45 /** Render handle not equals comparison */
46 inline bool operator!=(const RenderHandle& lhs, const RenderHandle& rhs) noexcept
47 {
48     return (lhs.id != rhs.id);
49 }
50 
51 /** Render handle hash */
hash(const RenderHandle & handle)52 inline uint64_t hash(const RenderHandle& handle)
53 {
54     return handle.id;
55 }
56 
57 /** Render handle types */
58 enum class RenderHandleType : uint8_t {
59     /** Undefined. */
60     UNDEFINED = 0,
61     /** Generic data. Often just handle to specific data. */
62     GENERIC_DATA = 1,
63     /** GPU buffer. */
64     GPU_BUFFER = 2,
65     /** GPU image. */
66     GPU_IMAGE = 3,
67     /** GPU buffer. */
68     GPU_SAMPLER = 4,
69     /** Graphics pipe shader. */
70     SHADER_STATE_OBJECT = 6,
71     /** Compute shader. */
72     COMPUTE_SHADER_STATE_OBJECT = 7,
73     /** Pipeline layout. */
74     PIPELINE_LAYOUT = 8,
75     /** Vertex input declaration. */
76     VERTEX_INPUT_DECLARATION = 9,
77     /** Graphics state. */
78     GRAPHICS_STATE = 10,
79     /** Render node graph. */
80     RENDER_NODE_GRAPH = 11,
81     /** Graphics pso. */
82     GRAPHICS_PSO = 12,
83     /** Compute pso. */
84     COMPUTE_PSO = 13,
85     /** Descriptor set. */
86     DESCRIPTOR_SET = 14,
87 };
88 
89 /** Render handle util */
90 namespace RenderHandleUtil {
91 /** Render handle type mask */
92 constexpr const uint64_t RENDER_HANDLE_TYPE_MASK { 0xf };
93 
94 /** Checks validity of a handle */
IsValid(const RenderHandle handle)95 inline constexpr bool IsValid(const RenderHandle handle)
96 {
97     return (handle.id != INVALID_RESOURCE_HANDLE);
98 }
99 
100 /** Returns handle type */
GetHandleType(const RenderHandle handle)101 inline constexpr RenderHandleType GetHandleType(const RenderHandle handle)
102 {
103     return (RenderHandleType)(handle.id & RENDER_HANDLE_TYPE_MASK);
104 }
105 }; // namespace RenderHandleUtil
106 
107 class RenderHandleReference;
108 
109 /** Ref counted generic render resource counter. */
110 class IRenderReferenceCounter {
111 public:
112     using Ptr = BASE_NS::refcnt_ptr<IRenderReferenceCounter>;
113 
114 protected:
115     virtual void Ref() = 0;
116     virtual void Unref() = 0;
117     virtual int32_t GetRefCount() const = 0;
118     friend Ptr;
119     friend RenderHandleReference;
120 
121     IRenderReferenceCounter() = default;
122     virtual ~IRenderReferenceCounter() = default;
123     IRenderReferenceCounter(const IRenderReferenceCounter&) = delete;
124     IRenderReferenceCounter& operator=(const IRenderReferenceCounter&) = delete;
125     IRenderReferenceCounter(IRenderReferenceCounter&&) = delete;
126     IRenderReferenceCounter& operator=(IRenderReferenceCounter&&) = delete;
127 };
128 
129 /** Reference to a render handle. */
130 class RenderHandleReference final {
131 public:
132     /** Destructor releases the reference from the owner.
133      */
134     ~RenderHandleReference() = default;
135 
136     /** Construct an empty reference. */
137     RenderHandleReference() = default;
138 
139     /** Copy a reference. Reference count will be increased. */
140     inline RenderHandleReference(const RenderHandleReference& other) noexcept;
141 
142     /** Copy a reference. Previous reference will be released and the new one aquired. */
143     inline RenderHandleReference& operator=(const RenderHandleReference& other) noexcept;
144 
145     /** Construct a reference for tracking the given handle.
146      * @param handle referenced handle
147      * @param counter owner of the referenced handle.
148      */
149     inline RenderHandleReference(const RenderHandle handle, const IRenderReferenceCounter::Ptr& counter) noexcept;
150 
151     /** Move a reference. Moved from reference will be empty and reusable. */
152     inline RenderHandleReference(RenderHandleReference&& other) noexcept;
153 
154     /** Move a reference. Previous reference will be released and the moved from reference will be empty and
155      * reusable. */
156     inline RenderHandleReference& operator=(RenderHandleReference&& other) noexcept;
157 
158     /** Check validity of the reference.
159      * @return true if the reference is valid.
160      */
161     inline explicit operator bool() const noexcept;
162 
163     /** Get raw handle.
164      * @return RenderHandle.
165      */
166     inline RenderHandle GetHandle() const noexcept;
167 
168     /** Check validity of the reference.
169      * @return RenderHandleType.
170      */
171     inline RenderHandleType GetHandleType() const noexcept;
172 
173     /** Get ref count. Return 0, if invalid.
174      * @return Get reference count of render handle reference.
175      */
176     inline int32_t GetRefCount() const noexcept;
177 
178 private:
179     RenderHandle handle_ {};
180     IRenderReferenceCounter::Ptr counter_;
181 };
182 
RenderHandleReference(const RenderHandle handle,const IRenderReferenceCounter::Ptr & counter)183 RenderHandleReference::RenderHandleReference(
184     const RenderHandle handle, const IRenderReferenceCounter::Ptr& counter) noexcept
185     : handle_(handle), counter_(counter)
186 {}
187 
RenderHandleReference(const RenderHandleReference & other)188 RenderHandleReference::RenderHandleReference(const RenderHandleReference& other) noexcept
189     : handle_(other.handle_), counter_(other.counter_)
190 {}
191 
192 RenderHandleReference& RenderHandleReference::operator=(const RenderHandleReference& other) noexcept
193 {
194     if (&other != this) {
195         handle_ = other.handle_;
196         counter_ = other.counter_;
197     }
198     return *this;
199 }
200 
RenderHandleReference(RenderHandleReference && other)201 RenderHandleReference::RenderHandleReference(RenderHandleReference&& other) noexcept
202     : handle_(BASE_NS::exchange(other.handle_, {})), counter_(BASE_NS::exchange(other.counter_, nullptr))
203 {}
204 
205 RenderHandleReference& RenderHandleReference::operator=(RenderHandleReference&& other) noexcept
206 {
207     if (&other != this) {
208         handle_ = BASE_NS::exchange(other.handle_, {});
209         counter_ = BASE_NS::exchange(other.counter_, nullptr);
210     }
211     return *this;
212 }
213 
214 RenderHandleReference::operator bool() const noexcept
215 {
216     return (handle_.id != INVALID_RESOURCE_HANDLE) && (counter_);
217 }
218 
GetHandle()219 RenderHandle RenderHandleReference::GetHandle() const noexcept
220 {
221     return handle_;
222 }
223 
GetHandleType()224 RenderHandleType RenderHandleReference::GetHandleType() const noexcept
225 {
226     return RenderHandleUtil::GetHandleType(handle_);
227 }
228 
GetRefCount()229 int32_t RenderHandleReference::GetRefCount() const noexcept
230 {
231     if (counter_) {
232         return counter_->GetRefCount();
233     } else {
234         return 0u;
235     }
236 }
237 RENDER_END_NAMESPACE()
238 
CORE_BEGIN_NAMESPACE()239 CORE_BEGIN_NAMESPACE()
240 namespace PropertyType {
241 inline constexpr PropertyTypeDecl RENDER_HANDLE_T = PROPERTYTYPE(RENDER_NS::RenderHandle);
242 inline constexpr PropertyTypeDecl RENDER_HANDLE_ARRAY_T = PROPERTYTYPE_ARRAY(RENDER_NS::RenderHandle);
243 inline constexpr PropertyTypeDecl RENDER_HANDLE_REFERENCE_T = PROPERTYTYPE(RENDER_NS::RenderHandleReference);
244 inline constexpr PropertyTypeDecl RENDER_HANDLE_REFERENCE_ARRAY_T =
245     PROPERTYTYPE_ARRAY(RENDER_NS::RenderHandleReference);
246 } // namespace PropertyType
247 #ifdef DECLARE_PROPERTY_TYPE
248 DECLARE_PROPERTY_TYPE(RENDER_NS::RenderHandle);
249 DECLARE_PROPERTY_TYPE(RENDER_NS::RenderHandleReference);
250 #endif
251 CORE_END_NAMESPACE()
252 #endif // API_RENDER_RESOURCE_HANDLE_H
253