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