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