// 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 "VkConfig.hpp"
#include "VkObject.hpp"

#include "marl/event.h"
#include "marl/mutex.h"
#include "marl/tsa.h"

#if VK_USE_PLATFORM_FUCHSIA
#	include <zircon/types.h>
#endif

namespace vk {

class Semaphore : public Object<Semaphore, VkSemaphore>
{
public:
	Semaphore(const VkSemaphoreCreateInfo *pCreateInfo, void *mem, const VkAllocationCallbacks *pAllocator);
	void destroy(const VkAllocationCallbacks *pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo *pCreateInfo);

	void wait();

	void wait(const VkPipelineStageFlags &flag)
	{
		// NOTE: not sure what else to do here?
		wait();
	}

	void signal();

#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
	VkResult importFd(int fd, bool temporaryImport);
	VkResult exportFd(int *pFd);
#endif

#if VK_USE_PLATFORM_FUCHSIA
	VkResult importHandle(zx_handle_t handle, bool temporaryImport);
	VkResult exportHandle(zx_handle_t *pHandle);
#endif

	class External;

private:
	// 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;
	VkExternalSemaphoreHandleTypeFlags exportableHandleTypes = (VkExternalSemaphoreHandleTypeFlags)0;
	marl::Event internal;
	marl::mutex mutex;
	External *external GUARDED_BY(mutex) = nullptr;
	External *tempExternal GUARDED_BY(mutex) = nullptr;
};

static inline Semaphore *Cast(VkSemaphore object)
{
	return Semaphore::Cast(object);
}

}  // namespace vk

#endif  // VK_SEMAPHORE_HPP_
