/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 * Copyright (c) 2019 Valve Corporation.
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Tests for the present id and present wait extensions.
 *//*--------------------------------------------------------------------*/

#include "vktWsiPresentIdWaitTests.hpp"
#include "vktTestCase.hpp"
#include "vktCustomInstancesDevices.hpp"
#include "vktNativeObjectsUtil.hpp"

#include "vkQueryUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkWsiUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkRefUtil.hpp"

#include "tcuTestContext.hpp"
#include "tcuPlatform.hpp"
#include "tcuCommandLine.hpp"
#include "tcuTestLog.hpp"

#include "deDefs.hpp"

#include <vector>
#include <string>
#include <set>
#include <sstream>
#include <chrono>
#include <algorithm>
#include <utility>
#include <limits>

using std::vector;
using std::string;
using std::set;

namespace vkt
{
namespace wsi
{

namespace
{

// Handy time constants in nanoseconds.
constexpr deUint64 k10sec	= 10000000000ull;
constexpr deUint64 k1sec	=  1000000000ull;

// 100 milliseconds, way above 1/50 seconds for systems with 50Hz ticks.
// This should also take into account possible measure deviations due to the machine being loaded.
constexpr deUint64 kMargin	=   100000000ull;

using TimeoutRange = std::pair<deInt64, deInt64>;

// Calculate acceptable timeout range based on indicated timeout and taking into account kMargin.
TimeoutRange calcTimeoutRange (deUint64 timeout)
{
	constexpr auto kUnsignedMax	= std::numeric_limits<deUint64>::max();
	constexpr auto kSignedMax	= static_cast<deUint64>(std::numeric_limits<deInt64>::max());

	// Watch for over- and under-flows.
	deUint64 timeoutMin = ((timeout < kMargin) ? 0ull : (timeout - kMargin));
	deUint64 timeoutMax = ((kUnsignedMax - timeout < kMargin) ? kUnsignedMax : timeout + kMargin);

	// Make sure casting is safe.
	timeoutMin = de::min(kSignedMax, timeoutMin);
	timeoutMax = de::min(kSignedMax, timeoutMax);

	return TimeoutRange(static_cast<deInt64>(timeoutMin), static_cast<deInt64>(timeoutMax));
}

class PresentIdWaitInstance : public TestInstance
{
public:
								PresentIdWaitInstance	(Context& context, vk::wsi::Type wsiType) : TestInstance(context), m_wsiType(wsiType) {}
	virtual						~PresentIdWaitInstance	(void) {}

	virtual tcu::TestStatus		iterate					(void);

	virtual tcu::TestStatus		run						(const vk::DeviceInterface&				vkd,
														 vk::VkDevice							device,
														 vk::VkQueue							queue,
														 vk::VkCommandPool						commandPool,
														 vk::VkSwapchainKHR						swapchain,
														 size_t									swapchainSize,
														 const vk::wsi::WsiTriangleRenderer&	renderer) = 0;

	// Subclasses will need to implement a static method like this one indicating which extensions they need.
	static vector<const char*>	requiredDeviceExts		(void) { return vector<const char*>(); }

	// Subclasses will also need to implement this nonstatic method returning the same information as above.
	virtual vector<const char*>	getRequiredDeviceExts	(void) = 0;

protected:
	vk::wsi::Type				m_wsiType;
};

vector<const char*> getRequiredInstanceExtensions (vk::wsi::Type wsiType)
{
	vector<const char*> extensions;
	extensions.push_back("VK_KHR_surface");
	extensions.push_back(getExtensionName(wsiType));
	return extensions;
}

CustomInstance createInstanceWithWsi (Context&							context,
									  vk::wsi::Type						wsiType,
									  const vk::VkAllocationCallbacks*	pAllocator	= nullptr)
{
	const auto version				= context.getUsedApiVersion();
	const auto requiredExtensions	= getRequiredInstanceExtensions(wsiType);

	vector<string> requestedExtensions;
	for (const auto& extensionName : requiredExtensions)
	{
		if (!vk::isCoreInstanceExtension(version, extensionName))
			requestedExtensions.push_back(extensionName);
	}

	return vkt::createCustomInstanceWithExtensions(context, requestedExtensions, pAllocator);
}

struct InstanceHelper
{
	const vector<vk::VkExtensionProperties>	supportedExtensions;
	CustomInstance							instance;
	const vk::InstanceDriver&				vki;

	InstanceHelper (Context& context, vk::wsi::Type wsiType, const vk::VkAllocationCallbacks* pAllocator = nullptr)
		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(), nullptr))
		, instance				(createInstanceWithWsi(context, wsiType, pAllocator))
		, vki					(instance.getDriver())
	{}
};

vector<const char*> getMandatoryDeviceExtensions ()
{
	vector<const char*> mandatoryExtensions;
	mandatoryExtensions.push_back("VK_KHR_swapchain");
	return mandatoryExtensions;
}

vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface&				vkp,
											vk::VkInstance								instance,
											const vk::InstanceInterface&				vki,
											vk::VkPhysicalDevice						physicalDevice,
											const vector<const char*>&					extraExtensions,
											const deUint32								queueFamilyIndex,
											bool										validationEnabled,
											const vk::VkAllocationCallbacks*			pAllocator = nullptr)
{
	const float							queuePriorities[]	= { 1.0f };
	const vk::VkDeviceQueueCreateInfo	queueInfos[]		=
	{
		{
			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
			nullptr,
			(vk::VkDeviceQueueCreateFlags)0,
			queueFamilyIndex,
			DE_LENGTH_OF_ARRAY(queuePriorities),
			&queuePriorities[0]
		}
	};
	vk::VkPhysicalDeviceFeatures		features;
	std::vector<const char*>			extensions			= extraExtensions;
	const auto							mandatoryExtensions	= getMandatoryDeviceExtensions();

	for (const auto& ext : mandatoryExtensions)
		extensions.push_back(ext);

	deMemset(&features, 0, sizeof(features));
	const vk::VkDeviceCreateInfo		deviceParams	=
	{
		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
		nullptr,
		(vk::VkDeviceCreateFlags)0,
		DE_LENGTH_OF_ARRAY(queueInfos),
		&queueInfos[0],
		0u,											// enabledLayerCount
		nullptr,									// ppEnabledLayerNames
		static_cast<deUint32>(extensions.size()),	// enabledExtensionCount
		extensions.data(),							// ppEnabledExtensionNames
		&features
	};

	return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
}

struct DeviceHelper
{
	const vk::VkPhysicalDevice		physicalDevice;
	const deUint32					queueFamilyIndex;
	const vk::Unique<vk::VkDevice>	device;
	const vk::DeviceDriver			vkd;
	const vk::VkQueue				queue;

	DeviceHelper (Context&						context,
				  const vk::InstanceInterface&		vki,
				  vk::VkInstance					instance,
				  const vector<vk::VkSurfaceKHR>&	surfaces,
				  const vector<const char*>&		extraExtensions,
				  const vk::VkAllocationCallbacks*	pAllocator = nullptr)
		: physicalDevice	(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
		, queueFamilyIndex	(vk::wsi::chooseQueueFamilyIndex(vki, physicalDevice, surfaces))
		, device			(createDeviceWithWsi(context.getPlatformInterface(),
												 instance,
												 vki,
												 physicalDevice,
												 extraExtensions,
												 queueFamilyIndex,
												 context.getTestContext().getCommandLine().isValidationEnabled(),
												 pAllocator))
		, vkd				(context.getPlatformInterface(), instance, *device)
		, queue				(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
	{
	}
};

vk::VkSwapchainCreateInfoKHR getBasicSwapchainParameters (vk::wsi::Type					wsiType,
														  const vk::InstanceInterface&	vki,
														  vk::VkPhysicalDevice			physicalDevice,
														  vk::VkSurfaceKHR				surface,
														  const tcu::UVec2&				desiredSize,
														  deUint32						desiredImageCount)
{
	const vk::VkSurfaceCapabilitiesKHR		capabilities		= vk::wsi::getPhysicalDeviceSurfaceCapabilities(vki,
																								   physicalDevice,
																								   surface);
	const vector<vk::VkSurfaceFormatKHR>	formats				= vk::wsi::getPhysicalDeviceSurfaceFormats(vki,
																							  physicalDevice,
																							  surface);
	const vk::wsi::PlatformProperties&		platformProperties	= vk::wsi::getPlatformProperties(wsiType);
	const vk::VkSurfaceTransformFlagBitsKHR transform			= (capabilities.supportedTransforms & vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
	const vk::VkSwapchainCreateInfoKHR		parameters			=
	{
		vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
		nullptr,
		(vk::VkSwapchainCreateFlagsKHR)0,
		surface,
		de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
		formats[0].format,
		formats[0].colorSpace,
		(platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
			? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
		1u,									// imageArrayLayers
		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
		vk::VK_SHARING_MODE_EXCLUSIVE,
		0u,
		nullptr,
		transform,
		vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
		vk::VK_PRESENT_MODE_FIFO_KHR,
		VK_FALSE,							// clipped
		(vk::VkSwapchainKHR)0				// oldSwapchain
	};

	return parameters;
}

using CommandBufferSp	= de::SharedPtr<vk::Unique<vk::VkCommandBuffer>>;
using FenceSp			= de::SharedPtr<vk::Unique<vk::VkFence>>;
using SemaphoreSp		= de::SharedPtr<vk::Unique<vk::VkSemaphore>>;

vector<FenceSp> createFences (const vk::DeviceInterface&	vkd,
							  const vk::VkDevice			device,
							  size_t						numFences)
{
	vector<FenceSp> fences(numFences);

	for (size_t ndx = 0; ndx < numFences; ++ndx)
		fences[ndx] = FenceSp(new vk::Unique<vk::VkFence>(createFence(vkd, device, vk::VK_FENCE_CREATE_SIGNALED_BIT)));

	return fences;
}

vector<SemaphoreSp> createSemaphores (const vk::DeviceInterface&	vkd,
									  const vk::VkDevice			device,
									  size_t						numSemaphores)
{
	vector<SemaphoreSp> semaphores(numSemaphores);

	for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
		semaphores[ndx] = SemaphoreSp(new vk::Unique<vk::VkSemaphore>(createSemaphore(vkd, device)));

	return semaphores;
}

vector<CommandBufferSp> allocateCommandBuffers (const vk::DeviceInterface&		vkd,
												const vk::VkDevice				device,
												const vk::VkCommandPool			commandPool,
												const vk::VkCommandBufferLevel	level,
												const size_t					numCommandBuffers)
{
	vector<CommandBufferSp>				buffers		(numCommandBuffers);

	for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
		buffers[ndx] = CommandBufferSp(new vk::Unique<vk::VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));

	return buffers;
}

class FrameStreamObjects
{
public:
	struct FrameObjects
	{
		const vk::VkFence&			renderCompleteFence;
		const vk::VkSemaphore&		renderCompleteSemaphore;
		const vk::VkSemaphore&		imageAvailableSemaphore;
		const vk::VkCommandBuffer&	commandBuffer;
	};

	FrameStreamObjects (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkCommandPool cmdPool, size_t maxQueuedFrames)
		: renderingCompleteFences		(createFences(vkd, device, maxQueuedFrames))
		, renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames))
		, imageAvailableSemaphores		(createSemaphores(vkd, device, maxQueuedFrames))
		, commandBuffers				(allocateCommandBuffers(vkd, device, cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames))
		, m_maxQueuedFrames				(maxQueuedFrames)
		, m_nextFrame					(0u)
	{}

	size_t frameNumber (void) const { DE_ASSERT(m_nextFrame > 0u); return m_nextFrame - 1u; }

	FrameObjects newFrame ()
	{
		const size_t mod = m_nextFrame % m_maxQueuedFrames;
		FrameObjects ret =
		{
			**renderingCompleteFences[mod],
			**renderingCompleteSemaphores[mod],
			**imageAvailableSemaphores[mod],
			**commandBuffers[mod],
		};
		++m_nextFrame;
		return ret;
	}

private:
	const vector<FenceSp>			renderingCompleteFences;
	const vector<SemaphoreSp>		renderingCompleteSemaphores;
	const vector<SemaphoreSp>		imageAvailableSemaphores;
	const vector<CommandBufferSp>	commandBuffers;

	const size_t	m_maxQueuedFrames;
	size_t			m_nextFrame;
};

tcu::TestStatus PresentIdWaitInstance::iterate (void)
{
	const tcu::UVec2						desiredSize					(256, 256);
	const InstanceHelper					instHelper					(m_context, m_wsiType);
	const NativeObjects						native						(m_context, instHelper.supportedExtensions, m_wsiType, 1u, tcu::just(desiredSize));
	const vk::Unique<vk::VkSurfaceKHR>		surface						(createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow()));
	const DeviceHelper						devHelper					(m_context, instHelper.vki, instHelper.instance, vector<vk::VkSurfaceKHR>(1u, surface.get()), getRequiredDeviceExts());
	const vk::DeviceInterface&				vkd							= devHelper.vkd;
	const vk::VkDevice						device						= *devHelper.device;
	vk::SimpleAllocator						allocator					(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
	const vk::VkSwapchainCreateInfoKHR		swapchainInfo				= getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
	const vk::Unique<vk::VkSwapchainKHR>	swapchain					(vk::createSwapchainKHR(vkd, device, &swapchainInfo));
	const vector<vk::VkImage>				swapchainImages				= vk::wsi::getSwapchainImages(vkd, device, *swapchain);
	const vk::Unique<vk::VkCommandPool>		commandPool					(createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
	const vk::wsi::WsiTriangleRenderer		renderer					(vkd,
																		 device,
																		 allocator,
																		 m_context.getBinaryCollection(),
																		 false,
																		 swapchainImages,
																		 swapchainImages,
																		 swapchainInfo.imageFormat,
																		 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));

	try
	{
		return run(vkd, device, devHelper.queue, commandPool.get(), swapchain.get(), swapchainImages.size(), renderer);
	}
	catch (...)
	{
		// Make sure device is idle before destroying resources
		vkd.deviceWaitIdle(device);
		throw;
	}

	return tcu::TestStatus(QP_TEST_RESULT_INTERNAL_ERROR, "Reached unreachable code");
}

struct PresentParameters
{
	tcu::Maybe<deUint64>		presentId;
	tcu::Maybe<vk::VkResult>	expectedResult;
};

struct WaitParameters
{
	deUint64	presentId;
	deUint64	timeout; // Nanoseconds.
	bool		timeoutExpected;
};

// This structure represents a set of present operations to be run followed by a set of wait operations to be run after them.
// When running the present operations, the present id can be provided, together with an optional expected result to be checked.
// When runing the wait operations, the present id must be provided together with a timeout and an indication of whether the operation is expected to time out or not.
struct PresentAndWaitOps
{
	vector<PresentParameters>	presentOps;
	vector<WaitParameters>		waitOps;
};

// Parent class for VK_KHR_present_id and VK_KHR_present_wait simple tests.
class PresentIdWaitSimpleInstance : public PresentIdWaitInstance
{
public:
	PresentIdWaitSimpleInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
		: PresentIdWaitInstance(context, wsiType), m_sequence(sequence)
	{}

	virtual ~PresentIdWaitSimpleInstance() {}

	virtual tcu::TestStatus		run						(const vk::DeviceInterface&				vkd,
														 vk::VkDevice							device,
														 vk::VkQueue							queue,
														 vk::VkCommandPool						commandPool,
														 vk::VkSwapchainKHR						swapchain,
														 size_t									swapchainSize,
														 const vk::wsi::WsiTriangleRenderer&	renderer);
protected:
	const vector<PresentAndWaitOps> m_sequence;
};

// Waits for the appropriate fences, acquires swapchain image, records frame and submits it to the given queue, signaling the appropriate frame semaphores.
// Returns the image index from the swapchain.
deUint32 recordAndSubmitFrame (FrameStreamObjects::FrameObjects& frameObjects, const vk::wsi::WsiTriangleRenderer& triangleRenderer, const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkSwapchainKHR swapchain, size_t swapchainSize, vk::VkQueue queue, size_t frameNumber, tcu::TestLog& testLog)
{
	// Wait and reset the render complete fence to avoid having too many submitted frames.
	VK_CHECK(vkd.waitForFences(device, 1u, &frameObjects.renderCompleteFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
	VK_CHECK(vkd.resetFences(device, 1, &frameObjects.renderCompleteFence));

	// Acquire swapchain image.
	deUint32 imageNdx = std::numeric_limits<deUint32>::max();
	const vk::VkResult acquireResult = vkd.acquireNextImageKHR(device,
																swapchain,
																std::numeric_limits<deUint64>::max(),
																frameObjects.imageAvailableSemaphore,
																(vk::VkFence)0,
																&imageNdx);

	if (acquireResult == vk::VK_SUBOPTIMAL_KHR)
		testLog << tcu::TestLog::Message << "Got " << acquireResult << " at frame " << frameNumber << tcu::TestLog::EndMessage;
	else
		VK_CHECK(acquireResult);
	TCU_CHECK(static_cast<size_t>(imageNdx) < swapchainSize);

	// Submit frame to the queue.
	const vk::VkPipelineStageFlags	waitDstStage	= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
	const vk::VkSubmitInfo			submitInfo		=
	{
		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
		nullptr,
		1u,
		&frameObjects.imageAvailableSemaphore,
		&waitDstStage,
		1u,
		&frameObjects.commandBuffer,
		1u,
		&frameObjects.renderCompleteSemaphore,
	};

	triangleRenderer.recordFrame(frameObjects.commandBuffer, imageNdx, static_cast<deUint32>(frameNumber));
	VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, frameObjects.renderCompleteFence));

	return imageNdx;
}

tcu::TestStatus PresentIdWaitSimpleInstance::run (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkQueue queue, vk::VkCommandPool commandPool, vk::VkSwapchainKHR swapchain, size_t swapchainSize, const vk::wsi::WsiTriangleRenderer& renderer)
{
	const size_t		maxQueuedFrames		= swapchainSize*2;
	FrameStreamObjects	frameStreamObjects	(vkd, device, commandPool, maxQueuedFrames);

	for (const auto& step : m_sequence)
	{
		for (const auto& presentOp : step.presentOps)
		{
			// Get objects for the next frame.
			FrameStreamObjects::FrameObjects frameObjects = frameStreamObjects.newFrame();

			// Record and submit new frame.
			deUint32 imageNdx = recordAndSubmitFrame(frameObjects, renderer, vkd, device, swapchain, swapchainSize, queue, frameStreamObjects.frameNumber(), m_context.getTestContext().getLog());

			// Present rendered frame.
			const vk::VkPresentIdKHR		presentId		=
			{
				vk::VK_STRUCTURE_TYPE_PRESENT_ID_KHR,							// VkStructureType		sType;
				nullptr,														// const void*			pNext;
				(presentOp.presentId ? 1u : 0u),								// deUint32				swapchainCount;
				(presentOp.presentId ? &presentOp.presentId.get() : nullptr ),	// const deUint64*		pPresentIds;
			};

			const vk::VkPresentInfoKHR		presentInfo		=
			{
				vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
				(presentOp.presentId ? &presentId : nullptr),
				1u,
				&frameObjects.renderCompleteSemaphore,
				1u,
				&swapchain,
				&imageNdx,
				nullptr,
			};

			vk::VkResult result = vkd.queuePresentKHR(queue, &presentInfo);

			if (presentOp.expectedResult)
			{
				const vk::VkResult expected = presentOp.expectedResult.get();
				if ((expected == vk::VK_SUCCESS && result != vk::VK_SUCCESS && result != vk::VK_SUBOPTIMAL_KHR) ||
					(expected != vk::VK_SUCCESS && result != expected))
				{
					std::ostringstream msg;
					msg << "Got " << result << " while expecting " << expected << " after presenting with ";
					if (presentOp.presentId)
						msg << "id " << presentOp.presentId.get();
					else
						msg << "no id";
					TCU_FAIL(msg.str());
				}
			}
		}

		// Wait operations.
		for (const auto& waitOp : step.waitOps)
		{
			auto			before		= std::chrono::high_resolution_clock::now();
			vk::VkResult	waitResult	= vkd.waitForPresentKHR(device, swapchain, waitOp.presentId, waitOp.timeout);
			auto			after		= std::chrono::high_resolution_clock::now();
			auto			diff		= std::chrono::nanoseconds(after - before).count();

			if (waitOp.timeoutExpected)
			{
				if (waitResult != vk::VK_TIMEOUT)
				{
					std::ostringstream msg;
					msg << "Got " << waitResult << " while expecting a timeout in vkWaitForPresentKHR call";
					TCU_FAIL(msg.str());
				}

				const auto timeoutRange = calcTimeoutRange(waitOp.timeout);

				if (diff < timeoutRange.first || diff > timeoutRange.second)
				{
					std::ostringstream msg;
					msg << "vkWaitForPresentKHR waited for " << diff << " nanoseconds with a timeout of " << waitOp.timeout << " nanoseconds";
					TCU_FAIL(msg.str());
				}
			}
			else if (waitResult != vk::VK_SUCCESS)
			{
				std::ostringstream msg;
				msg << "Got " << waitResult << " while expecting success in vkWaitForPresentKHR call";
				TCU_FAIL(msg.str());
			}
		}
	}

	// Wait until device is idle.
	VK_CHECK(vkd.deviceWaitIdle(device));

	return tcu::TestStatus::pass("Pass");
}

// Parent class for VK_KHR_present_id simple tests.
class PresentIdInstance : public PresentIdWaitSimpleInstance
{
public:
	PresentIdInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
		: PresentIdWaitSimpleInstance(context, wsiType, sequence)
	{}

	virtual ~PresentIdInstance() {}

	static vector<const char*>	requiredDeviceExts (void)
	{
		vector<const char*> extensions;
		extensions.push_back("VK_KHR_present_id");
		return extensions;
	}

	virtual vector<const char*> getRequiredDeviceExts (void)
	{
		return requiredDeviceExts();
	}
};

// Parent class for VK_KHR_present_wait simple tests.
class PresentWaitInstance : public PresentIdWaitSimpleInstance
{
public:
	PresentWaitInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
		: PresentIdWaitSimpleInstance(context, wsiType, sequence)
	{}

	virtual ~PresentWaitInstance() {}

	static vector<const char*>	requiredDeviceExts (void)
	{
		vector<const char*> extensions;
		extensions.push_back("VK_KHR_present_id");
		extensions.push_back("VK_KHR_present_wait");
		return extensions;
	}

	virtual vector<const char*>	getRequiredDeviceExts (void)
	{
		return requiredDeviceExts();
	}
};

class PresentIdZeroInstance : public PresentIdInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentIdZeroInstance (Context& context, vk::wsi::Type wsiType)
		: PresentIdInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentIdZeroInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(0), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
		},
	},
};

class PresentIdIncreasingInstance : public PresentIdInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentIdIncreasingInstance (Context& context, vk::wsi::Type wsiType)
		: PresentIdInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentIdIncreasingInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(1),							tcu::just(vk::VK_SUCCESS) },
			{ tcu::just(std::numeric_limits<deUint64>::max()),	tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
		},
	},
};

class PresentIdInterleavedInstance : public PresentIdInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentIdInterleavedInstance (Context& context, vk::wsi::Type wsiType)
		: PresentIdInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentIdInterleavedInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(0),							tcu::just(vk::VK_SUCCESS) },
			{ tcu::just<deUint64>(1),							tcu::just(vk::VK_SUCCESS) },
			{ tcu::nothing<deUint64>(),							tcu::just(vk::VK_SUCCESS) },
			{ tcu::just(std::numeric_limits<deUint64>::max()),	tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
		},
	},
};

class PresentWaitSingleFrameInstance : public PresentWaitInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentWaitSingleFrameInstance (Context& context, vk::wsi::Type wsiType)
		: PresentWaitInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentWaitSingleFrameInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ 1ull, k10sec, false },
		},
	},
};

class PresentWaitPastFrameInstance : public PresentWaitInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentWaitPastFrameInstance (Context& context, vk::wsi::Type wsiType)
		: PresentWaitInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentWaitPastFrameInstance::sequence =
{
	// Start with present id 1.
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ 1ull, k10sec, false },
			{ 1ull, 0ull,   false },
		},
	},
	// Then the maximum value. Both waiting for id 1 and the max id should work.
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just(std::numeric_limits<deUint64>::max()), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ 1ull,                                 0ull,   false },
			{ 1ull,                                 k10sec, false },
			{ std::numeric_limits<deUint64>::max(), k10sec, false },
			{ std::numeric_limits<deUint64>::max(), 0ull,   false },
		},
	},
	// Submit some frames without id after having used the maximum value. This should also work.
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::nothing<deUint64>(),	tcu::just(vk::VK_SUCCESS) },
			{ tcu::just<deUint64>(0),	tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
		},
	},
};

class PresentWaitNoFramesInstance : public PresentWaitInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentWaitNoFramesInstance (Context& context, vk::wsi::Type wsiType)
		: PresentWaitInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentWaitNoFramesInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
		},
		{	// waitOps vector
			{ 1ull, 0ull,  true },
			{ 1ull, k1sec, true },
		},
	},
};

class PresentWaitNoFrameIdInstance : public PresentWaitInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentWaitNoFrameIdInstance (Context& context, vk::wsi::Type wsiType)
		: PresentWaitInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentWaitNoFrameIdInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(0), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ 1ull, 0ull,  true },
			{ 1ull, k1sec, true },
		},
	},
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::nothing<deUint64>(), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ 1ull, 0ull,  true },
			{ 1ull, k1sec, true },
		},
	},
};

class PresentWaitFutureFrameInstance : public PresentWaitInstance
{
public:
	static const vector<PresentAndWaitOps> sequence;

	PresentWaitFutureFrameInstance (Context& context, vk::wsi::Type wsiType)
		: PresentWaitInstance(context, wsiType, sequence)
	{}
};

const vector<PresentAndWaitOps> PresentWaitFutureFrameInstance::sequence =
{
	{ // PresentAndWaitOps
		{	// presentOps vector
			{ tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
		},
		{	// waitOps vector
			{ std::numeric_limits<deUint64>::max(), k1sec, true },
			{ std::numeric_limits<deUint64>::max(), 0ull,  true },
			{ 2ull,                                 0ull,  true },
			{ 2ull,                                 k1sec, true },
		},
	},
};

// Instance with two windows and surfaces to check present ids are not mixed up.
class PresentWaitDualInstance : public TestInstance
{
public:
								PresentWaitDualInstance		(Context& context, vk::wsi::Type wsiType) : TestInstance(context), m_wsiType(wsiType) {}
	virtual						~PresentWaitDualInstance	(void) {}

	virtual tcu::TestStatus		iterate						(void);

	static vector<const char*>	requiredDeviceExts			(void)
	{
		vector<const char*> extensions;
		extensions.push_back("VK_KHR_present_id");
		extensions.push_back("VK_KHR_present_wait");
		return extensions;
	}

	virtual vector<const char*>	getRequiredDeviceExts		(void)
	{
		return requiredDeviceExts();
	}

protected:
	vk::wsi::Type				m_wsiType;
};

struct IdAndWait
{
	deUint64	presentId;
	bool		wait;
};

struct DualIdAndWait
{
	IdAndWait idWait1;
	IdAndWait idWait2;
};

tcu::TestStatus PresentWaitDualInstance::iterate (void)
{
	const tcu::UVec2						desiredSize					(256, 256);
	const InstanceHelper					instHelper					(m_context, m_wsiType);
	const NativeObjects						native						(m_context, instHelper.supportedExtensions, m_wsiType, 2u, tcu::just(desiredSize));
	const vk::Unique<vk::VkSurfaceKHR>		surface1					(createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow(0)));
	const vk::Unique<vk::VkSurfaceKHR>		surface2					(createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow(1)));
	const DeviceHelper						devHelper					(m_context, instHelper.vki, instHelper.instance, vector<vk::VkSurfaceKHR>{surface1.get(), surface2.get()}, getRequiredDeviceExts());
	const vk::DeviceInterface&				vkd							= devHelper.vkd;
	const vk::VkDevice						device						= *devHelper.device;
	vk::SimpleAllocator						allocator					(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
	const vk::VkSwapchainCreateInfoKHR		swapchainInfo1				= getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, surface1.get(), desiredSize, 2);
	const vk::VkSwapchainCreateInfoKHR		swapchainInfo2				= getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, surface2.get(), desiredSize, 2);
	const vk::Unique<vk::VkSwapchainKHR>	swapchain1					(vk::createSwapchainKHR(vkd, device, &swapchainInfo1));
	const vk::Unique<vk::VkSwapchainKHR>	swapchain2					(vk::createSwapchainKHR(vkd, device, &swapchainInfo2));
	const vector<vk::VkImage>				swapchainImages1			= vk::wsi::getSwapchainImages(vkd, device, swapchain1.get());
	const vector<vk::VkImage>				swapchainImages2			= vk::wsi::getSwapchainImages(vkd, device, swapchain2.get());
	const vk::Unique<vk::VkCommandPool>		commandPool					(createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
	const vk::wsi::WsiTriangleRenderer		renderer1					(vkd,
																		 device,
																		 allocator,
																		 m_context.getBinaryCollection(),
																		 false,
																		 swapchainImages1,
																		 swapchainImages1,
																		 swapchainInfo1.imageFormat,
																		 tcu::UVec2(swapchainInfo1.imageExtent.width, swapchainInfo1.imageExtent.height));
	const vk::wsi::WsiTriangleRenderer		renderer2					(vkd,
																		 device,
																		 allocator,
																		 m_context.getBinaryCollection(),
																		 false,
																		 swapchainImages2,
																		 swapchainImages2,
																		 swapchainInfo2.imageFormat,
																		 tcu::UVec2(swapchainInfo2.imageExtent.width, swapchainInfo2.imageExtent.height));
	tcu::TestLog&							testLog						= m_context.getTestContext().getLog();

	try
	{
		const size_t		maxQueuedFrames		= swapchainImages1.size()*2;
		FrameStreamObjects	frameStreamObjects1	(vkd, device, commandPool.get(), maxQueuedFrames);
		FrameStreamObjects	frameStreamObjects2	(vkd, device, commandPool.get(), maxQueuedFrames);

		// Increasing ids for both swapchains, waiting on some to make sure we do not time out unexpectedly.
		const vector<DualIdAndWait> sequence =
		{
			{
				{ 1ull, false },
				{ 2ull, true  },
			},
			{
				{ 4ull, true  },
				{ 3ull, false },
			},
			{
				{ 5ull, true  },
				{ 6ull, true  },
			},
		};

		for (const auto& step : sequence)
		{
			// Get objects for the next frames.
			FrameStreamObjects::FrameObjects frameObjects1 = frameStreamObjects1.newFrame();
			FrameStreamObjects::FrameObjects frameObjects2 = frameStreamObjects2.newFrame();

			// Record and submit frame.
			deUint32 imageNdx1 = recordAndSubmitFrame(frameObjects1, renderer1, vkd, device, swapchain1.get(), swapchainImages1.size(), devHelper.queue, frameStreamObjects1.frameNumber(), testLog);
			deUint32 imageNdx2 = recordAndSubmitFrame(frameObjects2, renderer2, vkd, device, swapchain2.get(), swapchainImages2.size(), devHelper.queue, frameStreamObjects2.frameNumber(), testLog);

			// Present both images at the same time with their corresponding ids.
			const deUint64				presentIdsArr[] = { step.idWait1.presentId, step.idWait2.presentId };
			const vk::VkPresentIdKHR	presentId		=
			{
				vk::VK_STRUCTURE_TYPE_PRESENT_ID_KHR,							// VkStructureType		sType;
				nullptr,														// const void*			pNext;
				static_cast<deUint32>(DE_LENGTH_OF_ARRAY(presentIdsArr)),		// deUint32				swapchainCount;
				presentIdsArr,													// const deUint64*		pPresentIds;
			};

			const vk::VkSemaphore		semaphoreArr[]	= { frameObjects1.renderCompleteSemaphore, frameObjects2.renderCompleteSemaphore };
			const vk::VkSwapchainKHR	swapchainArr[]	= { swapchain1.get(), swapchain2.get() };
			const deUint32				imgIndexArr[]	= { imageNdx1, imageNdx2 };
			const vk::VkPresentInfoKHR	presentInfo		=
			{
				vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
				&presentId,
				static_cast<deUint32>(DE_LENGTH_OF_ARRAY(semaphoreArr)),
				semaphoreArr,
				static_cast<deUint32>(DE_LENGTH_OF_ARRAY(swapchainArr)),
				swapchainArr,
				imgIndexArr,
				nullptr,
			};

			VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));

			const IdAndWait* idWaitArr[] = { &step.idWait1, &step.idWait2 };
			for (int i = 0; i < DE_LENGTH_OF_ARRAY(idWaitArr); ++i)
			{
				if (idWaitArr[i]->wait)
					VK_CHECK(vkd.waitForPresentKHR(device, swapchainArr[i], idWaitArr[i]->presentId, k10sec));
			}
		}

		// Wait until device is idle.
		VK_CHECK(vkd.deviceWaitIdle(device));

		return tcu::TestStatus::pass("Pass");
	}
	catch (...)
	{
		// Make sure device is idle before destroying resources
		vkd.deviceWaitIdle(device);
		throw;
	}

	return tcu::TestStatus(QP_TEST_RESULT_INTERNAL_ERROR, "Reached unreachable code");
}

// Templated class for every instance type.
template <class T>	// T is the test instance class.
class PresentIdWaitCase : public TestCase
{
public:
							PresentIdWaitCase	(vk::wsi::Type wsiType, tcu::TestContext& ctx, const std::string& name, const std::string& description);
	virtual					~PresentIdWaitCase	(void) {}
	virtual void			initPrograms		(vk::SourceCollections& programCollection) const;
	virtual TestInstance*	createInstance		(Context& context) const;
	virtual void			checkSupport		(Context& context) const;

protected:
	vk::wsi::Type			m_wsiType;
};

template <class T>
PresentIdWaitCase<T>::PresentIdWaitCase (vk::wsi::Type wsiType, tcu::TestContext& ctx, const std::string& name, const std::string& description)
	: TestCase(ctx, name, description), m_wsiType(wsiType)
{
}

template <class T>
void PresentIdWaitCase<T>::initPrograms (vk::SourceCollections& programCollection) const
{
	vk::wsi::WsiTriangleRenderer::getPrograms(programCollection);
}

template <class T>
TestInstance* PresentIdWaitCase<T>::createInstance (Context& context) const
{
	return new T(context, m_wsiType);
}

template <class T>
void PresentIdWaitCase<T>::checkSupport (Context& context) const
{
	// Check instance extension support.
	const auto instanceExtensions = getRequiredInstanceExtensions(m_wsiType);
	for (const auto& ext : instanceExtensions)
	{
		if (!context.isInstanceFunctionalitySupported(ext))
			TCU_THROW(NotSupportedError, ext + string(" is not supported"));
	}

	// Check device extension support.
	const auto& vki                 = context.getInstanceInterface();
	const auto  physDev             = context.getPhysicalDevice();
	const auto  supportedDeviceExts = vk::enumerateDeviceExtensionProperties(vki, physDev, nullptr);
	const auto  mandatoryDeviceExts = getMandatoryDeviceExtensions();

	auto checkedDeviceExts = T::requiredDeviceExts();
	for (const auto& ext : mandatoryDeviceExts)
		checkedDeviceExts.push_back(ext);

	for (const auto& ext : checkedDeviceExts)
	{
		if (!vk::isExtensionSupported(supportedDeviceExts, vk::RequiredExtension(ext)))
			TCU_THROW(NotSupportedError, ext + string(" is not supported"));
	}
}

void createPresentIdTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
{
	testGroup->addChild(new PresentIdWaitCase<PresentIdZeroInstance>		(wsiType, testGroup->getTestContext(), "zero",			"Use present id zero"));
	testGroup->addChild(new PresentIdWaitCase<PresentIdIncreasingInstance>	(wsiType, testGroup->getTestContext(), "increasing",	"Use increasing present ids"));
	testGroup->addChild(new PresentIdWaitCase<PresentIdInterleavedInstance>	(wsiType, testGroup->getTestContext(), "interleaved",	"Use increasing present ids interleaved with no ids"));
}

void createPresentWaitTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
{
	testGroup->addChild(new PresentIdWaitCase<PresentWaitSingleFrameInstance>	(wsiType, testGroup->getTestContext(), "single_no_timeout",	"Present single frame with no expected timeout"));
	testGroup->addChild(new PresentIdWaitCase<PresentWaitPastFrameInstance>		(wsiType, testGroup->getTestContext(), "past_no_timeout",	"Wait for past frame with no expected timeout"));
	testGroup->addChild(new PresentIdWaitCase<PresentWaitNoFramesInstance>		(wsiType, testGroup->getTestContext(), "no_frames",			"Expect timeout before submitting any frame"));
	testGroup->addChild(new PresentIdWaitCase<PresentWaitNoFrameIdInstance>		(wsiType, testGroup->getTestContext(), "no_frame_id",		"Expect timeout after submitting frames with no id"));
	testGroup->addChild(new PresentIdWaitCase<PresentWaitFutureFrameInstance>	(wsiType, testGroup->getTestContext(), "future_frame",		"Expect timeout when waiting for a future frame"));
	testGroup->addChild(new PresentIdWaitCase<PresentWaitDualInstance>			(wsiType, testGroup->getTestContext(), "two_swapchains",	"Smoke test using two windows, surfaces and swapchains"));
}

} // anonymous

void createPresentIdWaitTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
{
	de::MovePtr<tcu::TestCaseGroup>	idGroup		(new tcu::TestCaseGroup(testGroup->getTestContext(), "id",		"VK_KHR_present_id tests"));
	de::MovePtr<tcu::TestCaseGroup>	waitGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), "wait",	"VK_KHR_present_wait tests"));

	createPresentIdTests	(idGroup.get(),		wsiType);
	createPresentWaitTests	(waitGroup.get(),	wsiType);

	testGroup->addChild(idGroup.release());
	testGroup->addChild(waitGroup.release());
}

} // wsi
} // vkt

