xref: /aosp_15_r20/external/deqp/external/vulkancts/framework/vulkan/vkRef.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _VKREF_HPP
2 #define _VKREF_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan CTS Framework
5  * --------------------
6  *
7  * Copyright (c) 2015 Google Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Vulkan object reference holder.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vkDefs.hpp"
27 #include "vkStrUtil.hpp"
28 #include "deMeta.hpp"
29 
30 #include <algorithm>
31 
32 namespace vk
33 {
34 
35 namespace refdetails
36 {
37 
38 using std::swap;
39 
40 template <typename T>
41 struct Checked
42 {
Checkedvk::refdetails::Checked43     explicit inline Checked(T object_) : object(object_)
44     {
45     }
46 
47     T object;
48 };
49 
50 //! Check that object is not null
51 template <typename T>
check(T object)52 inline Checked<T> check(T object)
53 {
54     if (!object)
55         throw tcu::TestError("Object check() failed", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__,
56                              __LINE__);
57     return Checked<T>(object);
58 }
59 
60 //! Declare object as checked earlier
61 template <typename T>
notNull(T object)62 inline Checked<T> notNull(T object)
63 {
64     if (!object)
65         throw tcu::InternalError("Null object was given to notNull()", (std::string(getTypeName<T>()) + " = 0").c_str(),
66                                  __FILE__, __LINE__);
67     return Checked<T>(object);
68 }
69 
70 //! Allow null object
71 template <typename T>
allowNull(T object)72 inline Checked<T> allowNull(T object)
73 {
74     return Checked<T>(object);
75 }
76 
77 template <typename T>
78 class Deleter
79 {
80 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,const VkAllocationCallbacks * allocator)81     Deleter(const DeviceInterface &deviceIface, VkDevice device, const VkAllocationCallbacks *allocator)
82         : m_deviceIface(&deviceIface)
83         , m_device(device)
84         , m_allocator(allocator)
85     {
86     }
Deleter(void)87     Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_allocator(DE_NULL)
88     {
89     }
90 
91     void operator()(T obj) const;
92 
93 private:
94     const DeviceInterface *m_deviceIface;
95     VkDevice m_device;
96     const VkAllocationCallbacks *m_allocator;
97 };
98 
99 template <>
100 class Deleter<VkInstance>
101 {
102 public:
Deleter(const PlatformInterface & platformIface,VkInstance instance,const VkAllocationCallbacks * allocator)103     Deleter(const PlatformInterface &platformIface, VkInstance instance, const VkAllocationCallbacks *allocator)
104         : m_destroyInstance((DestroyInstanceFunc)platformIface.getInstanceProcAddr(instance, "vkDestroyInstance"))
105         , m_allocator(allocator)
106     {
107     }
Deleter(void)108     Deleter(void) : m_destroyInstance((DestroyInstanceFunc)DE_NULL), m_allocator(DE_NULL)
109     {
110     }
111 
operator ()(VkInstance obj) const112     void operator()(VkInstance obj) const
113     {
114         m_destroyInstance(obj, m_allocator);
115     }
116 
117 private:
118     DestroyInstanceFunc m_destroyInstance;
119     const VkAllocationCallbacks *m_allocator;
120 };
121 
122 template <>
123 class Deleter<VkDevice>
124 {
125 public:
Deleter(const PlatformInterface & platformIface,VkInstance instance,VkDevice device,const VkAllocationCallbacks * allocator)126     Deleter(const PlatformInterface &platformIface, VkInstance instance, VkDevice device,
127             const VkAllocationCallbacks *allocator)
128     {
129         GetDeviceProcAddrFunc getDeviceProcAddr =
130             (GetDeviceProcAddrFunc)platformIface.getInstanceProcAddr(instance, "vkGetDeviceProcAddr");
131         m_destroyDevice = (DestroyDeviceFunc)getDeviceProcAddr(device, "vkDestroyDevice");
132         m_allocator     = allocator;
133     }
Deleter(void)134     Deleter(void) : m_destroyDevice((DestroyDeviceFunc)DE_NULL), m_allocator(DE_NULL)
135     {
136     }
137 
operator ()(VkDevice obj) const138     void operator()(VkDevice obj) const
139     {
140         m_destroyDevice(obj, m_allocator);
141     }
142 
143 private:
144     DestroyDeviceFunc m_destroyDevice;
145     const VkAllocationCallbacks *m_allocator;
146 };
147 
148 template <>
149 class Deleter<VkSurfaceKHR>
150 {
151 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)152     Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator)
153         : m_instanceIface(&instanceIface)
154         , m_instance(instance)
155         , m_allocator(allocator)
156     {
157     }
Deleter(void)158     Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL)
159     {
160     }
161 
operator ()(VkSurfaceKHR obj) const162     void operator()(VkSurfaceKHR obj) const
163     {
164         m_instanceIface->destroySurfaceKHR(m_instance, obj, m_allocator);
165     }
166 
167 private:
168     const InstanceInterface *m_instanceIface;
169     VkInstance m_instance;
170     const VkAllocationCallbacks *m_allocator;
171 };
172 
173 #ifndef CTS_USES_VULKANSC
174 
175 template <>
176 class Deleter<VkDebugReportCallbackEXT>
177 {
178 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)179     Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator)
180         : m_instanceIface(&instanceIface)
181         , m_instance(instance)
182         , m_allocator(allocator)
183     {
184     }
Deleter(void)185     Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL)
186     {
187     }
188 
operator ()(VkDebugReportCallbackEXT obj) const189     void operator()(VkDebugReportCallbackEXT obj) const
190     {
191         m_instanceIface->destroyDebugReportCallbackEXT(m_instance, obj, m_allocator);
192     }
193 
194 private:
195     const InstanceInterface *m_instanceIface;
196     VkInstance m_instance;
197     const VkAllocationCallbacks *m_allocator;
198 };
199 
200 #endif // CTS_USES_VULKANSC
201 
202 template <>
203 class Deleter<VkDebugUtilsMessengerEXT>
204 {
205 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)206     Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator)
207         : m_instanceIface(&instanceIface)
208         , m_instance(instance)
209         , m_allocator(allocator)
210     {
211     }
Deleter(void)212     Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL)
213     {
214     }
215 
operator ()(VkDebugUtilsMessengerEXT obj) const216     void operator()(VkDebugUtilsMessengerEXT obj) const
217     {
218         m_instanceIface->destroyDebugUtilsMessengerEXT(m_instance, obj, m_allocator);
219     }
220 
221 private:
222     const InstanceInterface *m_instanceIface;
223     VkInstance m_instance;
224     const VkAllocationCallbacks *m_allocator;
225 };
226 
227 template <>
228 class Deleter<VkDescriptorSet>
229 {
230 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkDescriptorPool pool)231     Deleter(const DeviceInterface &deviceIface, VkDevice device, VkDescriptorPool pool)
232         : m_deviceIface(&deviceIface)
233         , m_device(device)
234         , m_pool(pool)
235     {
236     }
Deleter(void)237     Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_pool(DE_NULL)
238     {
239     }
240 
operator ()(VkDescriptorSet obj) const241     void operator()(VkDescriptorSet obj) const
242     {
243         m_deviceIface->freeDescriptorSets(m_device, m_pool, 1, &obj);
244     }
245 
246 private:
247     const DeviceInterface *m_deviceIface;
248     VkDevice m_device;
249     VkDescriptorPool m_pool;
250 };
251 
252 template <>
253 class Deleter<VkCommandBuffer>
254 {
255 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkCommandPool pool)256     Deleter(const DeviceInterface &deviceIface, VkDevice device, VkCommandPool pool)
257         : m_deviceIface(&deviceIface)
258         , m_device(device)
259         , m_pool(pool)
260     {
261     }
Deleter(void)262     Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_pool(DE_NULL)
263     {
264     }
265 
operator ()(VkCommandBuffer obj) const266     void operator()(VkCommandBuffer obj) const
267     {
268         m_deviceIface->freeCommandBuffers(m_device, m_pool, 1, &obj);
269     }
270 
271 private:
272     const DeviceInterface *m_deviceIface;
273     VkDevice m_device;
274     VkCommandPool m_pool;
275 };
276 
277 template <typename T>
278 struct RefData
279 {
RefDatavk::refdetails::RefData280     RefData(T object_, Deleter<T> deleter_) : object(object_), deleter(deleter_)
281     {
282     }
RefDatavk::refdetails::RefData283     RefData(void) : object(0)
284     {
285     }
286 
287     T object;
288     Deleter<T> deleter;
289 };
290 
291 template <typename T>
292 class RefBase
293 {
294 public:
295     ~RefBase(void);
296 
get(void) const297     inline const T &get(void) const throw()
298     {
299         return m_data.object;
300     }
operator *(void) const301     inline const T &operator*(void) const throw()
302     {
303         return get();
304     }
operator bool(void) const305     inline explicit operator bool(void) const throw()
306     {
307         return !!get();
308     }
309 
310 protected:
RefBase(RefData<T> data)311     RefBase(RefData<T> data) : m_data(data)
312     {
313     }
314 
315     void reset(void);                //!< Release previous object, set to null.
316     RefData<T> disown(void) throw(); //!< Disown and return object (ownership transferred to caller).
317     void assign(RefData<T> data);    //!< Set new pointer, release previous pointer.
318 
319 private:
320     RefData<T> m_data;
321 };
322 
323 template <typename T>
~RefBase(void)324 inline RefBase<T>::~RefBase(void)
325 {
326     this->reset();
327 }
328 
329 template <typename T>
reset(void)330 inline void RefBase<T>::reset(void)
331 {
332     if (!!m_data.object)
333         m_data.deleter(m_data.object);
334 
335     m_data = RefData<T>();
336 }
337 
338 template <typename T>
disown(void)339 inline RefData<T> RefBase<T>::disown(void) throw()
340 {
341     RefData<T> tmp;
342     swap(m_data, tmp);
343     return tmp;
344 }
345 
346 template <typename T>
assign(RefData<T> data)347 inline void RefBase<T>::assign(RefData<T> data)
348 {
349     this->reset();
350     m_data = data;
351 }
352 
353 /*--------------------------------------------------------------------*//*!
354  * \brief Movable Vulkan object reference.
355  *
356  * Similar to de::MovePtr.
357  *//*--------------------------------------------------------------------*/
358 template <typename T>
359 class Move : public RefBase<T>
360 {
361 public:
362     template <typename U>
Move(Checked<U> object,Deleter<U> deleter)363     Move(Checked<U> object, Deleter<U> deleter) : RefBase<T>(RefData<T>(object.object, deleter))
364     {
365     }
366 
Move(RefData<T> data)367     Move(RefData<T> data) : RefBase<T>(data)
368     {
369     }
Move(Move<T> & other)370     Move(Move<T> &other) : RefBase<T>(other.RefBase<T>::disown())
371     {
372     }
Move(void)373     Move(void) : RefBase<T>(RefData<T>())
374     {
375     }
376 
disown(void)377     T disown(void)
378     {
379         return this->RefBase<T>::disown().object;
380     }
381     Move<T> &operator=(Move<T> &other);
382     Move<T> &operator=(RefData<T> data);
383 
operator RefData<T>(void)384     operator RefData<T>(void)
385     {
386         return this->RefBase<T>::disown();
387     }
388 };
389 
390 template <typename T>
operator =(Move<T> & other)391 inline Move<T> &Move<T>::operator=(Move<T> &other)
392 {
393     if (this != &other)
394         this->assign(other.RefBase<T>::disown());
395 
396     return *this;
397 }
398 
399 template <typename T>
operator =(RefData<T> data)400 inline Move<T> &Move<T>::operator=(RefData<T> data)
401 {
402     this->assign(data);
403     return *this;
404 }
405 
406 /*--------------------------------------------------------------------*//*!
407  * \brief Unique Vulkan object reference.
408  *
409  * Similar to de::UniquePtr.
410  *//*--------------------------------------------------------------------*/
411 template <typename T>
412 class Unique : public RefBase<T>
413 {
414 public:
415     template <typename U>
Unique(Checked<U> object,Deleter<U> deleter)416     Unique(Checked<U> object, Deleter<U> deleter) : RefBase<T>(RefData<T>(object.object, deleter))
417     {
418     }
419 
Unique(RefData<T> data)420     Unique(RefData<T> data) : RefBase<T>(data)
421     {
422     }
423 
424 private:
425     Unique(const Unique<T> &);
426     Unique<T> &operator=(const Unique<T> &);
427 };
428 
429 } // namespace refdetails
430 
431 using refdetails::allowNull;
432 using refdetails::check;
433 using refdetails::Deleter;
434 using refdetails::Move;
435 using refdetails::notNull;
436 using refdetails::Unique;
437 
438 } // namespace vk
439 
440 #endif // _VKREF_HPP
441