// 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.h"
#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_
