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 T object;
46 };
47
48 //! Check that object is not null
49 template<typename T>
check(T object)50 inline Checked<T> check (T object)
51 {
52 if (!object)
53 throw tcu::TestError("Object check() failed", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__, __LINE__);
54 return Checked<T>(object);
55 }
56
57 //! Declare object as checked earlier
58 template<typename T>
notNull(T object)59 inline Checked<T> notNull (T object)
60 {
61 if (!object)
62 throw tcu::InternalError("Null object was given to notNull()", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__, __LINE__);
63 return Checked<T>(object);
64 }
65
66 //! Allow null object
67 template<typename T>
allowNull(T object)68 inline Checked<T> allowNull (T object)
69 {
70 return Checked<T>(object);
71 }
72
73 template<typename T>
74 class Deleter
75 {
76 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,const VkAllocationCallbacks * allocator)77 Deleter (const DeviceInterface& deviceIface, VkDevice device, const VkAllocationCallbacks* allocator)
78 : m_deviceIface (&deviceIface)
79 , m_device (device)
80 , m_allocator (allocator)
81 {}
Deleter(void)82 Deleter (void)
83 : m_deviceIface (DE_NULL)
84 , m_device (DE_NULL)
85 , m_allocator (DE_NULL)
86 {}
87
88 void operator() (T obj) const;
89
90 private:
91 const DeviceInterface* m_deviceIface;
92 VkDevice m_device;
93 const VkAllocationCallbacks* m_allocator;
94 };
95
96 template<>
97 class Deleter<VkInstance>
98 {
99 public:
Deleter(const PlatformInterface & platformIface,VkInstance instance,const VkAllocationCallbacks * allocator)100 Deleter (const PlatformInterface& platformIface, VkInstance instance, const VkAllocationCallbacks* allocator)
101 : m_destroyInstance ((DestroyInstanceFunc)platformIface.getInstanceProcAddr(instance, "vkDestroyInstance"))
102 , m_allocator (allocator)
103 {}
Deleter(void)104 Deleter (void)
105 : m_destroyInstance ((DestroyInstanceFunc)DE_NULL)
106 , m_allocator (DE_NULL)
107 {}
108
operator ()(VkInstance obj) const109 void operator() (VkInstance obj) const { m_destroyInstance(obj, m_allocator); }
110
111 private:
112 DestroyInstanceFunc m_destroyInstance;
113 const VkAllocationCallbacks* m_allocator;
114 };
115
116 template<>
117 class Deleter<VkDevice>
118 {
119 public:
Deleter(const InstanceInterface & instanceIface,VkDevice device,const VkAllocationCallbacks * allocator)120 Deleter (const InstanceInterface& instanceIface, VkDevice device, const VkAllocationCallbacks* allocator)
121 : m_destroyDevice ((DestroyDeviceFunc)instanceIface.getDeviceProcAddr(device, "vkDestroyDevice"))
122 , m_allocator (allocator)
123 {}
Deleter(void)124 Deleter (void)
125 : m_destroyDevice ((DestroyDeviceFunc)DE_NULL)
126 , m_allocator (DE_NULL)
127 {}
128
operator ()(VkDevice obj) const129 void operator() (VkDevice obj) const { m_destroyDevice(obj, m_allocator); }
130
131 private:
132 DestroyDeviceFunc m_destroyDevice;
133 const VkAllocationCallbacks* m_allocator;
134 };
135
136 template<>
137 class Deleter<VkSurfaceKHR>
138 {
139 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)140 Deleter (const InstanceInterface& instanceIface, VkInstance instance, const VkAllocationCallbacks* allocator)
141 : m_instanceIface (&instanceIface)
142 , m_instance (instance)
143 , m_allocator (allocator)
144 {}
Deleter(void)145 Deleter (void)
146 : m_instanceIface (DE_NULL)
147 , m_instance ((VkInstance)0)
148 , m_allocator (DE_NULL)
149 {}
150
operator ()(VkSurfaceKHR obj) const151 void operator() (VkSurfaceKHR obj) const { m_instanceIface->destroySurfaceKHR(m_instance, obj, m_allocator); }
152
153 private:
154 const InstanceInterface* m_instanceIface;
155 VkInstance m_instance;
156 const VkAllocationCallbacks* m_allocator;
157 };
158
159 template<>
160 class Deleter<VkDebugReportCallbackEXT>
161 {
162 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)163 Deleter (const InstanceInterface& instanceIface, VkInstance instance, const VkAllocationCallbacks* allocator)
164 : m_instanceIface (&instanceIface)
165 , m_instance (instance)
166 , m_allocator (allocator)
167 {}
Deleter(void)168 Deleter (void)
169 : m_instanceIface (DE_NULL)
170 , m_instance ((VkInstance)0)
171 , m_allocator (DE_NULL)
172 {}
173
operator ()(VkDebugReportCallbackEXT obj) const174 void operator() (VkDebugReportCallbackEXT obj) const { m_instanceIface->destroyDebugReportCallbackEXT(m_instance, obj, m_allocator); }
175
176 private:
177 const InstanceInterface* m_instanceIface;
178 VkInstance m_instance;
179 const VkAllocationCallbacks* m_allocator;
180 };
181
182 template<>
183 class Deleter<VkDescriptorSet>
184 {
185 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkDescriptorPool pool)186 Deleter (const DeviceInterface& deviceIface, VkDevice device, VkDescriptorPool pool)
187 : m_deviceIface (&deviceIface)
188 , m_device (device)
189 , m_pool (pool)
190 {}
Deleter(void)191 Deleter (void)
192 : m_deviceIface (DE_NULL)
193 , m_device (DE_NULL)
194 , m_pool (DE_NULL)
195 {}
196
operator ()(VkDescriptorSet obj) const197 void operator() (VkDescriptorSet obj) const { m_deviceIface->freeDescriptorSets(m_device, m_pool, 1, &obj); }
198
199 private:
200 const DeviceInterface* m_deviceIface;
201 VkDevice m_device;
202 VkDescriptorPool m_pool;
203 };
204
205 template<>
206 class Deleter<VkCommandBuffer>
207 {
208 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkCommandPool pool)209 Deleter (const DeviceInterface& deviceIface, VkDevice device, VkCommandPool pool)
210 : m_deviceIface (&deviceIface)
211 , m_device (device)
212 , m_pool (pool)
213 {}
Deleter(void)214 Deleter (void)
215 : m_deviceIface (DE_NULL)
216 , m_device (DE_NULL)
217 , m_pool (DE_NULL)
218 {}
219
operator ()(VkCommandBuffer obj) const220 void operator() (VkCommandBuffer obj) const { m_deviceIface->freeCommandBuffers(m_device, m_pool, 1, &obj); }
221
222 private:
223 const DeviceInterface* m_deviceIface;
224 VkDevice m_device;
225 VkCommandPool m_pool;
226 };
227
228 template<typename T>
229 struct RefData
230 {
RefDatavk::refdetails::RefData231 RefData (T object_, Deleter<T> deleter_)
232 : object (object_)
233 , deleter (deleter_)
234 {}
RefDatavk::refdetails::RefData235 RefData (void)
236 : object (0)
237 {}
238
239 T object;
240 Deleter<T> deleter;
241 };
242
243 template<typename T>
244 class RefBase
245 {
246 public:
247 ~RefBase (void);
248
get(void) const249 inline const T& get (void) const throw() { return m_data.object; }
operator *(void) const250 inline const T& operator* (void) const throw() { return get(); }
operator bool(void) const251 inline operator bool (void) const throw() { return !!get(); }
252
253 protected:
RefBase(RefData<T> data)254 RefBase (RefData<T> data) : m_data(data) {}
255
256 void reset (void); //!< Release previous object, set to null.
257 RefData<T> disown (void) throw(); //!< Disown and return object (ownership transferred to caller).
258 void assign (RefData<T> data); //!< Set new pointer, release previous pointer.
259
260 private:
261 RefData<T> m_data;
262 };
263
264 template<typename T>
~RefBase(void)265 inline RefBase<T>::~RefBase (void)
266 {
267 this->reset();
268 }
269
270 template<typename T>
reset(void)271 inline void RefBase<T>::reset (void)
272 {
273 if (!!m_data.object)
274 m_data.deleter(m_data.object);
275
276 m_data = RefData<T>();
277 }
278
279 template<typename T>
disown(void)280 inline RefData<T> RefBase<T>::disown (void) throw()
281 {
282 RefData<T> tmp;
283 swap(m_data, tmp);
284 return tmp;
285 }
286
287 template<typename T>
assign(RefData<T> data)288 inline void RefBase<T>::assign (RefData<T> data)
289 {
290 this->reset();
291 m_data = data;
292 }
293
294 /*--------------------------------------------------------------------*//*!
295 * \brief Movable Vulkan object reference.
296 *
297 * Similar to de::MovePtr.
298 *//*--------------------------------------------------------------------*/
299 template<typename T>
300 class Move : public RefBase<T>
301 {
302 public:
303 template<typename U>
Move(Checked<U> object,Deleter<U> deleter)304 Move (Checked<U> object, Deleter<U> deleter)
305 : RefBase<T>(RefData<T>(object.object, deleter))
306 {}
307
Move(RefData<T> data)308 Move (RefData<T> data)
309 : RefBase<T>(data)
310 {}
Move(Move<T> & other)311 Move (Move<T>& other)
312 : RefBase<T>(other.RefBase<T>::disown())
313 {}
Move(void)314 Move (void)
315 : RefBase<T>(RefData<T>())
316 {}
317
disown(void)318 T disown (void) { return this->RefBase<T>::disown().object; }
319 Move<T>& operator= (Move<T>& other);
320 Move<T>& operator= (RefData<T> data);
321
operator RefData<T>(void)322 operator RefData<T> (void) { return this->RefBase<T>::disown(); }
323 };
324
325 template<typename T>
operator =(Move<T> & other)326 inline Move<T>& Move<T>::operator= (Move<T>& other)
327 {
328 if (this != &other)
329 this->assign(other.RefBase<T>::disown());
330
331 return *this;
332 }
333
334 template<typename T>
operator =(RefData<T> data)335 inline Move<T>& Move<T>::operator= (RefData<T> data)
336 {
337 this->assign(data);
338 return *this;
339 }
340
341 /*--------------------------------------------------------------------*//*!
342 * \brief Unique Vulkan object reference.
343 *
344 * Similar to de::UniquePtr.
345 *//*--------------------------------------------------------------------*/
346 template<typename T>
347 class Unique : public RefBase<T>
348 {
349 public:
350 template<typename U>
Unique(Checked<U> object,Deleter<U> deleter)351 Unique (Checked<U> object, Deleter<U> deleter)
352 : RefBase<T>(RefData<T>(object.object, deleter))
353 {}
354
Unique(RefData<T> data)355 Unique (RefData<T> data)
356 : RefBase<T>(data)
357 {}
358
359 private:
360 Unique (const Unique<T>&);
361 Unique<T>& operator= (const Unique<T>&);
362 };
363
364 } // refdetails
365
366 using refdetails::Move;
367 using refdetails::Unique;
368 using refdetails::Deleter;
369 using refdetails::check;
370 using refdetails::notNull;
371 using refdetails::allowNull;
372
373 } // vk
374
375 #endif // _VKREF_HPP
376