Home | History | Annotate | Download | only in api
      1 /*-------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Object management tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktApiObjectManagementTests.hpp"
     25 #include "vktTestCaseUtil.hpp"
     26 
     27 #include "vkDefs.hpp"
     28 #include "vkRef.hpp"
     29 #include "vkRefUtil.hpp"
     30 #include "vkQueryUtil.hpp"
     31 #include "vkMemUtil.hpp"
     32 #include "vkPrograms.hpp"
     33 #include "vkTypeUtil.hpp"
     34 #include "vkPlatform.hpp"
     35 #include "vkStrUtil.hpp"
     36 #include "vkAllocationCallbackUtil.hpp"
     37 #include "vkObjUtil.hpp"
     38 
     39 #include "tcuVector.hpp"
     40 #include "tcuResultCollector.hpp"
     41 #include "tcuCommandLine.hpp"
     42 #include "tcuTestLog.hpp"
     43 #include "tcuPlatform.hpp"
     44 
     45 #include "deUniquePtr.hpp"
     46 #include "deSharedPtr.hpp"
     47 #include "deArrayUtil.hpp"
     48 #include "deSpinBarrier.hpp"
     49 #include "deThread.hpp"
     50 #include "deInt32.h"
     51 
     52 #include <limits>
     53 
     54 #define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
     55 
     56 namespace vkt
     57 {
     58 namespace api
     59 {
     60 
     61 namespace
     62 {
     63 
     64 using namespace vk;
     65 
     66 using de::UniquePtr;
     67 using de::MovePtr;
     68 using de::SharedPtr;
     69 
     70 using tcu::IVec3;
     71 using tcu::UVec3;
     72 using tcu::ResultCollector;
     73 using tcu::TestStatus;
     74 using tcu::TestLog;
     75 
     76 using std::string;
     77 using std::vector;
     78 
     79 typedef SharedPtr<Move<VkPipeline> >			VkPipelineSp;		// Move so it's possible to disown the handle
     80 typedef SharedPtr<Move<VkDescriptorSet> >		VkDescriptorSetSp;
     81 typedef SharedPtr<Move<VkCommandBuffer> >		VkCommandBufferSp;
     82 
     83 class ThreadGroupThread;
     84 
     85 /*--------------------------------------------------------------------*//*!
     86  * \brief Thread group
     87  *
     88  * Thread group manages collection of threads that are expected to be
     89  * launched simultaneously as a group.
     90  *
     91  * Shared barrier is provided for synchronizing execution. Terminating thread
     92  * early either by returning from ThreadGroupThread::runThread() or throwing
     93  * an exception is safe, and other threads will continue execution. The
     94  * thread that has been terminated is simply removed from the synchronization
     95  * group.
     96  *
     97  * TestException-based exceptions are collected and translated into a
     98  * tcu::TestStatus by using tcu::ResultCollector.
     99  *
    100  * Use cases for ThreadGroup include for example testing thread-safety of
    101  * certain API operations by poking API simultaneously from multiple
    102  * threads.
    103  *//*--------------------------------------------------------------------*/
    104 class ThreadGroup
    105 {
    106 public:
    107 							ThreadGroup			(void);
    108 							~ThreadGroup		(void);
    109 
    110 	void					add					(de::MovePtr<ThreadGroupThread> thread);
    111 	TestStatus				run					(void);
    112 
    113 private:
    114 	typedef std::vector<de::SharedPtr<ThreadGroupThread> >	ThreadVector;
    115 
    116 	ThreadVector			m_threads;
    117 	de::SpinBarrier			m_barrier;
    118 } DE_WARN_UNUSED_TYPE;
    119 
    120 class ThreadGroupThread : private de::Thread
    121 {
    122 public:
    123 							ThreadGroupThread	(void);
    124 	virtual					~ThreadGroupThread	(void);
    125 
    126 	void					start				(de::SpinBarrier* groupBarrier);
    127 
    128 	ResultCollector&		getResultCollector	(void) { return m_resultCollector; }
    129 
    130 	using de::Thread::join;
    131 
    132 protected:
    133 	virtual void			runThread			(void) = 0;
    134 
    135 	void					barrier				(void);
    136 
    137 private:
    138 							ThreadGroupThread	(const ThreadGroupThread&);
    139 	ThreadGroupThread&		operator=			(const ThreadGroupThread&);
    140 
    141 	void					run					(void);
    142 
    143 	ResultCollector			m_resultCollector;
    144 	de::SpinBarrier*		m_barrier;
    145 };
    146 
    147 // ThreadGroup
    148 
    149 ThreadGroup::ThreadGroup (void)
    150 	: m_barrier(1)
    151 {
    152 }
    153 
    154 ThreadGroup::~ThreadGroup (void)
    155 {
    156 }
    157 
    158 void ThreadGroup::add (de::MovePtr<ThreadGroupThread> thread)
    159 {
    160 	m_threads.push_back(de::SharedPtr<ThreadGroupThread>(thread.release()));
    161 }
    162 
    163 tcu::TestStatus ThreadGroup::run (void)
    164 {
    165 	tcu::ResultCollector	resultCollector;
    166 
    167 	m_barrier.reset((int)m_threads.size());
    168 
    169 	for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
    170 		(*threadIter)->start(&m_barrier);
    171 
    172 	for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
    173 	{
    174 		tcu::ResultCollector&	threadResult	= (*threadIter)->getResultCollector();
    175 		(*threadIter)->join();
    176 		resultCollector.addResult(threadResult.getResult(), threadResult.getMessage());
    177 	}
    178 
    179 	return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
    180 }
    181 
    182 // ThreadGroupThread
    183 
    184 ThreadGroupThread::ThreadGroupThread (void)
    185 	: m_barrier(DE_NULL)
    186 {
    187 }
    188 
    189 ThreadGroupThread::~ThreadGroupThread (void)
    190 {
    191 }
    192 
    193 void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
    194 {
    195 	m_barrier = groupBarrier;
    196 	de::Thread::start();
    197 }
    198 
    199 void ThreadGroupThread::run (void)
    200 {
    201 	try
    202 	{
    203 		runThread();
    204 	}
    205 	catch (const tcu::TestException& e)
    206 	{
    207 		getResultCollector().addResult(e.getTestResult(), e.getMessage());
    208 	}
    209 	catch (const std::exception& e)
    210 	{
    211 		getResultCollector().addResult(QP_TEST_RESULT_FAIL, e.what());
    212 	}
    213 	catch (...)
    214 	{
    215 		getResultCollector().addResult(QP_TEST_RESULT_FAIL, "Exception");
    216 	}
    217 
    218 	m_barrier->removeThread(de::SpinBarrier::WAIT_MODE_AUTO);
    219 }
    220 
    221 inline void ThreadGroupThread::barrier (void)
    222 {
    223 	m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
    224 }
    225 
    226 deUint32 getDefaultTestThreadCount (void)
    227 {
    228 	return de::clamp(deGetNumAvailableLogicalCores(), 2u, 8u);
    229 }
    230 
    231 // Utilities
    232 
    233 struct Environment
    234 {
    235 	const PlatformInterface&		vkp;
    236 	deUint32						apiVersion;
    237 	VkInstance						instance;
    238 	const DeviceInterface&			vkd;
    239 	VkDevice						device;
    240 	deUint32						queueFamilyIndex;
    241 	const BinaryCollection&			programBinaries;
    242 	const VkAllocationCallbacks*	allocationCallbacks;
    243 	deUint32						maxResourceConsumers;		// Maximum number of objects using same Object::Resources concurrently
    244 
    245 	Environment (Context& context, deUint32 maxResourceConsumers_)
    246 		: vkp					(context.getPlatformInterface())
    247 		, apiVersion			(context.getUsedApiVersion())
    248 		, instance				(context.getInstance())
    249 		, vkd					(context.getDeviceInterface())
    250 		, device				(context.getDevice())
    251 		, queueFamilyIndex		(context.getUniversalQueueFamilyIndex())
    252 		, programBinaries		(context.getBinaryCollection())
    253 		, allocationCallbacks	(DE_NULL)
    254 		, maxResourceConsumers	(maxResourceConsumers_)
    255 	{
    256 	}
    257 
    258 	Environment (const PlatformInterface&		vkp_,
    259 				 deUint32						apiVersion_,
    260 				 VkInstance						instance_,
    261 				 const DeviceInterface&			vkd_,
    262 				 VkDevice						device_,
    263 				 deUint32						queueFamilyIndex_,
    264 				 const BinaryCollection&		programBinaries_,
    265 				 const VkAllocationCallbacks*	allocationCallbacks_,
    266 				 deUint32						maxResourceConsumers_)
    267 		: vkp					(vkp_)
    268 		, apiVersion			(apiVersion_)
    269 		, instance				(instance_)
    270 		, vkd					(vkd_)
    271 		, device				(device_)
    272 		, queueFamilyIndex		(queueFamilyIndex_)
    273 		, programBinaries		(programBinaries_)
    274 		, allocationCallbacks	(allocationCallbacks_)
    275 		, maxResourceConsumers	(maxResourceConsumers_)
    276 	{
    277 	}
    278 };
    279 
    280 template<typename Case>
    281 struct Dependency
    282 {
    283 	typename Case::Resources		resources;
    284 	Unique<typename Case::Type>		object;
    285 
    286 	Dependency (const Environment& env, const typename Case::Parameters& params)
    287 		: resources	(env, params)
    288 		, object	(Case::create(env, resources, params))
    289 	{}
    290 };
    291 
    292 template<typename T>
    293 T roundUpToNextMultiple (T value, T multiple)
    294 {
    295 	if (value % multiple == 0)
    296 		return value;
    297 	else
    298 		return value + multiple - (value % multiple);
    299 }
    300 
    301 #if defined(DE_DEBUG)
    302 template<typename T>
    303 bool isPowerOfTwo (T value)
    304 {
    305 	return ((value & (value - T(1))) == 0);
    306 }
    307 #endif
    308 
    309 template<typename T>
    310 T alignToPowerOfTwo (T value, T align)
    311 {
    312 	DE_ASSERT(isPowerOfTwo(align));
    313 	return (value + align - T(1)) & ~(align - T(1));
    314 }
    315 
    316 inline bool hasDeviceExtension (Context& context, const string name)
    317 {
    318 	return isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), name);
    319 }
    320 
    321 VkDeviceSize getPageTableSize (const PlatformMemoryLimits& limits, VkDeviceSize allocationSize)
    322 {
    323 	VkDeviceSize	totalSize	= 0;
    324 
    325 	for (size_t levelNdx = 0; levelNdx < limits.devicePageTableHierarchyLevels; ++levelNdx)
    326 	{
    327 		const VkDeviceSize	coveredAddressSpaceSize	= limits.devicePageSize<<levelNdx;
    328 		const VkDeviceSize	numPagesNeeded			= alignToPowerOfTwo(allocationSize, coveredAddressSpaceSize) / coveredAddressSpaceSize;
    329 
    330 		totalSize += numPagesNeeded*limits.devicePageTableEntrySize;
    331 	}
    332 
    333 	return totalSize;
    334 }
    335 
    336 size_t getCurrentSystemMemoryUsage (const AllocationCallbackRecorder& allocRecoder)
    337 {
    338 	const size_t						systemAllocationOverhead	= sizeof(void*)*2;
    339 	AllocationCallbackValidationResults	validationResults;
    340 
    341 	validateAllocationCallbacks(allocRecoder, &validationResults);
    342 	TCU_CHECK(validationResults.violations.empty());
    343 
    344 	return getLiveSystemAllocationTotal(validationResults) + systemAllocationOverhead*validationResults.liveAllocations.size();
    345 }
    346 
    347 template<typename Object>
    348 size_t computeSystemMemoryUsage (Context& context, const typename Object::Parameters& params)
    349 {
    350 	AllocationCallbackRecorder			allocRecorder		(getSystemAllocator());
    351 	const Environment					env					(context.getPlatformInterface(),
    352 															 context.getUsedApiVersion(),
    353 															 context.getInstance(),
    354 															 context.getDeviceInterface(),
    355 															 context.getDevice(),
    356 															 context.getUniversalQueueFamilyIndex(),
    357 															 context.getBinaryCollection(),
    358 															 allocRecorder.getCallbacks(),
    359 															 1u);
    360 	const typename Object::Resources	res					(env, params);
    361 	const size_t						resourceMemoryUsage	= getCurrentSystemMemoryUsage(allocRecorder);
    362 
    363 	{
    364 		Unique<typename Object::Type>	obj					(Object::create(env, res, params));
    365 		const size_t					totalMemoryUsage	= getCurrentSystemMemoryUsage(allocRecorder);
    366 
    367 		return totalMemoryUsage - resourceMemoryUsage;
    368 	}
    369 }
    370 
    371 size_t getSafeObjectCount (const PlatformMemoryLimits&	memoryLimits,
    372 						   size_t						objectSystemMemoryUsage,
    373 						   VkDeviceSize					objectDeviceMemoryUsage = 0)
    374 {
    375 	const VkDeviceSize	roundedUpDeviceMemory	= roundUpToNextMultiple(objectDeviceMemoryUsage, memoryLimits.deviceMemoryAllocationGranularity);
    376 
    377 	if (memoryLimits.totalDeviceLocalMemory > 0 && roundedUpDeviceMemory > 0)
    378 	{
    379 		if (objectSystemMemoryUsage > 0)
    380 			return de::min(memoryLimits.totalSystemMemory / objectSystemMemoryUsage,
    381 						   (size_t)(memoryLimits.totalDeviceLocalMemory / roundedUpDeviceMemory));
    382 		else
    383 			return (size_t)(memoryLimits.totalDeviceLocalMemory / roundedUpDeviceMemory);
    384 	}
    385 	else if (objectSystemMemoryUsage + roundedUpDeviceMemory > 0)
    386 	{
    387 		DE_ASSERT(roundedUpDeviceMemory <= std::numeric_limits<size_t>::max() - objectSystemMemoryUsage);
    388 		return memoryLimits.totalSystemMemory / (objectSystemMemoryUsage + (size_t)roundedUpDeviceMemory);
    389 	}
    390 	else
    391 	{
    392 		// Warning: at this point driver has probably not implemented allocation callbacks correctly
    393 		return std::numeric_limits<size_t>::max();
    394 	}
    395 }
    396 
    397 PlatformMemoryLimits getPlatformMemoryLimits (Context& context)
    398 {
    399 	PlatformMemoryLimits	memoryLimits;
    400 
    401 	context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
    402 
    403 	return memoryLimits;
    404 }
    405 
    406 size_t getSafeObjectCount (Context& context, size_t objectSystemMemoryUsage, VkDeviceSize objectDeviceMemorySize = 0)
    407 {
    408 	return getSafeObjectCount(getPlatformMemoryLimits(context), objectSystemMemoryUsage, objectDeviceMemorySize);
    409 }
    410 
    411 VkDeviceSize getPageTableSize (Context& context, VkDeviceSize allocationSize)
    412 {
    413 	return getPageTableSize(getPlatformMemoryLimits(context), allocationSize);
    414 }
    415 
    416 template<typename Object>
    417 deUint32 getSafeObjectCount (Context&							context,
    418 							 const typename Object::Parameters&	params,
    419 							 deUint32							hardCountLimit,
    420 							 VkDeviceSize						deviceMemoryUsage = 0)
    421 {
    422 	return (deUint32)de::min((size_t)hardCountLimit,
    423 							 getSafeObjectCount(context,
    424 												computeSystemMemoryUsage<Object>(context, params),
    425 												deviceMemoryUsage));
    426 }
    427 
    428 // Object definitions
    429 
    430 enum
    431 {
    432 	MAX_CONCURRENT_INSTANCES		= 32,
    433 	MAX_CONCURRENT_DEVICES			= 32,
    434 	MAX_CONCURRENT_SYNC_PRIMITIVES	= 100,
    435 	MAX_CONCURRENT_PIPELINE_CACHES	= 128,
    436 	DEFAULT_MAX_CONCURRENT_OBJECTS	= 16*1024,
    437 };
    438 
    439 struct Instance
    440 {
    441 	typedef VkInstance Type;
    442 
    443 	struct Parameters
    444 	{
    445 		const vector<string>	instanceExtensions;
    446 
    447 		Parameters (void) {}
    448 
    449 		Parameters (vector<string>& extensions)
    450 			: instanceExtensions	(extensions)
    451 		{}
    452 	};
    453 
    454 	struct Resources
    455 	{
    456 		Resources (const Environment&, const Parameters&) {}
    457 	};
    458 
    459 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    460 	{
    461 		return getSafeObjectCount<Instance>(context, params, MAX_CONCURRENT_INSTANCES);
    462 	}
    463 
    464 	static Move<VkInstance> create (const Environment& env, const Resources&, const Parameters& params)
    465 	{
    466 		vector<const char*>					extensionNamePtrs;
    467 		const vector<VkExtensionProperties>	instanceExts = enumerateInstanceExtensionProperties(env.vkp, DE_NULL);
    468 		for (size_t extensionID = 0; extensionID < params.instanceExtensions.size(); extensionID++)
    469 		{
    470 			if (!isInstanceExtensionSupported(env.apiVersion, instanceExts, RequiredExtension(params.instanceExtensions[extensionID])))
    471 				TCU_THROW(NotSupportedError, (params.instanceExtensions[extensionID] + " is not supported").c_str());
    472 
    473 			if (!isCoreInstanceExtension(env.apiVersion, params.instanceExtensions[extensionID]))
    474 				extensionNamePtrs.push_back(params.instanceExtensions[extensionID].c_str());
    475 		}
    476 
    477 		const VkApplicationInfo		appInfo			=
    478 		{
    479 			VK_STRUCTURE_TYPE_APPLICATION_INFO,
    480 			DE_NULL,
    481 			DE_NULL,							// pApplicationName
    482 			0u,									// applicationVersion
    483 			DE_NULL,							// pEngineName
    484 			0u,									// engineVersion
    485 			env.apiVersion
    486 		};
    487 
    488 		const VkInstanceCreateInfo	instanceInfo	=
    489 		{
    490 			VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
    491 			DE_NULL,
    492 			(VkInstanceCreateFlags)0,
    493 			&appInfo,
    494 			0u,																// enabledLayerNameCount
    495 			DE_NULL,														// ppEnabledLayerNames
    496 			(deUint32)extensionNamePtrs.size(),								// enabledExtensionNameCount
    497 			extensionNamePtrs.empty() ? DE_NULL : &extensionNamePtrs[0],	// ppEnabledExtensionNames
    498 		};
    499 
    500 		return createInstance(env.vkp, &instanceInfo, env.allocationCallbacks);
    501 	}
    502 };
    503 
    504 struct Device
    505 {
    506 	typedef VkDevice Type;
    507 
    508 	struct Parameters
    509 	{
    510 		deUint32		deviceIndex;
    511 		VkQueueFlags	queueFlags;
    512 
    513 		Parameters (deUint32 deviceIndex_, VkQueueFlags queueFlags_)
    514 			: deviceIndex	(deviceIndex_)
    515 			, queueFlags	(queueFlags_)
    516 		{}
    517 	};
    518 
    519 	struct Resources
    520 	{
    521 		Dependency<Instance>	instance;
    522 		InstanceDriver			vki;
    523 		VkPhysicalDevice		physicalDevice;
    524 		deUint32				queueFamilyIndex;
    525 
    526 		Resources (const Environment& env, const Parameters& params)
    527 			: instance			(env, Instance::Parameters())
    528 			, vki				(env.vkp, *instance.object)
    529 			, physicalDevice	(0)
    530 			, queueFamilyIndex	(~0u)
    531 		{
    532 			{
    533 				const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(vki, *instance.object);
    534 
    535 				if (physicalDevices.size() <= (size_t)params.deviceIndex)
    536 					TCU_THROW(NotSupportedError, "Device not found");
    537 
    538 				physicalDevice = physicalDevices[params.deviceIndex];
    539 			}
    540 
    541 			{
    542 				const vector<VkQueueFamilyProperties>	queueProps		= getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
    543 				bool									foundMatching	= false;
    544 
    545 				for (size_t curQueueNdx = 0; curQueueNdx < queueProps.size(); curQueueNdx++)
    546 				{
    547 					if ((queueProps[curQueueNdx].queueFlags & params.queueFlags) == params.queueFlags)
    548 					{
    549 						queueFamilyIndex	= (deUint32)curQueueNdx;
    550 						foundMatching		= true;
    551 					}
    552 				}
    553 
    554 				if (!foundMatching)
    555 					TCU_THROW(NotSupportedError, "Matching queue not found");
    556 			}
    557 		}
    558 	};
    559 
    560 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    561 	{
    562 		return getSafeObjectCount<Device>(context, params, MAX_CONCURRENT_DEVICES);
    563 	}
    564 
    565 	static Move<VkDevice> create (const Environment& env, const Resources& res, const Parameters&)
    566 	{
    567 		const float	queuePriority	= 1.0;
    568 
    569 		const VkDeviceQueueCreateInfo	queues[]	=
    570 		{
    571 			{
    572 				VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
    573 				DE_NULL,
    574 				(VkDeviceQueueCreateFlags)0,
    575 				res.queueFamilyIndex,
    576 				1u,									// queueCount
    577 				&queuePriority,						// pQueuePriorities
    578 			}
    579 		};
    580 		const VkDeviceCreateInfo		deviceInfo	=
    581 		{
    582 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
    583 			DE_NULL,
    584 			(VkDeviceCreateFlags)0,
    585 			DE_LENGTH_OF_ARRAY(queues),
    586 			queues,
    587 			0u,										// enabledLayerNameCount
    588 			DE_NULL,								// ppEnabledLayerNames
    589 			0u,										// enabledExtensionNameCount
    590 			DE_NULL,								// ppEnabledExtensionNames
    591 			DE_NULL,								// pEnabledFeatures
    592 		};
    593 
    594 		return createDevice(env.vkp, env.instance, res.vki, res.physicalDevice, &deviceInfo, env.allocationCallbacks);
    595 	}
    596 };
    597 
    598 
    599 struct DeviceGroup
    600 {
    601 	typedef VkDevice Type;
    602 
    603 	struct Parameters
    604 	{
    605 		deUint32		deviceGroupIndex;
    606 		deUint32		deviceIndex;
    607 		VkQueueFlags	queueFlags;
    608 
    609 		Parameters (deUint32 deviceGroupIndex_, deUint32 deviceIndex_, VkQueueFlags queueFlags_)
    610 			: deviceGroupIndex	(deviceGroupIndex_)
    611 			, deviceIndex		(deviceIndex_)
    612 			, queueFlags		(queueFlags_)
    613 		{}
    614 	};
    615 
    616 	struct Resources
    617 	{
    618 		vector<string>				extensions;
    619 		Dependency<Instance>		instance;
    620 		InstanceDriver				vki;
    621 		vector<VkPhysicalDevice>	physicalDevices;
    622 		deUint32					physicalDeviceCount;
    623 		deUint32					queueFamilyIndex;
    624 
    625 		Resources (const Environment& env, const Parameters& params)
    626 			: extensions			(1, "VK_KHR_device_group_creation")
    627 			, instance				(env, Instance::Parameters(extensions))
    628 			, vki					(env.vkp, *instance.object)
    629 			, physicalDeviceCount	(0)
    630 			, queueFamilyIndex		(~0u)
    631 		{
    632 			{
    633 				const vector<VkPhysicalDeviceGroupProperties> devGroupProperties = enumeratePhysicalDeviceGroups(vki, *instance.object);
    634 
    635 				if (devGroupProperties.size() <= (size_t)params.deviceGroupIndex)
    636 					TCU_THROW(NotSupportedError, "Device Group not found");
    637 
    638 				physicalDeviceCount	= devGroupProperties[params.deviceGroupIndex].physicalDeviceCount;
    639 				physicalDevices.resize(physicalDeviceCount);
    640 
    641 				for (deUint32 physicalDeviceIdx = 0; physicalDeviceIdx < physicalDeviceCount; physicalDeviceIdx++)
    642 					physicalDevices[physicalDeviceIdx] = devGroupProperties[params.deviceGroupIndex].physicalDevices[physicalDeviceIdx];
    643 			}
    644 
    645 			{
    646 				const vector<VkQueueFamilyProperties>	queueProps = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevices[params.deviceIndex]);
    647 				bool									foundMatching = false;
    648 
    649 				for (size_t curQueueNdx = 0; curQueueNdx < queueProps.size(); curQueueNdx++)
    650 				{
    651 					if ((queueProps[curQueueNdx].queueFlags & params.queueFlags) == params.queueFlags)
    652 					{
    653 						queueFamilyIndex = (deUint32)curQueueNdx;
    654 						foundMatching = true;
    655 					}
    656 				}
    657 
    658 				if (!foundMatching)
    659 					TCU_THROW(NotSupportedError, "Matching queue not found");
    660 			}
    661 		}
    662 	};
    663 
    664 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    665 	{
    666 		return getSafeObjectCount<DeviceGroup>(context, params, MAX_CONCURRENT_DEVICES);
    667 	}
    668 
    669 	static Move<VkDevice> create (const Environment& env, const Resources& res, const Parameters& params)
    670 	{
    671 		const float	queuePriority = 1.0;
    672 
    673 		const VkDeviceQueueCreateInfo	queues[] =
    674 		{
    675 			{
    676 				VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
    677 				DE_NULL,							// pNext
    678 				(VkDeviceQueueCreateFlags)0,		// flags
    679 				res.queueFamilyIndex,				// queueFamilyIndex
    680 				1u,									// queueCount
    681 				&queuePriority,						// pQueuePriorities
    682 			}
    683 		};
    684 
    685 		const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
    686 		{
    687 			VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO,	//stype
    688 			DE_NULL,											//pNext
    689 			res.physicalDeviceCount,							//physicalDeviceCount
    690 			res.physicalDevices.data()							//physicalDevices
    691 		};
    692 
    693 		const VkDeviceCreateInfo			deviceGroupCreateInfo =
    694 		{
    695 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
    696 			&deviceGroupInfo,
    697 			(VkDeviceCreateFlags)0,
    698 			DE_LENGTH_OF_ARRAY(queues),
    699 			queues,
    700 			0u,													// enabledLayerNameCount
    701 			DE_NULL,											// ppEnabledLayerNames
    702 			0u,													// enabledExtensionNameCount
    703 			DE_NULL,											// ppEnabledExtensionNames
    704 			DE_NULL,											// pEnabledFeatures
    705 		};
    706 
    707 		return createDevice(env.vkp, env.instance, res.vki, res.physicalDevices[params.deviceIndex], &deviceGroupCreateInfo, env.allocationCallbacks);
    708 	}
    709 };
    710 
    711 struct DeviceMemory
    712 {
    713 	typedef VkDeviceMemory Type;
    714 
    715 	struct Parameters
    716 	{
    717 		VkDeviceSize	size;
    718 		deUint32		memoryTypeIndex;
    719 
    720 		Parameters (VkDeviceSize size_, deUint32 memoryTypeIndex_)
    721 			: size				(size_)
    722 			, memoryTypeIndex	(memoryTypeIndex_)
    723 		{
    724 			DE_ASSERT(memoryTypeIndex < VK_MAX_MEMORY_TYPES);
    725 		}
    726 	};
    727 
    728 	struct Resources
    729 	{
    730 		Resources (const Environment&, const Parameters&) {}
    731 	};
    732 
    733 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    734 	{
    735 		const VkDeviceSize	deviceMemoryUsage	= params.size + getPageTableSize(context, params.size);
    736 
    737 		return getSafeObjectCount<DeviceMemory>(context,
    738 												params,
    739 												de::min(context.getDeviceProperties().limits.maxMemoryAllocationCount,
    740 														(deUint32)DEFAULT_MAX_CONCURRENT_OBJECTS),
    741 												deviceMemoryUsage);
    742 	}
    743 
    744 	static Move<VkDeviceMemory> create (const Environment& env, const Resources&, const Parameters& params)
    745 	{
    746 		const VkMemoryAllocateInfo	allocInfo	=
    747 		{
    748 			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    749 			DE_NULL,
    750 			params.size,
    751 			params.memoryTypeIndex
    752 		};
    753 
    754 		return allocateMemory(env.vkd, env.device, &allocInfo, env.allocationCallbacks);
    755 	}
    756 };
    757 
    758 DeviceMemory::Parameters getDeviceMemoryParameters (const VkMemoryRequirements& memReqs)
    759 {
    760 	return DeviceMemory::Parameters(memReqs.size, deCtz32(memReqs.memoryTypeBits));
    761 }
    762 
    763 DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkImage image)
    764 {
    765 	return getDeviceMemoryParameters(getImageMemoryRequirements(env.vkd, env.device, image));
    766 }
    767 
    768 DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkBuffer image)
    769 {
    770 	return getDeviceMemoryParameters(getBufferMemoryRequirements(env.vkd, env.device, image));
    771 }
    772 
    773 struct Buffer
    774 {
    775 	typedef VkBuffer Type;
    776 
    777 	struct Parameters
    778 	{
    779 		VkDeviceSize		size;
    780 		VkBufferUsageFlags	usage;
    781 
    782 		Parameters (VkDeviceSize		size_,
    783 					VkBufferUsageFlags	usage_)
    784 			: size	(size_)
    785 			, usage	(usage_)
    786 		{}
    787 	};
    788 
    789 	struct Resources
    790 	{
    791 		Resources (const Environment&, const Parameters&) {}
    792 	};
    793 
    794 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    795 	{
    796 		const Environment			env		(context, 1u);
    797 		const Resources				res		(env, params);
    798 		const Unique<VkBuffer>		buffer	(create(env, res, params));
    799 		const VkMemoryRequirements	memReqs	= getBufferMemoryRequirements(env.vkd, env.device, *buffer);
    800 
    801 		return getSafeObjectCount<Buffer>(context,
    802 										  params,
    803 										  DEFAULT_MAX_CONCURRENT_OBJECTS,
    804 										  getPageTableSize(context, memReqs.size));
    805 	}
    806 
    807 	static Move<VkBuffer> create (const Environment& env, const Resources&, const Parameters& params)
    808 	{
    809 		const VkBufferCreateInfo	bufferInfo	=
    810 		{
    811 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
    812 			DE_NULL,
    813 			(VkBufferCreateFlags)0,
    814 			params.size,
    815 			params.usage,
    816 			VK_SHARING_MODE_EXCLUSIVE,
    817 			1u,
    818 			&env.queueFamilyIndex
    819 		};
    820 
    821 		return createBuffer(env.vkd, env.device, &bufferInfo, env.allocationCallbacks);
    822 	}
    823 };
    824 
    825 struct BufferView
    826 {
    827 	typedef VkBufferView Type;
    828 
    829 	struct Parameters
    830 	{
    831 		Buffer::Parameters	buffer;
    832 		VkFormat			format;
    833 		VkDeviceSize		offset;
    834 		VkDeviceSize		range;
    835 
    836 		Parameters (const Buffer::Parameters&	buffer_,
    837 					VkFormat					format_,
    838 					VkDeviceSize				offset_,
    839 					VkDeviceSize				range_)
    840 			: buffer	(buffer_)
    841 			, format	(format_)
    842 			, offset	(offset_)
    843 			, range		(range_)
    844 		{}
    845 	};
    846 
    847 	struct Resources
    848 	{
    849 		Dependency<Buffer>			buffer;
    850 		Dependency<DeviceMemory>	memory;
    851 
    852 		Resources (const Environment& env, const Parameters& params)
    853 			: buffer(env, params.buffer)
    854 			, memory(env, getDeviceMemoryParameters(env, *buffer.object))
    855 		{
    856 			VK_CHECK(env.vkd.bindBufferMemory(env.device, *buffer.object, *memory.object, 0));
    857 		}
    858 	};
    859 
    860 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    861 	{
    862 		return getSafeObjectCount<BufferView>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
    863 	}
    864 
    865 	static Move<VkBufferView> create (const Environment& env, const Resources& res, const Parameters& params)
    866 	{
    867 		const VkBufferViewCreateInfo	bufferViewInfo	=
    868 		{
    869 			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
    870 			DE_NULL,
    871 			(VkBufferViewCreateFlags)0,
    872 			*res.buffer.object,
    873 			params.format,
    874 			params.offset,
    875 			params.range
    876 		};
    877 
    878 		return createBufferView(env.vkd, env.device, &bufferViewInfo, env.allocationCallbacks);
    879 	}
    880 };
    881 
    882 struct Image
    883 {
    884 	typedef VkImage Type;
    885 
    886 	struct Parameters
    887 	{
    888 		VkImageCreateFlags		flags;
    889 		VkImageType				imageType;
    890 		VkFormat				format;
    891 		VkExtent3D				extent;
    892 		deUint32				mipLevels;
    893 		deUint32				arraySize;
    894 		VkSampleCountFlagBits	samples;
    895 		VkImageTiling			tiling;
    896 		VkImageUsageFlags		usage;
    897 		VkImageLayout			initialLayout;
    898 
    899 		Parameters (VkImageCreateFlags		flags_,
    900 					VkImageType				imageType_,
    901 					VkFormat				format_,
    902 					VkExtent3D				extent_,
    903 					deUint32				mipLevels_,
    904 					deUint32				arraySize_,
    905 					VkSampleCountFlagBits	samples_,
    906 					VkImageTiling			tiling_,
    907 					VkImageUsageFlags		usage_,
    908 					VkImageLayout			initialLayout_)
    909 			: flags			(flags_)
    910 			, imageType		(imageType_)
    911 			, format		(format_)
    912 			, extent		(extent_)
    913 			, mipLevels		(mipLevels_)
    914 			, arraySize		(arraySize_)
    915 			, samples		(samples_)
    916 			, tiling		(tiling_)
    917 			, usage			(usage_)
    918 			, initialLayout	(initialLayout_)
    919 		{}
    920 	};
    921 
    922 	struct Resources
    923 	{
    924 		Resources (const Environment&, const Parameters&) {}
    925 	};
    926 
    927 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
    928 	{
    929 		const Environment			env		(context, 1u);
    930 		const Resources				res		(env, params);
    931 		const Unique<VkImage>		image	(create(env, res, params));
    932 		const VkMemoryRequirements	memReqs	= getImageMemoryRequirements(env.vkd, env.device, *image);
    933 
    934 		return getSafeObjectCount<Image>(context,
    935 										 params,
    936 										 DEFAULT_MAX_CONCURRENT_OBJECTS,
    937 										 getPageTableSize(context, memReqs.size));
    938 	}
    939 
    940 	static Move<VkImage> create (const Environment& env, const Resources&, const Parameters& params)
    941 	{
    942 		const VkImageCreateInfo		imageInfo	=
    943 		{
    944 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    945 			DE_NULL,
    946 			params.flags,
    947 			params.imageType,
    948 			params.format,
    949 			params.extent,
    950 			params.mipLevels,
    951 			params.arraySize,
    952 			params.samples,
    953 			params.tiling,
    954 			params.usage,
    955 			VK_SHARING_MODE_EXCLUSIVE,		// sharingMode
    956 			1u,								// queueFamilyIndexCount
    957 			&env.queueFamilyIndex,			// pQueueFamilyIndices
    958 			params.initialLayout
    959 		};
    960 
    961 		return createImage(env.vkd, env.device, &imageInfo, env.allocationCallbacks);
    962 	}
    963 };
    964 
    965 struct ImageView
    966 {
    967 	typedef VkImageView Type;
    968 
    969 	struct Parameters
    970 	{
    971 		Image::Parameters		image;
    972 		VkImageViewType			viewType;
    973 		VkFormat				format;
    974 		VkComponentMapping		components;
    975 		VkImageSubresourceRange	subresourceRange;
    976 
    977 		Parameters (const Image::Parameters&	image_,
    978 					VkImageViewType				viewType_,
    979 					VkFormat					format_,
    980 					VkComponentMapping			components_,
    981 					VkImageSubresourceRange		subresourceRange_)
    982 			: image				(image_)
    983 			, viewType			(viewType_)
    984 			, format			(format_)
    985 			, components		(components_)
    986 			, subresourceRange	(subresourceRange_)
    987 		{}
    988 	};
    989 
    990 	struct Resources
    991 	{
    992 		Dependency<Image>			image;
    993 		Dependency<DeviceMemory>	memory;
    994 
    995 		Resources (const Environment& env, const Parameters& params)
    996 			: image	(env, params.image)
    997 			, memory(env, getDeviceMemoryParameters(env, *image.object))
    998 		{
    999 			VK_CHECK(env.vkd.bindImageMemory(env.device, *image.object, *memory.object, 0));
   1000 		}
   1001 	};
   1002 
   1003 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1004 	{
   1005 		return getSafeObjectCount<ImageView>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1006 	}
   1007 
   1008 	static Move<VkImageView> create (const Environment& env, const Resources& res, const Parameters& params)
   1009 	{
   1010 		const VkImageViewCreateInfo	imageViewInfo	=
   1011 		{
   1012 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
   1013 			DE_NULL,
   1014 			(VkImageViewCreateFlags)0,
   1015 			*res.image.object,
   1016 			params.viewType,
   1017 			params.format,
   1018 			params.components,
   1019 			params.subresourceRange,
   1020 		};
   1021 
   1022 		return createImageView(env.vkd, env.device, &imageViewInfo, env.allocationCallbacks);
   1023 	}
   1024 };
   1025 
   1026 struct Semaphore
   1027 {
   1028 	typedef VkSemaphore Type;
   1029 
   1030 	struct Parameters
   1031 	{
   1032 		VkSemaphoreCreateFlags	flags;
   1033 
   1034 		Parameters (VkSemaphoreCreateFlags flags_)
   1035 			: flags(flags_)
   1036 		{}
   1037 	};
   1038 
   1039 	struct Resources
   1040 	{
   1041 		Resources (const Environment&, const Parameters&) {}
   1042 	};
   1043 
   1044 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1045 	{
   1046 		return getSafeObjectCount<Semaphore>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
   1047 	}
   1048 
   1049 	static Move<VkSemaphore> create (const Environment& env, const Resources&, const Parameters& params)
   1050 	{
   1051 		const VkSemaphoreCreateInfo	semaphoreInfo	=
   1052 		{
   1053 			VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
   1054 			DE_NULL,
   1055 			params.flags
   1056 		};
   1057 
   1058 		return createSemaphore(env.vkd, env.device, &semaphoreInfo, env.allocationCallbacks);
   1059 	}
   1060 };
   1061 
   1062 struct Fence
   1063 {
   1064 	typedef VkFence Type;
   1065 
   1066 	struct Parameters
   1067 	{
   1068 		VkFenceCreateFlags	flags;
   1069 
   1070 		Parameters (VkFenceCreateFlags flags_)
   1071 			: flags(flags_)
   1072 		{}
   1073 	};
   1074 
   1075 	struct Resources
   1076 	{
   1077 		Resources (const Environment&, const Parameters&) {}
   1078 	};
   1079 
   1080 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1081 	{
   1082 		return getSafeObjectCount<Fence>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
   1083 	}
   1084 
   1085 	static Move<VkFence> create (const Environment& env, const Resources&, const Parameters& params)
   1086 	{
   1087 		const VkFenceCreateInfo	fenceInfo	=
   1088 		{
   1089 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
   1090 			DE_NULL,
   1091 			params.flags
   1092 		};
   1093 
   1094 		return createFence(env.vkd, env.device, &fenceInfo, env.allocationCallbacks);
   1095 	}
   1096 };
   1097 
   1098 struct Event
   1099 {
   1100 	typedef VkEvent Type;
   1101 
   1102 	struct Parameters
   1103 	{
   1104 		VkEventCreateFlags	flags;
   1105 
   1106 		Parameters (VkEventCreateFlags flags_)
   1107 			: flags(flags_)
   1108 		{}
   1109 	};
   1110 
   1111 	struct Resources
   1112 	{
   1113 		Resources (const Environment&, const Parameters&) {}
   1114 	};
   1115 
   1116 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1117 	{
   1118 		return getSafeObjectCount<Event>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
   1119 	}
   1120 
   1121 	static Move<VkEvent> create (const Environment& env, const Resources&, const Parameters& params)
   1122 	{
   1123 		const VkEventCreateInfo	eventInfo	=
   1124 		{
   1125 			VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
   1126 			DE_NULL,
   1127 			params.flags
   1128 		};
   1129 
   1130 		return createEvent(env.vkd, env.device, &eventInfo, env.allocationCallbacks);
   1131 	}
   1132 };
   1133 
   1134 struct QueryPool
   1135 {
   1136 	typedef VkQueryPool Type;
   1137 
   1138 	struct Parameters
   1139 	{
   1140 		VkQueryType						queryType;
   1141 		deUint32						entryCount;
   1142 		VkQueryPipelineStatisticFlags	pipelineStatistics;
   1143 
   1144 		Parameters (VkQueryType						queryType_,
   1145 					deUint32						entryCount_,
   1146 					VkQueryPipelineStatisticFlags	pipelineStatistics_)
   1147 			: queryType				(queryType_)
   1148 			, entryCount			(entryCount_)
   1149 			, pipelineStatistics	(pipelineStatistics_)
   1150 		{}
   1151 	};
   1152 
   1153 	struct Resources
   1154 	{
   1155 		Resources (const Environment&, const Parameters&) {}
   1156 	};
   1157 
   1158 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1159 	{
   1160 		return getSafeObjectCount<QueryPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1161 	}
   1162 
   1163 	static Move<VkQueryPool> create (const Environment& env, const Resources&, const Parameters& params)
   1164 	{
   1165 		const VkQueryPoolCreateInfo	queryPoolInfo	=
   1166 		{
   1167 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
   1168 			DE_NULL,
   1169 			(VkQueryPoolCreateFlags)0,
   1170 			params.queryType,
   1171 			params.entryCount,
   1172 			params.pipelineStatistics
   1173 		};
   1174 
   1175 		return createQueryPool(env.vkd, env.device, &queryPoolInfo, env.allocationCallbacks);
   1176 	}
   1177 };
   1178 
   1179 struct ShaderModule
   1180 {
   1181 	typedef VkShaderModule Type;
   1182 
   1183 	struct Parameters
   1184 	{
   1185 		VkShaderStageFlagBits	shaderStage;
   1186 		string					binaryName;
   1187 
   1188 		Parameters (VkShaderStageFlagBits	shaderStage_,
   1189 					const std::string&		binaryName_)
   1190 			: shaderStage	(shaderStage_)
   1191 			, binaryName	(binaryName_)
   1192 		{}
   1193 	};
   1194 
   1195 	struct Resources
   1196 	{
   1197 		const ProgramBinary&	binary;
   1198 
   1199 		Resources (const Environment& env, const Parameters& params)
   1200 			: binary(env.programBinaries.get(params.binaryName))
   1201 		{}
   1202 	};
   1203 
   1204 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1205 	{
   1206 		return getSafeObjectCount<ShaderModule>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1207 	}
   1208 
   1209 	static const char* getSource (VkShaderStageFlagBits stage)
   1210 	{
   1211 		switch (stage)
   1212 		{
   1213 			case VK_SHADER_STAGE_VERTEX_BIT:
   1214 				return "#version 310 es\n"
   1215 					   "layout(location = 0) in highp vec4 a_position;\n"
   1216 					   "void main () { gl_Position = a_position; }\n";
   1217 
   1218 			case VK_SHADER_STAGE_FRAGMENT_BIT:
   1219 				return "#version 310 es\n"
   1220 					   "layout(location = 0) out mediump vec4 o_color;\n"
   1221 					   "void main () { o_color = vec4(1.0, 0.5, 0.25, 1.0); }";
   1222 
   1223 			case VK_SHADER_STAGE_COMPUTE_BIT:
   1224 				return "#version 310 es\n"
   1225 					   "layout(binding = 0) buffer Input { highp uint dataIn[]; };\n"
   1226 					   "layout(binding = 1) buffer Output { highp uint dataOut[]; };\n"
   1227 					   "void main (void)\n"
   1228 					   "{\n"
   1229 					   "	dataOut[gl_GlobalInvocationID.x] = ~dataIn[gl_GlobalInvocationID.x];\n"
   1230 					   "}\n";
   1231 
   1232 			default:
   1233 				DE_FATAL("Not implemented");
   1234 				return DE_NULL;
   1235 		}
   1236 	}
   1237 
   1238 	static void initPrograms (SourceCollections& dst, Parameters params)
   1239 	{
   1240 		const char* const	source	= getSource(params.shaderStage);
   1241 
   1242 		DE_ASSERT(source);
   1243 
   1244 		dst.glslSources.add(params.binaryName)
   1245 			<< glu::ShaderSource(getGluShaderType(params.shaderStage), source);
   1246 	}
   1247 
   1248 	static Move<VkShaderModule> create (const Environment& env, const Resources& res, const Parameters&)
   1249 	{
   1250 		const VkShaderModuleCreateInfo	shaderModuleInfo	=
   1251 		{
   1252 			VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
   1253 			DE_NULL,
   1254 			(VkShaderModuleCreateFlags)0,
   1255 			res.binary.getSize(),
   1256 			(const deUint32*)res.binary.getBinary(),
   1257 		};
   1258 
   1259 		return createShaderModule(env.vkd, env.device, &shaderModuleInfo, env.allocationCallbacks);
   1260 	}
   1261 };
   1262 
   1263 struct PipelineCache
   1264 {
   1265 	typedef VkPipelineCache Type;
   1266 
   1267 	struct Parameters
   1268 	{
   1269 		Parameters (void) {}
   1270 	};
   1271 
   1272 	struct Resources
   1273 	{
   1274 		Resources (const Environment&, const Parameters&) {}
   1275 	};
   1276 
   1277 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1278 	{
   1279 		return getSafeObjectCount<PipelineCache>(context, params, MAX_CONCURRENT_PIPELINE_CACHES);
   1280 	}
   1281 
   1282 	static Move<VkPipelineCache> create (const Environment& env, const Resources&, const Parameters&)
   1283 	{
   1284 		const VkPipelineCacheCreateInfo	pipelineCacheInfo	=
   1285 		{
   1286 			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
   1287 			DE_NULL,
   1288 			(VkPipelineCacheCreateFlags)0u,
   1289 			0u,								// initialDataSize
   1290 			DE_NULL,						// pInitialData
   1291 		};
   1292 
   1293 		return createPipelineCache(env.vkd, env.device, &pipelineCacheInfo, env.allocationCallbacks);
   1294 	}
   1295 };
   1296 
   1297 struct Sampler
   1298 {
   1299 	typedef VkSampler Type;
   1300 
   1301 	struct Parameters
   1302 	{
   1303 		VkFilter				magFilter;
   1304 		VkFilter				minFilter;
   1305 		VkSamplerMipmapMode		mipmapMode;
   1306 		VkSamplerAddressMode	addressModeU;
   1307 		VkSamplerAddressMode	addressModeV;
   1308 		VkSamplerAddressMode	addressModeW;
   1309 		float					mipLodBias;
   1310 		VkBool32				anisotropyEnable;
   1311 		float					maxAnisotropy;
   1312 		VkBool32				compareEnable;
   1313 		VkCompareOp				compareOp;
   1314 		float					minLod;
   1315 		float					maxLod;
   1316 		VkBorderColor			borderColor;
   1317 		VkBool32				unnormalizedCoordinates;
   1318 
   1319 		// \todo [2015-09-17 pyry] Other configurations
   1320 		Parameters (void)
   1321 			: magFilter					(VK_FILTER_NEAREST)
   1322 			, minFilter					(VK_FILTER_NEAREST)
   1323 			, mipmapMode				(VK_SAMPLER_MIPMAP_MODE_NEAREST)
   1324 			, addressModeU				(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
   1325 			, addressModeV				(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
   1326 			, addressModeW				(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
   1327 			, mipLodBias				(0.0f)
   1328 			, anisotropyEnable			(VK_FALSE)
   1329 			, maxAnisotropy				(1.0f)
   1330 			, compareEnable				(VK_FALSE)
   1331 			, compareOp					(VK_COMPARE_OP_ALWAYS)
   1332 			, minLod					(-1000.f)
   1333 			, maxLod					(+1000.f)
   1334 			, borderColor				(VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK)
   1335 			, unnormalizedCoordinates	(VK_FALSE)
   1336 		{}
   1337 	};
   1338 
   1339 	struct Resources
   1340 	{
   1341 		Resources (const Environment&, const Parameters&) {}
   1342 	};
   1343 
   1344 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1345 	{
   1346 		return getSafeObjectCount<Sampler>(context,
   1347 										   params,
   1348 										   de::min(context.getDeviceProperties().limits.maxSamplerAllocationCount,
   1349 												   (deUint32)DEFAULT_MAX_CONCURRENT_OBJECTS));
   1350 	}
   1351 
   1352 	static Move<VkSampler> create (const Environment& env, const Resources&, const Parameters& params)
   1353 	{
   1354 		const VkSamplerCreateInfo	samplerInfo	=
   1355 		{
   1356 			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
   1357 			DE_NULL,
   1358 			(VkSamplerCreateFlags)0,
   1359 			params.magFilter,
   1360 			params.minFilter,
   1361 			params.mipmapMode,
   1362 			params.addressModeU,
   1363 			params.addressModeV,
   1364 			params.addressModeW,
   1365 			params.mipLodBias,
   1366 			params.anisotropyEnable,
   1367 			params.maxAnisotropy,
   1368 			params.compareEnable,
   1369 			params.compareOp,
   1370 			params.minLod,
   1371 			params.maxLod,
   1372 			params.borderColor,
   1373 			params.unnormalizedCoordinates
   1374 		};
   1375 
   1376 		return createSampler(env.vkd, env.device, &samplerInfo, env.allocationCallbacks);
   1377 	}
   1378 };
   1379 
   1380 struct DescriptorSetLayout
   1381 {
   1382 	typedef VkDescriptorSetLayout Type;
   1383 
   1384 	struct Parameters
   1385 	{
   1386 		struct Binding
   1387 		{
   1388 			deUint32			binding;
   1389 			VkDescriptorType	descriptorType;
   1390 			deUint32			descriptorCount;
   1391 			VkShaderStageFlags	stageFlags;
   1392 			bool				useImmutableSampler;
   1393 
   1394 			Binding (deUint32			binding_,
   1395 					 VkDescriptorType	descriptorType_,
   1396 					 deUint32			descriptorCount_,
   1397 					 VkShaderStageFlags	stageFlags_,
   1398 					 bool				useImmutableSampler_)
   1399 				: binding				(binding_)
   1400 				, descriptorType		(descriptorType_)
   1401 				, descriptorCount		(descriptorCount_)
   1402 				, stageFlags			(stageFlags_)
   1403 				, useImmutableSampler	(useImmutableSampler_)
   1404 			{}
   1405 
   1406 			Binding (void) {}
   1407 		};
   1408 
   1409 		vector<Binding>	bindings;
   1410 
   1411 		Parameters (const vector<Binding>& bindings_)
   1412 			: bindings(bindings_)
   1413 		{}
   1414 
   1415 		static Parameters empty (void)
   1416 		{
   1417 			return Parameters(vector<Binding>());
   1418 		}
   1419 
   1420 		static Parameters single (deUint32				binding,
   1421 								  VkDescriptorType		descriptorType,
   1422 								  deUint32				descriptorCount,
   1423 								  VkShaderStageFlags	stageFlags,
   1424 								  bool					useImmutableSampler = false)
   1425 		{
   1426 			vector<Binding> bindings;
   1427 			bindings.push_back(Binding(binding, descriptorType, descriptorCount, stageFlags, useImmutableSampler));
   1428 			return Parameters(bindings);
   1429 		}
   1430 	};
   1431 
   1432 	struct Resources
   1433 	{
   1434 		vector<VkDescriptorSetLayoutBinding>	bindings;
   1435 		MovePtr<Dependency<Sampler> >			immutableSampler;
   1436 		vector<VkSampler>						immutableSamplersPtr;
   1437 
   1438 		Resources (const Environment& env, const Parameters& params)
   1439 		{
   1440 			// Create immutable sampler if needed
   1441 			for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
   1442 			{
   1443 				if (cur->useImmutableSampler && !immutableSampler)
   1444 				{
   1445 					immutableSampler = de::newMovePtr<Dependency<Sampler> >(env, Sampler::Parameters());
   1446 
   1447 					if (cur->useImmutableSampler && immutableSamplersPtr.size() < (size_t)cur->descriptorCount)
   1448 						immutableSamplersPtr.resize(cur->descriptorCount, *immutableSampler->object);
   1449 				}
   1450 			}
   1451 
   1452 			for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
   1453 			{
   1454 				const VkDescriptorSetLayoutBinding	binding	=
   1455 				{
   1456 					cur->binding,
   1457 					cur->descriptorType,
   1458 					cur->descriptorCount,
   1459 					cur->stageFlags,
   1460 					(cur->useImmutableSampler ? &immutableSamplersPtr[0] : DE_NULL)
   1461 				};
   1462 
   1463 				bindings.push_back(binding);
   1464 			}
   1465 		}
   1466 	};
   1467 
   1468 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1469 	{
   1470 		return getSafeObjectCount<DescriptorSetLayout>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1471 	}
   1472 
   1473 	static Move<VkDescriptorSetLayout> create (const Environment& env, const Resources& res, const Parameters&)
   1474 	{
   1475 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutInfo	=
   1476 		{
   1477 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
   1478 			DE_NULL,
   1479 			(VkDescriptorSetLayoutCreateFlags)0,
   1480 			(deUint32)res.bindings.size(),
   1481 			(res.bindings.empty() ? DE_NULL : &res.bindings[0])
   1482 		};
   1483 
   1484 		return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutInfo, env.allocationCallbacks);
   1485 	}
   1486 };
   1487 
   1488 struct PipelineLayout
   1489 {
   1490 	typedef VkPipelineLayout Type;
   1491 
   1492 	struct Parameters
   1493 	{
   1494 		vector<DescriptorSetLayout::Parameters>	descriptorSetLayouts;
   1495 		vector<VkPushConstantRange>				pushConstantRanges;
   1496 
   1497 		Parameters (void) {}
   1498 
   1499 		static Parameters empty (void)
   1500 		{
   1501 			return Parameters();
   1502 		}
   1503 
   1504 		static Parameters singleDescriptorSet (const DescriptorSetLayout::Parameters& descriptorSetLayout)
   1505 		{
   1506 			Parameters params;
   1507 			params.descriptorSetLayouts.push_back(descriptorSetLayout);
   1508 			return params;
   1509 		}
   1510 	};
   1511 
   1512 	struct Resources
   1513 	{
   1514 		typedef SharedPtr<Dependency<DescriptorSetLayout> >	DescriptorSetLayoutDepSp;
   1515 		typedef vector<DescriptorSetLayoutDepSp>			DescriptorSetLayouts;
   1516 
   1517 		DescriptorSetLayouts			descriptorSetLayouts;
   1518 		vector<VkDescriptorSetLayout>	pSetLayouts;
   1519 
   1520 		Resources (const Environment& env, const Parameters& params)
   1521 		{
   1522 			for (vector<DescriptorSetLayout::Parameters>::const_iterator dsParams = params.descriptorSetLayouts.begin();
   1523 				 dsParams != params.descriptorSetLayouts.end();
   1524 				 ++dsParams)
   1525 			{
   1526 				descriptorSetLayouts.push_back(DescriptorSetLayoutDepSp(new Dependency<DescriptorSetLayout>(env, *dsParams)));
   1527 				pSetLayouts.push_back(*descriptorSetLayouts.back()->object);
   1528 			}
   1529 		}
   1530 	};
   1531 
   1532 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1533 	{
   1534 		return getSafeObjectCount<PipelineLayout>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1535 	}
   1536 
   1537 	static Move<VkPipelineLayout> create (const Environment& env, const Resources& res, const Parameters& params)
   1538 	{
   1539 		const VkPipelineLayoutCreateInfo	pipelineLayoutInfo	=
   1540 		{
   1541 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   1542 			DE_NULL,
   1543 			(VkPipelineLayoutCreateFlags)0,
   1544 			(deUint32)res.pSetLayouts.size(),
   1545 			(res.pSetLayouts.empty() ? DE_NULL : &res.pSetLayouts[0]),
   1546 			(deUint32)params.pushConstantRanges.size(),
   1547 			(params.pushConstantRanges.empty() ? DE_NULL : &params.pushConstantRanges[0]),
   1548 		};
   1549 
   1550 		return createPipelineLayout(env.vkd, env.device, &pipelineLayoutInfo, env.allocationCallbacks);
   1551 	}
   1552 };
   1553 
   1554 struct RenderPass
   1555 {
   1556 	typedef VkRenderPass Type;
   1557 
   1558 	// \todo [2015-09-17 pyry] More interesting configurations
   1559 	struct Parameters
   1560 	{
   1561 		Parameters (void) {}
   1562 	};
   1563 
   1564 	struct Resources
   1565 	{
   1566 		Resources (const Environment&, const Parameters&) {}
   1567 	};
   1568 
   1569 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1570 	{
   1571 		return getSafeObjectCount<RenderPass>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1572 	}
   1573 
   1574 	static Move<VkRenderPass> create (const Environment& env, const Resources&, const Parameters&)
   1575 	{
   1576 		return makeRenderPass(env.vkd, env.device, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_D16_UNORM,
   1577 			VK_ATTACHMENT_LOAD_OP_CLEAR,
   1578 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
   1579 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
   1580 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
   1581 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
   1582 			env.allocationCallbacks);
   1583 	}
   1584 };
   1585 
   1586 struct GraphicsPipeline
   1587 {
   1588 	typedef VkPipeline Type;
   1589 
   1590 	// \todo [2015-09-17 pyry] More interesting configurations
   1591 	struct Parameters
   1592 	{
   1593 		Parameters (void) {}
   1594 	};
   1595 
   1596 	struct Resources
   1597 	{
   1598 		Dependency<ShaderModule>	vertexShader;
   1599 		Dependency<ShaderModule>	fragmentShader;
   1600 		Dependency<PipelineLayout>	layout;
   1601 		Dependency<RenderPass>		renderPass;
   1602 		Dependency<PipelineCache>	pipelineCache;
   1603 
   1604 		Resources (const Environment& env, const Parameters&)
   1605 			: vertexShader		(env, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"))
   1606 			, fragmentShader	(env, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"))
   1607 			, layout			(env, PipelineLayout::Parameters::singleDescriptorSet(
   1608 										DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, true)))
   1609 			, renderPass		(env, RenderPass::Parameters())
   1610 			, pipelineCache		(env, PipelineCache::Parameters())
   1611 		{}
   1612 	};
   1613 
   1614 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1615 	{
   1616 		return getSafeObjectCount<GraphicsPipeline>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1617 	}
   1618 
   1619 	static void initPrograms (SourceCollections& dst, Parameters)
   1620 	{
   1621 		ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"));
   1622 		ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"));
   1623 	}
   1624 
   1625 	static vector<VkPipelineSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkPipeline>* const pOutHandles, VkResult* const pOutResult)
   1626 	{
   1627 		DE_ASSERT(pOutResult);
   1628 		DE_ASSERT(pOutHandles);
   1629 		DE_ASSERT(pOutHandles->size() != 0);
   1630 
   1631 		const VkPipelineShaderStageCreateInfo			stages[]			=
   1632 		{
   1633 			{
   1634 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1635 				DE_NULL,
   1636 				(VkPipelineShaderStageCreateFlags)0,
   1637 				VK_SHADER_STAGE_VERTEX_BIT,
   1638 				*res.vertexShader.object,
   1639 				"main",
   1640 				DE_NULL,							// pSpecializationInfo
   1641 			},
   1642 			{
   1643 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1644 				DE_NULL,
   1645 				(VkPipelineShaderStageCreateFlags)0,
   1646 				VK_SHADER_STAGE_FRAGMENT_BIT,
   1647 				*res.fragmentShader.object,
   1648 				"main",
   1649 				DE_NULL,							// pSpecializationInfo
   1650 			}
   1651 		};
   1652 		const VkVertexInputBindingDescription			vertexBindings[]	=
   1653 		{
   1654 			{
   1655 				0u,									// binding
   1656 				16u,								// stride
   1657 				VK_VERTEX_INPUT_RATE_VERTEX
   1658 			}
   1659 		};
   1660 		const VkVertexInputAttributeDescription			vertexAttribs[]		=
   1661 		{
   1662 			{
   1663 				0u,									// location
   1664 				0u,									// binding
   1665 				VK_FORMAT_R32G32B32A32_SFLOAT,
   1666 				0u,									// offset
   1667 			}
   1668 		};
   1669 		const VkPipelineVertexInputStateCreateInfo		vertexInputState	=
   1670 		{
   1671 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
   1672 			DE_NULL,
   1673 			(VkPipelineVertexInputStateCreateFlags)0,
   1674 			DE_LENGTH_OF_ARRAY(vertexBindings),
   1675 			vertexBindings,
   1676 			DE_LENGTH_OF_ARRAY(vertexAttribs),
   1677 			vertexAttribs
   1678 		};
   1679 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyState	=
   1680 		{
   1681 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
   1682 			DE_NULL,
   1683 			(VkPipelineInputAssemblyStateCreateFlags)0,
   1684 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
   1685 			VK_FALSE								// primitiveRestartEnable
   1686 		};
   1687 		const VkViewport								viewport			= makeViewport(tcu::UVec2(64));
   1688 		const VkRect2D									scissor				= makeRect2D(tcu::UVec2(64));
   1689 
   1690 		const VkPipelineViewportStateCreateInfo			viewportState		=
   1691 		{
   1692 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
   1693 			DE_NULL,
   1694 			(VkPipelineViewportStateCreateFlags)0,
   1695 			1u,
   1696 			&viewport,
   1697 			1u,
   1698 			&scissor,
   1699 		};
   1700 		const VkPipelineRasterizationStateCreateInfo	rasterState			=
   1701 		{
   1702 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
   1703 			DE_NULL,
   1704 			(VkPipelineRasterizationStateCreateFlags)0,
   1705 			VK_FALSE,								// depthClampEnable
   1706 			VK_FALSE,								// rasterizerDiscardEnable
   1707 			VK_POLYGON_MODE_FILL,
   1708 			VK_CULL_MODE_BACK_BIT,
   1709 			VK_FRONT_FACE_COUNTER_CLOCKWISE,
   1710 			VK_FALSE,								// depthBiasEnable
   1711 			0.0f,									// depthBiasConstantFactor
   1712 			0.0f,									// depthBiasClamp
   1713 			0.0f,									// depthBiasSlopeFactor
   1714 			1.0f,									// lineWidth
   1715 		};
   1716 		const VkPipelineMultisampleStateCreateInfo		multisampleState	=
   1717 		{
   1718 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
   1719 			DE_NULL,
   1720 			(VkPipelineMultisampleStateCreateFlags)0,
   1721 			VK_SAMPLE_COUNT_1_BIT,
   1722 			VK_FALSE,								// sampleShadingEnable
   1723 			1.0f,									// minSampleShading
   1724 			DE_NULL,								// pSampleMask
   1725 			VK_FALSE,								// alphaToCoverageEnable
   1726 			VK_FALSE,								// alphaToOneEnable
   1727 		};
   1728 		const VkPipelineDepthStencilStateCreateInfo		depthStencilState	=
   1729 		{
   1730 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
   1731 			DE_NULL,
   1732 			(VkPipelineDepthStencilStateCreateFlags)0,
   1733 			VK_TRUE,								// depthTestEnable
   1734 			VK_TRUE,								// depthWriteEnable
   1735 			VK_COMPARE_OP_LESS,						// depthCompareOp
   1736 			VK_FALSE,								// depthBoundsTestEnable
   1737 			VK_FALSE,								// stencilTestEnable
   1738 			{ VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
   1739 			{ VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
   1740 			0.0f,									// minDepthBounds
   1741 			1.0f,									// maxDepthBounds
   1742 		};
   1743 		const VkPipelineColorBlendAttachmentState		colorBlendAttState[]=
   1744 		{
   1745 			{
   1746 				VK_FALSE,							// blendEnable
   1747 				VK_BLEND_FACTOR_ONE,
   1748 				VK_BLEND_FACTOR_ZERO,
   1749 				VK_BLEND_OP_ADD,
   1750 				VK_BLEND_FACTOR_ONE,
   1751 				VK_BLEND_FACTOR_ZERO,
   1752 				VK_BLEND_OP_ADD,
   1753 				VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
   1754 			}
   1755 		};
   1756 		const VkPipelineColorBlendStateCreateInfo		colorBlendState		=
   1757 		{
   1758 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
   1759 			DE_NULL,
   1760 			(VkPipelineColorBlendStateCreateFlags)0,
   1761 			VK_FALSE,								// logicOpEnable
   1762 			VK_LOGIC_OP_COPY,
   1763 			DE_LENGTH_OF_ARRAY(colorBlendAttState),
   1764 			colorBlendAttState,
   1765 			{ 0.0f, 0.0f, 0.0f, 0.0f }				// blendConstants
   1766 		};
   1767 		const VkGraphicsPipelineCreateInfo				pipelineInfo		=
   1768 		{
   1769 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
   1770 			DE_NULL,
   1771 			(VkPipelineCreateFlags)0,
   1772 			DE_LENGTH_OF_ARRAY(stages),
   1773 			stages,
   1774 			&vertexInputState,
   1775 			&inputAssemblyState,
   1776 			DE_NULL,								// pTessellationState
   1777 			&viewportState,
   1778 			&rasterState,
   1779 			&multisampleState,
   1780 			&depthStencilState,
   1781 			&colorBlendState,
   1782 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
   1783 			*res.layout.object,
   1784 			*res.renderPass.object,
   1785 			0u,										// subpass
   1786 			(VkPipeline)0,							// basePipelineHandle
   1787 			0,										// basePipelineIndex
   1788 		};
   1789 
   1790 		const deUint32							numPipelines	= static_cast<deUint32>(pOutHandles->size());
   1791 		VkPipeline*	const						pHandles		= &(*pOutHandles)[0];
   1792 		vector<VkGraphicsPipelineCreateInfo>	pipelineInfos	(numPipelines, pipelineInfo);
   1793 
   1794 		*pOutResult = env.vkd.createGraphicsPipelines(env.device, *res.pipelineCache.object, numPipelines, &pipelineInfos[0], env.allocationCallbacks, pHandles);
   1795 
   1796 		vector<VkPipelineSp>	pipelines;
   1797 
   1798 		// Even if an error is returned, some pipelines may have been created successfully
   1799 		for (deUint32 i = 0; i < numPipelines; ++i)
   1800 		{
   1801 			if (pHandles[i] != DE_NULL)
   1802 				pipelines.push_back(VkPipelineSp(new Move<VkPipeline>(check<VkPipeline>(pHandles[i]), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks))));
   1803 		}
   1804 
   1805 		return pipelines;
   1806 	}
   1807 
   1808 	static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
   1809 	{
   1810 		vector<VkPipeline>		handles			(1, DE_NULL);
   1811 		VkResult				result			= VK_NOT_READY;
   1812 		vector<VkPipelineSp>	scopedHandles	= createMultiple(env, res, Parameters(), &handles, &result);
   1813 
   1814 		VK_CHECK(result);
   1815 		return Move<VkPipeline>(check<VkPipeline>(scopedHandles.front()->disown()), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks));
   1816 	}
   1817 };
   1818 
   1819 struct ComputePipeline
   1820 {
   1821 	typedef VkPipeline Type;
   1822 
   1823 	// \todo [2015-09-17 pyry] More interesting configurations
   1824 	struct Parameters
   1825 	{
   1826 		Parameters (void) {}
   1827 	};
   1828 
   1829 	struct Resources
   1830 	{
   1831 		Dependency<ShaderModule>	shaderModule;
   1832 		Dependency<PipelineLayout>	layout;
   1833 		Dependency<PipelineCache>	pipelineCache;
   1834 
   1835 		static DescriptorSetLayout::Parameters getDescriptorSetLayout (void)
   1836 		{
   1837 			typedef DescriptorSetLayout::Parameters::Binding Binding;
   1838 
   1839 			vector<Binding> bindings;
   1840 
   1841 			bindings.push_back(Binding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
   1842 			bindings.push_back(Binding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
   1843 
   1844 			return DescriptorSetLayout::Parameters(bindings);
   1845 		}
   1846 
   1847 		Resources (const Environment& env, const Parameters&)
   1848 			: shaderModule		(env, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"))
   1849 			, layout			(env, PipelineLayout::Parameters::singleDescriptorSet(getDescriptorSetLayout()))
   1850 			, pipelineCache		(env, PipelineCache::Parameters())
   1851 		{}
   1852 	};
   1853 
   1854 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1855 	{
   1856 		return getSafeObjectCount<ComputePipeline>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1857 	}
   1858 
   1859 	static void initPrograms (SourceCollections& dst, Parameters)
   1860 	{
   1861 		ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"));
   1862 	}
   1863 
   1864 	static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
   1865 	{
   1866 		const VkComputePipelineCreateInfo	pipelineInfo	=
   1867 		{
   1868 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
   1869 			DE_NULL,
   1870 			(VkPipelineCreateFlags)0,
   1871 			{
   1872 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1873 				DE_NULL,
   1874 				(VkPipelineShaderStageCreateFlags)0,
   1875 				VK_SHADER_STAGE_COMPUTE_BIT,
   1876 				*res.shaderModule.object,
   1877 				"main",
   1878 				DE_NULL					// pSpecializationInfo
   1879 			},
   1880 			*res.layout.object,
   1881 			(VkPipeline)0,				// basePipelineHandle
   1882 			0u,							// basePipelineIndex
   1883 		};
   1884 
   1885 		return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo, env.allocationCallbacks);
   1886 	}
   1887 
   1888 	static vector<VkPipelineSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkPipeline>* const pOutHandles, VkResult* const pOutResult)
   1889 	{
   1890 		DE_ASSERT(pOutResult);
   1891 		DE_ASSERT(pOutHandles);
   1892 		DE_ASSERT(pOutHandles->size() != 0);
   1893 
   1894 		const VkComputePipelineCreateInfo	commonPipelineInfo	=
   1895 		{
   1896 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
   1897 			DE_NULL,
   1898 			(VkPipelineCreateFlags)0,
   1899 			{
   1900 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1901 				DE_NULL,
   1902 				(VkPipelineShaderStageCreateFlags)0,
   1903 				VK_SHADER_STAGE_COMPUTE_BIT,
   1904 				*res.shaderModule.object,
   1905 				"main",
   1906 				DE_NULL					// pSpecializationInfo
   1907 			},
   1908 			*res.layout.object,
   1909 			(VkPipeline)0,				// basePipelineHandle
   1910 			0u,							// basePipelineIndex
   1911 		};
   1912 
   1913 		const deUint32						numPipelines	= static_cast<deUint32>(pOutHandles->size());
   1914 		VkPipeline*	const					pHandles		= &(*pOutHandles)[0];
   1915 		vector<VkComputePipelineCreateInfo>	pipelineInfos	(numPipelines, commonPipelineInfo);
   1916 
   1917 		*pOutResult = env.vkd.createComputePipelines(env.device, *res.pipelineCache.object, numPipelines, &pipelineInfos[0], env.allocationCallbacks, pHandles);
   1918 
   1919 		vector<VkPipelineSp>	pipelines;
   1920 
   1921 		// Even if an error is returned, some pipelines may have been created successfully
   1922 		for (deUint32 i = 0; i < numPipelines; ++i)
   1923 		{
   1924 			if (pHandles[i] != DE_NULL)
   1925 				pipelines.push_back(VkPipelineSp(new Move<VkPipeline>(check<VkPipeline>(pHandles[i]), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks))));
   1926 		}
   1927 
   1928 		return pipelines;
   1929 	}
   1930 };
   1931 
   1932 struct DescriptorPool
   1933 {
   1934 	typedef VkDescriptorPool Type;
   1935 
   1936 	struct Parameters
   1937 	{
   1938 		VkDescriptorPoolCreateFlags		flags;
   1939 		deUint32						maxSets;
   1940 		vector<VkDescriptorPoolSize>	poolSizes;
   1941 
   1942 		Parameters (VkDescriptorPoolCreateFlags				flags_,
   1943 					deUint32								maxSets_,
   1944 					const vector<VkDescriptorPoolSize>&		poolSizes_)
   1945 			: flags		(flags_)
   1946 			, maxSets	(maxSets_)
   1947 			, poolSizes	(poolSizes_)
   1948 		{}
   1949 
   1950 		static Parameters singleType (VkDescriptorPoolCreateFlags	flags,
   1951 									  deUint32						maxSets,
   1952 									  VkDescriptorType				type,
   1953 									  deUint32						count)
   1954 		{
   1955 			vector<VkDescriptorPoolSize> poolSizes;
   1956 			poolSizes.push_back(makeDescriptorPoolSize(type, count));
   1957 			return Parameters(flags, maxSets, poolSizes);
   1958 		}
   1959 	};
   1960 
   1961 	struct Resources
   1962 	{
   1963 		Resources (const Environment&, const Parameters&) {}
   1964 	};
   1965 
   1966 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   1967 	{
   1968 		return getSafeObjectCount<DescriptorPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   1969 	}
   1970 
   1971 	static Move<VkDescriptorPool> create (const Environment& env, const Resources&, const Parameters& params)
   1972 	{
   1973 		const VkDescriptorPoolCreateInfo	descriptorPoolInfo	=
   1974 		{
   1975 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
   1976 			DE_NULL,
   1977 			params.flags,
   1978 			params.maxSets,
   1979 			(deUint32)params.poolSizes.size(),
   1980 			(params.poolSizes.empty() ? DE_NULL : &params.poolSizes[0])
   1981 		};
   1982 
   1983 		return createDescriptorPool(env.vkd, env.device, &descriptorPoolInfo, env.allocationCallbacks);
   1984 	}
   1985 };
   1986 
   1987 struct DescriptorSet
   1988 {
   1989 	typedef VkDescriptorSet Type;
   1990 
   1991 	struct Parameters
   1992 	{
   1993 		DescriptorSetLayout::Parameters	descriptorSetLayout;
   1994 
   1995 		Parameters (const DescriptorSetLayout::Parameters& descriptorSetLayout_)
   1996 			: descriptorSetLayout(descriptorSetLayout_)
   1997 		{}
   1998 	};
   1999 
   2000 	struct Resources
   2001 	{
   2002 		Dependency<DescriptorPool>		descriptorPool;
   2003 		Dependency<DescriptorSetLayout>	descriptorSetLayout;
   2004 
   2005 		static vector<VkDescriptorPoolSize> computePoolSizes (const DescriptorSetLayout::Parameters& layout, int maxSets)
   2006 		{
   2007 			deUint32						countByType[VK_DESCRIPTOR_TYPE_LAST];
   2008 			vector<VkDescriptorPoolSize>	typeCounts;
   2009 
   2010 			std::fill(DE_ARRAY_BEGIN(countByType), DE_ARRAY_END(countByType), 0u);
   2011 
   2012 			for (vector<DescriptorSetLayout::Parameters::Binding>::const_iterator cur = layout.bindings.begin();
   2013 				 cur != layout.bindings.end();
   2014 				 ++cur)
   2015 			{
   2016 				DE_ASSERT((deUint32)cur->descriptorType < VK_DESCRIPTOR_TYPE_LAST);
   2017 				countByType[cur->descriptorType] += cur->descriptorCount * maxSets;
   2018 			}
   2019 
   2020 			for (deUint32 type = 0; type < VK_DESCRIPTOR_TYPE_LAST; ++type)
   2021 			{
   2022 				if (countByType[type] > 0)
   2023 					typeCounts.push_back(makeDescriptorPoolSize((VkDescriptorType)type, countByType[type]));
   2024 			}
   2025 
   2026 			return typeCounts;
   2027 		}
   2028 
   2029 		Resources (const Environment& env, const Parameters& params)
   2030 			: descriptorPool		(env, DescriptorPool::Parameters(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, env.maxResourceConsumers, computePoolSizes(params.descriptorSetLayout, env.maxResourceConsumers)))
   2031 			, descriptorSetLayout	(env, params.descriptorSetLayout)
   2032 		{
   2033 		}
   2034 	};
   2035 
   2036 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   2037 	{
   2038 		return getSafeObjectCount<DescriptorSet>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   2039 	}
   2040 
   2041 	static Move<VkDescriptorSet> create (const Environment& env, const Resources& res, const Parameters&)
   2042 	{
   2043 		const VkDescriptorSetAllocateInfo	allocateInfo	=
   2044 		{
   2045 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   2046 			DE_NULL,
   2047 			*res.descriptorPool.object,
   2048 			1u,
   2049 			&res.descriptorSetLayout.object.get(),
   2050 		};
   2051 
   2052 		return allocateDescriptorSet(env.vkd, env.device, &allocateInfo);
   2053 	}
   2054 
   2055 	static vector<VkDescriptorSetSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkDescriptorSet>* const pOutHandles, VkResult* const pOutResult)
   2056 	{
   2057 		DE_ASSERT(pOutResult);
   2058 		DE_ASSERT(pOutHandles);
   2059 		DE_ASSERT(pOutHandles->size() != 0);
   2060 
   2061 		const deUint32						numDescriptorSets		= static_cast<deUint32>(pOutHandles->size());
   2062 		VkDescriptorSet* const				pHandles				= &(*pOutHandles)[0];
   2063 		const vector<VkDescriptorSetLayout>	descriptorSetLayouts	(numDescriptorSets, res.descriptorSetLayout.object.get());
   2064 
   2065 		const VkDescriptorSetAllocateInfo	allocateInfo			=
   2066 		{
   2067 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   2068 			DE_NULL,
   2069 			*res.descriptorPool.object,
   2070 			numDescriptorSets,
   2071 			&descriptorSetLayouts[0],
   2072 		};
   2073 
   2074 		*pOutResult = env.vkd.allocateDescriptorSets(env.device, &allocateInfo, pHandles);
   2075 
   2076 		vector<VkDescriptorSetSp>	descriptorSets;
   2077 
   2078 		if (*pOutResult == VK_SUCCESS)
   2079 		{
   2080 			for (deUint32 i = 0; i < numDescriptorSets; ++i)
   2081 				descriptorSets.push_back(VkDescriptorSetSp(new Move<VkDescriptorSet>(check<VkDescriptorSet>(pHandles[i]), Deleter<VkDescriptorSet>(env.vkd, env.device, *res.descriptorPool.object))));
   2082 		}
   2083 
   2084 		return descriptorSets;
   2085 	}
   2086 };
   2087 
   2088 struct Framebuffer
   2089 {
   2090 	typedef VkFramebuffer Type;
   2091 
   2092 	struct Parameters
   2093 	{
   2094 		Parameters (void)
   2095 		{}
   2096 	};
   2097 
   2098 	struct Resources
   2099 	{
   2100 		Dependency<ImageView>	colorAttachment;
   2101 		Dependency<ImageView>	depthStencilAttachment;
   2102 		Dependency<RenderPass>	renderPass;
   2103 
   2104 		Resources (const Environment& env, const Parameters&)
   2105 			: colorAttachment			(env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
   2106 																					  makeExtent3D(256, 256, 1),
   2107 																					  1u, 1u,
   2108 																					  VK_SAMPLE_COUNT_1_BIT,
   2109 																					  VK_IMAGE_TILING_OPTIMAL,
   2110 																					  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
   2111 																					  VK_IMAGE_LAYOUT_UNDEFINED),
   2112 																		 VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
   2113 																		 makeComponentMappingRGBA(),
   2114 																		 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)))
   2115 			, depthStencilAttachment	(env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_D16_UNORM,
   2116 																					  makeExtent3D(256, 256, 1),
   2117 																					  1u, 1u,
   2118 																					  VK_SAMPLE_COUNT_1_BIT,
   2119 																					  VK_IMAGE_TILING_OPTIMAL,
   2120 																					  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
   2121 																					  VK_IMAGE_LAYOUT_UNDEFINED),
   2122 																		 VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
   2123 																		 makeComponentMappingRGBA(),
   2124 																		 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)))
   2125 			, renderPass				(env, RenderPass::Parameters())
   2126 		{}
   2127 	};
   2128 
   2129 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   2130 	{
   2131 		// \todo [2016-03-23 pyry] Take into account attachment sizes
   2132 		return getSafeObjectCount<Framebuffer>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   2133 	}
   2134 
   2135 	static Move<VkFramebuffer> create (const Environment& env, const Resources& res, const Parameters&)
   2136 	{
   2137 		const VkImageView				attachments[]	=
   2138 		{
   2139 			*res.colorAttachment.object,
   2140 			*res.depthStencilAttachment.object,
   2141 		};
   2142 		const VkFramebufferCreateInfo	framebufferInfo	=
   2143 		{
   2144 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
   2145 			DE_NULL,
   2146 			(VkFramebufferCreateFlags)0,
   2147 			*res.renderPass.object,
   2148 			(deUint32)DE_LENGTH_OF_ARRAY(attachments),
   2149 			attachments,
   2150 			256u,										// width
   2151 			256u,										// height
   2152 			1u											// layers
   2153 		};
   2154 
   2155 		return createFramebuffer(env.vkd, env.device, &framebufferInfo, env.allocationCallbacks);
   2156 	}
   2157 };
   2158 
   2159 struct CommandPool
   2160 {
   2161 	typedef VkCommandPool Type;
   2162 
   2163 	struct Parameters
   2164 	{
   2165 		VkCommandPoolCreateFlags	flags;
   2166 
   2167 		Parameters (VkCommandPoolCreateFlags flags_)
   2168 			: flags(flags_)
   2169 		{}
   2170 	};
   2171 
   2172 	struct Resources
   2173 	{
   2174 		Resources (const Environment&, const Parameters&) {}
   2175 	};
   2176 
   2177 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   2178 	{
   2179 		return getSafeObjectCount<CommandPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   2180 	}
   2181 
   2182 	static Move<VkCommandPool> create (const Environment& env, const Resources&, const Parameters& params)
   2183 	{
   2184 		const VkCommandPoolCreateInfo	cmdPoolInfo	=
   2185 		{
   2186 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
   2187 			DE_NULL,
   2188 			params.flags,
   2189 			env.queueFamilyIndex,
   2190 		};
   2191 
   2192 		return createCommandPool(env.vkd, env.device, &cmdPoolInfo, env.allocationCallbacks);
   2193 	}
   2194 };
   2195 
   2196 struct CommandBuffer
   2197 {
   2198 	typedef VkCommandBuffer Type;
   2199 
   2200 	struct Parameters
   2201 	{
   2202 		CommandPool::Parameters		commandPool;
   2203 		VkCommandBufferLevel		level;
   2204 
   2205 		Parameters (const CommandPool::Parameters&	commandPool_,
   2206 					VkCommandBufferLevel			level_)
   2207 			: commandPool	(commandPool_)
   2208 			, level			(level_)
   2209 		{}
   2210 	};
   2211 
   2212 	struct Resources
   2213 	{
   2214 		Dependency<CommandPool>	commandPool;
   2215 
   2216 		Resources (const Environment& env, const Parameters& params)
   2217 			: commandPool(env, params.commandPool)
   2218 		{}
   2219 	};
   2220 
   2221 	static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
   2222 	{
   2223 		return getSafeObjectCount<CommandBuffer>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
   2224 	}
   2225 
   2226 	static Move<VkCommandBuffer> create (const Environment& env, const Resources& res, const Parameters& params)
   2227 	{
   2228 		const VkCommandBufferAllocateInfo	cmdBufferInfo	=
   2229 		{
   2230 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
   2231 			DE_NULL,
   2232 			*res.commandPool.object,
   2233 			params.level,
   2234 			1,							// bufferCount
   2235 		};
   2236 
   2237 		return allocateCommandBuffer(env.vkd, env.device, &cmdBufferInfo);
   2238 	}
   2239 
   2240 	static vector<VkCommandBufferSp> createMultiple (const Environment& env, const Resources& res, const Parameters& params, vector<VkCommandBuffer>* const pOutHandles, VkResult* const pOutResult)
   2241 	{
   2242 		DE_ASSERT(pOutResult);
   2243 		DE_ASSERT(pOutHandles);
   2244 		DE_ASSERT(pOutHandles->size() != 0);
   2245 
   2246 		const deUint32						numCommandBuffers	= static_cast<deUint32>(pOutHandles->size());
   2247 		VkCommandBuffer* const				pHandles			= &(*pOutHandles)[0];
   2248 
   2249 		const VkCommandBufferAllocateInfo	cmdBufferInfo		=
   2250 		{
   2251 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
   2252 			DE_NULL,
   2253 			*res.commandPool.object,
   2254 			params.level,
   2255 			numCommandBuffers,
   2256 		};
   2257 
   2258 		*pOutResult = env.vkd.allocateCommandBuffers(env.device, &cmdBufferInfo, pHandles);
   2259 
   2260 		vector<VkCommandBufferSp>	commandBuffers;
   2261 
   2262 		if (*pOutResult == VK_SUCCESS)
   2263 		{
   2264 			for (deUint32 i = 0; i < numCommandBuffers; ++i)
   2265 				commandBuffers.push_back(VkCommandBufferSp(new Move<VkCommandBuffer>(check<VkCommandBuffer>(pHandles[i]), Deleter<VkCommandBuffer>(env.vkd, env.device, *res.commandPool.object))));
   2266 		}
   2267 
   2268 		return commandBuffers;
   2269 	}
   2270 };
   2271 
   2272 // Test cases
   2273 
   2274 template<typename Object>
   2275 tcu::TestStatus createSingleTest (Context& context, typename Object::Parameters params)
   2276 {
   2277 	const Environment					env	(context, 1u);
   2278 	const typename Object::Resources	res	(env, params);
   2279 
   2280 	{
   2281 		Unique<typename Object::Type>	obj	(Object::create(env, res, params));
   2282 	}
   2283 
   2284 	return tcu::TestStatus::pass("Ok");
   2285 }
   2286 
   2287 template<typename Object>
   2288 tcu::TestStatus createMultipleUniqueResourcesTest (Context& context, typename Object::Parameters params)
   2289 {
   2290 	const Environment					env		(context, 1u);
   2291 	const typename Object::Resources	res0	(env, params);
   2292 	const typename Object::Resources	res1	(env, params);
   2293 	const typename Object::Resources	res2	(env, params);
   2294 	const typename Object::Resources	res3	(env, params);
   2295 
   2296 	{
   2297 		Unique<typename Object::Type>	obj0	(Object::create(env, res0, params));
   2298 		Unique<typename Object::Type>	obj1	(Object::create(env, res1, params));
   2299 		Unique<typename Object::Type>	obj2	(Object::create(env, res2, params));
   2300 		Unique<typename Object::Type>	obj3	(Object::create(env, res3, params));
   2301 	}
   2302 
   2303 	return tcu::TestStatus::pass("Ok");
   2304 }
   2305 
   2306 template<typename Object>
   2307 tcu::TestStatus createMultipleSharedResourcesTest (Context& context, typename Object::Parameters params)
   2308 {
   2309 	const Environment					env	(context, 4u);
   2310 	const typename Object::Resources	res	(env, params);
   2311 
   2312 	{
   2313 		Unique<typename Object::Type>	obj0	(Object::create(env, res, params));
   2314 		Unique<typename Object::Type>	obj1	(Object::create(env, res, params));
   2315 		Unique<typename Object::Type>	obj2	(Object::create(env, res, params));
   2316 		Unique<typename Object::Type>	obj3	(Object::create(env, res, params));
   2317 	}
   2318 
   2319 	return tcu::TestStatus::pass("Ok");
   2320 }
   2321 
   2322 template<typename Object>
   2323 tcu::TestStatus createMaxConcurrentTest (Context& context, typename Object::Parameters params)
   2324 {
   2325 	typedef Unique<typename Object::Type>	UniqueObject;
   2326 	typedef SharedPtr<UniqueObject>			ObjectPtr;
   2327 
   2328 	const deUint32						numObjects			= Object::getMaxConcurrent(context, params);
   2329 	const Environment					env					(context, numObjects);
   2330 	const typename Object::Resources	res					(env, params);
   2331 	vector<ObjectPtr>					objects				(numObjects);
   2332 	const deUint32						watchdogInterval	= 1024;
   2333 
   2334 	context.getTestContext().getLog()
   2335 		<< TestLog::Message << "Creating " << numObjects << " " << getTypeName<typename Object::Type>() << " objects" << TestLog::EndMessage;
   2336 
   2337 	for (deUint32 ndx = 0; ndx < numObjects; ndx++)
   2338 	{
   2339 		objects[ndx] = ObjectPtr(new UniqueObject(Object::create(env, res, params)));
   2340 
   2341 		if ((ndx > 0) && ((ndx % watchdogInterval) == 0))
   2342 			context.getTestContext().touchWatchdog();
   2343 	}
   2344 
   2345 	context.getTestContext().touchWatchdog();
   2346 	objects.clear();
   2347 
   2348 	return tcu::TestStatus::pass("Ok");
   2349 }
   2350 
   2351 // How many objects to create per thread
   2352 template<typename Object>	int getCreateCount				(void) { return 100;	}
   2353 
   2354 // Creating VkDevice and VkInstance can take significantly longer than other object types
   2355 template<>					int getCreateCount<Instance>	(void) { return 20;		}
   2356 template<>					int getCreateCount<Device>		(void) { return 20;		}
   2357 template<>					int getCreateCount<DeviceGroup>	(void) { return 20;		}
   2358 
   2359 template<typename Object>
   2360 class CreateThread : public ThreadGroupThread
   2361 {
   2362 public:
   2363 	CreateThread (const Environment& env, const typename Object::Resources& resources, const typename Object::Parameters& params)
   2364 		: m_env			(env)
   2365 		, m_resources	(resources)
   2366 		, m_params		(params)
   2367 	{}
   2368 
   2369 	void runThread (void)
   2370 	{
   2371 		const int	numIters			= getCreateCount<Object>();
   2372 		const int	itersBetweenSyncs	= numIters / 5;
   2373 
   2374 		DE_ASSERT(itersBetweenSyncs > 0);
   2375 
   2376 		for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
   2377 		{
   2378 			// Sync every Nth iteration to make entering driver at the same time more likely
   2379 			if ((iterNdx % itersBetweenSyncs) == 0)
   2380 				barrier();
   2381 
   2382 			{
   2383 				Unique<typename Object::Type>	obj	(Object::create(m_env, m_resources, m_params));
   2384 			}
   2385 		}
   2386 	}
   2387 
   2388 private:
   2389 	const Environment&					m_env;
   2390 	const typename Object::Resources&	m_resources;
   2391 	const typename Object::Parameters&	m_params;
   2392 };
   2393 
   2394 template<typename Object>
   2395 tcu::TestStatus multithreadedCreateSharedResourcesTest (Context& context, typename Object::Parameters params)
   2396 {
   2397 	TestLog&							log			= context.getTestContext().getLog();
   2398 	const deUint32						numThreads	= getDefaultTestThreadCount();
   2399 	const Environment					env			(context, numThreads);
   2400 	const typename Object::Resources	res			(env, params);
   2401 	ThreadGroup							threads;
   2402 
   2403 	log << TestLog::Message << "numThreads = " << numThreads << TestLog::EndMessage;
   2404 
   2405 	for (deUint32 ndx = 0; ndx < numThreads; ndx++)
   2406 		threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, res, params)));
   2407 
   2408 	return threads.run();
   2409 }
   2410 
   2411 template<typename Object>
   2412 tcu::TestStatus multithreadedCreatePerThreadResourcesTest (Context& context, typename Object::Parameters params)
   2413 {
   2414 	typedef SharedPtr<typename Object::Resources>	ResPtr;
   2415 
   2416 	TestLog&			log			= context.getTestContext().getLog();
   2417 	const deUint32		numThreads	= getDefaultTestThreadCount();
   2418 	const Environment	env			(context, 1u);
   2419 	vector<ResPtr>		resources	(numThreads);
   2420 	ThreadGroup			threads;
   2421 
   2422 	log << TestLog::Message << "numThreads = " << numThreads << TestLog::EndMessage;
   2423 
   2424 	for (deUint32 ndx = 0; ndx < numThreads; ndx++)
   2425 	{
   2426 		resources[ndx] = ResPtr(new typename Object::Resources(env, params));
   2427 		threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, *resources[ndx], params)));
   2428 	}
   2429 
   2430 	return threads.run();
   2431 }
   2432 
   2433 struct EnvClone
   2434 {
   2435 	Device::Resources	deviceRes;
   2436 	Unique<VkDevice>	device;
   2437 	DeviceDriver		vkd;
   2438 	Environment			env;
   2439 
   2440 	EnvClone (const Environment& parent, const Device::Parameters& deviceParams, deUint32 maxResourceConsumers)
   2441 		: deviceRes	(parent, deviceParams)
   2442 		, device	(Device::create(parent, deviceRes, deviceParams))
   2443 		, vkd		(parent.vkp, parent.instance, *device)
   2444 		, env		(parent.vkp, parent.apiVersion, parent.instance, vkd, *device, deviceRes.queueFamilyIndex, parent.programBinaries, parent.allocationCallbacks, maxResourceConsumers)
   2445 	{
   2446 	}
   2447 };
   2448 
   2449 Device::Parameters getDefaulDeviceParameters (Context& context)
   2450 {
   2451 	return Device::Parameters(context.getTestContext().getCommandLine().getVKDeviceId()-1u,
   2452 							  VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT);
   2453 }
   2454 
   2455 template<typename Object>
   2456 tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typename Object::Parameters params)
   2457 {
   2458 	typedef SharedPtr<EnvClone>						EnvPtr;
   2459 	typedef SharedPtr<typename Object::Resources>	ResPtr;
   2460 
   2461 	TestLog&					log				= context.getTestContext().getLog();
   2462 	const deUint32				numThreads		= getDefaultTestThreadCount();
   2463 	const Device::Parameters	deviceParams	= getDefaulDeviceParameters(context);
   2464 	const Environment			sharedEnv		(context, numThreads);			// For creating Device's
   2465 	vector<EnvPtr>				perThreadEnv	(numThreads);
   2466 	vector<ResPtr>				resources		(numThreads);
   2467 	ThreadGroup					threads;
   2468 
   2469 	log << TestLog::Message << "numThreads = " << numThreads << TestLog::EndMessage;
   2470 
   2471 	for (deUint32 ndx = 0; ndx < numThreads; ndx++)
   2472 	{
   2473 		perThreadEnv[ndx]	= EnvPtr(new EnvClone(sharedEnv, deviceParams, 1u));
   2474 		resources[ndx]		= ResPtr(new typename Object::Resources(perThreadEnv[ndx]->env, params));
   2475 
   2476 		threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(perThreadEnv[ndx]->env, *resources[ndx], params)));
   2477 	}
   2478 
   2479 	return threads.run();
   2480 }
   2481 
   2482 template<typename Object>
   2483 tcu::TestStatus createSingleAllocCallbacksTest (Context& context, typename Object::Parameters params)
   2484 {
   2485 	const deUint32						noCmdScope		= (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)
   2486 														| (1u << VK_SYSTEM_ALLOCATION_SCOPE_DEVICE)
   2487 														| (1u << VK_SYSTEM_ALLOCATION_SCOPE_CACHE)
   2488 														| (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
   2489 
   2490 	// Callbacks used by resources
   2491 	AllocationCallbackRecorder			resCallbacks	(getSystemAllocator(), 128);
   2492 
   2493 	// Root environment still uses default instance and device, created without callbacks
   2494 	const Environment					rootEnv			(context.getPlatformInterface(),
   2495 														 context.getUsedApiVersion(),
   2496 														 context.getInstance(),
   2497 														 context.getDeviceInterface(),
   2498 														 context.getDevice(),
   2499 														 context.getUniversalQueueFamilyIndex(),
   2500 														 context.getBinaryCollection(),
   2501 														 resCallbacks.getCallbacks(),
   2502 														 1u);
   2503 
   2504 	{
   2505 		// Test env has instance & device created with callbacks
   2506 		const EnvClone						resEnv		(rootEnv, getDefaulDeviceParameters(context), 1u);
   2507 		const typename Object::Resources	res			(resEnv.env, params);
   2508 
   2509 		// Supply a separate callback recorder just for object construction
   2510 		AllocationCallbackRecorder			objCallbacks(getSystemAllocator(), 128);
   2511 		const Environment					objEnv		(resEnv.env.vkp,
   2512 														 resEnv.env.apiVersion,
   2513 														 resEnv.env.instance,
   2514 														 resEnv.env.vkd,
   2515 														 resEnv.env.device,
   2516 														 resEnv.env.queueFamilyIndex,
   2517 														 resEnv.env.programBinaries,
   2518 														 objCallbacks.getCallbacks(),
   2519 														 resEnv.env.maxResourceConsumers);
   2520 
   2521 		{
   2522 			Unique<typename Object::Type>	obj	(Object::create(objEnv, res, params));
   2523 
   2524 			// Validate that no command-level allocations are live
   2525 			if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, noCmdScope))
   2526 				return tcu::TestStatus::fail("Invalid allocation callback");
   2527 		}
   2528 
   2529 		// At this point all allocations made against object callbacks must have been freed
   2530 		if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, 0u))
   2531 			return tcu::TestStatus::fail("Invalid allocation callback");
   2532 	}
   2533 
   2534 	if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u))
   2535 		return tcu::TestStatus::fail("Invalid allocation callback");
   2536 
   2537 	return tcu::TestStatus::pass("Ok");
   2538 }
   2539 
   2540 template<typename Object>	deUint32	getOomIterLimit					(void) { return 1024;	}
   2541 template<>					deUint32	getOomIterLimit<Device>         (void) { return 20;		}
   2542 template<>					deUint32	getOomIterLimit<DeviceGroup>	(void) { return 20;		}
   2543 
   2544 template<typename Object>
   2545 tcu::TestStatus allocCallbackFailTest (Context& context, typename Object::Parameters params)
   2546 {
   2547 	AllocationCallbackRecorder			resCallbacks		(getSystemAllocator(), 128);
   2548 	const Environment					rootEnv				(context.getPlatformInterface(),
   2549 															 context.getUsedApiVersion(),
   2550 															 context.getInstance(),
   2551 															 context.getDeviceInterface(),
   2552 															 context.getDevice(),
   2553 															 context.getUniversalQueueFamilyIndex(),
   2554 															 context.getBinaryCollection(),
   2555 															 resCallbacks.getCallbacks(),
   2556 															 1u);
   2557 	deUint32							numPassingAllocs	= 0;
   2558 	const deUint32						cmdLineIterCount	= (deUint32)context.getTestContext().getCommandLine().getTestIterationCount();
   2559 	const deUint32						maxTries			= cmdLineIterCount != 0 ? cmdLineIterCount : getOomIterLimit<Object>();
   2560 
   2561 	{
   2562 		const EnvClone						resEnv	(rootEnv, getDefaulDeviceParameters(context), 1u);
   2563 		const typename Object::Resources	res		(resEnv.env, params);
   2564 
   2565 		// Iterate over test until object allocation succeeds
   2566 		for (; numPassingAllocs < maxTries; ++numPassingAllocs)
   2567 		{
   2568 			DeterministicFailAllocator			objAllocator(getSystemAllocator(),
   2569 															 DeterministicFailAllocator::MODE_COUNT_AND_FAIL,
   2570 															 numPassingAllocs);
   2571 			AllocationCallbackRecorder			recorder	(objAllocator.getCallbacks(), 128);
   2572 			const Environment					objEnv		(resEnv.env.vkp,
   2573 															 resEnv.env.apiVersion,
   2574 															 resEnv.env.instance,
   2575 															 resEnv.env.vkd,
   2576 															 resEnv.env.device,
   2577 															 resEnv.env.queueFamilyIndex,
   2578 															 resEnv.env.programBinaries,
   2579 															 recorder.getCallbacks(),
   2580 															 resEnv.env.maxResourceConsumers);
   2581 			bool								createOk	= false;
   2582 
   2583 			context.getTestContext().getLog()
   2584 				<< TestLog::Message
   2585 				<< "Trying to create object with " << numPassingAllocs << " allocation" << (numPassingAllocs != 1 ? "s" : "") << " passing"
   2586 				<< TestLog::EndMessage;
   2587 
   2588 			try
   2589 			{
   2590 				Unique<typename Object::Type>	obj	(Object::create(objEnv, res, params));
   2591 				createOk = true;
   2592 			}
   2593 			catch (const vk::OutOfMemoryError& e)
   2594 			{
   2595 				if (e.getError() != VK_ERROR_OUT_OF_HOST_MEMORY)
   2596 				{
   2597 					context.getTestContext().getLog() << e;
   2598 					return tcu::TestStatus::fail("Got invalid error code");
   2599 				}
   2600 			}
   2601 
   2602 			if (!validateAndLog(context.getTestContext().getLog(), recorder, 0u))
   2603 				return tcu::TestStatus::fail("Invalid allocation callback");
   2604 
   2605 			if (createOk)
   2606 			{
   2607 				context.getTestContext().getLog()
   2608 					<< TestLog::Message << "Object construction succeeded! " << TestLog::EndMessage;
   2609 				break;
   2610 			}
   2611 		}
   2612 	}
   2613 
   2614 	if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u))
   2615 		return tcu::TestStatus::fail("Invalid allocation callback");
   2616 
   2617 	if (numPassingAllocs == 0)
   2618 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks not called");
   2619 	else if (numPassingAllocs == maxTries)
   2620 	{
   2621 		context.getTestContext().getLog()
   2622 			<< TestLog::Message << "WARNING: Maximum iteration count (" << maxTries << ") reached without object construction passing. "
   2623 								<< "OOM testing incomplete, use --deqp-test-iteration-count= to test with higher limit." << TestLog::EndMessage;
   2624 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Max iter count reached");
   2625 	}
   2626 	else
   2627 		return tcu::TestStatus::pass("Ok");
   2628 }
   2629 
   2630 // Determine whether an API call sets the invalid handles to NULL (true) or leaves them undefined or not modified (false)
   2631 template<typename T> inline bool isNullHandleOnAllocationFailure				  (Context&)		 { return false; }
   2632 template<>			 inline bool isNullHandleOnAllocationFailure<VkCommandBuffer> (Context& context) { return hasDeviceExtension(context, "VK_KHR_maintenance1"); }
   2633 template<>			 inline bool isNullHandleOnAllocationFailure<VkDescriptorSet> (Context& context) { return hasDeviceExtension(context, "VK_KHR_maintenance1"); }
   2634 template<>			 inline bool isNullHandleOnAllocationFailure<VkPipeline>	  (Context&)		 { return true;  }
   2635 
   2636 template<typename T> inline bool isPooledObject					 (void) { return false; };
   2637 template<>			 inline bool isPooledObject<VkCommandBuffer> (void) { return true;  };
   2638 template<>			 inline bool isPooledObject<VkDescriptorSet> (void) { return true;  };
   2639 
   2640 template<typename Object>
   2641 tcu::TestStatus allocCallbackFailMultipleObjectsTest (Context& context, typename Object::Parameters params)
   2642 {
   2643 	typedef SharedPtr<Move<typename Object::Type> >	ObjectTypeSp;
   2644 
   2645 	static const deUint32	numObjects			= 4;
   2646 	const bool				expectNullHandles	= isNullHandleOnAllocationFailure<typename Object::Type>(context);
   2647 	deUint32				numPassingAllocs	= 0;
   2648 
   2649 	{
   2650 		vector<typename Object::Type>	handles	(numObjects);
   2651 		VkResult						result	= VK_NOT_READY;
   2652 
   2653 		for (; numPassingAllocs <= numObjects; ++numPassingAllocs)
   2654 		{
   2655 			ValidateQueryBits::fillBits(handles.begin(), handles.end());	// fill with garbage
   2656 
   2657 			// \note We have to use the same allocator for both resource dependencies and the object under test,
   2658 			//       because pooled objects take memory from the pool.
   2659 			DeterministicFailAllocator			objAllocator(getSystemAllocator(), DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0);
   2660 			AllocationCallbackRecorder			recorder	(objAllocator.getCallbacks(), 128);
   2661 			const Environment					objEnv		(context.getPlatformInterface(),
   2662 															 context.getUsedApiVersion(),
   2663 															 context.getInstance(),
   2664 															 context.getDeviceInterface(),
   2665 															 context.getDevice(),
   2666 															 context.getUniversalQueueFamilyIndex(),
   2667 															 context.getBinaryCollection(),
   2668 															 recorder.getCallbacks(),
   2669 															 numObjects);
   2670 
   2671 			context.getTestContext().getLog()
   2672 				<< TestLog::Message
   2673 				<< "Trying to create " << numObjects << " objects with " << numPassingAllocs << " allocation" << (numPassingAllocs != 1 ? "s" : "") << " passing"
   2674 				<< TestLog::EndMessage;
   2675 
   2676 			{
   2677 				const typename Object::Resources res (objEnv, params);
   2678 
   2679 				objAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
   2680 				const vector<ObjectTypeSp> scopedHandles = Object::createMultiple(objEnv, res, params, &handles, &result);
   2681 			}
   2682 
   2683 			if (result == VK_SUCCESS)
   2684 			{
   2685 				context.getTestContext().getLog() << TestLog::Message << "Construction of all objects succeeded! " << TestLog::EndMessage;
   2686 				break;
   2687 			}
   2688 			else
   2689 			{
   2690 				if (expectNullHandles)
   2691 				{
   2692 					for (deUint32 nullNdx = numPassingAllocs; nullNdx < numObjects; ++nullNdx)
   2693 					{
   2694 						if (handles[nullNdx] != DE_NULL)
   2695 							return tcu::TestStatus::fail("Some object handles weren't set to NULL");
   2696 					}
   2697 				}
   2698 
   2699 				if (result != VK_ERROR_OUT_OF_HOST_MEMORY)
   2700 					return tcu::TestStatus::fail("Got invalid error code: " + de::toString(getResultName(result)));
   2701 
   2702 				if (!validateAndLog(context.getTestContext().getLog(), recorder, 0u))
   2703 					return tcu::TestStatus::fail("Invalid allocation callback");
   2704 			}
   2705 		}
   2706 	}
   2707 
   2708 	if (numPassingAllocs == 0)
   2709 	{
   2710 		if (isPooledObject<typename Object::Type>())
   2711 			return tcu::TestStatus::pass("Not validated: pooled objects didn't seem to use host memory");
   2712 		else
   2713 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks not called");
   2714 	}
   2715 	else
   2716 		return tcu::TestStatus::pass("Ok");
   2717 }
   2718 
   2719 // Utilities for creating groups
   2720 
   2721 template<typename Object>
   2722 struct NamedParameters
   2723 {
   2724 	const char*						name;
   2725 	typename Object::Parameters		parameters;
   2726 };
   2727 
   2728 template<typename Object>
   2729 struct CaseDescription
   2730 {
   2731 	typename FunctionInstance1<typename Object::Parameters>::Function	function;
   2732 	const NamedParameters<Object>*										paramsBegin;
   2733 	const NamedParameters<Object>*										paramsEnd;
   2734 };
   2735 
   2736 #define EMPTY_CASE_DESC(OBJECT)	\
   2737 	{ (FunctionInstance1<OBJECT::Parameters>::Function)DE_NULL, DE_NULL, DE_NULL }
   2738 
   2739 #define CASE_DESC(FUNCTION, CASES)	\
   2740 	{ FUNCTION, DE_ARRAY_BEGIN(CASES), DE_ARRAY_END(CASES)	}
   2741 
   2742 struct CaseDescriptions
   2743 {
   2744 	CaseDescription<Instance>				instance;
   2745 	CaseDescription<Device>					device;
   2746 	CaseDescription<DeviceGroup>			deviceGroup;
   2747 	CaseDescription<DeviceMemory>			deviceMemory;
   2748 	CaseDescription<Buffer>					buffer;
   2749 	CaseDescription<BufferView>				bufferView;
   2750 	CaseDescription<Image>					image;
   2751 	CaseDescription<ImageView>				imageView;
   2752 	CaseDescription<Semaphore>				semaphore;
   2753 	CaseDescription<Event>					event;
   2754 	CaseDescription<Fence>					fence;
   2755 	CaseDescription<QueryPool>				queryPool;
   2756 	CaseDescription<ShaderModule>			shaderModule;
   2757 	CaseDescription<PipelineCache>			pipelineCache;
   2758 	CaseDescription<PipelineLayout>			pipelineLayout;
   2759 	CaseDescription<RenderPass>				renderPass;
   2760 	CaseDescription<GraphicsPipeline>		graphicsPipeline;
   2761 	CaseDescription<ComputePipeline>		computePipeline;
   2762 	CaseDescription<DescriptorSetLayout>	descriptorSetLayout;
   2763 	CaseDescription<Sampler>				sampler;
   2764 	CaseDescription<DescriptorPool>			descriptorPool;
   2765 	CaseDescription<DescriptorSet>			descriptorSet;
   2766 	CaseDescription<Framebuffer>			framebuffer;
   2767 	CaseDescription<CommandPool>			commandPool;
   2768 	CaseDescription<CommandBuffer>			commandBuffer;
   2769 };
   2770 
   2771 template<typename Object>
   2772 void addCases (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
   2773 {
   2774 	for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
   2775 		addFunctionCase(group.get(), cur->name, "", cases.function, cur->parameters);
   2776 }
   2777 
   2778 template<typename Object>
   2779 void addCasesWithProgs (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
   2780 {
   2781 	for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
   2782 		addFunctionCaseWithPrograms(group.get(), cur->name, "", Object::initPrograms, cases.function, cur->parameters);
   2783 }
   2784 
   2785 tcu::TestCaseGroup* createGroup (tcu::TestContext& testCtx, const char* name, const char* desc, const CaseDescriptions& cases)
   2786 {
   2787 	MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, name, desc));
   2788 
   2789 	addCases			(group, cases.instance);
   2790 	addCases			(group, cases.device);
   2791 	addCases			(group, cases.deviceGroup);
   2792 	addCases			(group, cases.deviceMemory);
   2793 	addCases			(group, cases.buffer);
   2794 	addCases			(group, cases.bufferView);
   2795 	addCases			(group, cases.image);
   2796 	addCases			(group, cases.imageView);
   2797 	addCases			(group, cases.semaphore);
   2798 	addCases			(group, cases.event);
   2799 	addCases			(group, cases.fence);
   2800 	addCases			(group, cases.queryPool);
   2801 	addCases			(group, cases.sampler);
   2802 	addCasesWithProgs	(group, cases.shaderModule);
   2803 	addCases			(group, cases.pipelineCache);
   2804 	addCases			(group, cases.pipelineLayout);
   2805 	addCases			(group, cases.renderPass);
   2806 	addCasesWithProgs	(group, cases.graphicsPipeline);
   2807 	addCasesWithProgs	(group, cases.computePipeline);
   2808 	addCases			(group, cases.descriptorSetLayout);
   2809 	addCases			(group, cases.descriptorPool);
   2810 	addCases			(group, cases.descriptorSet);
   2811 	addCases			(group, cases.framebuffer);
   2812 	addCases			(group, cases.commandPool);
   2813 	addCases			(group, cases.commandBuffer);
   2814 
   2815 	return group.release();
   2816 }
   2817 
   2818 } // anonymous
   2819 
   2820 tcu::TestCaseGroup* createObjectManagementTests (tcu::TestContext& testCtx)
   2821 {
   2822 	MovePtr<tcu::TestCaseGroup>	objectMgmtTests	(new tcu::TestCaseGroup(testCtx, "object_management", "Object management tests"));
   2823 
   2824 	const Image::Parameters		img1D			(0u, VK_IMAGE_TYPE_1D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D(256,   1, 1), 1u,  4u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
   2825 	const Image::Parameters		img2D			(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
   2826 	const Image::Parameters		imgCube			(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
   2827 	const Image::Parameters		img3D			(0u, VK_IMAGE_TYPE_3D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 4), 1u,  1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
   2828 	const ImageView::Parameters	imgView1D		(img1D, VK_IMAGE_VIEW_TYPE_1D,			img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
   2829 	const ImageView::Parameters	imgView1DArr	(img1D, VK_IMAGE_VIEW_TYPE_1D_ARRAY,	img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 4u));
   2830 	const ImageView::Parameters	imgView2D		(img2D, VK_IMAGE_VIEW_TYPE_2D,			img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
   2831 	const ImageView::Parameters	imgView2DArr	(img2D, VK_IMAGE_VIEW_TYPE_2D_ARRAY,	img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 8u));
   2832 	const ImageView::Parameters	imgViewCube		(imgCube, VK_IMAGE_VIEW_TYPE_CUBE,		img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 6u));
   2833 	const ImageView::Parameters	imgViewCubeArr	(imgCube, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 12u));
   2834 	const ImageView::Parameters	imgView3D		(img3D, VK_IMAGE_VIEW_TYPE_3D,			img3D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
   2835 
   2836 	const DescriptorSetLayout::Parameters	singleUboDescLayout	= DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT);
   2837 
   2838 	static const NamedParameters<Instance>					s_instanceCases[]				=
   2839 	{
   2840 		{ "instance",					Instance::Parameters() },
   2841 	};
   2842 	// \note Device index may change - must not be static
   2843 
   2844 	const NamedParameters<Device>				s_deviceCases[]					=
   2845 	{
   2846 		{ "device",						Device::Parameters(testCtx.getCommandLine().getVKDeviceId()-1u, VK_QUEUE_GRAPHICS_BIT)	},
   2847 	};
   2848 	const NamedParameters<DeviceGroup>					s_deviceGroupCases[]			=
   2849 	{
   2850 		{ "device_group",				DeviceGroup::Parameters(testCtx.getCommandLine().getVKDeviceGroupId() - 1u, testCtx.getCommandLine().getVKDeviceId() - 1u, VK_QUEUE_GRAPHICS_BIT) },
   2851 	};
   2852 	static const NamedParameters<DeviceMemory>			s_deviceMemCases[]				=
   2853 	{
   2854 		{ "device_memory_small",		DeviceMemory::Parameters(1024, 0u)	},
   2855 	};
   2856 	static const NamedParameters<Buffer>				s_bufferCases[]					=
   2857 	{
   2858 		{ "buffer_uniform_small",		Buffer::Parameters(1024u,			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),	},
   2859 		{ "buffer_uniform_large",		Buffer::Parameters(1024u*1024u*16u,	VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),	},
   2860 		{ "buffer_storage_small",		Buffer::Parameters(1024u,			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),	},
   2861 		{ "buffer_storage_large",		Buffer::Parameters(1024u*1024u*16u,	VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),	},
   2862 	};
   2863 	static const NamedParameters<BufferView>			s_bufferViewCases[]				=
   2864 	{
   2865 		{ "buffer_view_uniform_r8g8b8a8_unorm",	BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u)	},
   2866 		{ "buffer_view_storage_r8g8b8a8_unorm",	BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u)	},
   2867 	};
   2868 	static const NamedParameters<Image>					s_imageCases[]					=
   2869 	{
   2870 		{ "image_1d",					img1D		},
   2871 		{ "image_2d",					img2D		},
   2872 		{ "image_3d",					img3D		},
   2873 	};
   2874 	static const NamedParameters<ImageView>				s_imageViewCases[]				=
   2875 	{
   2876 		{ "image_view_1d",				imgView1D		},
   2877 		{ "image_view_1d_arr",			imgView1DArr	},
   2878 		{ "image_view_2d",				imgView2D		},
   2879 		{ "image_view_2d_arr",			imgView2DArr	},
   2880 		{ "image_view_cube",			imgViewCube		},
   2881 		{ "image_view_cube_arr",		imgViewCubeArr	},
   2882 		{ "image_view_3d",				imgView3D		},
   2883 	};
   2884 	static const NamedParameters<Semaphore>				s_semaphoreCases[]				=
   2885 	{
   2886 		{ "semaphore",					Semaphore::Parameters(0u),	}
   2887 	};
   2888 	static const NamedParameters<Event>					s_eventCases[]					=
   2889 	{
   2890 		{ "event",						Event::Parameters(0u)		}
   2891 	};
   2892 	static const NamedParameters<Fence>					s_fenceCases[]					=
   2893 	{
   2894 		{ "fence",						Fence::Parameters(0u)								},
   2895 		{ "fence_signaled",				Fence::Parameters(VK_FENCE_CREATE_SIGNALED_BIT)		}
   2896 	};
   2897 	static const NamedParameters<QueryPool>				s_queryPoolCases[]				=
   2898 	{
   2899 		{ "query_pool",					QueryPool::Parameters(VK_QUERY_TYPE_OCCLUSION, 1u, 0u)	}
   2900 	};
   2901 	static const NamedParameters<ShaderModule>			s_shaderModuleCases[]			=
   2902 	{
   2903 		{ "shader_module",				ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "test")	}
   2904 	};
   2905 	static const NamedParameters<PipelineCache>			s_pipelineCacheCases[]			=
   2906 	{
   2907 		{ "pipeline_cache",				PipelineCache::Parameters()		}
   2908 	};
   2909 	static const NamedParameters<PipelineLayout>		s_pipelineLayoutCases[]			=
   2910 	{
   2911 		{ "pipeline_layout_empty",		PipelineLayout::Parameters::empty()										},
   2912 		{ "pipeline_layout_single",		PipelineLayout::Parameters::singleDescriptorSet(singleUboDescLayout)	}
   2913 	};
   2914 	static const NamedParameters<RenderPass>			s_renderPassCases[]				=
   2915 	{
   2916 		{ "render_pass",				RenderPass::Parameters()		}
   2917 	};
   2918 	static const NamedParameters<GraphicsPipeline>		s_graphicsPipelineCases[]		=
   2919 	{
   2920 		{ "graphics_pipeline",			GraphicsPipeline::Parameters()	}
   2921 	};
   2922 	static const NamedParameters<ComputePipeline>		s_computePipelineCases[]		=
   2923 	{
   2924 		{ "compute_pipeline",			ComputePipeline::Parameters()	}
   2925 	};
   2926 	static const NamedParameters<DescriptorSetLayout>	s_descriptorSetLayoutCases[]	=
   2927 	{
   2928 		{ "descriptor_set_layout_empty",	DescriptorSetLayout::Parameters::empty()	},
   2929 		{ "descriptor_set_layout_single",	singleUboDescLayout							}
   2930 	};
   2931 	static const NamedParameters<Sampler>				s_samplerCases[]				=
   2932 	{
   2933 		{ "sampler",					Sampler::Parameters()	}
   2934 	};
   2935 	static const NamedParameters<DescriptorPool>		s_descriptorPoolCases[]			=
   2936 	{
   2937 		{ "descriptor_pool",						DescriptorPool::Parameters::singleType((VkDescriptorPoolCreateFlags)0,						4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u)	},
   2938 		{ "descriptor_pool_free_descriptor_set",	DescriptorPool::Parameters::singleType(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u)	}
   2939 	};
   2940 	static const NamedParameters<DescriptorSet>			s_descriptorSetCases[]			=
   2941 	{
   2942 		{ "descriptor_set",				DescriptorSet::Parameters(singleUboDescLayout)	}
   2943 	};
   2944 	static const NamedParameters<Framebuffer>			s_framebufferCases[]			=
   2945 	{
   2946 		{ "framebuffer",				Framebuffer::Parameters()	}
   2947 	};
   2948 	static const NamedParameters<CommandPool>			s_commandPoolCases[]			=
   2949 	{
   2950 		{ "command_pool",				CommandPool::Parameters((VkCommandPoolCreateFlags)0)			},
   2951 		{ "command_pool_transient",		CommandPool::Parameters(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT)	}
   2952 	};
   2953 	static const NamedParameters<CommandBuffer>			s_commandBufferCases[]			=
   2954 	{
   2955 		{ "command_buffer_primary",		CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_PRIMARY)	},
   2956 		{ "command_buffer_secondary",	CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_SECONDARY)	}
   2957 	};
   2958 
   2959 	const CaseDescriptions	s_createSingleGroup	=
   2960 	{
   2961 		CASE_DESC(createSingleTest	<Instance>,					s_instanceCases),
   2962 		CASE_DESC(createSingleTest	<Device>,					s_deviceCases),
   2963 		CASE_DESC(createSingleTest	<DeviceGroup>,				s_deviceGroupCases),
   2964 		CASE_DESC(createSingleTest	<DeviceMemory>,				s_deviceMemCases),
   2965 		CASE_DESC(createSingleTest	<Buffer>,					s_bufferCases),
   2966 		CASE_DESC(createSingleTest	<BufferView>,				s_bufferViewCases),
   2967 		CASE_DESC(createSingleTest	<Image>,					s_imageCases),
   2968 		CASE_DESC(createSingleTest	<ImageView>,				s_imageViewCases),
   2969 		CASE_DESC(createSingleTest	<Semaphore>,				s_semaphoreCases),
   2970 		CASE_DESC(createSingleTest	<Event>,					s_eventCases),
   2971 		CASE_DESC(createSingleTest	<Fence>,					s_fenceCases),
   2972 		CASE_DESC(createSingleTest	<QueryPool>,				s_queryPoolCases),
   2973 		CASE_DESC(createSingleTest	<ShaderModule>,				s_shaderModuleCases),
   2974 		CASE_DESC(createSingleTest	<PipelineCache>,			s_pipelineCacheCases),
   2975 		CASE_DESC(createSingleTest	<PipelineLayout>,			s_pipelineLayoutCases),
   2976 		CASE_DESC(createSingleTest	<RenderPass>,				s_renderPassCases),
   2977 		CASE_DESC(createSingleTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   2978 		CASE_DESC(createSingleTest	<ComputePipeline>,			s_computePipelineCases),
   2979 		CASE_DESC(createSingleTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   2980 		CASE_DESC(createSingleTest	<Sampler>,					s_samplerCases),
   2981 		CASE_DESC(createSingleTest	<DescriptorPool>,			s_descriptorPoolCases),
   2982 		CASE_DESC(createSingleTest	<DescriptorSet>,			s_descriptorSetCases),
   2983 		CASE_DESC(createSingleTest	<Framebuffer>,				s_framebufferCases),
   2984 		CASE_DESC(createSingleTest	<CommandPool>,				s_commandPoolCases),
   2985 		CASE_DESC(createSingleTest	<CommandBuffer>,			s_commandBufferCases),
   2986 	};
   2987 	objectMgmtTests->addChild(createGroup(testCtx, "single", "Create single object", s_createSingleGroup));
   2988 
   2989 	const CaseDescriptions	s_createMultipleUniqueResourcesGroup	=
   2990 	{
   2991 		CASE_DESC(createMultipleUniqueResourcesTest	<Instance>,					s_instanceCases),
   2992 		CASE_DESC(createMultipleUniqueResourcesTest	<Device>,					s_deviceCases),
   2993 		CASE_DESC(createMultipleUniqueResourcesTest	<DeviceGroup>,				s_deviceGroupCases),
   2994 		CASE_DESC(createMultipleUniqueResourcesTest	<DeviceMemory>,				s_deviceMemCases),
   2995 		CASE_DESC(createMultipleUniqueResourcesTest	<Buffer>,					s_bufferCases),
   2996 		CASE_DESC(createMultipleUniqueResourcesTest	<BufferView>,				s_bufferViewCases),
   2997 		CASE_DESC(createMultipleUniqueResourcesTest	<Image>,					s_imageCases),
   2998 		CASE_DESC(createMultipleUniqueResourcesTest	<ImageView>,				s_imageViewCases),
   2999 		CASE_DESC(createMultipleUniqueResourcesTest	<Semaphore>,				s_semaphoreCases),
   3000 		CASE_DESC(createMultipleUniqueResourcesTest	<Event>,					s_eventCases),
   3001 		CASE_DESC(createMultipleUniqueResourcesTest	<Fence>,					s_fenceCases),
   3002 		CASE_DESC(createMultipleUniqueResourcesTest	<QueryPool>,				s_queryPoolCases),
   3003 		CASE_DESC(createMultipleUniqueResourcesTest	<ShaderModule>,				s_shaderModuleCases),
   3004 		CASE_DESC(createMultipleUniqueResourcesTest	<PipelineCache>,			s_pipelineCacheCases),
   3005 		CASE_DESC(createMultipleUniqueResourcesTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3006 		CASE_DESC(createMultipleUniqueResourcesTest	<RenderPass>,				s_renderPassCases),
   3007 		CASE_DESC(createMultipleUniqueResourcesTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3008 		CASE_DESC(createMultipleUniqueResourcesTest	<ComputePipeline>,			s_computePipelineCases),
   3009 		CASE_DESC(createMultipleUniqueResourcesTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3010 		CASE_DESC(createMultipleUniqueResourcesTest	<Sampler>,					s_samplerCases),
   3011 		CASE_DESC(createMultipleUniqueResourcesTest	<DescriptorPool>,			s_descriptorPoolCases),
   3012 		CASE_DESC(createMultipleUniqueResourcesTest	<DescriptorSet>,			s_descriptorSetCases),
   3013 		CASE_DESC(createMultipleUniqueResourcesTest	<Framebuffer>,				s_framebufferCases),
   3014 		CASE_DESC(createMultipleUniqueResourcesTest	<CommandPool>,				s_commandPoolCases),
   3015 		CASE_DESC(createMultipleUniqueResourcesTest	<CommandBuffer>,			s_commandBufferCases),
   3016 	};
   3017 	objectMgmtTests->addChild(createGroup(testCtx, "multiple_unique_resources", "Multiple objects with per-object unique resources", s_createMultipleUniqueResourcesGroup));
   3018 
   3019 	const CaseDescriptions	s_createMultipleSharedResourcesGroup	=
   3020 	{
   3021 		EMPTY_CASE_DESC(Instance), // No resources used
   3022 		CASE_DESC(createMultipleSharedResourcesTest	<Device>,					s_deviceCases),
   3023 		CASE_DESC(createMultipleSharedResourcesTest	<DeviceGroup>,				s_deviceGroupCases),
   3024 		CASE_DESC(createMultipleSharedResourcesTest	<DeviceMemory>,				s_deviceMemCases),
   3025 		CASE_DESC(createMultipleSharedResourcesTest	<Buffer>,					s_bufferCases),
   3026 		CASE_DESC(createMultipleSharedResourcesTest	<BufferView>,				s_bufferViewCases),
   3027 		CASE_DESC(createMultipleSharedResourcesTest	<Image>,					s_imageCases),
   3028 		CASE_DESC(createMultipleSharedResourcesTest	<ImageView>,				s_imageViewCases),
   3029 		CASE_DESC(createMultipleSharedResourcesTest	<Semaphore>,				s_semaphoreCases),
   3030 		CASE_DESC(createMultipleSharedResourcesTest	<Event>,					s_eventCases),
   3031 		CASE_DESC(createMultipleSharedResourcesTest	<Fence>,					s_fenceCases),
   3032 		CASE_DESC(createMultipleSharedResourcesTest	<QueryPool>,				s_queryPoolCases),
   3033 		CASE_DESC(createMultipleSharedResourcesTest	<ShaderModule>,				s_shaderModuleCases),
   3034 		CASE_DESC(createMultipleSharedResourcesTest	<PipelineCache>,			s_pipelineCacheCases),
   3035 		CASE_DESC(createMultipleSharedResourcesTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3036 		CASE_DESC(createMultipleSharedResourcesTest	<RenderPass>,				s_renderPassCases),
   3037 		CASE_DESC(createMultipleSharedResourcesTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3038 		CASE_DESC(createMultipleSharedResourcesTest	<ComputePipeline>,			s_computePipelineCases),
   3039 		CASE_DESC(createMultipleSharedResourcesTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3040 		CASE_DESC(createMultipleSharedResourcesTest	<Sampler>,					s_samplerCases),
   3041 		CASE_DESC(createMultipleSharedResourcesTest	<DescriptorPool>,			s_descriptorPoolCases),
   3042 		CASE_DESC(createMultipleSharedResourcesTest	<DescriptorSet>,			s_descriptorSetCases),
   3043 		CASE_DESC(createMultipleSharedResourcesTest	<Framebuffer>,				s_framebufferCases),
   3044 		CASE_DESC(createMultipleSharedResourcesTest	<CommandPool>,				s_commandPoolCases),
   3045 		CASE_DESC(createMultipleSharedResourcesTest	<CommandBuffer>,			s_commandBufferCases),
   3046 	};
   3047 	objectMgmtTests->addChild(createGroup(testCtx, "multiple_shared_resources", "Multiple objects with shared resources", s_createMultipleSharedResourcesGroup));
   3048 
   3049 	const CaseDescriptions	s_createMaxConcurrentGroup	=
   3050 	{
   3051 		CASE_DESC(createMaxConcurrentTest	<Instance>,					s_instanceCases),
   3052 		CASE_DESC(createMaxConcurrentTest	<Device>,					s_deviceCases),
   3053 		CASE_DESC(createMaxConcurrentTest	<DeviceGroup>,				s_deviceGroupCases),
   3054 		CASE_DESC(createMaxConcurrentTest	<DeviceMemory>,				s_deviceMemCases),
   3055 		CASE_DESC(createMaxConcurrentTest	<Buffer>,					s_bufferCases),
   3056 		CASE_DESC(createMaxConcurrentTest	<BufferView>,				s_bufferViewCases),
   3057 		CASE_DESC(createMaxConcurrentTest	<Image>,					s_imageCases),
   3058 		CASE_DESC(createMaxConcurrentTest	<ImageView>,				s_imageViewCases),
   3059 		CASE_DESC(createMaxConcurrentTest	<Semaphore>,				s_semaphoreCases),
   3060 		CASE_DESC(createMaxConcurrentTest	<Event>,					s_eventCases),
   3061 		CASE_DESC(createMaxConcurrentTest	<Fence>,					s_fenceCases),
   3062 		CASE_DESC(createMaxConcurrentTest	<QueryPool>,				s_queryPoolCases),
   3063 		CASE_DESC(createMaxConcurrentTest	<ShaderModule>,				s_shaderModuleCases),
   3064 		CASE_DESC(createMaxConcurrentTest	<PipelineCache>,			s_pipelineCacheCases),
   3065 		CASE_DESC(createMaxConcurrentTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3066 		CASE_DESC(createMaxConcurrentTest	<RenderPass>,				s_renderPassCases),
   3067 		CASE_DESC(createMaxConcurrentTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3068 		CASE_DESC(createMaxConcurrentTest	<ComputePipeline>,			s_computePipelineCases),
   3069 		CASE_DESC(createMaxConcurrentTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3070 		CASE_DESC(createMaxConcurrentTest	<Sampler>,					s_samplerCases),
   3071 		CASE_DESC(createMaxConcurrentTest	<DescriptorPool>,			s_descriptorPoolCases),
   3072 		CASE_DESC(createMaxConcurrentTest	<DescriptorSet>,			s_descriptorSetCases),
   3073 		CASE_DESC(createMaxConcurrentTest	<Framebuffer>,				s_framebufferCases),
   3074 		CASE_DESC(createMaxConcurrentTest	<CommandPool>,				s_commandPoolCases),
   3075 		CASE_DESC(createMaxConcurrentTest	<CommandBuffer>,			s_commandBufferCases),
   3076 	};
   3077 	objectMgmtTests->addChild(createGroup(testCtx, "max_concurrent", "Maximum number of concurrently live objects", s_createMaxConcurrentGroup));
   3078 
   3079 	const CaseDescriptions	s_multithreadedCreatePerThreadDeviceGroup	=
   3080 	{
   3081 		EMPTY_CASE_DESC(Instance),		// Does not make sense
   3082 		EMPTY_CASE_DESC(Device),		// Does not make sense
   3083 		EMPTY_CASE_DESC(DeviceGroup),	// Does not make sense
   3084 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<DeviceMemory>,				s_deviceMemCases),
   3085 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Buffer>,					s_bufferCases),
   3086 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<BufferView>,				s_bufferViewCases),
   3087 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Image>,					s_imageCases),
   3088 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<ImageView>,				s_imageViewCases),
   3089 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Semaphore>,				s_semaphoreCases),
   3090 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Event>,					s_eventCases),
   3091 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Fence>,					s_fenceCases),
   3092 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<QueryPool>,				s_queryPoolCases),
   3093 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<ShaderModule>,				s_shaderModuleCases),
   3094 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<PipelineCache>,			s_pipelineCacheCases),
   3095 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3096 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<RenderPass>,				s_renderPassCases),
   3097 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3098 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<ComputePipeline>,			s_computePipelineCases),
   3099 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3100 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Sampler>,					s_samplerCases),
   3101 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<DescriptorPool>,			s_descriptorPoolCases),
   3102 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<DescriptorSet>,			s_descriptorSetCases),
   3103 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<Framebuffer>,				s_framebufferCases),
   3104 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<CommandPool>,				s_commandPoolCases),
   3105 		CASE_DESC(multithreadedCreatePerThreadDeviceTest	<CommandBuffer>,			s_commandBufferCases),
   3106 	};
   3107 	objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_device", "Multithreaded object construction with per-thread device ", s_multithreadedCreatePerThreadDeviceGroup));
   3108 
   3109 	const CaseDescriptions	s_multithreadedCreatePerThreadResourcesGroup	=
   3110 	{
   3111 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Instance>,					s_instanceCases),
   3112 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Device>,					s_deviceCases),
   3113 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<DeviceGroup>,				s_deviceGroupCases),
   3114 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<DeviceMemory>,				s_deviceMemCases),
   3115 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Buffer>,					s_bufferCases),
   3116 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<BufferView>,				s_bufferViewCases),
   3117 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Image>,					s_imageCases),
   3118 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<ImageView>,				s_imageViewCases),
   3119 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Semaphore>,				s_semaphoreCases),
   3120 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Event>,					s_eventCases),
   3121 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Fence>,					s_fenceCases),
   3122 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<QueryPool>,				s_queryPoolCases),
   3123 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<ShaderModule>,				s_shaderModuleCases),
   3124 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<PipelineCache>,			s_pipelineCacheCases),
   3125 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3126 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<RenderPass>,				s_renderPassCases),
   3127 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3128 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<ComputePipeline>,			s_computePipelineCases),
   3129 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3130 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Sampler>,					s_samplerCases),
   3131 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<DescriptorPool>,			s_descriptorPoolCases),
   3132 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<DescriptorSet>,			s_descriptorSetCases),
   3133 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<Framebuffer>,				s_framebufferCases),
   3134 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<CommandPool>,				s_commandPoolCases),
   3135 		CASE_DESC(multithreadedCreatePerThreadResourcesTest	<CommandBuffer>,			s_commandBufferCases),
   3136 	};
   3137 	objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_resources", "Multithreaded object construction with per-thread resources", s_multithreadedCreatePerThreadResourcesGroup));
   3138 
   3139 	const CaseDescriptions	s_multithreadedCreateSharedResourcesGroup	=
   3140 	{
   3141 		EMPTY_CASE_DESC(Instance),
   3142 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Device>,					s_deviceCases),
   3143 		CASE_DESC(multithreadedCreateSharedResourcesTest	<DeviceGroup>,				s_deviceGroupCases),
   3144 		CASE_DESC(multithreadedCreateSharedResourcesTest	<DeviceMemory>,				s_deviceMemCases),
   3145 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Buffer>,					s_bufferCases),
   3146 		CASE_DESC(multithreadedCreateSharedResourcesTest	<BufferView>,				s_bufferViewCases),
   3147 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Image>,					s_imageCases),
   3148 		CASE_DESC(multithreadedCreateSharedResourcesTest	<ImageView>,				s_imageViewCases),
   3149 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Semaphore>,				s_semaphoreCases),
   3150 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Event>,					s_eventCases),
   3151 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Fence>,					s_fenceCases),
   3152 		CASE_DESC(multithreadedCreateSharedResourcesTest	<QueryPool>,				s_queryPoolCases),
   3153 		CASE_DESC(multithreadedCreateSharedResourcesTest	<ShaderModule>,				s_shaderModuleCases),
   3154 		CASE_DESC(multithreadedCreateSharedResourcesTest	<PipelineCache>,			s_pipelineCacheCases),
   3155 		CASE_DESC(multithreadedCreateSharedResourcesTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3156 		CASE_DESC(multithreadedCreateSharedResourcesTest	<RenderPass>,				s_renderPassCases),
   3157 		CASE_DESC(multithreadedCreateSharedResourcesTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3158 		CASE_DESC(multithreadedCreateSharedResourcesTest	<ComputePipeline>,			s_computePipelineCases),
   3159 		CASE_DESC(multithreadedCreateSharedResourcesTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3160 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Sampler>,					s_samplerCases),
   3161 		CASE_DESC(multithreadedCreateSharedResourcesTest	<DescriptorPool>,			s_descriptorPoolCases),
   3162 		EMPTY_CASE_DESC(DescriptorSet),		// \note Needs per-thread DescriptorPool
   3163 		CASE_DESC(multithreadedCreateSharedResourcesTest	<Framebuffer>,				s_framebufferCases),
   3164 		CASE_DESC(multithreadedCreateSharedResourcesTest	<CommandPool>,				s_commandPoolCases),
   3165 		EMPTY_CASE_DESC(CommandBuffer),			// \note Needs per-thread CommandPool
   3166 	};
   3167 	objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_shared_resources", "Multithreaded object construction with shared resources", s_multithreadedCreateSharedResourcesGroup));
   3168 
   3169 	const CaseDescriptions	s_createSingleAllocCallbacksGroup	=
   3170 	{
   3171 		CASE_DESC(createSingleAllocCallbacksTest	<Instance>,					s_instanceCases),
   3172 		CASE_DESC(createSingleAllocCallbacksTest	<Device>,					s_deviceCases),
   3173 		CASE_DESC(createSingleAllocCallbacksTest	<DeviceGroup>,				s_deviceGroupCases),
   3174 		CASE_DESC(createSingleAllocCallbacksTest	<DeviceMemory>,				s_deviceMemCases),
   3175 		CASE_DESC(createSingleAllocCallbacksTest	<Buffer>,					s_bufferCases),
   3176 		CASE_DESC(createSingleAllocCallbacksTest	<BufferView>,				s_bufferViewCases),
   3177 		CASE_DESC(createSingleAllocCallbacksTest	<Image>,					s_imageCases),
   3178 		CASE_DESC(createSingleAllocCallbacksTest	<ImageView>,				s_imageViewCases),
   3179 		CASE_DESC(createSingleAllocCallbacksTest	<Semaphore>,				s_semaphoreCases),
   3180 		CASE_DESC(createSingleAllocCallbacksTest	<Event>,					s_eventCases),
   3181 		CASE_DESC(createSingleAllocCallbacksTest	<Fence>,					s_fenceCases),
   3182 		CASE_DESC(createSingleAllocCallbacksTest	<QueryPool>,				s_queryPoolCases),
   3183 		CASE_DESC(createSingleAllocCallbacksTest	<ShaderModule>,				s_shaderModuleCases),
   3184 		CASE_DESC(createSingleAllocCallbacksTest	<PipelineCache>,			s_pipelineCacheCases),
   3185 		CASE_DESC(createSingleAllocCallbacksTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3186 		CASE_DESC(createSingleAllocCallbacksTest	<RenderPass>,				s_renderPassCases),
   3187 		CASE_DESC(createSingleAllocCallbacksTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3188 		CASE_DESC(createSingleAllocCallbacksTest	<ComputePipeline>,			s_computePipelineCases),
   3189 		CASE_DESC(createSingleAllocCallbacksTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3190 		CASE_DESC(createSingleAllocCallbacksTest	<Sampler>,					s_samplerCases),
   3191 		CASE_DESC(createSingleAllocCallbacksTest	<DescriptorPool>,			s_descriptorPoolCases),
   3192 		CASE_DESC(createSingleAllocCallbacksTest	<DescriptorSet>,			s_descriptorSetCases),
   3193 		CASE_DESC(createSingleAllocCallbacksTest	<Framebuffer>,				s_framebufferCases),
   3194 		CASE_DESC(createSingleAllocCallbacksTest	<CommandPool>,				s_commandPoolCases),
   3195 		CASE_DESC(createSingleAllocCallbacksTest	<CommandBuffer>,			s_commandBufferCases),
   3196 	};
   3197 	objectMgmtTests->addChild(createGroup(testCtx, "single_alloc_callbacks", "Create single object", s_createSingleAllocCallbacksGroup));
   3198 
   3199 	// \note Skip pooled objects in this test group. They are properly handled by the "multiple" group farther down below.
   3200 	const CaseDescriptions	s_allocCallbackFailGroup	=
   3201 	{
   3202 		CASE_DESC(allocCallbackFailTest	<Instance>,					s_instanceCases),
   3203 		CASE_DESC(allocCallbackFailTest	<Device>,					s_deviceCases),
   3204 		CASE_DESC(allocCallbackFailTest	<DeviceGroup>,				s_deviceGroupCases),
   3205 		CASE_DESC(allocCallbackFailTest	<DeviceMemory>,				s_deviceMemCases),
   3206 		CASE_DESC(allocCallbackFailTest	<Buffer>,					s_bufferCases),
   3207 		CASE_DESC(allocCallbackFailTest	<BufferView>,				s_bufferViewCases),
   3208 		CASE_DESC(allocCallbackFailTest	<Image>,					s_imageCases),
   3209 		CASE_DESC(allocCallbackFailTest	<ImageView>,				s_imageViewCases),
   3210 		CASE_DESC(allocCallbackFailTest	<Semaphore>,				s_semaphoreCases),
   3211 		CASE_DESC(allocCallbackFailTest	<Event>,					s_eventCases),
   3212 		CASE_DESC(allocCallbackFailTest	<Fence>,					s_fenceCases),
   3213 		CASE_DESC(allocCallbackFailTest	<QueryPool>,				s_queryPoolCases),
   3214 		CASE_DESC(allocCallbackFailTest	<ShaderModule>,				s_shaderModuleCases),
   3215 		CASE_DESC(allocCallbackFailTest	<PipelineCache>,			s_pipelineCacheCases),
   3216 		CASE_DESC(allocCallbackFailTest	<PipelineLayout>,			s_pipelineLayoutCases),
   3217 		CASE_DESC(allocCallbackFailTest	<RenderPass>,				s_renderPassCases),
   3218 		CASE_DESC(allocCallbackFailTest	<GraphicsPipeline>,			s_graphicsPipelineCases),
   3219 		CASE_DESC(allocCallbackFailTest	<ComputePipeline>,			s_computePipelineCases),
   3220 		CASE_DESC(allocCallbackFailTest	<DescriptorSetLayout>,		s_descriptorSetLayoutCases),
   3221 		CASE_DESC(allocCallbackFailTest	<Sampler>,					s_samplerCases),
   3222 		CASE_DESC(allocCallbackFailTest	<DescriptorPool>,			s_descriptorPoolCases),
   3223 		EMPTY_CASE_DESC(DescriptorSet),
   3224 		CASE_DESC(allocCallbackFailTest	<Framebuffer>,				s_framebufferCases),
   3225 		CASE_DESC(allocCallbackFailTest	<CommandPool>,				s_commandPoolCases),
   3226 		EMPTY_CASE_DESC(CommandBuffer),
   3227 	};
   3228 	objectMgmtTests->addChild(createGroup(testCtx, "alloc_callback_fail", "Allocation callback failure", s_allocCallbackFailGroup));
   3229 
   3230 	// \note Test objects that can be created in bulk
   3231 	const CaseDescriptions	s_allocCallbackFailMultipleObjectsGroup	=
   3232 	{
   3233 		EMPTY_CASE_DESC(Instance),			// most objects can be created one at a time only
   3234 		EMPTY_CASE_DESC(Device),
   3235 		EMPTY_CASE_DESC(DeviceGroup),
   3236 		EMPTY_CASE_DESC(DeviceMemory),
   3237 		EMPTY_CASE_DESC(Buffer),
   3238 		EMPTY_CASE_DESC(BufferView),
   3239 		EMPTY_CASE_DESC(Image),
   3240 		EMPTY_CASE_DESC(ImageView),
   3241 		EMPTY_CASE_DESC(Semaphore),
   3242 		EMPTY_CASE_DESC(Event),
   3243 		EMPTY_CASE_DESC(Fence),
   3244 		EMPTY_CASE_DESC(QueryPool),
   3245 		EMPTY_CASE_DESC(ShaderModule),
   3246 		EMPTY_CASE_DESC(PipelineCache),
   3247 		EMPTY_CASE_DESC(PipelineLayout),
   3248 		EMPTY_CASE_DESC(RenderPass),
   3249 		CASE_DESC(allocCallbackFailMultipleObjectsTest <GraphicsPipeline>,		s_graphicsPipelineCases),
   3250 		CASE_DESC(allocCallbackFailMultipleObjectsTest <ComputePipeline>,		s_computePipelineCases),
   3251 		EMPTY_CASE_DESC(DescriptorSetLayout),
   3252 		EMPTY_CASE_DESC(Sampler),
   3253 		EMPTY_CASE_DESC(DescriptorPool),
   3254 		CASE_DESC(allocCallbackFailMultipleObjectsTest <DescriptorSet>,			s_descriptorSetCases),
   3255 		EMPTY_CASE_DESC(Framebuffer),
   3256 		EMPTY_CASE_DESC(CommandPool),
   3257 		CASE_DESC(allocCallbackFailMultipleObjectsTest <CommandBuffer>,			s_commandBufferCases),
   3258 	};
   3259 	objectMgmtTests->addChild(createGroup(testCtx, "alloc_callback_fail_multiple", "Allocation callback failure creating multiple objects with one call", s_allocCallbackFailMultipleObjectsGroup));
   3260 
   3261 	return objectMgmtTests.release();
   3262 }
   3263 
   3264 } // api
   3265 } // vkt
   3266