• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 PlatformInterface & platformIface,VkInstance instance,VkDevice device,const VkAllocationCallbacks * allocator)120 									Deleter		(const PlatformInterface& platformIface, VkInstance instance, VkDevice device, const VkAllocationCallbacks* allocator)
121 									{
122 										GetDeviceProcAddrFunc getDeviceProcAddr = (GetDeviceProcAddrFunc)platformIface.getInstanceProcAddr(instance, "vkGetDeviceProcAddr");
123 										m_destroyDevice = (DestroyDeviceFunc)getDeviceProcAddr(device, "vkDestroyDevice");
124 										m_allocator = allocator;
125 									}
Deleter(void)126 									Deleter		(void)
127 										: m_destroyDevice	((DestroyDeviceFunc)DE_NULL)
128 										, m_allocator		(DE_NULL)
129 									{}
130 
operator ()(VkDevice obj) const131 	void							operator()	(VkDevice obj) const { m_destroyDevice(obj, m_allocator); }
132 
133 private:
134 	DestroyDeviceFunc				m_destroyDevice;
135 	const VkAllocationCallbacks*	m_allocator;
136 };
137 
138 template<>
139 class Deleter<VkSurfaceKHR>
140 {
141 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)142 									Deleter		(const InstanceInterface& instanceIface, VkInstance instance, const VkAllocationCallbacks* allocator)
143 										: m_instanceIface	(&instanceIface)
144 										, m_instance		(instance)
145 										, m_allocator		(allocator)
146 									{}
Deleter(void)147 									Deleter		(void)
148 										: m_instanceIface	(DE_NULL)
149 										, m_instance		((VkInstance)0)
150 										, m_allocator		(DE_NULL)
151 									{}
152 
operator ()(VkSurfaceKHR obj) const153 	void							operator()	(VkSurfaceKHR obj) const { m_instanceIface->destroySurfaceKHR(m_instance, obj, m_allocator); }
154 
155 private:
156 	const InstanceInterface*		m_instanceIface;
157 	VkInstance						m_instance;
158 	const VkAllocationCallbacks*	m_allocator;
159 };
160 
161 #ifndef CTS_USES_VULKANSC
162 
163 template<>
164 class Deleter<VkDebugReportCallbackEXT>
165 {
166 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)167 									Deleter		(const InstanceInterface& instanceIface, VkInstance instance, const VkAllocationCallbacks* allocator)
168 										: m_instanceIface	(&instanceIface)
169 										, m_instance		(instance)
170 										, m_allocator		(allocator)
171 									{}
Deleter(void)172 									Deleter		(void)
173 										: m_instanceIface	(DE_NULL)
174 										, m_instance		((VkInstance)0)
175 										, m_allocator		(DE_NULL)
176 									{}
177 
operator ()(VkDebugReportCallbackEXT obj) const178 	void							operator()	(VkDebugReportCallbackEXT obj) const { m_instanceIface->destroyDebugReportCallbackEXT(m_instance, obj, m_allocator); }
179 
180 private:
181 	const InstanceInterface*		m_instanceIface;
182 	VkInstance						m_instance;
183 	const VkAllocationCallbacks*	m_allocator;
184 };
185 
186 #endif // CTS_USES_VULKANSC
187 
188 template<>
189 class Deleter<VkDebugUtilsMessengerEXT>
190 {
191 public:
Deleter(const InstanceInterface & instanceIface,VkInstance instance,const VkAllocationCallbacks * allocator)192 									Deleter		(const InstanceInterface& instanceIface, VkInstance instance, const VkAllocationCallbacks* allocator)
193 										: m_instanceIface	(&instanceIface)
194 										, m_instance		(instance)
195 										, m_allocator		(allocator)
196 									{}
Deleter(void)197 									Deleter		(void)
198 										: m_instanceIface	(DE_NULL)
199 										, m_instance		((VkInstance)0)
200 										, m_allocator		(DE_NULL)
201 									{}
202 
operator ()(VkDebugUtilsMessengerEXT obj) const203 	void							operator()	(VkDebugUtilsMessengerEXT obj) const { m_instanceIface->destroyDebugUtilsMessengerEXT(m_instance, obj, m_allocator); }
204 
205 private:
206 	const InstanceInterface*		m_instanceIface;
207 	VkInstance						m_instance;
208 	const VkAllocationCallbacks*	m_allocator;
209 };
210 
211 template<>
212 class Deleter<VkDescriptorSet>
213 {
214 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkDescriptorPool pool)215 							Deleter		(const DeviceInterface& deviceIface, VkDevice device, VkDescriptorPool pool)
216 								: m_deviceIface	(&deviceIface)
217 								, m_device		(device)
218 								, m_pool		(pool)
219 							{}
Deleter(void)220 							Deleter		(void)
221 								: m_deviceIface	(DE_NULL)
222 								, m_device		(DE_NULL)
223 								, m_pool		(DE_NULL)
224 							{}
225 
operator ()(VkDescriptorSet obj) const226 	void					operator()	(VkDescriptorSet obj) const { m_deviceIface->freeDescriptorSets(m_device, m_pool, 1, &obj); }
227 
228 private:
229 	const DeviceInterface*	m_deviceIface;
230 	VkDevice				m_device;
231 	VkDescriptorPool		m_pool;
232 };
233 
234 template<>
235 class Deleter<VkCommandBuffer>
236 {
237 public:
Deleter(const DeviceInterface & deviceIface,VkDevice device,VkCommandPool pool)238 							Deleter		(const DeviceInterface& deviceIface, VkDevice device, VkCommandPool pool)
239 								: m_deviceIface	(&deviceIface)
240 								, m_device		(device)
241 								, m_pool		(pool)
242 							{}
Deleter(void)243 							Deleter		(void)
244 								: m_deviceIface	(DE_NULL)
245 								, m_device		(DE_NULL)
246 								, m_pool		(DE_NULL)
247 							{}
248 
operator ()(VkCommandBuffer obj) const249 	void					operator()	(VkCommandBuffer obj) const { m_deviceIface->freeCommandBuffers(m_device, m_pool, 1, &obj); }
250 
251 private:
252 	const DeviceInterface*	m_deviceIface;
253 	VkDevice				m_device;
254 	VkCommandPool			m_pool;
255 };
256 
257 template<typename T>
258 struct RefData
259 {
RefDatavk::refdetails::RefData260 				RefData		(T object_, Deleter<T> deleter_)
261 								: object	(object_)
262 								, deleter	(deleter_)
263 				{}
RefDatavk::refdetails::RefData264 				RefData		(void)
265 								: object	(0)
266 				{}
267 
268 	T			object;
269 	Deleter<T>	deleter;
270 };
271 
272 template<typename T>
273 class RefBase
274 {
275 public:
276 						~RefBase		(void);
277 
get(void) const278 	inline const T&		get				(void) const throw() { return m_data.object;	}
operator *(void) const279 	inline const T&		operator*		(void) const throw() { return get();			}
operator bool(void) const280 	inline explicit		operator bool	(void) const throw() { return !!get();			}
281 
282 protected:
RefBase(RefData<T> data)283 						RefBase			(RefData<T> data) : m_data(data)	{}
284 
285 	void				reset			(void);				//!< Release previous object, set to null.
286 	RefData<T>			disown			(void) throw();		//!< Disown and return object (ownership transferred to caller).
287 	void				assign			(RefData<T> data);	//!< Set new pointer, release previous pointer.
288 
289 private:
290 	RefData<T>			m_data;
291 };
292 
293 template<typename T>
~RefBase(void)294 inline RefBase<T>::~RefBase (void)
295 {
296 	this->reset();
297 }
298 
299 template<typename T>
reset(void)300 inline void RefBase<T>::reset (void)
301 {
302 	if (!!m_data.object)
303 		m_data.deleter(m_data.object);
304 
305 	m_data = RefData<T>();
306 }
307 
308 template<typename T>
disown(void)309 inline RefData<T> RefBase<T>::disown (void) throw()
310 {
311 	RefData<T> tmp;
312 	swap(m_data, tmp);
313 	return tmp;
314 }
315 
316 template<typename T>
assign(RefData<T> data)317 inline void RefBase<T>::assign (RefData<T> data)
318 {
319 	this->reset();
320 	m_data = data;
321 }
322 
323 /*--------------------------------------------------------------------*//*!
324  * \brief Movable Vulkan object reference.
325  *
326  * Similar to de::MovePtr.
327  *//*--------------------------------------------------------------------*/
328 template<typename T>
329 class Move : public RefBase<T>
330 {
331 public:
332 	template<typename U>
Move(Checked<U> object,Deleter<U> deleter)333 				Move		(Checked<U> object, Deleter<U> deleter)
334 								: RefBase<T>(RefData<T>(object.object, deleter))
335 				{}
336 
Move(RefData<T> data)337 				Move		(RefData<T> data)
338 								: RefBase<T>(data)
339 				{}
Move(Move<T> & other)340 				Move		(Move<T>& other)
341 								: RefBase<T>(other.RefBase<T>::disown())
342 				{}
Move(void)343 				Move		(void)
344 								: RefBase<T>(RefData<T>())
345 				{}
346 
disown(void)347 	T			disown		(void) { return this->RefBase<T>::disown().object; }
348 	Move<T>&	operator=	(Move<T>& other);
349 	Move<T>&	operator=	(RefData<T> data);
350 
operator RefData<T>(void)351 	operator	RefData<T>	(void) { return this->RefBase<T>::disown(); }
352 };
353 
354 template<typename T>
operator =(Move<T> & other)355 inline Move<T>& Move<T>::operator= (Move<T>& other)
356 {
357 	if (this != &other)
358 		this->assign(other.RefBase<T>::disown());
359 
360 	return *this;
361 }
362 
363 template<typename T>
operator =(RefData<T> data)364 inline Move<T>& Move<T>::operator= (RefData<T> data)
365 {
366 	this->assign(data);
367 	return *this;
368 }
369 
370 /*--------------------------------------------------------------------*//*!
371  * \brief Unique Vulkan object reference.
372  *
373  * Similar to de::UniquePtr.
374  *//*--------------------------------------------------------------------*/
375 template<typename T>
376 class Unique : public RefBase<T>
377 {
378 public:
379 	template<typename U>
Unique(Checked<U> object,Deleter<U> deleter)380 				Unique		(Checked<U> object, Deleter<U> deleter)
381 								: RefBase<T>(RefData<T>(object.object, deleter))
382 				{}
383 
Unique(RefData<T> data)384 				Unique		(RefData<T> data)
385 								: RefBase<T>(data)
386 				{}
387 
388 private:
389 				Unique		(const Unique<T>&);
390 	Unique<T>&	operator=	(const Unique<T>&);
391 };
392 
393 } // refdetails
394 
395 using refdetails::Move;
396 using refdetails::Unique;
397 using refdetails::Deleter;
398 using refdetails::check;
399 using refdetails::notNull;
400 using refdetails::allowNull;
401 
402 } // vk
403 
404 #endif // _VKREF_HPP
405