1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #ifndef VK_SEMAPHORE_HPP_
16*03ce13f7SAndroid Build Coastguard Worker #define VK_SEMAPHORE_HPP_
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Worker #include "VkConfig.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "VkObject.hpp"
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard Worker #include "marl/event.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "marl/mutex.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "marl/tsa.h"
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker #include "System/Synchronization.hpp"
26*03ce13f7SAndroid Build Coastguard Worker
27*03ce13f7SAndroid Build Coastguard Worker #if VK_USE_PLATFORM_FUCHSIA
28*03ce13f7SAndroid Build Coastguard Worker # include <zircon/types.h>
29*03ce13f7SAndroid Build Coastguard Worker #endif
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker namespace vk {
32*03ce13f7SAndroid Build Coastguard Worker
33*03ce13f7SAndroid Build Coastguard Worker class BinarySemaphore;
34*03ce13f7SAndroid Build Coastguard Worker class TimelineSemaphore;
35*03ce13f7SAndroid Build Coastguard Worker
36*03ce13f7SAndroid Build Coastguard Worker class Semaphore
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker public:
39*03ce13f7SAndroid Build Coastguard Worker Semaphore(VkSemaphoreType type);
40*03ce13f7SAndroid Build Coastguard Worker
41*03ce13f7SAndroid Build Coastguard Worker virtual ~Semaphore() = default;
42*03ce13f7SAndroid Build Coastguard Worker
Cast(VkSemaphore semaphore)43*03ce13f7SAndroid Build Coastguard Worker static inline Semaphore *Cast(VkSemaphore semaphore)
44*03ce13f7SAndroid Build Coastguard Worker {
45*03ce13f7SAndroid Build Coastguard Worker return static_cast<Semaphore *>(static_cast<void *>(semaphore));
46*03ce13f7SAndroid Build Coastguard Worker }
47*03ce13f7SAndroid Build Coastguard Worker
destroy(const VkAllocationCallbacks * pAllocator)48*03ce13f7SAndroid Build Coastguard Worker virtual void destroy(const VkAllocationCallbacks *pAllocator)
49*03ce13f7SAndroid Build Coastguard Worker {
50*03ce13f7SAndroid Build Coastguard Worker }
51*03ce13f7SAndroid Build Coastguard Worker
52*03ce13f7SAndroid Build Coastguard Worker VkSemaphoreType getSemaphoreType() const;
53*03ce13f7SAndroid Build Coastguard Worker // static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo *pCreateInfo);
54*03ce13f7SAndroid Build Coastguard Worker
55*03ce13f7SAndroid Build Coastguard Worker protected:
56*03ce13f7SAndroid Build Coastguard Worker VkSemaphoreType type;
57*03ce13f7SAndroid Build Coastguard Worker marl::mutex mutex;
58*03ce13f7SAndroid Build Coastguard Worker };
59*03ce13f7SAndroid Build Coastguard Worker
60*03ce13f7SAndroid Build Coastguard Worker class BinarySemaphore : public Semaphore, public Object<BinarySemaphore, VkSemaphore>
61*03ce13f7SAndroid Build Coastguard Worker {
62*03ce13f7SAndroid Build Coastguard Worker public:
63*03ce13f7SAndroid Build Coastguard Worker BinarySemaphore(const VkSemaphoreCreateInfo *pCreateInfo, void *mem, const VkAllocationCallbacks *pAllocator);
64*03ce13f7SAndroid Build Coastguard Worker void destroy(const VkAllocationCallbacks *pAllocator);
65*03ce13f7SAndroid Build Coastguard Worker
66*03ce13f7SAndroid Build Coastguard Worker static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo *pCreateInfo);
67*03ce13f7SAndroid Build Coastguard Worker
68*03ce13f7SAndroid Build Coastguard Worker void wait();
69*03ce13f7SAndroid Build Coastguard Worker
wait(const VkPipelineStageFlags & flag)70*03ce13f7SAndroid Build Coastguard Worker void wait(const VkPipelineStageFlags &flag)
71*03ce13f7SAndroid Build Coastguard Worker {
72*03ce13f7SAndroid Build Coastguard Worker // NOTE: not sure what else to do here?
73*03ce13f7SAndroid Build Coastguard Worker wait();
74*03ce13f7SAndroid Build Coastguard Worker }
75*03ce13f7SAndroid Build Coastguard Worker
76*03ce13f7SAndroid Build Coastguard Worker void signal();
77*03ce13f7SAndroid Build Coastguard Worker
78*03ce13f7SAndroid Build Coastguard Worker #if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
79*03ce13f7SAndroid Build Coastguard Worker VkResult importFd(int fd, bool temporaryImport);
80*03ce13f7SAndroid Build Coastguard Worker VkResult exportFd(int *pFd);
81*03ce13f7SAndroid Build Coastguard Worker #endif
82*03ce13f7SAndroid Build Coastguard Worker
83*03ce13f7SAndroid Build Coastguard Worker #if VK_USE_PLATFORM_FUCHSIA
84*03ce13f7SAndroid Build Coastguard Worker VkResult importHandle(zx_handle_t handle, bool temporaryImport);
85*03ce13f7SAndroid Build Coastguard Worker VkResult exportHandle(zx_handle_t *pHandle);
86*03ce13f7SAndroid Build Coastguard Worker #endif
87*03ce13f7SAndroid Build Coastguard Worker
88*03ce13f7SAndroid Build Coastguard Worker class External;
89*03ce13f7SAndroid Build Coastguard Worker
90*03ce13f7SAndroid Build Coastguard Worker private:
91*03ce13f7SAndroid Build Coastguard Worker // Small technical note on how semaphores are imported/exported with Vulkan:
92*03ce13f7SAndroid Build Coastguard Worker //
93*03ce13f7SAndroid Build Coastguard Worker // - A Vulkan Semaphore objects has a "payload", corresponding to a
94*03ce13f7SAndroid Build Coastguard Worker // simple atomic boolean flag.
95*03ce13f7SAndroid Build Coastguard Worker //
96*03ce13f7SAndroid Build Coastguard Worker // - A Vulkan Semaphore object can be "exported": this creates a
97*03ce13f7SAndroid Build Coastguard Worker // platform-specific handle / descriptor (which can be passed to other
98*03ce13f7SAndroid Build Coastguard Worker // processes), and is linked in some way to the original semaphore's
99*03ce13f7SAndroid Build Coastguard Worker // payload.
100*03ce13f7SAndroid Build Coastguard Worker //
101*03ce13f7SAndroid Build Coastguard Worker // - Similarly, said handle / descriptor can be "imported" into a Vulkan
102*03ce13f7SAndroid Build Coastguard Worker // Semaphore object. By default, that semaphore loses its payload, and
103*03ce13f7SAndroid Build Coastguard Worker // instead uses the one referenced / shared through the descriptor.
104*03ce13f7SAndroid Build Coastguard Worker //
105*03ce13f7SAndroid Build Coastguard Worker // Hence if semaphore A exports its payload through a descriptor that
106*03ce13f7SAndroid Build Coastguard Worker // is later imported into semaphore B, then both A and B will use/share
107*03ce13f7SAndroid Build Coastguard Worker // the same payload (i.e. signal flag), making cross-process
108*03ce13f7SAndroid Build Coastguard Worker // synchronization possible.
109*03ce13f7SAndroid Build Coastguard Worker //
110*03ce13f7SAndroid Build Coastguard Worker // - There are also "temporary imports", where the target semaphore's
111*03ce13f7SAndroid Build Coastguard Worker // payload is not lost, but is simply hidden/stashed. But the next wait()
112*03ce13f7SAndroid Build Coastguard Worker // operation on the same semaphore should remove the temporary import,
113*03ce13f7SAndroid Build Coastguard Worker // and restore the previous payload.
114*03ce13f7SAndroid Build Coastguard Worker //
115*03ce13f7SAndroid Build Coastguard Worker // - There are many handle / descriptor types, which are listed through
116*03ce13f7SAndroid Build Coastguard Worker // the VkExternalSemaphoreHandleTypeFlagBits. A given Vulkan
117*03ce13f7SAndroid Build Coastguard Worker // implementation might support onle one or several at the same time
118*03ce13f7SAndroid Build Coastguard Worker // (e.g. on Linux or Android, it could support both OPAQUE_FD_BIT and
119*03ce13f7SAndroid Build Coastguard Worker // SYNC_FD_BIT, while on Windows, it would be OPAQUE_WIN32_BIT +
120*03ce13f7SAndroid Build Coastguard Worker // OPAQUE_WIN32_KMT_BIT + D3D12_FENCE_BIT).
121*03ce13f7SAndroid Build Coastguard Worker //
122*03ce13f7SAndroid Build Coastguard Worker // - To be able to export a semaphore, VkCreateSemaphore() must be called
123*03ce13f7SAndroid Build Coastguard Worker // with a VkSemaphoreCreateInfo that lists the types of all possible
124*03ce13f7SAndroid Build Coastguard Worker // platform-specific handles the semaphore could be exported to
125*03ce13f7SAndroid Build Coastguard Worker // (e.g. on Linux, it is possible to specify that a semaphore might be
126*03ce13f7SAndroid Build Coastguard Worker // exported as an opaque FD, or as a Linux Sync FD).
127*03ce13f7SAndroid Build Coastguard Worker //
128*03ce13f7SAndroid Build Coastguard Worker // However, which exact type is however only determined later by the
129*03ce13f7SAndroid Build Coastguard Worker // export operation itself (e.g. vkGetSemaphoreFdKHR() could be called to export
130*03ce13f7SAndroid Build Coastguard Worker // either a VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT or a
131*03ce13f7SAndroid Build Coastguard Worker // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).
132*03ce13f7SAndroid Build Coastguard Worker //
133*03ce13f7SAndroid Build Coastguard Worker // Once a semaphore has been exported as one type, it is not possible
134*03ce13f7SAndroid Build Coastguard Worker // to export the same payload with a different type (though the spec
135*03ce13f7SAndroid Build Coastguard Worker // doesn't seem to be explicit about this, it's simply impossible in
136*03ce13f7SAndroid Build Coastguard Worker // general).
137*03ce13f7SAndroid Build Coastguard Worker //
138*03ce13f7SAndroid Build Coastguard Worker // This leads to the following design:
139*03ce13f7SAndroid Build Coastguard Worker //
140*03ce13f7SAndroid Build Coastguard Worker // - |internal| is a simple marl::Event that represents the semaphore's
141*03ce13f7SAndroid Build Coastguard Worker // payload when it is not exported, or imported non-temporarily.
142*03ce13f7SAndroid Build Coastguard Worker //
143*03ce13f7SAndroid Build Coastguard Worker // - |external| points to an external semaphore payload. It is created
144*03ce13f7SAndroid Build Coastguard Worker // on demand if the semaphore is exported or imported non-temporarily.
145*03ce13f7SAndroid Build Coastguard Worker // Note that once |external| is created, |internal| is ignored.
146*03ce13f7SAndroid Build Coastguard Worker //
147*03ce13f7SAndroid Build Coastguard Worker // - |tempExternal| points to a linked-list of temporary external
148*03ce13f7SAndroid Build Coastguard Worker // semaphore payloads. The list head corresponds to the most recent
149*03ce13f7SAndroid Build Coastguard Worker // temporary import.
150*03ce13f7SAndroid Build Coastguard Worker //
151*03ce13f7SAndroid Build Coastguard Worker
152*03ce13f7SAndroid Build Coastguard Worker // Internal template to allocate a new External implementation.
153*03ce13f7SAndroid Build Coastguard Worker template<class EXTERNAL>
154*03ce13f7SAndroid Build Coastguard Worker External *allocateExternal();
155*03ce13f7SAndroid Build Coastguard Worker
156*03ce13f7SAndroid Build Coastguard Worker void deallocateExternal(External *ext);
157*03ce13f7SAndroid Build Coastguard Worker
158*03ce13f7SAndroid Build Coastguard Worker // Used internally to import an external payload.
159*03ce13f7SAndroid Build Coastguard Worker // |temporaryImport| is true iff the import is temporary.
160*03ce13f7SAndroid Build Coastguard Worker // |alloc_func| is callable that allocates a new External instance of the
161*03ce13f7SAndroid Build Coastguard Worker // appropriate type.
162*03ce13f7SAndroid Build Coastguard Worker // |import_func| is callable that takes a single parameter, which
163*03ce13f7SAndroid Build Coastguard Worker // corresponds to the external handle/descriptor, and returns a VkResult
164*03ce13f7SAndroid Build Coastguard Worker // values.
165*03ce13f7SAndroid Build Coastguard Worker template<typename ALLOC_FUNC, typename IMPORT_FUNC>
166*03ce13f7SAndroid Build Coastguard Worker VkResult importPayload(bool temporaryImport,
167*03ce13f7SAndroid Build Coastguard Worker ALLOC_FUNC alloc_func,
168*03ce13f7SAndroid Build Coastguard Worker IMPORT_FUNC import_func);
169*03ce13f7SAndroid Build Coastguard Worker
170*03ce13f7SAndroid Build Coastguard Worker // Used internally to export a given payload.
171*03ce13f7SAndroid Build Coastguard Worker // |alloc_func| is a callable that allocates a new External instance of
172*03ce13f7SAndroid Build Coastguard Worker // the appropriate type.
173*03ce13f7SAndroid Build Coastguard Worker // |export_func| is a callable that takes a pointer to an External instance,
174*03ce13f7SAndroid Build Coastguard Worker // and a pointer to a handle/descriptor, and returns a VkResult.
175*03ce13f7SAndroid Build Coastguard Worker template<typename ALLOC_FUNC, typename EXPORT_FUNC>
176*03ce13f7SAndroid Build Coastguard Worker VkResult exportPayload(ALLOC_FUNC alloc_func, EXPORT_FUNC export_func);
177*03ce13f7SAndroid Build Coastguard Worker
178*03ce13f7SAndroid Build Coastguard Worker const VkAllocationCallbacks *allocator = nullptr;
179*03ce13f7SAndroid Build Coastguard Worker VkExternalSemaphoreHandleTypeFlags exportableHandleTypes = (VkExternalSemaphoreHandleTypeFlags)0;
180*03ce13f7SAndroid Build Coastguard Worker marl::Event internal;
181*03ce13f7SAndroid Build Coastguard Worker External *external GUARDED_BY(mutex) = nullptr;
182*03ce13f7SAndroid Build Coastguard Worker External *tempExternal GUARDED_BY(mutex) = nullptr;
183*03ce13f7SAndroid Build Coastguard Worker };
184*03ce13f7SAndroid Build Coastguard Worker
Cast(VkSemaphore object)185*03ce13f7SAndroid Build Coastguard Worker static inline Semaphore *Cast(VkSemaphore object)
186*03ce13f7SAndroid Build Coastguard Worker {
187*03ce13f7SAndroid Build Coastguard Worker return Semaphore::Cast(object);
188*03ce13f7SAndroid Build Coastguard Worker }
189*03ce13f7SAndroid Build Coastguard Worker
190*03ce13f7SAndroid Build Coastguard Worker template<typename T>
DynamicCast(VkSemaphore object)191*03ce13f7SAndroid Build Coastguard Worker static inline T *DynamicCast(VkSemaphore object)
192*03ce13f7SAndroid Build Coastguard Worker {
193*03ce13f7SAndroid Build Coastguard Worker Semaphore *semaphore = vk::Cast(object);
194*03ce13f7SAndroid Build Coastguard Worker if(semaphore == nullptr)
195*03ce13f7SAndroid Build Coastguard Worker {
196*03ce13f7SAndroid Build Coastguard Worker return nullptr;
197*03ce13f7SAndroid Build Coastguard Worker }
198*03ce13f7SAndroid Build Coastguard Worker
199*03ce13f7SAndroid Build Coastguard Worker static_assert(std::is_same_v<T, BinarySemaphore> || std::is_same_v<T, TimelineSemaphore>);
200*03ce13f7SAndroid Build Coastguard Worker if constexpr(std::is_same_v<T, BinarySemaphore>)
201*03ce13f7SAndroid Build Coastguard Worker {
202*03ce13f7SAndroid Build Coastguard Worker if(semaphore->getSemaphoreType() != VK_SEMAPHORE_TYPE_BINARY)
203*03ce13f7SAndroid Build Coastguard Worker {
204*03ce13f7SAndroid Build Coastguard Worker return nullptr;
205*03ce13f7SAndroid Build Coastguard Worker }
206*03ce13f7SAndroid Build Coastguard Worker }
207*03ce13f7SAndroid Build Coastguard Worker else
208*03ce13f7SAndroid Build Coastguard Worker {
209*03ce13f7SAndroid Build Coastguard Worker if(semaphore->getSemaphoreType() != VK_SEMAPHORE_TYPE_TIMELINE)
210*03ce13f7SAndroid Build Coastguard Worker {
211*03ce13f7SAndroid Build Coastguard Worker return nullptr;
212*03ce13f7SAndroid Build Coastguard Worker }
213*03ce13f7SAndroid Build Coastguard Worker }
214*03ce13f7SAndroid Build Coastguard Worker return static_cast<T *>(semaphore);
215*03ce13f7SAndroid Build Coastguard Worker }
216*03ce13f7SAndroid Build Coastguard Worker
217*03ce13f7SAndroid Build Coastguard Worker // This struct helps parse VkSemaphoreCreateInfo. It also looks at the pNext
218*03ce13f7SAndroid Build Coastguard Worker // structures and stores their data flatly in a single struct. The default
219*03ce13f7SAndroid Build Coastguard Worker // values of each data member are what the absence of a pNext struct implies
220*03ce13f7SAndroid Build Coastguard Worker // for those values.
221*03ce13f7SAndroid Build Coastguard Worker struct SemaphoreCreateInfo
222*03ce13f7SAndroid Build Coastguard Worker {
223*03ce13f7SAndroid Build Coastguard Worker bool exportSemaphore = false;
224*03ce13f7SAndroid Build Coastguard Worker VkExternalSemaphoreHandleTypeFlags exportHandleTypes = 0;
225*03ce13f7SAndroid Build Coastguard Worker
226*03ce13f7SAndroid Build Coastguard Worker VkSemaphoreType semaphoreType = VK_SEMAPHORE_TYPE_BINARY;
227*03ce13f7SAndroid Build Coastguard Worker uint64_t initialPayload = 0;
228*03ce13f7SAndroid Build Coastguard Worker
229*03ce13f7SAndroid Build Coastguard Worker SemaphoreCreateInfo(const VkSemaphoreCreateInfo *pCreateInfo);
230*03ce13f7SAndroid Build Coastguard Worker };
231*03ce13f7SAndroid Build Coastguard Worker
232*03ce13f7SAndroid Build Coastguard Worker } // namespace vk
233*03ce13f7SAndroid Build Coastguard Worker
234*03ce13f7SAndroid Build Coastguard Worker #endif // VK_SEMAPHORE_HPP_
235