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