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