Skip to content

Commit fda994c

Browse files
committed
[vulkan] Implement external semaphore support for Fuchsia
This corresponds to the VK_FUCHSIA_external_semaphore extension which uses a Zircon event object to communicate across processes. Bug: b/140421726 Change-Id: I47b235d4ff7d787491738422bda6fdf853803ab7 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35969 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Tested-by: David Turner <digit@google.com>
1 parent c47ee16 commit fda994c

File tree

8 files changed

+235
-0
lines changed

8 files changed

+235
-0
lines changed

src/Vulkan/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ swiftshader_source_set("swiftshader_libvulkan_headers") {
9292
sources += [
9393
"VkSemaphoreExternalLinux.hpp",
9494
]
95+
} else if (is_fuchsia) {
96+
sources += [
97+
"VkSemaphoreExternalFuchsia.hpp",
98+
]
9599
} else {
96100
sources += [
97101
"VkSemaphoreExternalNone.hpp",

src/Vulkan/VkConfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,8 @@ constexpr int SUBPIXEL_PRECISION_MASK = 0xFFFFFFFF >> (32 - SUBPIXEL_PRECISION_B
8888
#define SWIFTSHADER_EXTERNAL_SEMAPHORE_LINUX_MEMFD 1
8989
#endif
9090

91+
#if VK_USE_PLATFORM_FUCHSIA
92+
#define SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT 1
93+
#endif
94+
9195
#endif // VK_CONFIG_HPP_

src/Vulkan/VkGetProcAddress.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,17 @@ static const std::vector<std::pair<const char*, std::unordered_map<std::string,
346346
}
347347
},
348348
#endif
349+
350+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
351+
// VK_FUCHSIA_external_semaphore
352+
{
353+
VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
354+
{
355+
MAKE_VULKAN_DEVICE_ENTRY(vkGetSemaphoreZirconHandleFUCHSIA),
356+
MAKE_VULKAN_DEVICE_ENTRY(vkImportSemaphoreZirconHandleFUCHSIA),
357+
}
358+
},
359+
#endif
349360
};
350361

351362
#undef MAKE_VULKAN_DEVICE_ENTRY

src/Vulkan/VkPhysicalDevice.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,15 @@ void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalSemaphoreInfo*
380380
pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
381381
return;
382382
}
383+
#endif
384+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
385+
if (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA)
386+
{
387+
pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
388+
pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
389+
pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
390+
return;
391+
}
383392
#endif
384393
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
385394
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;

src/Vulkan/VkSemaphore.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_LINUX_MEMFD
2020
#include "VkSemaphoreExternalLinux.hpp"
21+
#elif SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
22+
#include "VkSemaphoreExternalFuchsia.hpp"
2123
#else
2224
#include "VkSemaphoreExternalNone.hpp"
2325
#endif
@@ -226,4 +228,30 @@ VkResult Semaphore::exportFd(int* pFd) const
226228
}
227229
#endif // SWIFTSHADER_EXTERNAL_SEMAPHORE_LINUX_MEMFD
228230

231+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
232+
VkResult Semaphore::importHandle(zx_handle_t handle, bool temporaryImport)
233+
{
234+
std::unique_lock<std::mutex> lock(impl->mutex);
235+
if (!impl->external)
236+
{
237+
impl->allocateExternalNoInit();
238+
}
239+
// NOTE: Imports are just moving a handle so cannot fail.
240+
impl->external->importHandle(handle);
241+
impl->temporaryImport = temporaryImport;
242+
return VK_SUCCESS;
243+
}
244+
245+
VkResult Semaphore::exportHandle(zx_handle_t *pHandle) const
246+
{
247+
std::unique_lock<std::mutex> lock(impl->mutex);
248+
if (!impl->external)
249+
{
250+
TRACE("Cannot export non-external semaphore");
251+
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
252+
}
253+
return impl->external->exportHandle(pHandle);
254+
}
255+
#endif // SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
256+
229257
} // namespace vk

src/Vulkan/VkSemaphore.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
#include "VkConfig.h"
1919
#include "VkObject.hpp"
2020

21+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
22+
#include <zircon/types.h>
23+
#endif
24+
2125
namespace vk
2226
{
2327

@@ -44,6 +48,11 @@ class Semaphore : public Object<Semaphore, VkSemaphore>
4448
VkResult exportFd(int* pFd) const;
4549
#endif
4650

51+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
52+
VkResult importHandle(zx_handle_t handle, bool temporaryImport);
53+
VkResult exportHandle(zx_handle_t *pHandle) const;
54+
#endif
55+
4756
private:
4857
class External;
4958
class Impl;
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_
16+
#define VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_
17+
18+
#include "VkDebug.hpp"
19+
20+
#include <zircon/syscalls.h>
21+
22+
// An external semaphore implementation for the Zircon kernel using a simple
23+
// Zircon event handle. This matches
24+
// VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA
25+
// which is not official yet but used by Fuchsia at the moment.
26+
27+
namespace vk
28+
{
29+
30+
class Semaphore::External {
31+
public:
32+
// The type of external semaphore handle types supported by this implementation.
33+
static const VkExternalSemaphoreHandleTypeFlags kExternalSemaphoreHandleType =
34+
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
35+
36+
// Default constructor. Note that one should call either init() or
37+
// importFd() before any call to wait() or signal().
38+
External() = default;
39+
40+
~External()
41+
{
42+
zx_handle_close(handle);
43+
}
44+
45+
void init()
46+
{
47+
zx_status_t status = zx_event_create(0, &handle);
48+
if (status != ZX_OK)
49+
{
50+
ABORT("zx_event_create() returned %d", status);
51+
}
52+
}
53+
54+
void importHandle(zx_handle_t new_handle)
55+
{
56+
zx_handle_close(handle);
57+
handle = new_handle;
58+
}
59+
60+
VkResult exportHandle(zx_handle_t* pHandle) const
61+
{
62+
zx_handle_t new_handle = ZX_HANDLE_INVALID;
63+
zx_status_t status = zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &new_handle);
64+
if (status != ZX_OK)
65+
{
66+
TRACE("zx_handle_duplicate() returned %d", status);
67+
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
68+
}
69+
*pHandle = new_handle;
70+
return VK_SUCCESS;
71+
}
72+
73+
void wait()
74+
{
75+
zx_signals_t observed = 0;
76+
zx_status_t status = zx_object_wait_one(
77+
handle, ZX_EVENT_SIGNALED, ZX_TIME_INFINITE, &observed);
78+
if (status != ZX_OK)
79+
{
80+
ABORT("zx_object_wait_one() returned %d", status);
81+
}
82+
if (observed != ZX_EVENT_SIGNALED)
83+
{
84+
ABORT("zx_object_wait_one() returned observed %x (%x expected)", observed, ZX_EVENT_SIGNALED);
85+
}
86+
// Need to unsignal the event now, as required by the Vulkan spec.
87+
status = zx_object_signal(handle, ZX_EVENT_SIGNALED, 0);
88+
if (status != ZX_OK)
89+
{
90+
ABORT("zx_object_signal() returned %d", status);
91+
}
92+
}
93+
94+
bool tryWait()
95+
{
96+
zx_signals_t observed = 0;
97+
zx_status_t status = zx_object_wait_one(
98+
handle, ZX_EVENT_SIGNALED, zx_clock_get_monotonic(), &observed);
99+
if (status != ZX_OK)
100+
{
101+
ABORT("zx_object_wait_one() returned %d", status);
102+
}
103+
if (observed != ZX_EVENT_SIGNALED)
104+
{
105+
return false;
106+
}
107+
// Need to unsignal the event now, as required by the Vulkan spec.
108+
status = zx_object_signal(handle, ZX_EVENT_SIGNALED, 0);
109+
if (status != ZX_OK)
110+
{
111+
ABORT("zx_object_signal() returned %d", status);
112+
}
113+
return true;
114+
}
115+
116+
void signal()
117+
{
118+
zx_status_t status = zx_object_signal(handle, 0, ZX_EVENT_SIGNALED);
119+
if (status != ZX_OK)
120+
{
121+
ABORT("zx_object_signal() returned %d", status);
122+
}
123+
}
124+
125+
private:
126+
zx_handle_t handle = ZX_HANDLE_INVALID;
127+
};
128+
129+
} // namespace vk
130+
131+
#endif // VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_

src/Vulkan/libVulkan.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ static const VkExtensionProperties deviceExtensionProperties[] =
232232
#endif
233233
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_LINUX_MEMFD
234234
{ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION },
235+
#endif
236+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
237+
{ VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION },
235238
#endif
236239
{ VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, VK_EXT_PROVOKING_VERTEX_SPEC_VERSION },
237240
};
@@ -1022,6 +1025,42 @@ VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR(VkDevice device, const VkI
10221025
}
10231026
#endif // SWIFTSHADER_EXTERNAL_SEMAPHORE_LINUX_MEMFD
10241027

1028+
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
1029+
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA(
1030+
VkDevice device,
1031+
const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo)
1032+
{
1033+
TRACE("(VkDevice device = %p, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo = %p)",
1034+
device, pImportSemaphoreZirconHandleInfo);
1035+
1036+
if (pImportSemaphoreZirconHandleInfo->handleType != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA)
1037+
{
1038+
UNIMPLEMENTED("pImportSemaphoreZirconHandleInfo->handleType");
1039+
}
1040+
bool temporaryImport = (pImportSemaphoreZirconHandleInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) != 0;
1041+
1042+
return vk::Cast(pImportSemaphoreZirconHandleInfo->semaphore)->importHandle(
1043+
pImportSemaphoreZirconHandleInfo->handle,
1044+
temporaryImport);
1045+
}
1046+
1047+
VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA(
1048+
VkDevice device,
1049+
const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
1050+
zx_handle_t* pZirconHandle)
1051+
{
1052+
TRACE("(VkDevice device = %p, const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo = %p, zx_handle_t* pZirconHandle = %p)",
1053+
device, static_cast<const void*>(pGetZirconHandleInfo), static_cast<void*>(pZirconHandle));
1054+
1055+
if (pGetZirconHandleInfo->handleType != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA)
1056+
{
1057+
UNIMPLEMENTED("pGetZirconHandleInfo->handleType");
1058+
}
1059+
1060+
return vk::Cast(pGetZirconHandleInfo->semaphore)->exportHandle(pZirconHandle);
1061+
}
1062+
#endif // SWIFTSHADER_EXTERNAL_SEMAPHORE_ZIRCON_EVENT
1063+
10251064
VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent)
10261065
{
10271066
TRACE("(VkDevice device = %p, const VkEventCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkEvent* pEvent = %p)",

0 commit comments

Comments
 (0)