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