[vulkan]: Implement VkSemaphore using Marl primitives.
Proper implementation of a VkSemaphore using an std::mutex
and a marl::ConditionVariable. This should make the implementation
compatible with both fibers and threads at the same time.
A future CL will add platform-specific implementations to cover
external semaphores as well. Which explains why the implementation
details are hidden from VkSemaphore.hpp.
Bug: b/140421726
Change-Id: I1db55493a41db0eb60ce9181fe864253db09f4f8
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35933
Tested-by: David Turner <digit@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/BUILD.gn b/src/Vulkan/BUILD.gn
index 8c6141b..8e19658 100644
--- a/src/Vulkan/BUILD.gn
+++ b/src/Vulkan/BUILD.gn
@@ -113,6 +113,7 @@
"VkQueue.cpp",
"VkRenderPass.cpp",
"VkSampler.cpp",
+ "VkSemaphore.cpp",
"VkShaderModule.cpp",
"Vulkan.rc",
"libVulkan.cpp",
diff --git a/src/Vulkan/VkSemaphore.cpp b/src/Vulkan/VkSemaphore.cpp
new file mode 100644
index 0000000..04a1c26
--- /dev/null
+++ b/src/Vulkan/VkSemaphore.cpp
@@ -0,0 +1,78 @@
+// 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.
+
+#include "VkSemaphore.hpp"
+
+#include "marl/conditionvariable.h"
+#include <mutex>
+
+namespace vk
+{
+
+// An implementation of VkSemaphore based on Marl primitives.
+class Semaphore::Impl
+{
+public:
+ Impl() = default;
+
+ void wait()
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ condition.wait(lock, [this]{ return this->signaled; });
+ signaled = false; // Vulkan requires resetting after waiting.
+ }
+
+ void signal()
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ if (!signaled)
+ {
+ signaled = true;
+ condition.notify_one();
+ }
+ }
+
+private:
+ std::mutex mutex;
+ marl::ConditionVariable condition;
+ bool signaled = false;
+};
+
+Semaphore::Semaphore(const VkSemaphoreCreateInfo* pCreateInfo, void* mem)
+{
+ impl = new (mem) Impl();
+}
+
+void Semaphore::destroy(const VkAllocationCallbacks* pAllocator)
+{
+ impl->~Impl();
+ vk::deallocate(impl, pAllocator);
+}
+
+size_t Semaphore::ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo* pCreateInfo)
+{
+ return sizeof(Semaphore::Impl);
+}
+
+void Semaphore::wait()
+{
+ impl->wait();
+}
+
+void Semaphore::signal()
+{
+ impl->signal();
+}
+
+} // namespace vk
diff --git a/src/Vulkan/VkSemaphore.hpp b/src/Vulkan/VkSemaphore.hpp
index d3ecae4..1f9b160 100644
--- a/src/Vulkan/VkSemaphore.hpp
+++ b/src/Vulkan/VkSemaphore.hpp
@@ -23,31 +23,24 @@
class Semaphore : public Object<Semaphore, VkSemaphore>
{
public:
- Semaphore(const VkSemaphoreCreateInfo* pCreateInfo, void* mem) {}
+ Semaphore(const VkSemaphoreCreateInfo* pCreateInfo, void* mem);
+ void destroy(const VkAllocationCallbacks* pAllocator);
- static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo* pCreateInfo)
- {
- return 0;
- }
+ static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo* pCreateInfo);
- void wait()
- {
- // Semaphores are noop for now
- }
+ void wait();
void wait(const VkPipelineStageFlags& flag)
{
- // VkPipelineStageFlags is the pipeline stage at which the semaphore wait will occur
-
- // Semaphores are noop for now
+ // NOTE: not sure what else to do here?
+ wait();
}
- void signal()
- {
- // Semaphores are noop for now
- }
+ void signal();
private:
+ class Impl;
+ Impl* impl = nullptr;
};
static inline Semaphore* Cast(VkSemaphore object)