/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 Google Inc.
 *
 * 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 VkSwapchain Tests
 *//*--------------------------------------------------------------------*/

#include "vktWsiSwapchainTests.hpp"

#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"

#include "vkDefs.hpp"
#include "vkPlatform.hpp"
#include "vkStrUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
#include "vkWsiPlatform.hpp"
#include "vkWsiUtil.hpp"
#include "vkAllocationCallbackUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuFormatUtil.hpp"
#include "tcuPlatform.hpp"
#include "tcuResultCollector.hpp"

#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"
#include "deArrayUtil.hpp"
#include "deSharedPtr.hpp"

#include <limits>

namespace vkt
{
namespace wsi
{

namespace
{

using namespace vk;
using namespace vk::wsi;

using tcu::TestLog;
using tcu::Maybe;
using tcu::UVec2;

using de::MovePtr;
using de::UniquePtr;

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

typedef vector<VkExtensionProperties> Extensions;

void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
{
	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
		 requiredExtName != requiredExtensions.end();
		 ++requiredExtName)
	{
		if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
	}
}

Move<VkInstance> createInstanceWithWsi (const PlatformInterface&		vkp,
										const Extensions&				supportedExtensions,
										Type							wsiType,
										const VkAllocationCallbacks*	pAllocator	= DE_NULL)
{
	vector<string>	extensions;

	extensions.push_back("VK_KHR_surface");
	extensions.push_back(getExtensionName(wsiType));

	// VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
	// the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
	// but using them without enabling the extension is not allowed. Thus we have
	// two options:
	//
	// 1) Filter out non-core formats to stay within valid usage.
	//
	// 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
	//
	// We opt for (2) as it provides basic coverage for the extension as a bonus.
	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
		extensions.push_back("VK_EXT_swapchain_colorspace");

	checkAllSupported(supportedExtensions, extensions);

	return createDefaultInstance(vkp, vector<string>(), extensions, pAllocator);
}

VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
{
	VkPhysicalDeviceFeatures features;
	deMemset(&features, 0, sizeof(features));
	return features;
}

Move<VkDevice> createDeviceWithWsi (const InstanceInterface&		vki,
									VkPhysicalDevice				physicalDevice,
									const Extensions&				supportedExtensions,
									const deUint32					queueFamilyIndex,
									const VkAllocationCallbacks*	pAllocator = DE_NULL)
{
	const float						queuePriorities[]	= { 1.0f };
	const VkDeviceQueueCreateInfo	queueInfos[]		=
	{
		{
			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
			DE_NULL,
			(VkDeviceQueueCreateFlags)0,
			queueFamilyIndex,
			DE_LENGTH_OF_ARRAY(queuePriorities),
			&queuePriorities[0]
		}
	};
	const VkPhysicalDeviceFeatures	features		= getDeviceFeaturesForWsi();
	const char* const				extensions[]	= { "VK_KHR_swapchain" };
	const VkDeviceCreateInfo		deviceParams	=
	{
		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
		DE_NULL,
		(VkDeviceCreateFlags)0,
		DE_LENGTH_OF_ARRAY(queueInfos),
		&queueInfos[0],
		0u,									// enabledLayerCount
		DE_NULL,							// ppEnabledLayerNames
		DE_LENGTH_OF_ARRAY(extensions),		// enabledExtensionCount
		DE_ARRAY_BEGIN(extensions),			// ppEnabledExtensionNames
		&features
	};

	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
	{
		if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx])))
			TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
	}

	return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
}

deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
{
	deUint32	numFamilies		= 0;

	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);

	return numFamilies;
}

vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
{
	const deUint32		numTotalFamilyIndices	= getNumQueueFamilyIndices(vki, physicalDevice);
	vector<deUint32>	supportedFamilyIndices;

	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
	{
		if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
			supportedFamilyIndices.push_back(queueFamilyNdx);
	}

	return supportedFamilyIndices;
}

deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
{
	const vector<deUint32>	supportedFamilyIndices	= getSupportedQueueFamilyIndices(vki, physicalDevice, surface);

	if (supportedFamilyIndices.empty())
		TCU_THROW(NotSupportedError, "Device doesn't support presentation");

	return supportedFamilyIndices[0];
}

struct InstanceHelper
{
	const vector<VkExtensionProperties>	supportedExtensions;
	const Unique<VkInstance>			instance;
	const InstanceDriver				vki;

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

VkQueue getDeviceQueue (const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)
{
	VkQueue queue = (VkQueue)0;
	vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
	return queue;
}

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

	DeviceHelper (Context&						context,
				  const InstanceInterface&		vki,
				  VkInstance					instance,
				  VkSurfaceKHR					surface,
				  const VkAllocationCallbacks*	pAllocator = DE_NULL)
		: physicalDevice	(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
		, queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, surface))
		, device			(createDeviceWithWsi(vki,
												 physicalDevice,
												 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
												 queueFamilyIndex,
												 pAllocator))
		, vkd				(vki, *device)
		, queue				(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
	{
	}
};

MovePtr<Display> createDisplay (const vk::Platform&	platform,
								const Extensions&	supportedExtensions,
								Type				wsiType)
{
	try
	{
		return MovePtr<Display>(platform.createWsiDisplay(wsiType));
	}
	catch (const tcu::NotSupportedError& e)
	{
		if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
		{
			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
			// must support creating native display & window for that WSI type.
			throw tcu::TestError(e.getMessage());
		}
		else
			throw;
	}
}

MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
{
	try
	{
		return MovePtr<Window>(display.createWindow(initialSize));
	}
	catch (const tcu::NotSupportedError& e)
	{
		// See createDisplay - assuming that wsi::Display was supported platform port
		// should also support creating a window.
		throw tcu::TestError(e.getMessage());
	}
}

struct NativeObjects
{
	const UniquePtr<Display>	display;
	const UniquePtr<Window>		window;

	NativeObjects (Context&				context,
				   const Extensions&	supportedExtensions,
				   Type					wsiType,
				   const Maybe<UVec2>&	initialWindowSize = tcu::nothing<UVec2>())
		: display	(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
		, window	(createWindow(*display, initialWindowSize))
	{}
};

enum TestDimension
{
	TEST_DIMENSION_MIN_IMAGE_COUNT = 0,	//!< Test all supported image counts
	TEST_DIMENSION_IMAGE_FORMAT,		//!< Test all supported formats
	TEST_DIMENSION_IMAGE_EXTENT,		//!< Test various (supported) extents
	TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
	TEST_DIMENSION_IMAGE_USAGE,
	TEST_DIMENSION_IMAGE_SHARING_MODE,
	TEST_DIMENSION_PRE_TRANSFORM,
	TEST_DIMENSION_COMPOSITE_ALPHA,
	TEST_DIMENSION_PRESENT_MODE,
	TEST_DIMENSION_CLIPPED,

	TEST_DIMENSION_LAST
};

const char* getTestDimensionName (TestDimension dimension)
{
	static const char* const s_names[] =
	{
		"min_image_count",
		"image_format",
		"image_extent",
		"image_array_layers",
		"image_usage",
		"image_sharing_mode",
		"pre_transform",
		"composite_alpha",
		"present_mode",
		"clipped"
	};
	return de::getSizedArrayElement<TEST_DIMENSION_LAST>(s_names, dimension);
}

struct TestParameters
{
	Type			wsiType;
	TestDimension	dimension;

	TestParameters (Type wsiType_, TestDimension dimension_)
		: wsiType	(wsiType_)
		, dimension	(dimension_)
	{}

	TestParameters (void)
		: wsiType	(TYPE_LAST)
		, dimension	(TEST_DIMENSION_LAST)
	{}
};

vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type								wsiType,
																  TestDimension						dimension,
																  const VkSurfaceCapabilitiesKHR&	capabilities,
																  const vector<VkSurfaceFormatKHR>&	formats,
																  const vector<VkPresentModeKHR>&	presentModes)
{
	const PlatformProperties&			platformProperties	= getPlatformProperties(wsiType);
	vector<VkSwapchainCreateInfoKHR>	cases;
	const VkSurfaceTransformFlagBitsKHR defaultTransform	= (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
	const VkSwapchainCreateInfoKHR		baseParameters		=
	{
		VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
		DE_NULL,
		(VkSwapchainCreateFlagsKHR)0,
		(VkSurfaceKHR)0,
		capabilities.minImageCount,
		formats[0].format,
		formats[0].colorSpace,
		(platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE
			? capabilities.minImageExtent : capabilities.currentExtent),
		1u,									// imageArrayLayers
		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
		VK_SHARING_MODE_EXCLUSIVE,
		0u,
		(const deUint32*)DE_NULL,
		defaultTransform,
		VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
		VK_PRESENT_MODE_FIFO_KHR,
		VK_FALSE,							// clipped
		(VkSwapchainKHR)0					// oldSwapchain
	};

	switch (dimension)
	{
		case TEST_DIMENSION_MIN_IMAGE_COUNT:
		{
			const deUint32	maxImageCountToTest	= de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u);

			for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount)
			{
				cases.push_back(baseParameters);
				cases.back().minImageCount = imageCount;
			}

			break;
		}

		case TEST_DIMENSION_IMAGE_FORMAT:
		{
			for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
			{
				cases.push_back(baseParameters);
				cases.back().imageFormat		= curFmt->format;
				cases.back().imageColorSpace	= curFmt->colorSpace;
			}

			break;
		}

		case TEST_DIMENSION_IMAGE_EXTENT:
		{
			static const VkExtent2D	s_testSizes[]	=
			{
				{ 1, 1 },
				{ 16, 32 },
				{ 32, 16 },
				{ 632, 231 },
				{ 117, 998 },
			};

			if (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE ||
				platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
			{
				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_testSizes); ++ndx)
				{
					cases.push_back(baseParameters);
					cases.back().imageExtent.width	= de::clamp(s_testSizes[ndx].width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
					cases.back().imageExtent.height	= de::clamp(s_testSizes[ndx].height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
				}
			}

			if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE)
			{
				cases.push_back(baseParameters);
				cases.back().imageExtent = capabilities.currentExtent;
			}

			if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
			{
				cases.push_back(baseParameters);
				cases.back().imageExtent = capabilities.minImageExtent;

				cases.push_back(baseParameters);
				cases.back().imageExtent = capabilities.maxImageExtent;
			}

			break;
		}

		case TEST_DIMENSION_IMAGE_ARRAY_LAYERS:
		{
			const deUint32	maxLayers	= de::min(capabilities.maxImageArrayLayers, 16u);

			for (deUint32 numLayers = 1; numLayers <= maxLayers; ++numLayers)
			{
				cases.push_back(baseParameters);
				cases.back().imageArrayLayers = numLayers;
			}

			break;
		}

		case TEST_DIMENSION_IMAGE_USAGE:
		{
			for (deUint32 flags = 1u; flags <= capabilities.supportedUsageFlags; ++flags)
			{
				if ((flags & ~capabilities.supportedUsageFlags) == 0)
				{
					cases.push_back(baseParameters);
					cases.back().imageUsage = flags;
				}
			}

			break;
		}

		case TEST_DIMENSION_IMAGE_SHARING_MODE:
		{
			cases.push_back(baseParameters);
			cases.back().imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;

			cases.push_back(baseParameters);
			cases.back().imageSharingMode = VK_SHARING_MODE_CONCURRENT;

			break;
		}

		case TEST_DIMENSION_PRE_TRANSFORM:
		{
			for (deUint32 transform = 1u;
				 transform <= capabilities.supportedTransforms;
				 transform = transform<<1u)
			{
				if ((transform & capabilities.supportedTransforms) != 0)
				{
					cases.push_back(baseParameters);
					cases.back().preTransform = (VkSurfaceTransformFlagBitsKHR)transform;
				}
			}

			break;
		}

		case TEST_DIMENSION_COMPOSITE_ALPHA:
		{
			for (deUint32 alphaMode = 1u;
				 alphaMode <= capabilities.supportedCompositeAlpha;
				 alphaMode = alphaMode<<1u)
			{
				if ((alphaMode & capabilities.supportedCompositeAlpha) != 0)
				{
					cases.push_back(baseParameters);
					cases.back().compositeAlpha = (VkCompositeAlphaFlagBitsKHR)alphaMode;
				}
			}

			break;
		}

		case TEST_DIMENSION_PRESENT_MODE:
		{
			for (vector<VkPresentModeKHR>::const_iterator curMode = presentModes.begin(); curMode != presentModes.end(); ++curMode)
			{
				cases.push_back(baseParameters);
				cases.back().presentMode = *curMode;
			}

			break;
		}

		case TEST_DIMENSION_CLIPPED:
		{
			cases.push_back(baseParameters);
			cases.back().clipped = VK_FALSE;

			cases.push_back(baseParameters);
			cases.back().clipped = VK_TRUE;

			break;
		}

		default:
			DE_FATAL("Impossible");
	}

	DE_ASSERT(!cases.empty());
	return cases;
}

vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type								wsiType,
																  TestDimension						dimension,
																  const InstanceInterface&			vki,
																  VkPhysicalDevice					physicalDevice,
																  VkSurfaceKHR						surface)
{
	const VkSurfaceCapabilitiesKHR		capabilities	= getPhysicalDeviceSurfaceCapabilities(vki,
																							   physicalDevice,
																							   surface);
	const vector<VkSurfaceFormatKHR>	formats			= getPhysicalDeviceSurfaceFormats(vki,
																						  physicalDevice,
																						  surface);
	const vector<VkPresentModeKHR>		presentModes	= getPhysicalDeviceSurfacePresentModes(vki,
																							   physicalDevice,
																							   surface);

	return generateSwapchainParameterCases(wsiType, dimension, capabilities, formats, presentModes);
}

tcu::TestStatus createSwapchainTest (Context& context, TestParameters params)
{
	const InstanceHelper					instHelper	(context, params.wsiType);
	const NativeObjects						native		(context, instHelper.supportedExtensions, params.wsiType);
	const Unique<VkSurfaceKHR>				surface		(createSurface(instHelper.vki, *instHelper.instance, params.wsiType, *native.display, *native.window));
	const DeviceHelper						devHelper	(context, instHelper.vki, *instHelper.instance, *surface);
	const vector<VkSwapchainCreateInfoKHR>	cases		(generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));

	for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
	{
		VkSwapchainCreateInfoKHR	curParams	= cases[caseNdx];

		curParams.surface				= *surface;
		curParams.queueFamilyIndexCount	= 1u;
		curParams.pQueueFamilyIndices	= &devHelper.queueFamilyIndex;

		context.getTestContext().getLog()
			<< TestLog::Message << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": " << curParams << TestLog::EndMessage;

		{
			const Unique<VkSwapchainKHR>	swapchain	(createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams));
		}
	}

	return tcu::TestStatus::pass("Creating swapchain succeeded");
}

tcu::TestStatus createSwapchainSimulateOOMTest (Context& context, TestParameters params)
{
	const size_t				maxCases			= 300u;
	const deUint32				maxAllocs			= 1024u;

	tcu::TestLog&				log					= context.getTestContext().getLog();
	tcu::ResultCollector		results				(log);

	AllocationCallbackRecorder	allocationRecorder	(getSystemAllocator());
	DeterministicFailAllocator	failingAllocator	(allocationRecorder.getCallbacks(),
													 DeterministicFailAllocator::MODE_DO_NOT_COUNT,
													 0);
	{
		const InstanceHelper					instHelper	(context, params.wsiType, failingAllocator.getCallbacks());
		const NativeObjects						native		(context, instHelper.supportedExtensions, params.wsiType);
		const Unique<VkSurfaceKHR>				surface		(createSurface(instHelper.vki,
																			*instHelper.instance,
																			params.wsiType,
																			*native.display,
																			*native.window,
																			failingAllocator.getCallbacks()));
		const DeviceHelper						devHelper	(context, instHelper.vki, *instHelper.instance, *surface, failingAllocator.getCallbacks());
		const vector<VkSwapchainCreateInfoKHR>	allCases	(generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));

		if (maxCases < allCases.size())
			log << TestLog::Message << "Note: Will only test first " << maxCases << " cases out of total of " << allCases.size() << " parameter combinations" << TestLog::EndMessage;

		for (size_t caseNdx = 0; caseNdx < de::min(maxCases, allCases.size()); ++caseNdx)
		{
			log << TestLog::Message << "Testing parameter case " << caseNdx << ": " << allCases[caseNdx] << TestLog::EndMessage;

			for (deUint32 numPassingAllocs = 0; numPassingAllocs <= maxAllocs; ++numPassingAllocs)
			{
				bool	gotOOM	= false;

				failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);

				log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;

				try
				{
					VkSwapchainCreateInfoKHR	curParams	= allCases[caseNdx];

					curParams.surface				= *surface;
					curParams.queueFamilyIndexCount	= 1u;
					curParams.pQueueFamilyIndices	= &devHelper.queueFamilyIndex;

					{
						const Unique<VkSwapchainKHR>	swapchain	(createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks()));
					}
				}
				catch (const OutOfMemoryError& e)
				{
					log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
					gotOOM = true;
				}

				if (!gotOOM)
				{
					log << TestLog::Message << "Creating swapchain succeeded!" << TestLog::EndMessage;

					if (numPassingAllocs == 0)
						results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");

					break;
				}
				else if (numPassingAllocs == maxAllocs)
					results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded");
			}
		}

		context.getTestContext().touchWatchdog();
	}

	if (!validateAndLog(log, allocationRecorder, 0u))
		results.fail("Detected invalid system allocation callback");

	return tcu::TestStatus(results.getResult(), results.getMessage());
}

struct GroupParameters
{
	typedef FunctionInstance1<TestParameters>::Function	Function;

	Type		wsiType;
	Function	function;

	GroupParameters (Type wsiType_, Function function_)
		: wsiType	(wsiType_)
		, function	(function_)
	{}

	GroupParameters (void)
		: wsiType	(TYPE_LAST)
		, function	((Function)DE_NULL)
	{}
};

void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters params)
{
	for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
	{
		const TestDimension		testDimension	= (TestDimension)dimensionNdx;

		addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension));
	}
}

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

	return parameters;
}

typedef de::SharedPtr<Unique<VkImageView> >		ImageViewSp;
typedef de::SharedPtr<Unique<VkFramebuffer> >	FramebufferSp;

class TriangleRenderer
{
public:
									TriangleRenderer	(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 Allocator&					allocator,
														 const BinaryCollection&	binaryRegistry,
														 const vector<VkImage>		swapchainImages,
														 const VkFormat				framebufferFormat,
														 const UVec2&				renderSize);
									~TriangleRenderer	(void);

	void							recordFrame			(VkCommandBuffer			cmdBuffer,
														 deUint32					imageNdx,
														 deUint32					frameNdx) const;

	static void						getPrograms			(SourceCollections& dst);

private:
	static Move<VkRenderPass>		createRenderPass	(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 const VkFormat				colorAttachmentFormat);
	static Move<VkPipelineLayout>	createPipelineLayout(const DeviceInterface&		vkd,
														 VkDevice					device);
	static Move<VkPipeline>			createPipeline		(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 const VkRenderPass			renderPass,
														 const VkPipelineLayout		pipelineLayout,
														 const BinaryCollection&	binaryCollection,
														 const UVec2&				renderSize);

	static Move<VkImageView>		createAttachmentView(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 const VkImage				image,
														 const VkFormat				format);
	static Move<VkFramebuffer>		createFramebuffer	(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 const VkRenderPass			renderPass,
														 const VkImageView			colorAttachment,
														 const UVec2&				renderSize);

	static Move<VkBuffer>			createBuffer		(const DeviceInterface&		vkd,
														 VkDevice					device,
														 VkDeviceSize				size,
														 VkBufferUsageFlags			usage);

	const DeviceInterface&			m_vkd;

	const vector<VkImage>			m_swapchainImages;
	const tcu::UVec2				m_renderSize;

	const Unique<VkRenderPass>		m_renderPass;
	const Unique<VkPipelineLayout>	m_pipelineLayout;
	const Unique<VkPipeline>		m_pipeline;

	const Unique<VkBuffer>			m_vertexBuffer;
	const UniquePtr<Allocation>		m_vertexBufferMemory;

	vector<ImageViewSp>				m_attachmentViews;
	vector<FramebufferSp>			m_framebuffers;
};

Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface&	vkd,
													   const VkDevice			device,
													   const VkFormat			colorAttachmentFormat)
{
	const VkAttachmentDescription	colorAttDesc		=
	{
		(VkAttachmentDescriptionFlags)0,
		colorAttachmentFormat,
		VK_SAMPLE_COUNT_1_BIT,
		VK_ATTACHMENT_LOAD_OP_CLEAR,
		VK_ATTACHMENT_STORE_OP_STORE,
		VK_ATTACHMENT_LOAD_OP_DONT_CARE,
		VK_ATTACHMENT_STORE_OP_DONT_CARE,
		VK_IMAGE_LAYOUT_UNDEFINED,
		VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
	};
	const VkAttachmentReference		colorAttRef			=
	{
		0u,
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
	};
	const VkSubpassDescription		subpassDesc			=
	{
		(VkSubpassDescriptionFlags)0u,
		VK_PIPELINE_BIND_POINT_GRAPHICS,
		0u,							// inputAttachmentCount
		DE_NULL,					// pInputAttachments
		1u,							// colorAttachmentCount
		&colorAttRef,				// pColorAttachments
		DE_NULL,					// pResolveAttachments
		DE_NULL,					// depthStencilAttachment
		0u,							// preserveAttachmentCount
		DE_NULL,					// pPreserveAttachments
	};
	const VkSubpassDependency		dependencies[]		=
	{
		{
			VK_SUBPASS_EXTERNAL,	// srcSubpass
			0u,						// dstSubpass
			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
			VK_ACCESS_MEMORY_READ_BIT,
			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
			VK_DEPENDENCY_BY_REGION_BIT
		},
		{
			0u,						// srcSubpass
			VK_SUBPASS_EXTERNAL,	// dstSubpass
			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
			VK_ACCESS_MEMORY_READ_BIT,
			VK_DEPENDENCY_BY_REGION_BIT
		},
	};
	const VkRenderPassCreateInfo	renderPassParams	=
	{
		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
		DE_NULL,
		(VkRenderPassCreateFlags)0,
		1u,
		&colorAttDesc,
		1u,
		&subpassDesc,
		DE_LENGTH_OF_ARRAY(dependencies),
		dependencies,
	};

	return vk::createRenderPass(vkd, device, &renderPassParams);
}

Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface&	vkd,
															   const VkDevice			device)
{
	const VkPushConstantRange						pushConstantRange		=
	{
		VK_SHADER_STAGE_VERTEX_BIT,
		0u,											// offset
		(deUint32)sizeof(deUint32),					// size
	};
	const VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
		DE_NULL,
		(vk::VkPipelineLayoutCreateFlags)0,
		0u,											// setLayoutCount
		DE_NULL,									// pSetLayouts
		1u,
		&pushConstantRange,
	};

	return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
}

Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface&	vkd,
												   const VkDevice			device,
												   const VkRenderPass		renderPass,
												   const VkPipelineLayout	pipelineLayout,
												   const BinaryCollection&	binaryCollection,
												   const UVec2&				renderSize)
{
	// \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
	//		 and can be deleted immediately following that call.
	const Unique<VkShaderModule>					vertShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
	const Unique<VkShaderModule>					fragShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));

	const VkSpecializationInfo						emptyShaderSpecParams	=
	{
		0u,											// mapEntryCount
		DE_NULL,									// pMap
		0,											// dataSize
		DE_NULL,									// pData
	};
	const VkPipelineShaderStageCreateInfo			shaderStageParams[]		=
	{
		{
			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
			DE_NULL,
			(VkPipelineShaderStageCreateFlags)0,
			VK_SHADER_STAGE_VERTEX_BIT,
			*vertShaderModule,
			"main",
			&emptyShaderSpecParams,
		},
		{
			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
			DE_NULL,
			(VkPipelineShaderStageCreateFlags)0,
			VK_SHADER_STAGE_FRAGMENT_BIT,
			*fragShaderModule,
			"main",
			&emptyShaderSpecParams,
		}
	};
	const VkPipelineDepthStencilStateCreateInfo		depthStencilParams		=
	{
		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineDepthStencilStateCreateFlags)0,
		DE_FALSE,									// depthTestEnable
		DE_FALSE,									// depthWriteEnable
		VK_COMPARE_OP_ALWAYS,						// depthCompareOp
		DE_FALSE,									// depthBoundsTestEnable
		DE_FALSE,									// stencilTestEnable
		{
			VK_STENCIL_OP_KEEP,							// failOp
			VK_STENCIL_OP_KEEP,							// passOp
			VK_STENCIL_OP_KEEP,							// depthFailOp
			VK_COMPARE_OP_ALWAYS,						// compareOp
			0u,											// compareMask
			0u,											// writeMask
			0u,											// reference
		},											// front
		{
			VK_STENCIL_OP_KEEP,							// failOp
			VK_STENCIL_OP_KEEP,							// passOp
			VK_STENCIL_OP_KEEP,							// depthFailOp
			VK_COMPARE_OP_ALWAYS,						// compareOp
			0u,											// compareMask
			0u,											// writeMask
			0u,											// reference
		},											// back
		-1.0f,										// minDepthBounds
		+1.0f,										// maxDepthBounds
	};
	const VkViewport								viewport0				=
	{
		0.0f,										// x
		0.0f,										// y
		(float)renderSize.x(),						// width
		(float)renderSize.y(),						// height
		0.0f,										// minDepth
		1.0f,										// maxDepth
	};
	const VkRect2D									scissor0				=
	{
		{ 0u, 0u, },								// offset
		{ renderSize.x(), renderSize.y() },			// extent
	};
	const VkPipelineViewportStateCreateInfo			viewportParams			=
	{
		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineViewportStateCreateFlags)0,
		1u,
		&viewport0,
		1u,
		&scissor0
	};
	const VkPipelineMultisampleStateCreateInfo		multisampleParams		=
	{
		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineMultisampleStateCreateFlags)0,
		VK_SAMPLE_COUNT_1_BIT,						// rasterizationSamples
		VK_FALSE,									// sampleShadingEnable
		0.0f,										// minSampleShading
		(const VkSampleMask*)DE_NULL,				// sampleMask
		VK_FALSE,									// alphaToCoverageEnable
		VK_FALSE,									// alphaToOneEnable
	};
	const VkPipelineRasterizationStateCreateInfo	rasterParams			=
	{
		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineRasterizationStateCreateFlags)0,
		VK_FALSE,									// depthClampEnable
		VK_FALSE,									// rasterizerDiscardEnable
		VK_POLYGON_MODE_FILL,						// polygonMode
		VK_CULL_MODE_NONE,							// cullMode
		VK_FRONT_FACE_COUNTER_CLOCKWISE,			// frontFace
		VK_FALSE,									// depthBiasEnable
		0.0f,										// depthBiasConstantFactor
		0.0f,										// depthBiasClamp
		0.0f,										// depthBiasSlopeFactor
		1.0f,										// lineWidth
	};
	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams		=
	{
		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineInputAssemblyStateCreateFlags)0,
		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
		DE_FALSE,									// primitiveRestartEnable
	};
	const VkVertexInputBindingDescription			vertexBinding0			=
	{
		0u,											// binding
		(deUint32)sizeof(tcu::Vec4),				// stride
		VK_VERTEX_INPUT_RATE_VERTEX,				// inputRate
	};
	const VkVertexInputAttributeDescription			vertexAttrib0			=
	{
		0u,											// location
		0u,											// binding
		VK_FORMAT_R32G32B32A32_SFLOAT,				// format
		0u,											// offset
	};
	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineVertexInputStateCreateFlags)0,
		1u,
		&vertexBinding0,
		1u,
		&vertexAttrib0,
	};
	const VkPipelineColorBlendAttachmentState		attBlendParams0			=
	{
		VK_FALSE,									// blendEnable
		VK_BLEND_FACTOR_ONE,						// srcColorBlendFactor
		VK_BLEND_FACTOR_ZERO,						// dstColorBlendFactor
		VK_BLEND_OP_ADD,							// colorBlendOp
		VK_BLEND_FACTOR_ONE,						// srcAlphaBlendFactor
		VK_BLEND_FACTOR_ZERO,						// dstAlphaBlendFactor
		VK_BLEND_OP_ADD,							// alphaBlendOp
		(VK_COLOR_COMPONENT_R_BIT|
		 VK_COLOR_COMPONENT_G_BIT|
		 VK_COLOR_COMPONENT_B_BIT|
		 VK_COLOR_COMPONENT_A_BIT),					// colorWriteMask
	};
	const VkPipelineColorBlendStateCreateInfo		blendParams				=
	{
		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineColorBlendStateCreateFlags)0,
		VK_FALSE,									// logicOpEnable
		VK_LOGIC_OP_COPY,
		1u,
		&attBlendParams0,
		{ 0.0f, 0.0f, 0.0f, 0.0f },					// blendConstants[4]
	};
	const VkGraphicsPipelineCreateInfo				pipelineParams			=
	{
		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
		DE_NULL,
		(VkPipelineCreateFlags)0,
		(deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams),
		shaderStageParams,
		&vertexInputStateParams,
		&inputAssemblyParams,
		(const VkPipelineTessellationStateCreateInfo*)DE_NULL,
		&viewportParams,
		&rasterParams,
		&multisampleParams,
		&depthStencilParams,
		&blendParams,
		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
		pipelineLayout,
		renderPass,
		0u,											// subpass
		DE_NULL,									// basePipelineHandle
		0u,											// basePipelineIndex
	};

	return vk::createGraphicsPipeline(vkd, device, (VkPipelineCache)0, &pipelineParams);
}

Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface&	vkd,
														  const VkDevice			device,
														  const VkImage				image,
														  const VkFormat			format)
{
	const VkImageViewCreateInfo		viewParams	=
	{
		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
		DE_NULL,
		(VkImageViewCreateFlags)0,
		image,
		VK_IMAGE_VIEW_TYPE_2D,
		format,
		vk::makeComponentMappingRGBA(),
		{
			VK_IMAGE_ASPECT_COLOR_BIT,
			0u,						// baseMipLevel
			1u,						// levelCount
			0u,						// baseArrayLayer
			1u,						// layerCount
		},
	};

	return vk::createImageView(vkd, device, &viewParams);
}

Move<VkFramebuffer> TriangleRenderer::createFramebuffer	(const DeviceInterface&		vkd,
														 const VkDevice				device,
														 const VkRenderPass			renderPass,
														 const VkImageView			colorAttachment,
														 const UVec2&				renderSize)
{
	const VkFramebufferCreateInfo	framebufferParams	=
	{
		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
		DE_NULL,
		(VkFramebufferCreateFlags)0,
		renderPass,
		1u,
		&colorAttachment,
		renderSize.x(),
		renderSize.y(),
		1u,							// layers
	};

	return vk::createFramebuffer(vkd, device, &framebufferParams);
}

Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface&	vkd,
											   VkDevice					device,
											   VkDeviceSize				size,
											   VkBufferUsageFlags		usage)
{
	const VkBufferCreateInfo	bufferParams	=
	{
		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
		DE_NULL,
		(VkBufferCreateFlags)0,
		size,
		usage,
		VK_SHARING_MODE_EXCLUSIVE,
		0,
		DE_NULL
	};

	return vk::createBuffer(vkd, device, &bufferParams);
}

TriangleRenderer::TriangleRenderer (const DeviceInterface&	vkd,
									const VkDevice			device,
									Allocator&				allocator,
									const BinaryCollection&	binaryRegistry,
									const vector<VkImage>	swapchainImages,
									const VkFormat			framebufferFormat,
									const UVec2&			renderSize)
	: m_vkd					(vkd)
	, m_swapchainImages		(swapchainImages)
	, m_renderSize			(renderSize)
	, m_renderPass			(createRenderPass(vkd, device, framebufferFormat))
	, m_pipelineLayout		(createPipelineLayout(vkd, device))
	, m_pipeline			(createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
	, m_vertexBuffer		(createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
	, m_vertexBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
							 MemoryRequirement::HostVisible))
{
	m_attachmentViews.resize(swapchainImages.size());
	m_framebuffers.resize(swapchainImages.size());

	for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
	{
		m_attachmentViews[imageNdx]	= ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
		m_framebuffers[imageNdx]	= FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
	}

	VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));

	{
		const VkMappedMemoryRange	memRange	=
		{
			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
			DE_NULL,
			m_vertexBufferMemory->getMemory(),
			m_vertexBufferMemory->getOffset(),
			VK_WHOLE_SIZE
		};
		const tcu::Vec4				vertices[]	=
		{
			tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
			tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
			tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
		};
		DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);

		deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
		VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
	}
}

TriangleRenderer::~TriangleRenderer (void)
{
}

void TriangleRenderer::recordFrame (VkCommandBuffer	cmdBuffer,
									deUint32		imageNdx,
									deUint32		frameNdx) const
{
	const VkFramebuffer	curFramebuffer	= **m_framebuffers[imageNdx];

	{
		const VkCommandBufferBeginInfo	cmdBufBeginParams	=
		{
			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
			DE_NULL,
			(VkCommandBufferUsageFlags)0,
			(const VkCommandBufferInheritanceInfo*)DE_NULL,
		};
		VK_CHECK(m_vkd.beginCommandBuffer(cmdBuffer, &cmdBufBeginParams));
	}

	{
		const VkClearValue			clearValue		= makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
		const VkRenderPassBeginInfo	passBeginParams	=
		{
			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
			DE_NULL,
			*m_renderPass,
			curFramebuffer,
			{
				{ 0, 0 },
				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
			},													// renderArea
			1u,													// clearValueCount
			&clearValue,										// pClearValues
		};
		m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
	}

	m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);

	{
		const VkDeviceSize bindingOffset = 0;
		m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
	}

	m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
	m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
	m_vkd.cmdEndRenderPass(cmdBuffer);

	VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer));
}

void TriangleRenderer::getPrograms (SourceCollections& dst)
{
	dst.glslSources.add("tri-vert") << glu::VertexSource(
		"#version 310 es\n"
		"layout(location = 0) in highp vec4 a_position;\n"
		"layout(push_constant) uniform FrameData\n"
		"{\n"
		"    highp uint frameNdx;\n"
		"} frameData;\n"
		"void main (void)\n"
		"{\n"
		"    highp float angle = float(frameData.frameNdx) / 100.0;\n"
		"    highp float c     = cos(angle);\n"
		"    highp float s     = sin(angle);\n"
		"    highp mat4  t     = mat4( c, -s,  0,  0,\n"
		"                              s,  c,  0,  0,\n"
		"                              0,  0,  1,  0,\n"
		"                              0,  0,  0,  1);\n"
		"    gl_Position = t * a_position;\n"
		"}\n");
	dst.glslSources.add("tri-frag") << glu::FragmentSource(
		"#version 310 es\n"
		"layout(location = 0) out lowp vec4 o_color;\n"
		"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
}

typedef de::SharedPtr<Unique<VkCommandBuffer> >	CommandBufferSp;
typedef de::SharedPtr<Unique<VkFence> >			FenceSp;
typedef de::SharedPtr<Unique<VkSemaphore> >		SemaphoreSp;

Move<VkFence> createFence (const DeviceInterface&	vkd,
						   const VkDevice			device)
{
	const VkFenceCreateInfo	fenceParams	=
	{
		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
		DE_NULL,
		(VkFenceCreateFlags)0,
	};
	return vk::createFence(vkd, device, &fenceParams);
}

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

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

	return fences;
}

Move<VkSemaphore> createSemaphore (const DeviceInterface&	vkd,
								   const VkDevice			device)
{
	const VkSemaphoreCreateInfo	semaphoreParams	=
	{
		VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
		DE_NULL,
		(VkSemaphoreCreateFlags)0,
	};
	return vk::createSemaphore(vkd, device, &semaphoreParams);
}

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

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

	return semaphores;
}

Move<VkCommandPool> createCommandPool (const DeviceInterface&	vkd,
									   const VkDevice			device,
									   VkCommandPoolCreateFlags	flags,
									   deUint32					queueFamilyIndex)
{
	const VkCommandPoolCreateInfo	commandPoolParams	=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
		DE_NULL,
		flags,
		queueFamilyIndex
	};

	return createCommandPool(vkd, device, &commandPoolParams);
}

vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&		vkd,
												const VkDevice				device,
												const VkCommandPool			commandPool,
												const VkCommandBufferLevel	level,
												const size_t				numCommandBuffers)
{
	const VkCommandBufferAllocateInfo	allocInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
		DE_NULL,
		commandPool,
		level,
		1u,
	};

	vector<CommandBufferSp>				buffers		(numCommandBuffers);

	for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
		buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, &allocInfo)));

	return buffers;
}

tcu::TestStatus basicRenderTest (Context& context, Type wsiType)
{
	const tcu::UVec2				desiredSize					(256, 256);
	const InstanceHelper			instHelper					(context, wsiType);
	const NativeObjects				native						(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
	const Unique<VkSurfaceKHR>		surface						(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
	const DeviceHelper				devHelper					(context, instHelper.vki, *instHelper.instance, *surface);
	const DeviceInterface&			vkd							= devHelper.vkd;
	const VkDevice					device						= *devHelper.device;
	SimpleAllocator					allocator					(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
	const VkSwapchainCreateInfoKHR	swapchainInfo				= getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
	const Unique<VkSwapchainKHR>	swapchain					(createSwapchainKHR(vkd, device, &swapchainInfo));
	const vector<VkImage>			swapchainImages				= getSwapchainImages(vkd, device, *swapchain);

	const TriangleRenderer			renderer					(vkd,
																 device,
																 allocator,
																 context.getBinaryCollection(),
																 swapchainImages,
																 swapchainInfo.imageFormat,
																 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));

	const Unique<VkCommandPool>		commandPool					(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));

	const size_t					maxQueuedFrames				= swapchainImages.size()*2;

	// We need to keep hold of fences from vkAcquireNextImageKHR to actually
	// limit number of frames we allow to be queued.
	const vector<FenceSp>			imageReadyFences			(createFences(vkd, device, maxQueuedFrames));

	// We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
	// the semaphore in same time as the fence we use to meter rendering.
	const vector<SemaphoreSp>		imageReadySemaphores		(createSemaphores(vkd, device, maxQueuedFrames+1));

	// For rest we simply need maxQueuedFrames as we will wait for image
	// from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
	// previous uses must have completed.
	const vector<SemaphoreSp>		renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames));
	const vector<CommandBufferSp>	commandBuffers				(allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));

	try
	{
		const deUint32	numFramesToRender	= 60*10;

		for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
		{
			const VkFence		imageReadyFence		= **imageReadyFences[frameNdx%imageReadyFences.size()];
			const VkSemaphore	imageReadySemaphore	= **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
			deUint32			imageNdx			= ~0u;

			if (frameNdx >= maxQueuedFrames)
				VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));

			VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));

			{
				const VkResult	acquireResult	= vkd.acquireNextImageKHR(device,
																		  *swapchain,
																		  std::numeric_limits<deUint64>::max(),
																		  imageReadySemaphore,
																		  imageReadyFence,
																		  &imageNdx);

				if (acquireResult == VK_SUBOPTIMAL_KHR)
					context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
				else
					VK_CHECK(acquireResult);
			}

			TCU_CHECK((size_t)imageNdx < swapchainImages.size());

			{
				const VkSemaphore			renderingCompleteSemaphore	= **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
				const VkCommandBuffer		commandBuffer				= **commandBuffers[frameNdx%commandBuffers.size()];
				const VkPipelineStageFlags	waitDstStage				= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
				const VkSubmitInfo			submitInfo					=
				{
					VK_STRUCTURE_TYPE_SUBMIT_INFO,
					DE_NULL,
					1u,
					&imageReadySemaphore,
					&waitDstStage,
					1u,
					&commandBuffer,
					1u,
					&renderingCompleteSemaphore
				};
				const VkPresentInfoKHR		presentInfo					=
				{
					VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
					DE_NULL,
					1u,
					&renderingCompleteSemaphore,
					1u,
					&*swapchain,
					&imageNdx,
					(VkResult*)DE_NULL
				};

				renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
				VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, (VkFence)0));
				VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
			}
		}

		VK_CHECK(vkd.deviceWaitIdle(device));
	}
	catch (...)
	{
		// Make sure device is idle before destroying resources
		vkd.deviceWaitIdle(device);
		throw;
	}

	return tcu::TestStatus::pass("Rendering tests succeeded");
}

vector<tcu::UVec2> getSwapchainSizeSequence (const VkSurfaceCapabilitiesKHR& capabilities, const tcu::UVec2& defaultSize)
{
	vector<tcu::UVec2> sizes(3);
	sizes[0] = defaultSize / 2u;
	sizes[1] = defaultSize;
	sizes[2] = defaultSize * 2u;

	for (deUint32 i = 0; i < sizes.size(); ++i)
	{
		sizes[i].x() = de::clamp(sizes[i].x(), capabilities.minImageExtent.width,  capabilities.maxImageExtent.width);
		sizes[i].y() = de::clamp(sizes[i].y(), capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
	}

	return sizes;
}

tcu::TestStatus resizeSwapchainTest (Context& context, Type wsiType)
{
	const tcu::UVec2				desiredSize			(256, 256);
	const InstanceHelper			instHelper			(context, wsiType);
	const NativeObjects				native				(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
	const Unique<VkSurfaceKHR>		surface				(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
	const DeviceHelper				devHelper			(context, instHelper.vki, *instHelper.instance, *surface);
	const PlatformProperties&		platformProperties	= getPlatformProperties(wsiType);
	const VkSurfaceCapabilitiesKHR	capabilities		= getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface);
	const DeviceInterface&			vkd					= devHelper.vkd;
	const VkDevice					device				= *devHelper.device;
	SimpleAllocator					allocator			(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
	vector<tcu::UVec2>				sizes				= getSwapchainSizeSequence(capabilities, desiredSize);
	Move<VkSwapchainKHR>			prevSwapchain;

	DE_ASSERT(platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE);
	DE_UNREF(platformProperties);

	for (deUint32 sizeNdx = 0; sizeNdx < sizes.size(); ++sizeNdx)
	{
		// \todo [2016-05-30 jesse] This test currently waits for idle and
		// recreates way more than necessary when recreating the swapchain. Make
		// it match expected real app behavior better by smoothly switching from
		// old to new swapchain. Once that is done, it will also be possible to
		// test creating a new swapchain while images from the previous one are
		// still acquired.

		VkSwapchainCreateInfoKHR		swapchainInfo				= getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, sizes[sizeNdx], 2);
		swapchainInfo.oldSwapchain = *prevSwapchain;

		Move<VkSwapchainKHR>			swapchain					(createSwapchainKHR(vkd, device, &swapchainInfo));
		const vector<VkImage>			swapchainImages				= getSwapchainImages(vkd, device, *swapchain);
		const TriangleRenderer			renderer					(vkd,
																	device,
																	allocator,
																	context.getBinaryCollection(),
																	swapchainImages,
																	swapchainInfo.imageFormat,
																	tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
		const Unique<VkCommandPool>		commandPool					(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
		const size_t					maxQueuedFrames				= swapchainImages.size()*2;

		// We need to keep hold of fences from vkAcquireNextImageKHR to actually
		// limit number of frames we allow to be queued.
		const vector<FenceSp>			imageReadyFences			(createFences(vkd, device, maxQueuedFrames));

		// We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
		// the semaphore in same time as the fence we use to meter rendering.
		const vector<SemaphoreSp>		imageReadySemaphores		(createSemaphores(vkd, device, maxQueuedFrames+1));

		// For rest we simply need maxQueuedFrames as we will wait for image
		// from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
		// previous uses must have completed.
		const vector<SemaphoreSp>		renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames));
		const vector<CommandBufferSp>	commandBuffers				(allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));

		try
		{
			const deUint32	numFramesToRender	= 60;

			for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
			{
				const VkFence		imageReadyFence		= **imageReadyFences[frameNdx%imageReadyFences.size()];
				const VkSemaphore	imageReadySemaphore	= **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
				deUint32			imageNdx			= ~0u;

				if (frameNdx >= maxQueuedFrames)
					VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));

				VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));

				{
					const VkResult	acquireResult	= vkd.acquireNextImageKHR(device,
																			  *swapchain,
																			  std::numeric_limits<deUint64>::max(),
																			  imageReadySemaphore,
																			  imageReadyFence,
																			  &imageNdx);

					if (acquireResult == VK_SUBOPTIMAL_KHR)
						context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
					else
						VK_CHECK(acquireResult);
				}

				TCU_CHECK((size_t)imageNdx < swapchainImages.size());

				{
					const VkSemaphore			renderingCompleteSemaphore	= **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
					const VkCommandBuffer		commandBuffer				= **commandBuffers[frameNdx%commandBuffers.size()];
					const VkPipelineStageFlags	waitDstStage				= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
					const VkSubmitInfo			submitInfo					=
					{
						VK_STRUCTURE_TYPE_SUBMIT_INFO,
						DE_NULL,
						1u,
						&imageReadySemaphore,
						&waitDstStage,
						1u,
						&commandBuffer,
						1u,
						&renderingCompleteSemaphore
					};
					const VkPresentInfoKHR		presentInfo					=
					{
						VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
						DE_NULL,
						1u,
						&renderingCompleteSemaphore,
						1u,
						&*swapchain,
						&imageNdx,
						(VkResult*)DE_NULL
					};

					renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
					VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, (VkFence)0));
					VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
				}
			}

			VK_CHECK(vkd.deviceWaitIdle(device));

			prevSwapchain = swapchain;
		}
		catch (...)
		{
			// Make sure device is idle before destroying resources
			vkd.deviceWaitIdle(device);
			throw;
		}
	}

	return tcu::TestStatus::pass("Resizing tests succeeded");
}

tcu::TestStatus getImagesIncompleteResultTest (Context& context, Type wsiType)
{
	const tcu::UVec2				desiredSize		(256, 256);
	const InstanceHelper			instHelper		(context, wsiType);
	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
	const DeviceHelper				devHelper		(context, instHelper.vki, *instHelper.instance, *surface);
	const VkSwapchainCreateInfoKHR	swapchainInfo	= getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
	const Unique<VkSwapchainKHR>	swapchain		(createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));

	vector<VkImage>		swapchainImages	= getSwapchainImages(devHelper.vkd, *devHelper.device, *swapchain);

	ValidateQueryBits::fillBits(swapchainImages.begin(), swapchainImages.end());

	const deUint32		usedCount		= static_cast<deUint32>(swapchainImages.size() / 2);
	deUint32			count			= usedCount;
	const VkResult		result			= devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &count, &swapchainImages[0]);

	if (count != usedCount || result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(swapchainImages.begin() + count, swapchainImages.end()))
		return tcu::TestStatus::fail("Get swapchain images didn't return VK_INCOMPLETE");
	else
		return tcu::TestStatus::pass("Get swapchain images tests succeeded");
}

tcu::TestStatus destroyNullHandleSwapchainTest (Context& context, Type wsiType)
{
	const InstanceHelper		instHelper	(context, wsiType);
	const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
	const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
	const DeviceHelper			devHelper	(context, instHelper.vki, *instHelper.instance, *surface);
	const VkSwapchainKHR		nullHandle	= DE_NULL;

	// Default allocator
	devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, DE_NULL);

	// Custom allocator
	{
		AllocationCallbackRecorder	recordingAllocator	(getSystemAllocator(), 1u);

		devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, recordingAllocator.getCallbacks());

		if (recordingAllocator.getNumRecords() != 0u)
			return tcu::TestStatus::fail("Implementation allocated/freed the memory");
	}

	return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
}

void getBasicRenderPrograms (SourceCollections& dst, Type)
{
	TriangleRenderer::getPrograms(dst);
}

void populateRenderGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
{
	addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest, wsiType);
}

void populateGetImagesGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
{
	addFunctionCase(testGroup, "incomplete", "Test VK_INCOMPLETE return code", getImagesIncompleteResultTest, wsiType);
}

void populateModifyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
{
	const PlatformProperties&	platformProperties	= getPlatformProperties(wsiType);

	if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
	{
		addFunctionCaseWithPrograms(testGroup, "resize", "Resize Swapchain Test", getBasicRenderPrograms, resizeSwapchainTest, wsiType);
	}

	// \todo [2016-05-30 jesse] Add tests for modifying preTransform, compositeAlpha, presentMode
}

void populateDestroyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
{
	addFunctionCase(testGroup, "null_handle", "Destroying a VK_NULL_HANDLE swapchain", destroyNullHandleSwapchainTest, wsiType);
}

} // anonymous

void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
{
	addTestGroup(testGroup, "create",			"Create VkSwapchain with various parameters",					populateSwapchainGroup,		GroupParameters(wsiType, createSwapchainTest));
	addTestGroup(testGroup, "simulate_oom",		"Simulate OOM using callbacks during swapchain construction",	populateSwapchainGroup,		GroupParameters(wsiType, createSwapchainSimulateOOMTest));
	addTestGroup(testGroup, "render",			"Rendering Tests",												populateRenderGroup,		wsiType);
	addTestGroup(testGroup, "modify",			"Modify VkSwapchain",											populateModifyGroup,		wsiType);
	addTestGroup(testGroup, "destroy",			"Destroy VkSwapchain",											populateDestroyGroup,		wsiType);
	addTestGroup(testGroup, "get_images",		"Get swapchain images",											populateGetImagesGroup,		wsiType);
}

} // wsi
} // vkt
