[vulkan]: Support multiple external semaphore implementations.
This CL refactors the implementation of VkSemaphore objects
in the following way:
- Add the ability to support several external handle types
concurrently. Before this CL, each platform could support
a single handle type (e.g. on Linux,
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT only).
The changes here will allow future CLs to support more than
one type per platform (e.g. the Linux implementation may
support OPAQUE_FD_BIT as well as SYNC_FD_BIT at the same
time).
- Better implementation of temporary imports. In particular,
the following sequence now works properly:
1) Create exportable semaphore A.
2) Export A to an external handle/descriptor.
3) Signal A.
4) Temporarily import _another_ handle into A.
5) A.wait() // waits on the temporary payload, then discard it.
Before the CL, A would end up, incorrectly, unsignalled. Because
the export operation created an External instance that held
the payload modified in 3), which was then discarded after
the wait() in 5).
- Improved and consistent handling of errors during import/export
operations, through the use of templates.
+ Add a technical note in VkSemaphore.h explaining how everything
works, since there are several subtle points in the spec.
Bug: b/140421736
Change-Id: I9b6935db3238fec7af8e0c81666e2f5c72075756
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39880
Tested-by: David Turner <digit@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Kokoro-Presubmit: David Turner <digit@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Vulkan/BUILD.gn b/src/Vulkan/BUILD.gn
index 9ea2d28..19b7e79 100644
--- a/src/Vulkan/BUILD.gn
+++ b/src/Vulkan/BUILD.gn
@@ -101,8 +101,6 @@
]
} else if (is_fuchsia) {
sources += [ "VkSemaphoreExternalFuchsia.hpp" ]
- } else {
- sources += [ "VkSemaphoreExternalNone.hpp" ]
}
}
diff --git a/src/Vulkan/VkSemaphore.cpp b/src/Vulkan/VkSemaphore.cpp
index 72bee8b..8daef84 100644
--- a/src/Vulkan/VkSemaphore.cpp
+++ b/src/Vulkan/VkSemaphore.cpp
@@ -17,18 +17,6 @@
#include "VkConfig.h"
#include "VkStringify.hpp"
-#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
-# if defined(__linux__) || defined(__ANDROID__)
-# include "VkSemaphoreExternalLinux.hpp"
-# else
-# error "Missing VK_KHR_external_semaphore_fd implementation for this platform!"
-# endif
-#elif VK_USE_PLATFORM_FUCHSIA
-# include "VkSemaphoreExternalFuchsia.hpp"
-#else
-# include "VkSemaphoreExternalNone.hpp"
-#endif
-
#include "marl/blockingcall.h"
#include "marl/conditionvariable.h"
@@ -38,11 +26,76 @@
namespace vk {
+// This is a base abstract class for all external semaphore implementations
+// used in this source file.
+class Semaphore::External
+{
+public:
+ virtual ~External() = default;
+
+ // Initialize new instance with a given initial state.
+ virtual VkResult init(bool initialState) = 0;
+
+ virtual bool tryWait() = 0;
+ virtual void wait() = 0;
+ virtual void signal() = 0;
+
+ // For VK_KHR_external_semaphore_fd
+ virtual VkResult importOpaqueFd(int fd)
+ {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+
+ virtual VkResult exportOpaqueFd(int *pFd)
+ {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+
+#if VK_USE_PLATFORM_FUCHSIA
+ // For VK_FUCHSIA_external_semaphore
+ virtual VkResult importHandle(zx_handle_t handle)
+ {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ virtual VkResult exportHandle(zx_handle_t *pHandle)
+ {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+#endif
+ // Pointer to previous temporary external instanc,e used for |tempExternal| only.
+ External *previous = nullptr;
+};
+
+} // namespace vk
+
+#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
+# if defined(__linux__) || defined(__ANDROID__)
+# include "VkSemaphoreExternalLinux.hpp"
+# else
+# error "Missing VK_KHR_external_semaphore_fd implementation for this platform!"
+# endif
+#elif VK_USE_PLATFORM_FUCHSIA
+# include "VkSemaphoreExternalFuchsia.hpp"
+#endif
+
+namespace vk {
+
+// The bitmask of all external semaphore handle types supported by this source file.
+static const VkExternalSemaphoreHandleTypeFlags kSupportedTypes =
+#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
+#endif
+#if VK_USE_PLATFORM_FUCHSIA
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA |
+#endif
+ 0;
+
namespace {
struct SemaphoreCreateInfo
{
bool exportSemaphore = false;
+ VkExternalSemaphoreHandleTypeFlags exportHandleTypes = 0;
// Create a new instance. The external instance will be allocated only
// the pCreateInfo->pNext chain indicates it needs to be exported.
@@ -57,9 +110,12 @@
{
const auto *exportInfo = reinterpret_cast<const VkExportSemaphoreCreateInfo *>(nextInfo);
exportSemaphore = true;
- if(exportInfo->handleTypes != Semaphore::External::kExternalSemaphoreHandleType)
+ exportHandleTypes = exportInfo->handleTypes;
+ if((exportHandleTypes & ~kSupportedTypes) != 0)
{
- UNSUPPORTED("exportInfo->handleTypes %d", int(exportInfo->handleTypes));
+ UNSUPPORTED("exportInfo->handleTypes 0x%X (supports 0x%X)",
+ int(exportHandleTypes),
+ int(kSupportedTypes));
}
}
break;
@@ -74,27 +130,30 @@
void Semaphore::wait()
{
- if(external)
+ std::unique_lock<std::mutex> lock(mutex);
+ External *ext = tempExternal ? tempExternal : external;
+ if(ext)
{
- if(!external->tryWait())
+ if(!ext->tryWait())
{
- // Dispatch the external wait to a background thread.
+ // Dispatch the ext wait to a background thread.
// Even if this creates a new thread on each
// call, it is assumed that this is negligible
// compared with the actual semaphore wait()
// operation.
- marl::blocking_call([this]() {
- external->wait();
+ marl::blocking_call([ext, &lock]() {
+ lock.unlock();
+ ext->wait();
+ lock.lock();
});
}
- // If the import was temporary, reset the semaphore to its
- // permanent state by getting rid of |external|.
+ // If the import was temporary, reset the semaphore to its previous state.
// See "6.4.5. Importing Semaphore Payloads" in Vulkan 1.1 spec.
- if(temporaryImport)
+ if(ext == tempExternal)
{
- deallocateExternal();
- temporaryImport = false;
+ tempExternal = ext->previous;
+ deallocateExternal(ext);
}
}
else
@@ -105,11 +164,13 @@
void Semaphore::signal()
{
- if(external)
+ std::unique_lock<std::mutex> lock(mutex);
+ External *ext = tempExternal ? tempExternal : external;
+ if(ext)
{
// Assumes that signalling an external semaphore is non-blocking,
// so it can be performed directly either from a fiber or thread.
- external->signal();
+ ext->signal();
}
else
{
@@ -121,16 +182,22 @@
: allocator(pAllocator)
{
SemaphoreCreateInfo info(pCreateInfo);
- if(info.exportSemaphore)
- {
- allocateExternal();
- external->init();
- }
+ exportableHandleTypes = info.exportHandleTypes;
}
void Semaphore::destroy(const VkAllocationCallbacks *pAllocator)
{
- deallocateExternal();
+ while(tempExternal)
+ {
+ External *ext = tempExternal;
+ tempExternal = ext->previous;
+ deallocateExternal(ext);
+ }
+ if(external)
+ {
+ deallocateExternal(external);
+ external = nullptr;
+ }
}
size_t Semaphore::ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo *pCreateInfo)
@@ -139,78 +206,140 @@
return 0;
}
-void Semaphore::allocateExternal()
+template<class EXTERNAL>
+Semaphore::External *Semaphore::allocateExternal()
{
- ASSERT(external == nullptr);
- external = reinterpret_cast<Semaphore::External *>(
- vk::allocate(sizeof(Semaphore::External), vk::REQUIRED_MEMORY_ALIGNMENT, allocator));
- new(external) Semaphore::External();
+ auto *ext = reinterpret_cast<Semaphore::External *>(
+ vk::allocate(sizeof(EXTERNAL), alignof(EXTERNAL), allocator));
+ new(ext) EXTERNAL();
+ return ext;
}
-void Semaphore::deallocateExternal()
+void Semaphore::deallocateExternal(Semaphore::External *ext)
{
- if(external)
+ ext->~External();
+ vk::deallocate(ext, allocator);
+}
+
+template<typename ALLOC_FUNC, typename IMPORT_FUNC>
+VkResult Semaphore::importPayload(bool temporaryImport,
+ ALLOC_FUNC alloc_func,
+ IMPORT_FUNC import_func)
+{
+ std::unique_lock<std::mutex> lock(mutex);
+
+ // Create new External instance if needed.
+ External *ext = external;
+ if(temporaryImport || !ext)
{
- vk::deallocate(external, allocator);
- external = nullptr;
+ ext = alloc_func();
}
+ VkResult result = import_func(ext);
+ if(result != VK_SUCCESS)
+ {
+ if(temporaryImport || !external)
+ {
+ deallocateExternal(ext);
+ }
+ return result;
+ }
+
+ if(temporaryImport)
+ {
+ ext->previous = tempExternal;
+ tempExternal = ext;
+ }
+ else if(!external)
+ {
+ external = ext;
+ }
+ return VK_SUCCESS;
+}
+
+template<typename ALLOC_FUNC, typename EXPORT_FUNC>
+VkResult Semaphore::exportPayload(ALLOC_FUNC alloc_func, EXPORT_FUNC export_func)
+{
+ std::unique_lock<std::mutex> lock(mutex);
+ // Sanity check, do not try to export a semaphore that has a temporary import.
+ if(tempExternal != nullptr)
+ {
+ TRACE("Cannot export semaphore with a temporary import!");
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ // Allocate |external| if it doesn't exist yet.
+ if(!external)
+ {
+ External *ext = alloc_func();
+ VkResult result = ext->init(internal.isSignalled());
+ if(result != VK_SUCCESS)
+ {
+ deallocateExternal(ext);
+ return result;
+ }
+ external = ext;
+ }
+ return export_func(external);
}
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
-VkResult Semaphore::importFd(int fd, bool tempImport)
+VkResult Semaphore::importFd(int fd, bool temporaryImport)
{
- std::unique_lock<std::mutex> lock(mutex);
- if(!external)
- {
- allocateExternal();
- }
- VkResult result = external->importFd(fd);
- if(result != VK_SUCCESS)
- {
- deallocateExternal();
- }
- else
- {
- temporaryImport = tempImport;
- }
- return result;
+ return importPayload(
+ temporaryImport,
+ [this]() {
+ return allocateExternal<OpaqueFdExternalSemaphore>();
+ },
+ [fd](External *ext) {
+ return ext->importOpaqueFd(fd);
+ });
}
VkResult Semaphore::exportFd(int *pFd)
{
- std::unique_lock<std::mutex> lock(mutex);
- if(!external)
+ if((exportableHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) == 0)
{
- TRACE("Cannot export non-external semaphore");
+ TRACE("Cannot export semaphore as opaque FD (exportableHandleType = 0x%X, want 0x%X)",
+ exportableHandleTypes,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
+
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
- return external->exportFd(pFd);
+
+ return exportPayload([this]() { return allocateExternal<OpaqueFdExternalSemaphore>(); },
+ [pFd](External *ext) {
+ return ext->exportOpaqueFd(pFd);
+ });
}
#endif // SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
#if VK_USE_PLATFORM_FUCHSIA
-VkResult Semaphore::importHandle(zx_handle_t handle, bool tempImport)
+VkResult Semaphore::importHandle(zx_handle_t handle, bool temporaryImport)
{
- std::unique_lock<std::mutex> lock(mutex);
- if(!external)
- {
- allocateExternal();
- }
- // NOTE: Imports are just moving a handle so cannot fail.
- external->importHandle(handle);
- temporaryImport = tempImport;
- return VK_SUCCESS;
+ return importPayload(
+ temporaryImport,
+ [this]() {
+ return allocateExternal<ZirconEventExternalSemaphore>();
+ },
+ [handle](External *ext) {
+ return ext->importHandle(handle);
+ });
}
VkResult Semaphore::exportHandle(zx_handle_t *pHandle)
{
- std::unique_lock<std::mutex> lock(mutex);
- if(!external)
+ if((exportableHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA) == 0)
{
- TRACE("Cannot export non-external semaphore");
+ TRACE("Cannot export semaphore as Zircon handle (exportableHandleType = 0x%X, want 0x%X)",
+ exportableHandleTypes,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA);
+
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
- return external->exportHandle(pHandle);
+
+ return exportPayload([this]() { return allocateExternal<ZirconEventExternalSemaphore>(); },
+ [pHandle](External *ext) {
+ return ext->exportHandle(pHandle);
+ });
}
#endif // VK_USE_PLATFORM_FUCHSIA
diff --git a/src/Vulkan/VkSemaphore.hpp b/src/Vulkan/VkSemaphore.hpp
index 54004d8..b67d4d9 100644
--- a/src/Vulkan/VkSemaphore.hpp
+++ b/src/Vulkan/VkSemaphore.hpp
@@ -58,14 +58,99 @@
class External;
private:
- void allocateExternal();
- void deallocateExternal();
+ // Small technical note on how semaphores are imported/exported with Vulkan:
+ //
+ // - A Vulkan Semaphore objects has a "payload", corresponding to a
+ // simple atomic boolean flag.
+ //
+ // - A Vulkan Semaphore object can be "exported": this creates a
+ // platform-specific handle / descriptor (which can be passed to other
+ // processes), and is linked in some way to the original semaphore's
+ // payload.
+ //
+ // - Similarly, said handle / descriptor can be "imported" into a Vulkan
+ // Semaphore object. By default, that semaphore loses its payload, and
+ // instead uses the one referenced / shared through the descriptor.
+ //
+ // Hence if semaphore A exports its payload through a descriptor that
+ // is later imported into semaphore B, then both A and B will use/share
+ // the same payload (i.e. signal flag), making cross-process
+ // synchronization possible.
+ //
+ // - There are also "temporary imports", where the target semaphore's
+ // payload is not lost, but is simply hidden/stashed. But the next wait()
+ // operation on the same semaphore should remove the temporary import,
+ // and restore the previous payload.
+ //
+ // - There are many handle / descriptor types, which are listed through
+ // the VkExternalSemaphoreHandleTypeFlagBits. A given Vulkan
+ // implementation might support onle one or several at the same time
+ // (e.g. on Linux or Android, it could support both OPAQUE_FD_BIT and
+ // SYNC_FD_BIT, while on Windows, it would be OPAQUE_WIN32_BIT +
+ // OPAQUE_WIN32_KMT_BIT + D3D12_FENCE_BIT).
+ //
+ // - To be able to export a semaphore, VkCreateSemaphore() must be called
+ // with a VkSemaphoreCreateInfo that lists the types of all possible
+ // platform-specific handles the semaphore could be exported to
+ // (e.g. on Linux, it is possible to specify that a semaphore might be
+ // exported as an opaque FD, or as a Linux Sync FD).
+ //
+ // However, which exact type is however only determined later by the
+ // export operation itself (e.g. vkGetSemaphoreFdKHR() could be called to export
+ // either a VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT or a
+ // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).
+ //
+ // Once a semaphore has been exported as one type, it is not possible
+ // to export the same payload with a different type (though the spec
+ // doesn't seem to be explicit about this, it's simply impossible in
+ // general).
+ //
+ // This leads to the following design:
+ //
+ // - |internal| is a simple marl::Event that represents the semaphore's
+ // payload when it is not exported, or imported non-temporarily.
+ //
+ // - |external| points to an external semaphore payload. It is created
+ // on demand if the semaphore is exported or imported non-temporarily.
+ // Note that once |external| is created, |internal| is ignored.
+ //
+ // - |tempExternal| points to a linked-list of temporary external
+ // semaphore payloads. The list head corresponds to the most recent
+ // temporary import.
+ //
+
+ // Internal template to allocate a new External implementation.
+ template<class EXTERNAL>
+ External *allocateExternal();
+
+ void deallocateExternal(External *ext);
+
+ // Used internally to import an external payload.
+ // |temporaryImport| is true iff the import is temporary.
+ // |alloc_func| is callable that allocates a new External instance of the
+ // appropriate type.
+ // |import_func| is callable that takes a single parameter, which
+ // corresponds to the external handle/descriptor, and returns a VkResult
+ // values.
+ template<typename ALLOC_FUNC, typename IMPORT_FUNC>
+ VkResult importPayload(bool temporaryImport,
+ ALLOC_FUNC alloc_func,
+ IMPORT_FUNC import_func);
+
+ // Used internally to export a given payload.
+ // |alloc_func| is a callable that allocates a new External instance of
+ // the appropriate type.
+ // |export_func| is a callable that takes a pointer to an External instance,
+ // and a pointer to a handle/descriptor, and returns a VkResult.
+ template<typename ALLOC_FUNC, typename EXPORT_FUNC>
+ VkResult exportPayload(ALLOC_FUNC alloc_func, EXPORT_FUNC export_func);
const VkAllocationCallbacks *allocator = nullptr;
- marl::Event internal;
+ VkExternalSemaphoreHandleTypeFlags exportableHandleTypes = (VkExternalSemaphoreHandleTypeFlags)0;
std::mutex mutex;
+ marl::Event internal;
External *external = nullptr;
- bool temporaryImport = false;
+ External *tempExternal = nullptr;
};
static inline Semaphore *Cast(VkSemaphore object)
diff --git a/src/Vulkan/VkSemaphoreExternalFuchsia.hpp b/src/Vulkan/VkSemaphoreExternalFuchsia.hpp
index a45f0b8..90f68d4 100644
--- a/src/Vulkan/VkSemaphoreExternalFuchsia.hpp
+++ b/src/Vulkan/VkSemaphoreExternalFuchsia.hpp
@@ -26,38 +26,44 @@
namespace vk {
-class Semaphore::External
+class ZirconEventExternalSemaphore : public Semaphore::External
{
public:
- // The type of external semaphore handle types supported by this implementation.
- static const VkExternalSemaphoreHandleTypeFlags kExternalSemaphoreHandleType =
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
-
- // Default constructor. Note that one should call either init() or
- // importFd() before any call to wait() or signal().
- External() = default;
-
- ~External()
+ ~ZirconEventExternalSemaphore()
{
zx_handle_close(handle);
}
- void init()
+ VkResult init(bool initialValue) override
{
zx_status_t status = zx_event_create(0, &handle);
if(status != ZX_OK)
{
- ABORT("zx_event_create() returned %d", status);
+ TRACE("zx_event_create() returned %d", status);
+ return VK_ERROR_INITIALIZATION_FAILED;
}
+ if(initialValue)
+ {
+ status = zx_object_signal(handle, 0, ZX_EVENT_SIGNALED);
+ if(status != ZX_OK)
+ {
+ TRACE("zx_object_signal() returned %d", status);
+ zx_handle_close(handle);
+ handle = ZX_HANDLE_INVALID;
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ }
+ return VK_SUCCESS;
}
- void importHandle(zx_handle_t new_handle)
+ VkResult importHandle(zx_handle_t new_handle) override
{
zx_handle_close(handle);
handle = new_handle;
+ return VK_SUCCESS;
}
- VkResult exportHandle(zx_handle_t *pHandle) const
+ VkResult exportHandle(zx_handle_t *pHandle) override
{
zx_handle_t new_handle = ZX_HANDLE_INVALID;
zx_status_t status = zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &new_handle);
@@ -70,7 +76,7 @@
return VK_SUCCESS;
}
- void wait()
+ void wait() override
{
zx_signals_t observed = 0;
zx_status_t status = zx_object_wait_one(
@@ -91,7 +97,7 @@
}
}
- bool tryWait()
+ bool tryWait() override
{
zx_signals_t observed = 0;
zx_status_t status = zx_object_wait_one(
@@ -113,7 +119,7 @@
return true;
}
- void signal()
+ void signal() override
{
zx_status_t status = zx_object_signal(handle, 0, ZX_EVENT_SIGNALED);
if(status != ZX_OK)
diff --git a/src/Vulkan/VkSemaphoreExternalLinux.hpp b/src/Vulkan/VkSemaphoreExternalLinux.hpp
index 36bac26..d4e4cd2 100644
--- a/src/Vulkan/VkSemaphoreExternalLinux.hpp
+++ b/src/Vulkan/VkSemaphoreExternalLinux.hpp
@@ -44,7 +44,8 @@
class SharedSemaphore
{
public:
- SharedSemaphore()
+ SharedSemaphore(bool initialValue)
+ : signaled(initialValue)
{
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
@@ -129,20 +130,13 @@
namespace vk {
-class Semaphore::External
+class OpaqueFdExternalSemaphore : public Semaphore::External
{
public:
- // The type of external semaphore handle types supported by this implementation.
- static const VkExternalSemaphoreHandleTypeFlags kExternalSemaphoreHandleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
-
- // Default constructor. Note that one should call either init() or
- // importFd() before any call to wait() or signal().
- External() = default;
-
- ~External() { close(); }
+ ~OpaqueFdExternalSemaphore() { unmapRegion(); }
// Initialize instance by creating a new shared memory region.
- void init()
+ VkResult init(bool initialState) override
{
// Allocate or import the region's file descriptor.
const size_t size = sw::memoryPageSize();
@@ -153,24 +147,30 @@
snprintf(name, sizeof(name), "SwiftShader.Semaphore.%d", ++counter);
if(!memfd.allocate(name, size))
{
- ABORT("memfd.allocate() returned %s", strerror(errno));
+ TRACE("memfd.allocate() returned %s", strerror(errno));
+ return VK_ERROR_INITIALIZATION_FAILED;
}
- mapRegion(size, true);
+ if(!mapRegion(size, true, initialState))
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ return VK_SUCCESS;
}
// Import an existing semaphore through its file descriptor.
- VkResult importFd(int fd)
+ VkResult importOpaqueFd(int fd) override
{
- close();
+ unmapRegion();
memfd.importFd(fd);
- mapRegion(sw::memoryPageSize(), false);
+ if(!mapRegion(sw::memoryPageSize(), false, false))
+ return VK_ERROR_INITIALIZATION_FAILED;
+
return VK_SUCCESS;
}
// Export the current semaphore as a duplicated file descriptor to the same
// region. This can be consumed by importFd() running in a different
// process.
- VkResult exportFd(int *pFd) const
+ VkResult exportOpaqueFd(int *pFd) override
{
int fd = memfd.exportFd();
if(fd < 0)
@@ -181,24 +181,23 @@
return VK_SUCCESS;
}
- void wait()
+ void wait() override
{
semaphore->wait();
}
- bool tryWait()
+ bool tryWait() override
{
return semaphore->tryWait();
}
- void signal()
+ void signal() override
{
semaphore->signal();
}
private:
- // Unmap the semaphore if needed and close its file descriptor.
- void close()
+ void unmapRegion()
{
if(semaphore)
{
@@ -213,23 +212,25 @@
}
// Remap the shared region and setup the semaphore or increment its reference count.
- void mapRegion(size_t size, bool needInitialization)
+ bool mapRegion(size_t size, bool needsInitialization, bool initialValue)
{
// Map the region into memory and point the semaphore to it.
void *addr = memfd.mapReadWrite(0, size);
if(!addr)
{
- ABORT("mmap() failed: %s", strerror(errno));
+ TRACE("mmap() failed: %s", strerror(errno));
+ return false;
}
semaphore = reinterpret_cast<SharedSemaphore *>(addr);
- if(needInitialization)
+ if(needsInitialization)
{
- new(semaphore) SharedSemaphore();
+ new(semaphore) SharedSemaphore(initialValue);
}
else
{
semaphore->addRef();
}
+ return true;
}
LinuxMemFd memfd;
diff --git a/src/Vulkan/VkSemaphoreExternalNone.hpp b/src/Vulkan/VkSemaphoreExternalNone.hpp
deleted file mode 100644
index 9592e3f..0000000
--- a/src/Vulkan/VkSemaphoreExternalNone.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef VK_SEMAPHORE_EXTERNAL_NONE_H_
-#define VK_SEMAPHORE_EXTERNAL_NONE_H_
-
-namespace vk {
-
-// Empty external sempahore implementation.
-class Semaphore::External
-{
-public:
- // The type of external semaphore handle types supported by this implementation.
- static const VkExternalSemaphoreHandleTypeFlags kExternalSemaphoreHandleType = 0;
-
- void init() {}
-
- void wait() {}
-
- bool tryWait() { return true; }
-
- void signal() {}
-
-private:
- int dummy;
-};
-
-} // namespace vk
-
-#endif // VK_SEMAPHORE_EXTERNAL_NONE_H_