1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group 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 Synchronization internally synchronized objects tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSynchronizationInternallySynchronizedObjectsTests.hpp"
25#include "vktTestCaseUtil.hpp"
26#include "vktSynchronizationUtil.hpp"
27#include "vktCustomInstancesDevices.hpp"
28
29#include "vkRef.hpp"
30#include "tcuDefs.hpp"
31#include "vkTypeUtil.hpp"
32#include "vkBarrierUtil.hpp"
33#include "vkPlatform.hpp"
34#include "vkBuilderUtil.hpp"
35#include "vkImageUtil.hpp"
36#include "vkCmdUtil.hpp"
37#include "vkObjUtil.hpp"
38#include "vkDeviceUtil.hpp"
39#include "vkSafetyCriticalUtil.hpp"
40
41#include "tcuResultCollector.hpp"
42#include "tcuCommandLine.hpp"
43
44#include "deThread.hpp"
45#include "deMutex.hpp"
46#include "deSharedPtr.hpp"
47#include "deSpinBarrier.hpp"
48
49
50#include <limits>
51#include <iterator>
52
53namespace vkt
54{
55namespace synchronization
56{
57namespace
58{
59using namespace vk;
60
61using std::vector;
62using std::string;
63using std::map;
64using std::exception;
65using std::ostringstream;
66
67using tcu::TestStatus;
68using tcu::TestContext;
69using tcu::ResultCollector;
70using tcu::TestException;
71
72using de::UniquePtr;
73using de::MovePtr;
74using de::SharedPtr;
75using de::Mutex;
76using de::Thread;
77using de::clamp;
78
79template<typename T>
80inline SharedPtr<Move<T> > makeVkSharedPtr(Move<T> move)
81{
82	return SharedPtr<Move<T> >(new Move<T>(move));
83}
84
85#ifndef CTS_USES_VULKANSC
86enum
87{
88	EXECUTION_PER_THREAD	= 100,
89	BUFFER_ELEMENT_COUNT	= 16,
90	BUFFER_SIZE				= BUFFER_ELEMENT_COUNT*4
91};
92#else
93enum
94{
95	EXECUTION_PER_THREAD	= 10,
96	BUFFER_ELEMENT_COUNT	= 16,
97	BUFFER_SIZE				= BUFFER_ELEMENT_COUNT*4
98};
99#endif // CTS_USES_VULKANSC
100
101class MultiQueues
102{
103	typedef struct QueueType
104	{
105		vector<VkQueue>							queues;
106		vector<bool>							available;
107		vector<SharedPtr<Move<VkCommandPool>>>	commandPools;
108	} Queues;
109
110public:
111	inline void		addQueueFamilyIndex		(const deUint32& queueFamilyIndex, const deUint32& count)
112	{
113		Queues temp;
114		vector<bool>::iterator it;
115		it = temp.available.begin();
116		temp.available.insert(it, count, false);
117
118		temp.queues.resize(count);
119
120		m_queues[queueFamilyIndex] = temp;
121	}
122
123	deUint32 getQueueFamilyIndex (const int index) const
124	{
125		map<deUint32,Queues>::const_iterator it = begin(m_queues);
126		std::advance(it, index);
127		return it->first;
128	}
129
130	inline size_t	countQueueFamilyIndex	(void)
131	{
132		return m_queues.size();
133	}
134
135	Queues &		getQueues				(int index)
136	{
137		map<deUint32,Queues>::iterator it = m_queues.begin();
138		advance (it, index);
139		return it->second;
140	}
141
142	bool			getFreeQueue			(const DeviceInterface& vk, const VkDevice device, deUint32& returnQueueFamilyIndex, VkQueue& returnQueues, Move<VkCommandBuffer>& commandBuffer, int& returnQueueIndex)
143	{
144		for (int queueFamilyIndexNdx = 0 ; queueFamilyIndexNdx < static_cast<int>(m_queues.size()); ++queueFamilyIndexNdx)
145		{
146			Queues& queue = m_queues[getQueueFamilyIndex(queueFamilyIndexNdx)];
147			for (int queueNdx = 0; queueNdx < static_cast<int>(queue.queues.size()); ++queueNdx)
148			{
149				m_mutex.lock();
150				if (queue.available[queueNdx])
151				{
152					queue.available[queueNdx]	= false;
153					returnQueueFamilyIndex		= getQueueFamilyIndex(queueFamilyIndexNdx);
154					returnQueues				= queue.queues[queueNdx];
155					commandBuffer				= makeCommandBuffer(vk, device, queue.commandPools[queueNdx]->get());
156					returnQueueIndex			= queueNdx;
157					m_mutex.unlock();
158					return true;
159				}
160				m_mutex.unlock();
161			}
162		}
163		return false;
164	}
165
166	void			releaseQueue			(const deUint32& queueFamilyIndex, const int& queueIndex, Move<VkCommandBuffer>& commandBuffer)
167	{
168		m_mutex.lock();
169		commandBuffer = Move<VkCommandBuffer>();
170		m_queues[queueFamilyIndex].available[queueIndex] = true;
171		m_mutex.unlock();
172	}
173
174	inline void		setDevice				(Move<VkDevice> device, const Context& context)
175	{
176		m_logicalDevice = device;
177#ifndef CTS_USES_VULKANSC
178		m_deviceDriver = de::MovePtr<DeviceDriver>		(new DeviceDriver(context.getPlatformInterface(), context.getInstance(), *m_logicalDevice, context.getUsedApiVersion()));
179#else
180		m_deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), context.getInstance(), *m_logicalDevice, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(), context.getUsedApiVersion()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *m_logicalDevice));
181#endif // CTS_USES_VULKANSC
182	}
183
184	inline VkDevice	getDevice				(void)
185	{
186		return *m_logicalDevice;
187	}
188
189	inline DeviceInterface&	getDeviceInterface(void)
190	{
191		return *m_deviceDriver;
192	}
193
194	MovePtr<Allocator>				m_allocator;
195protected:
196	Move<VkDevice>					m_logicalDevice;
197#ifndef CTS_USES_VULKANSC
198	de::MovePtr<vk::DeviceDriver>	m_deviceDriver;
199#else
200	de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>	m_deviceDriver;
201#endif // CTS_USES_VULKANSC
202	map<deUint32,Queues>			m_queues;
203	Mutex							m_mutex;
204};
205
206MovePtr<Allocator> createAllocator (const Context& context, const VkDevice& device)
207{
208	const DeviceInterface&					deviceInterface			= context.getDeviceInterface();
209	const InstanceInterface&				instance				= context.getInstanceInterface();
210	const VkPhysicalDevice					physicalDevice			= context.getPhysicalDevice();
211	const VkPhysicalDeviceMemoryProperties	deviceMemoryProperties	= getPhysicalDeviceMemoryProperties(instance, physicalDevice);
212
213	// Create memory allocator for device
214	return MovePtr<Allocator> (new SimpleAllocator(deviceInterface, device, deviceMemoryProperties));
215}
216
217bool checkQueueFlags (const VkQueueFlags& availableFlag, const VkQueueFlags& neededFlag)
218{
219	if (VK_QUEUE_TRANSFER_BIT == neededFlag)
220	{
221		if ( (availableFlag & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT ||
222			 (availableFlag & VK_QUEUE_COMPUTE_BIT)  == VK_QUEUE_COMPUTE_BIT  ||
223			 (availableFlag & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT
224		   )
225			return true;
226	}
227	else if ((availableFlag & neededFlag) == neededFlag)
228	{
229		return true;
230	}
231	return false;
232}
233
234MovePtr<MultiQueues> createQueues (Context& context, const VkQueueFlags& queueFlag, const VkInstance& instance, const InstanceInterface& vki)
235{
236	const VkPhysicalDevice					physicalDevice			= chooseDevice(vki, instance, context.getTestContext().getCommandLine());
237	MovePtr<MultiQueues>					moveQueues				(new MultiQueues());
238	MultiQueues&							queues					= *moveQueues;
239	VkDeviceCreateInfo						deviceInfo;
240	VkPhysicalDeviceFeatures				deviceFeatures;
241	vector<VkQueueFamilyProperties>			queueFamilyProperties;
242	vector<float>							queuePriorities;
243	vector<VkDeviceQueueCreateInfo>			queueInfos;
244
245	queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
246
247	for (deUint32 queuePropertiesNdx = 0; queuePropertiesNdx < queueFamilyProperties.size(); ++queuePropertiesNdx)
248	{
249		if (checkQueueFlags(queueFamilyProperties[queuePropertiesNdx].queueFlags, queueFlag))
250		{
251			queues.addQueueFamilyIndex(queuePropertiesNdx, queueFamilyProperties[queuePropertiesNdx].queueCount);
252		}
253	}
254
255	if (queues.countQueueFamilyIndex() == 0)
256	{
257		TCU_THROW(NotSupportedError, "Queue not found");
258	}
259
260	{
261		vector<float>::iterator it				= queuePriorities.begin();
262		unsigned int			maxQueueCount	= 0;
263		for (int queueFamilyIndexNdx = 0; queueFamilyIndexNdx < static_cast<int>(queues.countQueueFamilyIndex()); ++queueFamilyIndexNdx)
264		{
265			if (queues.getQueues(queueFamilyIndexNdx).queues.size() > maxQueueCount)
266				maxQueueCount = static_cast<unsigned int>(queues.getQueues(queueFamilyIndexNdx).queues.size());
267		}
268		queuePriorities.insert(it, maxQueueCount, 1.0);
269	}
270
271	for (int queueFamilyIndexNdx = 0; queueFamilyIndexNdx < static_cast<int>(queues.countQueueFamilyIndex()); ++queueFamilyIndexNdx)
272	{
273		VkDeviceQueueCreateInfo	queueInfo;
274		const deUint32			queueCount	= static_cast<deUint32>(queues.getQueues(queueFamilyIndexNdx).queues.size());
275
276		deMemset(&queueInfo, 0, sizeof(queueInfo));
277
278		queueInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
279		queueInfo.pNext				= DE_NULL;
280		queueInfo.flags				= (VkDeviceQueueCreateFlags)0u;
281		queueInfo.queueFamilyIndex	= queues.getQueueFamilyIndex(queueFamilyIndexNdx);
282		queueInfo.queueCount		= queueCount;
283		queueInfo.pQueuePriorities	= &queuePriorities[0];
284
285		queueInfos.push_back(queueInfo);
286	}
287
288	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
289	vki.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
290
291	void* pNext												= DE_NULL;
292#ifdef CTS_USES_VULKANSC
293	VkDeviceObjectReservationCreateInfo memReservationInfo	= context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
294	memReservationInfo.pNext								= pNext;
295	pNext													= &memReservationInfo;
296
297	VkPhysicalDeviceVulkanSC10Features sc10Features			= createDefaultSC10Features();
298	sc10Features.pNext										= pNext;
299	pNext													= &sc10Features;
300
301	VkPipelineCacheCreateInfo			pcCI;
302	std::vector<VkPipelinePoolSize>		poolSizes;
303	if (context.getTestContext().getCommandLine().isSubProcess())
304	{
305		if (context.getResourceInterface()->getCacheDataSize() > 0)
306		{
307			pcCI =
308			{
309				VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,		// VkStructureType				sType;
310				DE_NULL,											// const void*					pNext;
311				VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
312					VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
313				context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
314				context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
315			};
316			memReservationInfo.pipelineCacheCreateInfoCount		= 1;
317			memReservationInfo.pPipelineCacheCreateInfos		= &pcCI;
318		}
319
320		poolSizes							= context.getResourceInterface()->getPipelinePoolSizes();
321		if (!poolSizes.empty())
322		{
323			memReservationInfo.pipelinePoolSizeCount		= deUint32(poolSizes.size());
324			memReservationInfo.pPipelinePoolSizes			= poolSizes.data();
325		}
326	}
327#endif // CTS_USES_VULKANSC
328
329	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
330	deviceInfo.pNext					= pNext;
331	deviceInfo.enabledExtensionCount	= 0u;
332	deviceInfo.ppEnabledExtensionNames	= DE_NULL;
333	deviceInfo.enabledLayerCount		= 0u;
334	deviceInfo.ppEnabledLayerNames		= DE_NULL;
335	deviceInfo.pEnabledFeatures			= &deviceFeatures;
336	deviceInfo.queueCreateInfoCount		= static_cast<deUint32>(queues.countQueueFamilyIndex());
337	deviceInfo.pQueueCreateInfos		= &queueInfos[0];
338
339	queues.setDevice(createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instance, vki, physicalDevice, &deviceInfo), context);
340	vk::DeviceInterface& vk = queues.getDeviceInterface();
341
342	for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < queues.countQueueFamilyIndex(); ++queueFamilyIndex)
343	{
344		for (deUint32 queueReqNdx = 0; queueReqNdx < queues.getQueues(queueFamilyIndex).queues.size(); ++queueReqNdx)
345		{
346			vk.getDeviceQueue(queues.getDevice(), queues.getQueueFamilyIndex(queueFamilyIndex), queueReqNdx, &queues.getQueues(queueFamilyIndex).queues[queueReqNdx]);
347			queues.getQueues(queueFamilyIndex).available[queueReqNdx]=true;
348			queues.getQueues(queueFamilyIndex).commandPools.push_back(makeVkSharedPtr(createCommandPool(vk, queues.getDevice(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues.getQueueFamilyIndex(queueFamilyIndex))));
349		}
350	}
351
352	queues.m_allocator = createAllocator(context, queues.getDevice());
353	return moveQueues;
354}
355
356TestStatus executeComputePipeline (const Context& context, const VkPipeline& pipeline, const VkPipelineLayout& pipelineLayout,
357									const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const deUint32& shadersExecutions)
358{
359	DE_UNREF(context);
360	const DeviceInterface&			vk					= queues.getDeviceInterface();
361	const VkDevice					device				= queues.getDevice();
362	deUint32						queueFamilyIndex;
363	VkQueue							queue;
364	int								queueIndex;
365	Move<VkCommandBuffer>			cmdBuffer;
366	while(!queues.getFreeQueue(vk, device, queueFamilyIndex, queue, cmdBuffer, queueIndex)){}
367
368	{
369		const Unique<VkDescriptorPool>	descriptorPool		(DescriptorPoolBuilder()
370																.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
371																.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
372		Buffer							resultBuffer		(vk, device, *queues.m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
373		const VkBufferMemoryBarrier		bufferBarrier		= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, BUFFER_SIZE);
374
375		{
376			const Allocation& alloc = resultBuffer.getAllocation();
377			deMemset(alloc.getHostPtr(), 0, BUFFER_SIZE);
378			flushAlloc(vk, device, alloc);
379		}
380
381		// Start recording commands
382		beginCommandBuffer(vk, *cmdBuffer);
383
384		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
385
386		// Create descriptor set
387		const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, descriptorSetLayout));
388
389		const VkDescriptorBufferInfo resultDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, 0ull, BUFFER_SIZE);
390
391		DescriptorSetUpdateBuilder()
392			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
393			.update(vk, device);
394
395		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
396
397		// Dispatch indirect compute command
398		vk.cmdDispatch(*cmdBuffer, shadersExecutions, 1u, 1u);
399
400		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
401								 0, (const VkMemoryBarrier*)DE_NULL,
402								 1, &bufferBarrier,
403								 0, (const VkImageMemoryBarrier*)DE_NULL);
404
405		// End recording commands
406		endCommandBuffer(vk, *cmdBuffer);
407
408		// Wait for command buffer execution finish
409		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
410		queues.releaseQueue(queueFamilyIndex, queueIndex, cmdBuffer);
411
412		{
413			const Allocation& resultAlloc = resultBuffer.getAllocation();
414			invalidateAlloc(vk, device, resultAlloc);
415
416			const deInt32*	ptr = reinterpret_cast<deInt32*>(resultAlloc.getHostPtr());
417			for (deInt32 ndx = 0; ndx < BUFFER_ELEMENT_COUNT; ++ndx)
418			{
419				if (ptr[ndx] != ndx)
420				{
421					return TestStatus::fail("The data don't match");
422				}
423			}
424		}
425		return TestStatus::pass("Passed");
426	}
427}
428
429
430TestStatus executeGraphicPipeline (const Context& context, const VkPipeline& pipeline, const VkPipelineLayout& pipelineLayout,
431									const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const VkRenderPass& renderPass, const deUint32 shadersExecutions)
432{
433	DE_UNREF(context);
434	const DeviceInterface&			vk					= queues.getDeviceInterface();
435	const VkDevice					device				= queues.getDevice();
436	deUint32						queueFamilyIndex;
437	VkQueue							queue;
438	int								queueIndex;
439	Move<VkCommandBuffer>			cmdBuffer;
440	while (!queues.getFreeQueue(vk, device, queueFamilyIndex, queue, cmdBuffer, queueIndex)) {}
441
442	{
443		const Unique<VkDescriptorPool>	descriptorPool				(DescriptorPoolBuilder()
444																		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
445																		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
446		Move<VkDescriptorSet>			descriptorSet				= makeDescriptorSet(vk, device, *descriptorPool, descriptorSetLayout);
447		Buffer							resultBuffer				(vk, device, *queues.m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
448		const VkBufferMemoryBarrier		bufferBarrier				= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, BUFFER_SIZE);
449		const VkFormat					colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
450		const VkExtent3D				colorImageExtent			= makeExtent3D(1u, 1u, 1u);
451		const VkImageSubresourceRange	colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
452		de::MovePtr<Image>				colorAttachmentImage		= de::MovePtr<Image>(new Image(vk, device, *queues.m_allocator,
453																		makeImageCreateInfo(VK_IMAGE_TYPE_2D, colorImageExtent, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
454																		MemoryRequirement::Any));
455		Move<VkImageView>				colorAttachmentView			= makeImageView(vk, device, **colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange);
456		Move<VkFramebuffer>				framebuffer					= makeFramebuffer(vk, device, renderPass, *colorAttachmentView, colorImageExtent.width, colorImageExtent.height);
457		const VkDescriptorBufferInfo	outputBufferDescriptorInfo	= makeDescriptorBufferInfo(*resultBuffer, 0ull, BUFFER_SIZE);
458
459		DescriptorSetUpdateBuilder()
460			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
461			.update		(vk, device);
462
463		{
464			const Allocation& alloc = resultBuffer.getAllocation();
465			deMemset(alloc.getHostPtr(), 0, BUFFER_SIZE);
466			flushAlloc(vk, device, alloc);
467		}
468
469		// Start recording commands
470		beginCommandBuffer(vk, *cmdBuffer);
471		// Change color attachment image layout
472		{
473			const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
474				(VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
475				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
476				**colorAttachmentImage, colorImageSubresourceRange);
477
478			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
479				0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
480		}
481
482		{
483			const VkRect2D	renderArea	= makeRect2D(1u, 1u);
484			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
485			beginRenderPass(vk, *cmdBuffer, renderPass, *framebuffer, renderArea, clearColor);
486		}
487
488		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
489		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
490
491		vk.cmdDraw(*cmdBuffer, shadersExecutions, 1u, 0u, 0u);
492		endRenderPass(vk, *cmdBuffer);
493
494		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
495						0, (const VkMemoryBarrier*)DE_NULL,
496						1, &bufferBarrier,
497						0, (const VkImageMemoryBarrier*)DE_NULL);
498
499		// End recording commands
500		endCommandBuffer(vk, *cmdBuffer);
501
502		// Wait for command buffer execution finish
503		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
504		queues.releaseQueue(queueFamilyIndex, queueIndex, cmdBuffer);
505
506		{
507			const Allocation& resultAlloc = resultBuffer.getAllocation();
508			invalidateAlloc(vk, device, resultAlloc);
509
510			const deInt32*	ptr = reinterpret_cast<deInt32*>(resultAlloc.getHostPtr());
511			for (deInt32 ndx = 0; ndx < BUFFER_ELEMENT_COUNT; ++ndx)
512			{
513				if (ptr[ndx] != ndx)
514				{
515					return TestStatus::fail("The data don't match");
516				}
517			}
518		}
519		return TestStatus::pass("Passed");
520	}
521}
522
523class ThreadGroupThread : private Thread
524{
525public:
526							ThreadGroupThread	(const Context& context, VkPipelineCache pipelineCache, const VkPipelineLayout& pipelineLayout,
527												const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const vector<deUint32>& shadersExecutions)
528								: m_context				(context)
529								, m_pipelineCache		(pipelineCache)
530								, m_pipelineLayout		(pipelineLayout)
531								, m_descriptorSetLayout	(descriptorSetLayout)
532								, m_queues				(queues)
533								, m_shadersExecutions	(shadersExecutions)
534								, m_barrier				(DE_NULL)
535	{
536	}
537
538	virtual					~ThreadGroupThread	(void)
539	{
540	}
541
542	ResultCollector&		getResultCollector	(void)
543	{
544		return m_resultCollector;
545	}
546
547	void					start				(de::SpinBarrier* groupBarrier);
548	using Thread::join;
549
550protected:
551	virtual TestStatus		runThread		() = 0;
552	const Context&							m_context;
553	VkPipelineCache							m_pipelineCache;
554	const VkPipelineLayout&					m_pipelineLayout;
555	const VkDescriptorSetLayout&			m_descriptorSetLayout;
556	MultiQueues&							m_queues;
557	const vector<deUint32>&					m_shadersExecutions;
558
559	void					barrier				(void);
560
561private:
562							ThreadGroupThread	(const ThreadGroupThread&);
563	ThreadGroupThread&		operator=			(const ThreadGroupThread&);
564
565	void					run					(void)
566	{
567		try
568		{
569			TestStatus result = runThread();
570			m_resultCollector.addResult(result.getCode(), result.getDescription());
571		}
572		catch (const TestException& e)
573		{
574			m_resultCollector.addResult(e.getTestResult(), e.getMessage());
575		}
576		catch (const exception& e)
577		{
578			m_resultCollector.addResult(QP_TEST_RESULT_FAIL, e.what());
579		}
580		catch (...)
581		{
582			m_resultCollector.addResult(QP_TEST_RESULT_FAIL, "Exception");
583		}
584
585		m_barrier->removeThread(de::SpinBarrier::WAIT_MODE_AUTO);
586	}
587
588	ResultCollector							m_resultCollector;
589	de::SpinBarrier*						m_barrier;
590};
591
592void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
593{
594	m_barrier = groupBarrier;
595	de::Thread::start();
596}
597
598inline void ThreadGroupThread::barrier (void)
599{
600	m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
601}
602
603class ThreadGroup
604{
605	typedef vector<SharedPtr<ThreadGroupThread> >	ThreadVector;
606public:
607							ThreadGroup			(void)
608								: m_barrier(1)
609	{
610	}
611							~ThreadGroup		(void)
612	{
613	}
614
615	void					add					(MovePtr<ThreadGroupThread> thread)
616	{
617		m_threads.push_back(SharedPtr<ThreadGroupThread>(thread.release()));
618	}
619
620	TestStatus				run					(void)
621	{
622		ResultCollector	resultCollector;
623
624		m_barrier.reset((int)m_threads.size());
625
626		for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
627			(*threadIter)->start(&m_barrier);
628
629		for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
630		{
631			ResultCollector&	threadResult	= (*threadIter)->getResultCollector();
632			(*threadIter)->join();
633			resultCollector.addResult(threadResult.getResult(), threadResult.getMessage());
634		}
635
636		return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
637	}
638
639private:
640	ThreadVector							m_threads;
641	de::SpinBarrier							m_barrier;
642};
643
644
645class CreateComputeThread : public ThreadGroupThread
646{
647public:
648			CreateComputeThread	(const Context& context, VkPipelineCache pipelineCache, vector<VkComputePipelineCreateInfo>& pipelineInfo,
649								const VkPipelineLayout& pipelineLayout, const VkDescriptorSetLayout& descriptorSetLayout,
650								MultiQueues& queues, const vector<deUint32>& shadersExecutions)
651				: ThreadGroupThread		(context, pipelineCache, pipelineLayout, descriptorSetLayout, queues, shadersExecutions)
652				, m_pipelineInfo		(pipelineInfo)
653	{
654	}
655
656	TestStatus	runThread		(void)
657	{
658		ResultCollector		resultCollector;
659		for (int executionNdx = 0; executionNdx < EXECUTION_PER_THREAD; ++executionNdx)
660		{
661			const int shaderNdx					= executionNdx % (int)m_pipelineInfo.size();
662			const DeviceInterface&	vk			= m_context.getDeviceInterface();
663			const VkDevice			device		= m_queues.getDevice();
664			Move<VkPipeline>		pipeline	= createComputePipeline(vk,device,m_pipelineCache, &m_pipelineInfo[shaderNdx]);
665
666			TestStatus result = executeComputePipeline(m_context, *pipeline, m_pipelineLayout, m_descriptorSetLayout, m_queues, m_shadersExecutions[shaderNdx]);
667
668#ifdef CTS_USES_VULKANSC
669			// While collecting pipelines, synchronize between all threads for each pipeline that gets
670			// created, so we will reserve the maximum amount of pipeline pool space that could need.
671			if (!m_context.getTestContext().getCommandLine().isSubProcess()) {
672				barrier();
673			}
674#endif
675
676			resultCollector.addResult(result.getCode(), result.getDescription());
677		}
678		return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
679	}
680private:
681	vector<VkComputePipelineCreateInfo>&	m_pipelineInfo;
682};
683
684class CreateGraphicThread : public ThreadGroupThread
685{
686public:
687			CreateGraphicThread	(const Context& context, VkPipelineCache pipelineCache, vector<VkGraphicsPipelineCreateInfo>& pipelineInfo,
688								const VkPipelineLayout& pipelineLayout, const VkDescriptorSetLayout& descriptorSetLayout,
689								MultiQueues& queues, const VkRenderPass& renderPass, const vector<deUint32>& shadersExecutions)
690				: ThreadGroupThread		(context, pipelineCache, pipelineLayout, descriptorSetLayout, queues, shadersExecutions)
691				, m_pipelineInfo		(pipelineInfo)
692				, m_renderPass			(renderPass)
693	{}
694
695	TestStatus	runThread		(void)
696	{
697		ResultCollector		resultCollector;
698		for (int executionNdx = 0; executionNdx < EXECUTION_PER_THREAD; ++executionNdx)
699		{
700			const int shaderNdx					= executionNdx % (int)m_pipelineInfo.size();
701			const DeviceInterface&	vk			= m_context.getDeviceInterface();
702			const VkDevice			device		= m_queues.getDevice();
703			Move<VkPipeline>		pipeline	= createGraphicsPipeline(vk,device, m_pipelineCache, &m_pipelineInfo[shaderNdx]);
704
705			TestStatus result = executeGraphicPipeline(m_context, *pipeline, m_pipelineLayout, m_descriptorSetLayout, m_queues, m_renderPass, m_shadersExecutions[shaderNdx]);
706
707#ifdef CTS_USES_VULKANSC
708			// While collecting pipelines, synchronize between all threads for each pipeline that gets
709			// created, so we will reserve the maximum amount of pipeline pool space that could need.
710			if (!m_context.getTestContext().getCommandLine().isSubProcess()) {
711				barrier();
712			}
713#endif
714
715			resultCollector.addResult(result.getCode(), result.getDescription());
716		}
717		return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
718	}
719
720private:
721	vector<VkGraphicsPipelineCreateInfo>&	m_pipelineInfo;
722	const VkRenderPass&						m_renderPass;
723};
724
725class PipelineCacheComputeTestInstance  : public TestInstance
726{
727	typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
728public:
729				PipelineCacheComputeTestInstance	(Context& context, const vector<deUint32>& shadersExecutions)
730					: TestInstance			(context)
731					, m_shadersExecutions	(shadersExecutions)
732
733	{
734	}
735
736	TestStatus	iterate								(void)
737	{
738#ifdef CTS_USES_VULKANSC
739		MultithreadedDestroyGuard				mdGuard				(m_context.getResourceInterface());
740#endif // CTS_USES_VULKANSC
741		const CustomInstance					instance			(createCustomInstanceFromContext(m_context));
742		const InstanceDriver&					instanceDriver		(instance.getDriver());
743
744		MovePtr<MultiQueues>					queues				= createQueues(m_context, VK_QUEUE_COMPUTE_BIT, instance, instanceDriver);
745		const DeviceInterface&					vk					= queues->getDeviceInterface();
746		const VkDevice							device				= queues->getDevice();
747		ShaderModuleVector						shaderCompModules	= addShaderModules(device);
748		Buffer									resultBuffer		(vk, device, *queues->m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
749		const Move<VkDescriptorSetLayout>		descriptorSetLayout	(DescriptorSetLayoutBuilder()
750																		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
751																		.build(vk, device));
752		const Move<VkPipelineLayout>			pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
753		vector<VkPipelineShaderStageCreateInfo>	shaderStageInfos	= addShaderStageInfo(shaderCompModules);
754		vector<VkComputePipelineCreateInfo>		pipelineInfo		= addPipelineInfo(*pipelineLayout, shaderStageInfos);
755		const VkPipelineCacheCreateInfo			pipelineCacheInfo	=
756																	{
757																		VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,	// VkStructureType             sType;
758																		DE_NULL,										// const void*                 pNext;
759#ifndef CTS_USES_VULKANSC
760																		0u,												// VkPipelineCacheCreateFlags  flags;
761																		0u,												// deUintptr                   initialDataSize;
762																		DE_NULL,										// const void*                 pInitialData;
763#else
764																		VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
765																			VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
766																		m_context.getResourceInterface()->getCacheDataSize(),		// deUintptr					initialDataSize;
767																		m_context.getResourceInterface()->getCacheData()			// const void*					pInitialData;
768#endif // CTS_USES_VULKANSC
769																	};
770		Move<VkPipelineCache>					pipelineCache		= createPipelineCache(vk, device, &pipelineCacheInfo);
771		Move<VkPipeline>						pipeline			= createComputePipeline(vk, device, *pipelineCache, &pipelineInfo[0]);
772#ifndef CTS_USES_VULKANSC
773		const deUint32							numThreads			= clamp(deGetNumAvailableLogicalCores(), 4u, 32u);
774#else
775		const deUint32							numThreads			= 2u;
776#endif // CTS_USES_VULKANSC
777		ThreadGroup								threads;
778
779		executeComputePipeline(m_context, *pipeline, *pipelineLayout, *descriptorSetLayout, *queues, m_shadersExecutions[0]);
780
781		for (deUint32 ndx = 0; ndx < numThreads; ++ndx)
782			threads.add(MovePtr<ThreadGroupThread>(new CreateComputeThread(
783				m_context, *pipelineCache, pipelineInfo, *pipelineLayout, *descriptorSetLayout, *queues, m_shadersExecutions)));
784
785		{
786			TestStatus thread_result = threads.run();
787			if(thread_result.getCode())
788			{
789				return thread_result;
790			}
791		}
792		return TestStatus::pass("Passed");
793	}
794
795private:
796	ShaderModuleVector							addShaderModules					(const VkDevice& device)
797	{
798		const DeviceInterface&	vk	= m_context.getDeviceInterface();
799		ShaderModuleVector		shaderCompModules;
800		shaderCompModules.resize(m_shadersExecutions.size());
801		for (int shaderNdx = 0; shaderNdx <  static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
802		{
803			ostringstream shaderName;
804			shaderName<<"compute_"<<shaderNdx;
805			shaderCompModules[shaderNdx] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get(shaderName.str()), (VkShaderModuleCreateFlags)0)));
806		}
807		return shaderCompModules;
808	}
809
810	vector<VkPipelineShaderStageCreateInfo>		addShaderStageInfo					(const ShaderModuleVector& shaderCompModules)
811	{
812		VkPipelineShaderStageCreateInfo			shaderStageInfo;
813		vector<VkPipelineShaderStageCreateInfo>	shaderStageInfos;
814		shaderStageInfo.sType				=	VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
815		shaderStageInfo.pNext				=	DE_NULL;
816		shaderStageInfo.flags				=	(VkPipelineShaderStageCreateFlags)0;
817		shaderStageInfo.stage				=	VK_SHADER_STAGE_COMPUTE_BIT;
818		shaderStageInfo.pName				=	"main";
819		shaderStageInfo.pSpecializationInfo	=	DE_NULL;
820
821		for (int shaderNdx = 0; shaderNdx <  static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
822		{
823			shaderStageInfo.module = *(*shaderCompModules[shaderNdx]);
824			shaderStageInfos.push_back(shaderStageInfo);
825		}
826		return shaderStageInfos;
827	}
828
829	vector<VkComputePipelineCreateInfo>		addPipelineInfo						(VkPipelineLayout pipelineLayout, const vector<VkPipelineShaderStageCreateInfo>& shaderStageInfos)
830	{
831		vector<VkComputePipelineCreateInfo> pipelineInfos;
832		VkComputePipelineCreateInfo	computePipelineInfo;
833									computePipelineInfo.sType				= VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
834									computePipelineInfo.pNext				= DE_NULL;
835									computePipelineInfo.flags				= (VkPipelineCreateFlags)0;
836									computePipelineInfo.layout				= pipelineLayout;
837									computePipelineInfo.basePipelineHandle	= DE_NULL;
838									computePipelineInfo.basePipelineIndex	= 0;
839
840		for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
841		{
842			computePipelineInfo.stage = shaderStageInfos[shaderNdx];
843			pipelineInfos.push_back(computePipelineInfo);
844		}
845		return pipelineInfos;
846	}
847
848	const vector<deUint32>	m_shadersExecutions;
849};
850
851class PipelineCacheGraphicTestInstance  : public TestInstance
852{
853	typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
854public:
855											PipelineCacheGraphicTestInstance	(Context& context, const vector<deUint32>& shadersExecutions)
856								: TestInstance			(context)
857								, m_shadersExecutions	(shadersExecutions)
858
859	{
860	}
861
862	TestStatus								iterate								(void)
863	{
864#ifdef CTS_USES_VULKANSC
865		MultithreadedDestroyGuard				mdGuard					(m_context.getResourceInterface());
866#endif // CTS_USES_VULKANSC
867		const CustomInstance					instance				(createCustomInstanceFromContext(m_context));
868		const InstanceDriver&					instanceDriver			(instance.getDriver());
869		const VkPhysicalDevice					physicalDevice			= chooseDevice(instanceDriver, instance, m_context.getTestContext().getCommandLine());
870		requireFeatures(instanceDriver, physicalDevice, FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
871
872		MovePtr<MultiQueues>					queues					= createQueues(m_context, VK_QUEUE_GRAPHICS_BIT, instance, instanceDriver);
873		const DeviceInterface&					vk						= m_context.getDeviceInterface();
874		const VkDevice							device					= queues->getDevice();
875		VkFormat								colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
876		Move<VkRenderPass>						renderPass				= makeRenderPass(vk, device, colorFormat);
877		const Move<VkDescriptorSetLayout>		descriptorSetLayout		(DescriptorSetLayoutBuilder()
878																			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
879																			.build(vk, device));
880		ShaderModuleVector						shaderGraphicModules	= addShaderModules(device);
881		const Move<VkPipelineLayout>			pipelineLayout			(makePipelineLayout(vk, device, *descriptorSetLayout));
882		vector<VkPipelineShaderStageCreateInfo>	shaderStageInfos		= addShaderStageInfo(shaderGraphicModules);
883		vector<VkGraphicsPipelineCreateInfo>	pipelineInfo			= addPipelineInfo(*pipelineLayout, shaderStageInfos, *renderPass);
884		const VkPipelineCacheCreateInfo			pipelineCacheInfo		=
885																		{
886																			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,	// VkStructureType             sType;
887																			DE_NULL,										// const void*                 pNext;
888#ifndef CTS_USES_VULKANSC
889																			0u,												// VkPipelineCacheCreateFlags  flags;
890																			0u,												// deUintptr                   initialDataSize;
891																			DE_NULL											// const void*                 pInitialData;
892#else
893																			VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
894																				VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
895																			m_context.getResourceInterface()->getCacheDataSize(),		// deUintptr					initialDataSize;
896																			m_context.getResourceInterface()->getCacheData()			// const void*					pInitialData;
897#endif // CTS_USES_VULKANSC
898																		};
899		Move<VkPipelineCache>					pipelineCache			= createPipelineCache(vk, device, &pipelineCacheInfo);
900		Move<VkPipeline>						pipeline				= createGraphicsPipeline(vk, device, *pipelineCache, &pipelineInfo[0]);
901#ifndef CTS_USES_VULKANSC
902		const deUint32							numThreads				= clamp(deGetNumAvailableLogicalCores(), 4u, 32u);
903#else
904		const deUint32							numThreads				= 2u;
905#endif // CTS_USES_VULKANSC
906		ThreadGroup								threads;
907
908		executeGraphicPipeline(m_context, *pipeline, *pipelineLayout, *descriptorSetLayout, *queues, *renderPass, m_shadersExecutions[0]);
909
910		for (deUint32 ndx = 0; ndx < numThreads; ++ndx)
911			threads.add(MovePtr<ThreadGroupThread>(new CreateGraphicThread(
912				m_context, *pipelineCache, pipelineInfo, *pipelineLayout, *descriptorSetLayout, *queues, *renderPass, m_shadersExecutions)));
913
914		{
915			TestStatus thread_result = threads.run();
916			if(thread_result.getCode())
917			{
918				return thread_result;
919			}
920		}
921		return TestStatus::pass("Passed");
922	}
923
924private:
925	ShaderModuleVector						addShaderModules					(const VkDevice& device)
926	{
927		const DeviceInterface&	vk					= m_context.getDeviceInterface();
928		ShaderModuleVector		shaderModules;
929		shaderModules.resize(m_shadersExecutions.size() + 1);
930		for (int shaderNdx = 0; shaderNdx <  static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
931		{
932			ostringstream shaderName;
933			shaderName<<"vert_"<<shaderNdx;
934			shaderModules[shaderNdx] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get(shaderName.str()), (VkShaderModuleCreateFlags)0)));
935		}
936		shaderModules[m_shadersExecutions.size()] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), (VkShaderModuleCreateFlags)0)));
937		return shaderModules;
938	}
939
940	vector<VkPipelineShaderStageCreateInfo>	addShaderStageInfo					(const ShaderModuleVector& shaderCompModules)
941	{
942		VkPipelineShaderStageCreateInfo			shaderStageInfo;
943		vector<VkPipelineShaderStageCreateInfo>	shaderStageInfos;
944		shaderStageInfo.sType				=	VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
945		shaderStageInfo.pNext				=	DE_NULL;
946		shaderStageInfo.flags				=	(VkPipelineShaderStageCreateFlags)0;
947		shaderStageInfo.pName				=	"main";
948		shaderStageInfo.pSpecializationInfo	=	DE_NULL;
949
950		for (int shaderNdx = 0; shaderNdx <  static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
951		{
952			shaderStageInfo.stage	=	VK_SHADER_STAGE_VERTEX_BIT;
953			shaderStageInfo.module	= *(*shaderCompModules[shaderNdx]);
954			shaderStageInfos.push_back(shaderStageInfo);
955
956			shaderStageInfo.stage	=	VK_SHADER_STAGE_FRAGMENT_BIT;
957			shaderStageInfo.module	= *(*shaderCompModules[m_shadersExecutions.size()]);
958			shaderStageInfos.push_back(shaderStageInfo);
959		}
960		return shaderStageInfos;
961	}
962
963	vector<VkGraphicsPipelineCreateInfo>	addPipelineInfo						(VkPipelineLayout pipelineLayout, const vector<VkPipelineShaderStageCreateInfo>& shaderStageInfos, const VkRenderPass& renderPass)
964	{
965		VkExtent3D								colorImageExtent	= makeExtent3D(1u, 1u, 1u);
966		vector<VkGraphicsPipelineCreateInfo>	pipelineInfo;
967
968		m_vertexInputStateParams.sType								= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
969		m_vertexInputStateParams.pNext								= DE_NULL;
970		m_vertexInputStateParams.flags								= 0u;
971		m_vertexInputStateParams.vertexBindingDescriptionCount		= 0u;
972		m_vertexInputStateParams.pVertexBindingDescriptions			= DE_NULL;
973		m_vertexInputStateParams.vertexAttributeDescriptionCount	= 0u;
974		m_vertexInputStateParams.pVertexAttributeDescriptions		= DE_NULL;
975
976		m_inputAssemblyStateParams.sType					= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
977		m_inputAssemblyStateParams.pNext					= DE_NULL;
978		m_inputAssemblyStateParams.flags					= 0u;
979		m_inputAssemblyStateParams.topology					= VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
980		m_inputAssemblyStateParams.primitiveRestartEnable	= VK_FALSE;
981
982		m_viewport.x			= 0.0f;
983		m_viewport.y			= 0.0f;
984		m_viewport.width		= (float)colorImageExtent.width;
985		m_viewport.height		= (float)colorImageExtent.height;
986		m_viewport.minDepth		= 0.0f;
987		m_viewport.maxDepth		= 1.0f;
988
989		//TODO
990		m_scissor.offset.x		= 0;
991		m_scissor.offset.y		= 0;
992		m_scissor.extent.width	= colorImageExtent.width;
993		m_scissor.extent.height	= colorImageExtent.height;
994
995		m_viewportStateParams.sType			= VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
996		m_viewportStateParams.pNext			= DE_NULL;
997		m_viewportStateParams.flags			= 0u;
998		m_viewportStateParams.viewportCount	= 1u;
999		m_viewportStateParams.pViewports	= &m_viewport;
1000		m_viewportStateParams.scissorCount	= 1u;
1001		m_viewportStateParams.pScissors		= &m_scissor;
1002
1003		m_rasterStateParams.sType					= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1004		m_rasterStateParams.pNext					= DE_NULL;
1005		m_rasterStateParams.flags					= 0u;
1006		m_rasterStateParams.depthClampEnable		= VK_FALSE;
1007		m_rasterStateParams.rasterizerDiscardEnable	= VK_FALSE;
1008		m_rasterStateParams.polygonMode				= VK_POLYGON_MODE_FILL;
1009		m_rasterStateParams.cullMode				= VK_CULL_MODE_NONE;
1010		m_rasterStateParams.frontFace				= VK_FRONT_FACE_COUNTER_CLOCKWISE;
1011		m_rasterStateParams.depthBiasEnable			= VK_FALSE;
1012		m_rasterStateParams.depthBiasConstantFactor	= 0.0f;
1013		m_rasterStateParams.depthBiasClamp			= 0.0f;
1014		m_rasterStateParams.depthBiasSlopeFactor	= 0.0f;
1015		m_rasterStateParams.lineWidth				= 1.0f;
1016
1017		m_colorBlendAttachmentState.blendEnable			= VK_FALSE;
1018		m_colorBlendAttachmentState.srcColorBlendFactor	= VK_BLEND_FACTOR_ONE;
1019		m_colorBlendAttachmentState.dstColorBlendFactor	= VK_BLEND_FACTOR_ZERO;
1020		m_colorBlendAttachmentState.colorBlendOp		= VK_BLEND_OP_ADD;
1021		m_colorBlendAttachmentState.srcAlphaBlendFactor	= VK_BLEND_FACTOR_ONE;
1022		m_colorBlendAttachmentState.dstAlphaBlendFactor	= VK_BLEND_FACTOR_ZERO;
1023		m_colorBlendAttachmentState.alphaBlendOp		= VK_BLEND_OP_ADD;
1024		m_colorBlendAttachmentState.colorWriteMask		= VK_COLOR_COMPONENT_R_BIT |
1025														  VK_COLOR_COMPONENT_G_BIT |
1026														  VK_COLOR_COMPONENT_B_BIT |
1027														  VK_COLOR_COMPONENT_A_BIT;
1028
1029		m_colorBlendStateParams.sType				= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1030		m_colorBlendStateParams.pNext				= DE_NULL;
1031		m_colorBlendStateParams.flags				= 0u;
1032		m_colorBlendStateParams.logicOpEnable		= VK_FALSE;
1033		m_colorBlendStateParams.logicOp				= VK_LOGIC_OP_COPY;
1034		m_colorBlendStateParams.attachmentCount		= 1u;
1035		m_colorBlendStateParams.pAttachments		= &m_colorBlendAttachmentState;
1036		m_colorBlendStateParams.blendConstants[0]	= 0.0f;
1037		m_colorBlendStateParams.blendConstants[1]	= 0.0f;
1038		m_colorBlendStateParams.blendConstants[2]	= 0.0f;
1039		m_colorBlendStateParams.blendConstants[3]	= 0.0f;
1040
1041		m_multisampleStateParams.sType					= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1042		m_multisampleStateParams.pNext					= DE_NULL;
1043		m_multisampleStateParams.flags					= 0u;
1044		m_multisampleStateParams.rasterizationSamples	= VK_SAMPLE_COUNT_1_BIT;
1045		m_multisampleStateParams.sampleShadingEnable	= VK_FALSE;
1046		m_multisampleStateParams.minSampleShading		= 0.0f;
1047		m_multisampleStateParams.pSampleMask			= DE_NULL;
1048		m_multisampleStateParams.alphaToCoverageEnable	= VK_FALSE;
1049		m_multisampleStateParams.alphaToOneEnable		= VK_FALSE;
1050
1051		m_depthStencilStateParams.sType					= VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1052		m_depthStencilStateParams.pNext					= DE_NULL;
1053		m_depthStencilStateParams.flags					= 0u;
1054		m_depthStencilStateParams.depthTestEnable		= VK_TRUE;
1055		m_depthStencilStateParams.depthWriteEnable		= VK_TRUE;
1056		m_depthStencilStateParams.depthCompareOp		= VK_COMPARE_OP_LESS_OR_EQUAL;
1057		m_depthStencilStateParams.depthBoundsTestEnable	= VK_FALSE;
1058		m_depthStencilStateParams.stencilTestEnable		= VK_FALSE;
1059		m_depthStencilStateParams.front.failOp			= VK_STENCIL_OP_KEEP;
1060		m_depthStencilStateParams.front.passOp			= VK_STENCIL_OP_KEEP;
1061		m_depthStencilStateParams.front.depthFailOp		= VK_STENCIL_OP_KEEP;
1062		m_depthStencilStateParams.front.compareOp		= VK_COMPARE_OP_NEVER;
1063		m_depthStencilStateParams.front.compareMask		= 0u;
1064		m_depthStencilStateParams.front.writeMask		= 0u;
1065		m_depthStencilStateParams.front.reference		= 0u;
1066		m_depthStencilStateParams.back.failOp			= VK_STENCIL_OP_KEEP;
1067		m_depthStencilStateParams.back.passOp			= VK_STENCIL_OP_KEEP;
1068		m_depthStencilStateParams.back.depthFailOp		= VK_STENCIL_OP_KEEP;
1069		m_depthStencilStateParams.back.compareOp		= VK_COMPARE_OP_NEVER;
1070		m_depthStencilStateParams.back.compareMask		= 0u;
1071		m_depthStencilStateParams.back.writeMask		= 0u;
1072		m_depthStencilStateParams.back.reference		= 0u;
1073		m_depthStencilStateParams.minDepthBounds		= 0.0f;
1074		m_depthStencilStateParams.maxDepthBounds		= 1.0f;
1075
1076		VkGraphicsPipelineCreateInfo	graphicsPipelineParams	=
1077																{
1078																	VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1079																	DE_NULL,											// const void*										pNext;
1080																	0u,													// VkPipelineCreateFlags							flags;
1081																	2u,													// deUint32											stageCount;
1082																	DE_NULL,											// const VkPipelineShaderStageCreateInfo*			pStages;
1083																	&m_vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1084																	&m_inputAssemblyStateParams,						// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1085																	DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1086																	&m_viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1087																	&m_rasterStateParams,								// const VkPipelineRasterizationStateCreateInfo*	pRasterState;
1088																	&m_multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1089																	&m_depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1090																	&m_colorBlendStateParams,							// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1091																	(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1092																	pipelineLayout,										// VkPipelineLayout									layout;
1093																	renderPass,											// VkRenderPass										renderPass;
1094																	0u,													// deUint32											subpass;
1095																	DE_NULL,											// VkPipeline										basePipelineHandle;
1096																	0,													// deInt32											basePipelineIndex;
1097																};
1098		for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()) * 2; shaderNdx+=2)
1099		{
1100			graphicsPipelineParams.pStages = &shaderStageInfos[shaderNdx];
1101			pipelineInfo.push_back(graphicsPipelineParams);
1102		}
1103		return pipelineInfo;
1104	}
1105
1106	const vector<deUint32>					m_shadersExecutions;
1107	VkPipelineVertexInputStateCreateInfo	m_vertexInputStateParams;
1108	VkPipelineInputAssemblyStateCreateInfo	m_inputAssemblyStateParams;
1109	VkViewport								m_viewport;
1110	VkRect2D								m_scissor;
1111	VkPipelineViewportStateCreateInfo		m_viewportStateParams;
1112	VkPipelineRasterizationStateCreateInfo	m_rasterStateParams;
1113	VkPipelineColorBlendAttachmentState		m_colorBlendAttachmentState;
1114	VkPipelineColorBlendStateCreateInfo		m_colorBlendStateParams;
1115	VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
1116	VkPipelineDepthStencilStateCreateInfo	m_depthStencilStateParams;
1117};
1118
1119class PipelineCacheComputeTest : public TestCase
1120{
1121public:
1122							PipelineCacheComputeTest	(TestContext&		testCtx,
1123														const string&		name)
1124								:TestCase	(testCtx, name)
1125	{
1126	}
1127
1128	void					initPrograms				(SourceCollections&	programCollection) const
1129	{
1130		ostringstream buffer;
1131		buffer	<< "layout(set = 0, binding = 0, std430) buffer Output\n"
1132				<< "{\n"
1133				<< "	int result[];\n"
1134				<< "} sb_out;\n";
1135		{
1136			ostringstream src;
1137			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1138				<< "\n"
1139				<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1140				<< "\n"
1141				<< buffer.str()
1142				<< "void main (void)\n"
1143				<< "{\n"
1144				<< "	highp uint ndx = gl_GlobalInvocationID.x;\n"
1145				<< "	sb_out.result[ndx] = int(ndx);\n"
1146				<< "}\n";
1147			programCollection.glslSources.add("compute_0") << glu::ComputeSource(src.str());
1148		}
1149		{
1150			ostringstream src;
1151			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1152				<< "\n"
1153				<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1154				<< "\n"
1155				<< buffer.str()
1156				<< "void main (void)\n"
1157				<< "{\n"
1158				<< "	for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1159				<< "	{\n"
1160				<< "		sb_out.result[ndx] = int(ndx);\n"
1161				<< "	}\n"
1162				<< "}\n";
1163			programCollection.glslSources.add("compute_1") << glu::ComputeSource(src.str());
1164		}
1165		{
1166			ostringstream src;
1167			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1168				<< "\n"
1169				<< "layout(local_size_x = "<<BUFFER_ELEMENT_COUNT<<", local_size_y = 1, local_size_z = 1) in;\n"
1170				<< "\n"
1171				<< buffer.str()
1172				<< "void main (void)\n"
1173				<< "{\n"
1174				<< "	highp uint ndx = gl_LocalInvocationID.x;\n"
1175				<< "	sb_out.result[ndx] = int(ndx);\n"
1176				<< "}\n";
1177			programCollection.glslSources.add("compute_2") << glu::ComputeSource(src.str());
1178		}
1179	}
1180
1181	TestInstance*			createInstance				(Context& context) const
1182	{
1183		vector<deUint32>	shadersExecutions;
1184		shadersExecutions.push_back(16u);	//compute_0
1185		shadersExecutions.push_back(1u);	//compute_1
1186		shadersExecutions.push_back(1u);	//compute_2
1187		return new PipelineCacheComputeTestInstance(context, shadersExecutions);
1188	}
1189};
1190
1191class PipelineCacheGraphicTest : public TestCase
1192{
1193public:
1194							PipelineCacheGraphicTest	(TestContext&		testCtx,
1195														const string&		name)
1196								:TestCase	(testCtx, name)
1197	{
1198
1199	}
1200
1201	void					initPrograms				(SourceCollections&	programCollection) const
1202	{
1203		ostringstream buffer;
1204		buffer	<< "layout(set = 0, binding = 0, std430) buffer Output\n"
1205				<< "{\n"
1206				<< "	int result[];\n"
1207				<< "} sb_out;\n";
1208
1209		// Vertex
1210		{
1211			std::ostringstream src;
1212			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1213				<< "\n"
1214				<< buffer.str()
1215				<< "\n"
1216				<< "void main (void)\n"
1217				<< "{\n"
1218				<< "   sb_out.result[gl_VertexIndex] = int(gl_VertexIndex);\n"
1219				<< "   gl_PointSize = 1.0f;\n"
1220				<< "}\n";
1221			programCollection.glslSources.add("vert_0") << glu::VertexSource(src.str());
1222		}
1223		// Vertex
1224		{
1225			std::ostringstream src;
1226			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1227				<< "\n"
1228				<< buffer.str()
1229				<< "\n"
1230				<< "void main (void)\n"
1231				<< "{\n"
1232				<< "	for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1233				<< "	{\n"
1234				<< "		sb_out.result[ndx] = int(ndx);\n"
1235				<< "	}\n"
1236				<< "	gl_PointSize = 1.0f;\n"
1237				<< "}\n";
1238			programCollection.glslSources.add("vert_1") << glu::VertexSource(src.str());
1239		}
1240		// Vertex
1241		{
1242			std::ostringstream src;
1243			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1244				<< "\n"
1245				<< buffer.str()
1246				<< "\n"
1247				<< "void main (void)\n"
1248				<< "{\n"
1249				<< "	for (int ndx = "<<BUFFER_ELEMENT_COUNT-1<<"; ndx >= 0; ndx--)\n"
1250				<< "	{\n"
1251				<< "		sb_out.result[uint(ndx)] = ndx;\n"
1252				<< "	}\n"
1253				<< "	gl_PointSize = 1.0f;\n"
1254				<< "}\n";
1255			programCollection.glslSources.add("vert_2") << glu::VertexSource(src.str());
1256		}
1257		// Fragment
1258		{
1259			std::ostringstream src;
1260			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1261				<< "\n"
1262				<< "layout(location = 0) out vec4 o_color;\n"
1263				<< "\n"
1264				<< "void main (void)\n"
1265				<< "{\n"
1266				<< "    o_color = vec4(1.0);\n"
1267				<< "}\n";
1268			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1269		}
1270	}
1271
1272	TestInstance*			createInstance				(Context& context) const
1273	{
1274		vector<deUint32>	shadersExecutions;
1275		shadersExecutions.push_back(16u);	//vert_0
1276		shadersExecutions.push_back(1u);	//vert_1
1277		shadersExecutions.push_back(1u);	//vert_2
1278		return new PipelineCacheGraphicTestInstance(context, shadersExecutions);
1279	}
1280};
1281
1282
1283} // anonymous
1284
1285tcu::TestCaseGroup* createInternallySynchronizedObjects (tcu::TestContext& testCtx)
1286{
1287	// Internally synchronized objects
1288	de::MovePtr<tcu::TestCaseGroup> tests(new tcu::TestCaseGroup(testCtx, "internally_synchronized_objects"));
1289	// Internally synchronized object VkPipelineCache for compute pipeline is tested
1290	tests->addChild(new PipelineCacheComputeTest(testCtx, "pipeline_cache_compute"));
1291	// Internally synchronized object VkPipelineCache for graphics pipeline is tested
1292	tests->addChild(new PipelineCacheGraphicTest(testCtx, "pipeline_cache_graphics"));
1293	return tests.release();
1294}
1295
1296} // synchronization
1297} // vkt
1298