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