1 /* Copyright (c) 2017-2018 Hans-Kristian Arntzen
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #pragma once
24 
25 #include "vulkan_common.hpp"
26 #include "vulkan.hpp"
27 #include "cookie.hpp"
28 #include "object_pool.hpp"
29 
30 namespace Vulkan
31 {
32 class Device;
33 
34 class SemaphoreHolder;
35 struct SemaphoreHolderDeleter
36 {
37 	void operator()(SemaphoreHolder *semaphore);
38 };
39 
40 class SemaphoreHolder : public Util::IntrusivePtrEnabled<SemaphoreHolder, SemaphoreHolderDeleter, HandleCounter>,
41                         public InternalSyncEnabled
42 {
43 public:
44 	friend struct SemaphoreHolderDeleter;
45 
46 	~SemaphoreHolder();
47 
get_semaphore() const48 	const VkSemaphore &get_semaphore() const
49 	{
50 		return semaphore;
51 	}
52 
is_signalled() const53 	bool is_signalled() const
54 	{
55 		return signalled;
56 	}
57 
consume()58 	VkSemaphore consume()
59 	{
60 		auto ret = semaphore;
61 		VK_ASSERT(semaphore);
62 		VK_ASSERT(signalled);
63 		semaphore = VK_NULL_HANDLE;
64 		signalled = false;
65 		return ret;
66 	}
67 
release_semaphore()68 	VkSemaphore release_semaphore()
69 	{
70 		auto ret = semaphore;
71 		semaphore = VK_NULL_HANDLE;
72 		signalled = false;
73 		return ret;
74 	}
75 
can_recycle() const76 	bool can_recycle() const
77 	{
78 		return !should_destroy_on_consume;
79 	}
80 
signal_external()81 	void signal_external()
82 	{
83 		VK_ASSERT(!signalled);
84 		VK_ASSERT(semaphore);
85 		signalled = true;
86 	}
87 
destroy_on_consume()88 	void destroy_on_consume()
89 	{
90 		should_destroy_on_consume = true;
91 	}
92 
signal_pending_wait()93 	void signal_pending_wait()
94 	{
95 		pending = true;
96 	}
97 
is_pending_wait() const98 	bool is_pending_wait() const
99 	{
100 		return pending;
101 	}
102 
103 private:
104 	friend class Util::ObjectPool<SemaphoreHolder>;
SemaphoreHolder(Device * device,VkSemaphore semaphore,bool signalled)105 	SemaphoreHolder(Device *device, VkSemaphore semaphore, bool signalled)
106 	    : device(device)
107 	    , semaphore(semaphore)
108 	    , signalled(signalled)
109 	{
110 	}
111 
112 	Device *device;
113 	VkSemaphore semaphore;
114 	bool signalled = true;
115 	bool pending = false;
116 	bool should_destroy_on_consume = false;
117 };
118 
119 using Semaphore = Util::IntrusivePtr<SemaphoreHolder>;
120 }
121