Synchonization objects

Vulkan has multiple synchronization objects:
- Events, which provide synchronization between commands submitted
  to the same queue, or between the host and a queue.
- Fences, which insert a dependency from a queue to the host
- Semaphores, which insert a dependency between batches submitted
  to queues

For now, SwiftShader will treat these synchronization primitives as noop, since:
- Commands will be executed in order
- SwiftShader currently only supports 1 queue

Change-Id: Ic335e2f7aa30ab7314bf7585e11f1f30a79f50d6
Reviewed-on: https://swiftshader-review.googlesource.com/c/21588
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkDestroy.h b/src/Vulkan/VkDestroy.h
index f45ebcd..cf7251f 100644
--- a/src/Vulkan/VkDestroy.h
+++ b/src/Vulkan/VkDestroy.h
@@ -14,9 +14,12 @@
 
 #include "VkCommandBuffer.hpp"
 #include "VkDevice.hpp"
+#include "VkEvent.hpp"
+#include "VkFence.hpp"
 #include "VkInstance.hpp"
 #include "VkPhysicalDevice.hpp"
 #include "VkQueue.hpp"
+#include "VkSemaphore.hpp"
 
 namespace vk
 {
diff --git a/src/Vulkan/VkEvent.hpp b/src/Vulkan/VkEvent.hpp
new file mode 100644
index 0000000..538668b
--- /dev/null
+++ b/src/Vulkan/VkEvent.hpp
@@ -0,0 +1,63 @@
+// Copyright 2018 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_EVENT_HPP_
+#define VK_EVENT_HPP_
+
+#include "VkObject.hpp"
+
+namespace vk
+{
+
+class Event : public Object<Event, VkEvent>
+{
+public:
+	Event(const VkEventCreateInfo* pCreateInfo, void* mem)
+	{
+	}
+
+	~Event() = delete;
+
+	static size_t ComputeRequiredAllocationSize(const VkEventCreateInfo* pCreateInfo)
+	{
+		return 0;
+	}
+
+	void signal()
+	{
+		status = VK_EVENT_SET;
+	}
+
+	void reset()
+	{
+		status = VK_EVENT_RESET;
+	}
+
+	VkResult getStatus() const
+	{
+		return status;
+	}
+
+private:
+	VkResult status = VK_EVENT_RESET;
+};
+
+static inline Event* Cast(VkEvent object)
+{
+	return reinterpret_cast<Event*>(object);
+}
+
+} // namespace vk
+
+#endif // VK_EVENT_HPP_
diff --git a/src/Vulkan/VkFence.hpp b/src/Vulkan/VkFence.hpp
new file mode 100644
index 0000000..ba2e764
--- /dev/null
+++ b/src/Vulkan/VkFence.hpp
@@ -0,0 +1,64 @@
+// Copyright 2018 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_FENCE_HPP_
+#define VK_FENCE_HPP_
+
+#include "VkObject.hpp"
+
+namespace vk
+{
+
+class Fence : public Object<Fence, VkFence>
+{
+public:
+	Fence(const VkFenceCreateInfo* pCreateInfo, void* mem) :
+		status((pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? VK_SUCCESS : VK_NOT_READY)
+	{
+	}
+
+	~Fence() = delete;
+
+	static size_t ComputeRequiredAllocationSize(const VkFenceCreateInfo* pCreateInfo)
+	{
+		return 0;
+	}
+
+	void signal()
+	{
+		status = VK_SUCCESS;
+	}
+
+	void reset()
+	{
+		status = VK_NOT_READY;
+	}
+
+	VkResult getStatus() const
+	{
+		return status;
+	}
+
+private:
+	VkResult status = VK_NOT_READY;
+};
+
+static inline Fence* Cast(VkFence object)
+{
+	return reinterpret_cast<Fence*>(object);
+}
+
+} // namespace vk
+
+#endif // VK_FENCE_HPP_
diff --git a/src/Vulkan/VkSemaphore.hpp b/src/Vulkan/VkSemaphore.hpp
new file mode 100644
index 0000000..5f3ca05
--- /dev/null
+++ b/src/Vulkan/VkSemaphore.hpp
@@ -0,0 +1,62 @@
+// Copyright 2018 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_HPP_
+#define VK_SEMAPHORE_HPP_
+
+#include "VkObject.hpp"
+
+namespace vk
+{
+
+class Semaphore : public Object<Semaphore, VkSemaphore>
+{
+public:
+	Semaphore(const VkSemaphoreCreateInfo* pCreateInfo, void* mem) {}
+
+	~Semaphore() = delete;
+
+	static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo* pCreateInfo)
+	{
+		return 0;
+	}
+
+	void wait()
+	{
+		// Semaphores are noop for now
+	}
+
+	void wait(const VkPipelineStageFlags& flag)
+	{
+		// VkPipelineStageFlags is the pipeline stage at which the semaphore wait will occur
+
+		// Semaphores are noop for now
+	}
+
+	void signal()
+	{
+		// Semaphores are noop for now
+	}
+
+private:
+};
+
+static inline Semaphore* Cast(VkSemaphore object)
+{
+	return reinterpret_cast<Semaphore*>(object);
+}
+
+} // namespace vk
+
+#endif // VK_SEMAPHORE_HPP_
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index b5bd7f6..26ee8cd 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -17,10 +17,13 @@
 #include "VkDebug.hpp"
 #include "VkDestroy.h"
 #include "VkDevice.hpp"
+#include "VkEvent.hpp"
+#include "VkFence.hpp"
 #include "VkGetProcAddress.h"
 #include "VkInstance.hpp"
 #include "VkPhysicalDevice.hpp"
 #include "VkQueue.hpp"
+#include "VkSemaphore.hpp"
 #include <cstring>
 #include <string>
 
@@ -487,9 +490,12 @@
 	TRACE("(VkDevice device = 0x%X, const VkFenceCreateInfo* pCreateInfo = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X, VkFence* pFence = 0x%X)",
 		    device, pCreateInfo, pAllocator, pFence);
 
-	UNIMPLEMENTED();
+	if(pCreateInfo->pNext)
+	{
+		UNIMPLEMENTED();
+	}
 
-	return VK_SUCCESS;
+	return vk::Fence::Create(pAllocator, pCreateInfo, pFence);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator)
@@ -497,21 +503,28 @@
 	TRACE("(VkDevice device = 0x%X, VkFence fence = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X)",
 		    device, fence, pAllocator);
 
-	UNIMPLEMENTED();
+
+	vk::destroy(fence, pAllocator);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, uint32_t fenceCount = %d, const VkFence* pFences = 0x%X)",
+	      device, fenceCount, pFences);
+
+	for(uint32_t i = 0; i < fenceCount; i++)
+	{
+		vk::Cast(pFences[i])->reset();
+	}
+
 	return VK_SUCCESS;
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
-	return VK_SUCCESS;
+	TRACE("(VkDevice device = 0x%X, VkFence fence = 0x%X)", device, fence);
+
+	return vk::Cast(fence)->getStatus();
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout)
@@ -523,48 +536,68 @@
 
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
-	return VK_SUCCESS;
+	TRACE("(VkDevice device = 0x%X, const VkSemaphoreCreateInfo* pCreateInfo = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X, VkSemaphore* pSemaphore = 0x%X)",
+	      device, pCreateInfo, pAllocator, pSemaphore);
+
+	if(pCreateInfo->pNext || pCreateInfo->flags)
+	{
+		UNIMPLEMENTED();
+	}
+
+	return vk::Semaphore::Create(pAllocator, pCreateInfo, pSemaphore);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, VkSemaphore semaphore = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X)",
+	      device, semaphore, pAllocator);
+
+	vk::destroy(semaphore, pAllocator);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
-	return VK_SUCCESS;
+	TRACE("(VkDevice device = 0x%X, const VkEventCreateInfo* pCreateInfo = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X, VkEvent* pEvent = 0x%X)",
+	      device, pCreateInfo, pAllocator, pEvent);
+
+	if(pCreateInfo->pNext || pCreateInfo->flags)
+	{
+		UNIMPLEMENTED();
+	}
+
+	return vk::Event::Create(pAllocator, pCreateInfo, pEvent);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, VkEvent event = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X)",
+	      device, event, pAllocator);
+
+	vk::destroy(event, pAllocator);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device, VkEvent event)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
-	return VK_SUCCESS;
+	TRACE("(VkDevice device = 0x%X, VkEvent event = 0x%X)", device, event);
+
+	return vk::Cast(event)->getStatus();
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, VkEvent event = 0x%X)", device, event);
+
+	vk::Cast(event)->signal();
+
 	return VK_SUCCESS;
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkEvent event)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, VkEvent event = 0x%X)", device, event);
+
+	vk::Cast(event)->reset();
+
 	return VK_SUCCESS;
 }
 
diff --git a/src/Vulkan/vulkan.vcxproj b/src/Vulkan/vulkan.vcxproj
index ce9f4a4..e498095 100644
--- a/src/Vulkan/vulkan.vcxproj
+++ b/src/Vulkan/vulkan.vcxproj
@@ -276,12 +276,15 @@
     <ClInclude Include="VkDebug.hpp" />

     <ClInclude Include="VkDestroy.h" />

     <ClInclude Include="VkDevice.hpp" />

+    <ClInclude Include="VkEvent.hpp" />

+    <ClInclude Include="VkFence.hpp" />

     <ClInclude Include="VkGetProcAddress.h" />

     <ClInclude Include="VkInstance.hpp" />

     <ClInclude Include="VkMemory.h" />

     <ClInclude Include="VkObject.hpp" />

     <ClInclude Include="VkPhysicalDevice.hpp" />

     <ClInclude Include="VkQueue.hpp" />

+    <ClInclude Include="VkSemaphore.hpp" />

     <ClInclude Include="..\Device\Blitter.hpp" />

     <ClInclude Include="..\Device\Clipper.hpp" />

     <ClInclude Include="..\Device\Color.hpp" />

diff --git a/src/Vulkan/vulkan.vcxproj.filters b/src/Vulkan/vulkan.vcxproj.filters
index 1317185..5486518 100644
--- a/src/Vulkan/vulkan.vcxproj.filters
+++ b/src/Vulkan/vulkan.vcxproj.filters
@@ -248,6 +248,12 @@
     <ClInclude Include="VkDevice.hpp">

       <Filter>Header Files\Vulkan</Filter>

     </ClInclude>

+    <ClInclude Include="VkEvent.hpp">

+      <Filter>Header Files\Vulkan</Filter>

+    </ClInclude>

+    <ClInclude Include="VkFence.hpp">

+      <Filter>Header Files\Vulkan</Filter>

+    </ClInclude>

     <ClInclude Include="VkGetProcAddress.h">

       <Filter>Header Files\Vulkan</Filter>

     </ClInclude>

@@ -266,6 +272,9 @@
     <ClInclude Include="VkQueue.hpp">

       <Filter>Header Files\Vulkan</Filter>

     </ClInclude>

+    <ClInclude Include="VkSemaphore.hpp">

+      <Filter>Header Files\Vulkan</Filter>

+    </ClInclude>

     <ClInclude Include="..\Device\VertexProcessor.hpp">

       <Filter>Header Files\Device</Filter>

     </ClInclude>