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