• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
53 namespace vkt
54 {
55 namespace synchronization
56 {
57 namespace
58 {
59 using namespace vk;
60 
61 using std::vector;
62 using std::string;
63 using std::map;
64 using std::exception;
65 using std::ostringstream;
66 
67 using tcu::TestStatus;
68 using tcu::TestContext;
69 using tcu::ResultCollector;
70 using tcu::TestException;
71 
72 using de::UniquePtr;
73 using de::MovePtr;
74 using de::SharedPtr;
75 using de::Mutex;
76 using de::Thread;
77 using de::clamp;
78 
79 template<typename T>
makeVkSharedPtr(Move<T> move)80 inline SharedPtr<Move<T> > makeVkSharedPtr(Move<T> move)
81 {
82 	return SharedPtr<Move<T> >(new Move<T>(move));
83 }
84 
85 #ifndef CTS_USES_VULKANSC
86 enum
87 {
88 	EXECUTION_PER_THREAD	= 100,
89 	BUFFER_ELEMENT_COUNT	= 16,
90 	BUFFER_SIZE				= BUFFER_ELEMENT_COUNT*4
91 };
92 #else
93 enum
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 
101 class MultiQueues
102 {
103 	typedef struct QueueType
104 	{
105 		vector<VkQueue>							queues;
106 		vector<bool>							available;
107 		vector<SharedPtr<Move<VkCommandPool>>>	commandPools;
108 	} Queues;
109 
110 public:
addQueueFamilyIndex(const deUint32 & queueFamilyIndex,const deUint32 & count)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 
getQueueFamilyIndex(const int index) const123 	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 
countQueueFamilyIndex(void)130 	inline size_t	countQueueFamilyIndex	(void)
131 	{
132 		return m_queues.size();
133 	}
134 
getQueues(int index)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 
getFreeQueue(const DeviceInterface & vk,const VkDevice device,deUint32 & returnQueueFamilyIndex,VkQueue & returnQueues,Move<VkCommandBuffer> & commandBuffer,int & returnQueueIndex)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 
releaseQueue(const deUint32 & queueFamilyIndex,const int & queueIndex,Move<VkCommandBuffer> & commandBuffer)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 
setDevice(Move<VkDevice> device,const Context & context)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));
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()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *m_logicalDevice));
181 #endif // CTS_USES_VULKANSC
182 	}
183 
getDevice(void)184 	inline VkDevice	getDevice				(void)
185 	{
186 		return *m_logicalDevice;
187 	}
188 
getDeviceInterface(void)189 	inline DeviceInterface&	getDeviceInterface(void)
190 	{
191 		return *m_deviceDriver;
192 	}
193 
194 	MovePtr<Allocator>				m_allocator;
195 protected:
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 
createAllocator(const Context & context,const VkDevice & device)206 MovePtr<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 
checkQueueFlags(const VkQueueFlags & availableFlag,const VkQueueFlags & neededFlag)217 bool 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 
createQueues(Context & context,const VkQueueFlags & queueFlag,const VkInstance & instance,const InstanceInterface & vki)234 MovePtr<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 
executeComputePipeline(const Context & context,const VkPipeline & pipeline,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const deUint32 & shadersExecutions)356 TestStatus 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 
executeGraphicPipeline(const Context & context,const VkPipeline & pipeline,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const VkRenderPass & renderPass,const deUint32 shadersExecutions)430 TestStatus 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 
523 class ThreadGroupThread : private Thread
524 {
525 public:
ThreadGroupThread(const Context & context,VkPipelineCache pipelineCache,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const vector<deUint32> & shadersExecutions)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 
~ThreadGroupThread(void)538 	virtual					~ThreadGroupThread	(void)
539 	{
540 	}
541 
getResultCollector(void)542 	ResultCollector&		getResultCollector	(void)
543 	{
544 		return m_resultCollector;
545 	}
546 
547 	void					start				(de::SpinBarrier* groupBarrier);
548 	using Thread::join;
549 
550 protected:
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 
561 private:
562 							ThreadGroupThread	(const ThreadGroupThread&);
563 	ThreadGroupThread&		operator=			(const ThreadGroupThread&);
564 
run(void)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 
start(de::SpinBarrier * groupBarrier)592 void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
593 {
594 	m_barrier = groupBarrier;
595 	de::Thread::start();
596 }
597 
barrier(void)598 inline void ThreadGroupThread::barrier (void)
599 {
600 	m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
601 }
602 
603 class ThreadGroup
604 {
605 	typedef vector<SharedPtr<ThreadGroupThread> >	ThreadVector;
606 public:
ThreadGroup(void)607 							ThreadGroup			(void)
608 								: m_barrier(1)
609 	{
610 	}
~ThreadGroup(void)611 							~ThreadGroup		(void)
612 	{
613 	}
614 
add(MovePtr<ThreadGroupThread> thread)615 	void					add					(MovePtr<ThreadGroupThread> thread)
616 	{
617 		m_threads.push_back(SharedPtr<ThreadGroupThread>(thread.release()));
618 	}
619 
run(void)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 
639 private:
640 	ThreadVector							m_threads;
641 	de::SpinBarrier							m_barrier;
642 };
643 
644 
645 class CreateComputeThread : public ThreadGroupThread
646 {
647 public:
CreateComputeThread(const Context & context,VkPipelineCache pipelineCache,vector<VkComputePipelineCreateInfo> & pipelineInfo,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const vector<deUint32> & shadersExecutions)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 
runThread(void)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 	}
680 private:
681 	vector<VkComputePipelineCreateInfo>&	m_pipelineInfo;
682 };
683 
684 class CreateGraphicThread : public ThreadGroupThread
685 {
686 public:
CreateGraphicThread(const Context & context,VkPipelineCache pipelineCache,vector<VkGraphicsPipelineCreateInfo> & pipelineInfo,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const VkRenderPass & renderPass,const vector<deUint32> & shadersExecutions)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 
runThread(void)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 
720 private:
721 	vector<VkGraphicsPipelineCreateInfo>&	m_pipelineInfo;
722 	const VkRenderPass&						m_renderPass;
723 };
724 
725 class PipelineCacheComputeTestInstance  : public TestInstance
726 {
727 	typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
728 public:
PipelineCacheComputeTestInstance(Context & context,const vector<deUint32> & shadersExecutions)729 				PipelineCacheComputeTestInstance	(Context& context, const vector<deUint32>& shadersExecutions)
730 					: TestInstance			(context)
731 					, m_shadersExecutions	(shadersExecutions)
732 
733 	{
734 	}
735 
iterate(void)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 
795 private:
addShaderModules(const VkDevice & device)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 
addShaderStageInfo(const ShaderModuleVector & shaderCompModules)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 
addPipelineInfo(VkPipelineLayout pipelineLayout,const vector<VkPipelineShaderStageCreateInfo> & shaderStageInfos)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 
851 class PipelineCacheGraphicTestInstance  : public TestInstance
852 {
853 	typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
854 public:
PipelineCacheGraphicTestInstance(Context & context,const vector<deUint32> & shadersExecutions)855 											PipelineCacheGraphicTestInstance	(Context& context, const vector<deUint32>& shadersExecutions)
856 								: TestInstance			(context)
857 								, m_shadersExecutions	(shadersExecutions)
858 
859 	{
860 	}
861 
iterate(void)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 
924 private:
addShaderModules(const VkDevice & device)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 
addShaderStageInfo(const ShaderModuleVector & shaderCompModules)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 
addPipelineInfo(VkPipelineLayout pipelineLayout,const vector<VkPipelineShaderStageCreateInfo> & shaderStageInfos,const VkRenderPass & renderPass)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 
1119 class PipelineCacheComputeTest : public TestCase
1120 {
1121 public:
PipelineCacheComputeTest(TestContext & testCtx,const string & name,const string & description)1122 							PipelineCacheComputeTest	(TestContext&		testCtx,
1123 														const string&		name,
1124 														const string&		description)
1125 								:TestCase	(testCtx, name, description)
1126 	{
1127 	}
1128 
initPrograms(SourceCollections & programCollection) const1129 	void					initPrograms				(SourceCollections&	programCollection) const
1130 	{
1131 		ostringstream buffer;
1132 		buffer	<< "layout(set = 0, binding = 0, std430) buffer Output\n"
1133 				<< "{\n"
1134 				<< "	int result[];\n"
1135 				<< "} sb_out;\n";
1136 		{
1137 			ostringstream src;
1138 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1139 				<< "\n"
1140 				<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1141 				<< "\n"
1142 				<< buffer.str()
1143 				<< "void main (void)\n"
1144 				<< "{\n"
1145 				<< "	highp uint ndx = gl_GlobalInvocationID.x;\n"
1146 				<< "	sb_out.result[ndx] = int(ndx);\n"
1147 				<< "}\n";
1148 			programCollection.glslSources.add("compute_0") << glu::ComputeSource(src.str());
1149 		}
1150 		{
1151 			ostringstream src;
1152 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1153 				<< "\n"
1154 				<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1155 				<< "\n"
1156 				<< buffer.str()
1157 				<< "void main (void)\n"
1158 				<< "{\n"
1159 				<< "	for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1160 				<< "	{\n"
1161 				<< "		sb_out.result[ndx] = int(ndx);\n"
1162 				<< "	}\n"
1163 				<< "}\n";
1164 			programCollection.glslSources.add("compute_1") << glu::ComputeSource(src.str());
1165 		}
1166 		{
1167 			ostringstream src;
1168 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1169 				<< "\n"
1170 				<< "layout(local_size_x = "<<BUFFER_ELEMENT_COUNT<<", local_size_y = 1, local_size_z = 1) in;\n"
1171 				<< "\n"
1172 				<< buffer.str()
1173 				<< "void main (void)\n"
1174 				<< "{\n"
1175 				<< "	highp uint ndx = gl_LocalInvocationID.x;\n"
1176 				<< "	sb_out.result[ndx] = int(ndx);\n"
1177 				<< "}\n";
1178 			programCollection.glslSources.add("compute_2") << glu::ComputeSource(src.str());
1179 		}
1180 	}
1181 
createInstance(Context & context) const1182 	TestInstance*			createInstance				(Context& context) const
1183 	{
1184 		vector<deUint32>	shadersExecutions;
1185 		shadersExecutions.push_back(16u);	//compute_0
1186 		shadersExecutions.push_back(1u);	//compute_1
1187 		shadersExecutions.push_back(1u);	//compute_2
1188 		return new PipelineCacheComputeTestInstance(context, shadersExecutions);
1189 	}
1190 };
1191 
1192 class PipelineCacheGraphicTest : public TestCase
1193 {
1194 public:
PipelineCacheGraphicTest(TestContext & testCtx,const string & name,const string & description)1195 							PipelineCacheGraphicTest	(TestContext&		testCtx,
1196 														const string&		name,
1197 														const string&		description)
1198 								:TestCase	(testCtx, name, description)
1199 	{
1200 
1201 	}
1202 
initPrograms(SourceCollections & programCollection) const1203 	void					initPrograms				(SourceCollections&	programCollection) const
1204 	{
1205 		ostringstream buffer;
1206 		buffer	<< "layout(set = 0, binding = 0, std430) buffer Output\n"
1207 				<< "{\n"
1208 				<< "	int result[];\n"
1209 				<< "} sb_out;\n";
1210 
1211 		// Vertex
1212 		{
1213 			std::ostringstream src;
1214 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1215 				<< "\n"
1216 				<< buffer.str()
1217 				<< "\n"
1218 				<< "void main (void)\n"
1219 				<< "{\n"
1220 				<< "   sb_out.result[gl_VertexIndex] = int(gl_VertexIndex);\n"
1221 				<< "   gl_PointSize = 1.0f;\n"
1222 				<< "}\n";
1223 			programCollection.glslSources.add("vert_0") << glu::VertexSource(src.str());
1224 		}
1225 		// Vertex
1226 		{
1227 			std::ostringstream src;
1228 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1229 				<< "\n"
1230 				<< buffer.str()
1231 				<< "\n"
1232 				<< "void main (void)\n"
1233 				<< "{\n"
1234 				<< "	for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1235 				<< "	{\n"
1236 				<< "		sb_out.result[ndx] = int(ndx);\n"
1237 				<< "	}\n"
1238 				<< "	gl_PointSize = 1.0f;\n"
1239 				<< "}\n";
1240 			programCollection.glslSources.add("vert_1") << glu::VertexSource(src.str());
1241 		}
1242 		// Vertex
1243 		{
1244 			std::ostringstream src;
1245 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1246 				<< "\n"
1247 				<< buffer.str()
1248 				<< "\n"
1249 				<< "void main (void)\n"
1250 				<< "{\n"
1251 				<< "	for (int ndx = "<<BUFFER_ELEMENT_COUNT-1<<"; ndx >= 0; ndx--)\n"
1252 				<< "	{\n"
1253 				<< "		sb_out.result[uint(ndx)] = ndx;\n"
1254 				<< "	}\n"
1255 				<< "	gl_PointSize = 1.0f;\n"
1256 				<< "}\n";
1257 			programCollection.glslSources.add("vert_2") << glu::VertexSource(src.str());
1258 		}
1259 		// Fragment
1260 		{
1261 			std::ostringstream src;
1262 			src	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1263 				<< "\n"
1264 				<< "layout(location = 0) out vec4 o_color;\n"
1265 				<< "\n"
1266 				<< "void main (void)\n"
1267 				<< "{\n"
1268 				<< "    o_color = vec4(1.0);\n"
1269 				<< "}\n";
1270 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1271 		}
1272 	}
1273 
createInstance(Context & context) const1274 	TestInstance*			createInstance				(Context& context) const
1275 	{
1276 		vector<deUint32>	shadersExecutions;
1277 		shadersExecutions.push_back(16u);	//vert_0
1278 		shadersExecutions.push_back(1u);	//vert_1
1279 		shadersExecutions.push_back(1u);	//vert_2
1280 		return new PipelineCacheGraphicTestInstance(context, shadersExecutions);
1281 	}
1282 };
1283 
1284 
1285 } // anonymous
1286 
createInternallySynchronizedObjects(tcu::TestContext & testCtx)1287 tcu::TestCaseGroup* createInternallySynchronizedObjects (tcu::TestContext& testCtx)
1288 {
1289 	de::MovePtr<tcu::TestCaseGroup> tests(new tcu::TestCaseGroup(testCtx, "internally_synchronized_objects", "Internally synchronized objects"));
1290 	tests->addChild(new PipelineCacheComputeTest(testCtx, "pipeline_cache_compute", "Internally synchronized object VkPipelineCache for compute pipeline is tested"));
1291 	tests->addChild(new PipelineCacheGraphicTest(testCtx, "pipeline_cache_graphics", "Internally synchronized object VkPipelineCache for graphics pipeline is tested"));
1292 	return tests.release();
1293 }
1294 
1295 } // synchronization
1296 } // vkt
1297