• 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 semaphore basic tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSynchronizationBasicSemaphoreTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktSynchronizationUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkRef.hpp"
34 
35 #include <thread>
36 
37 #include "tcuCommandLine.hpp"
38 
39 namespace vkt
40 {
41 namespace synchronization
42 {
43 namespace
44 {
45 
46 using namespace vk;
47 
48 struct TestConfig
49 {
50 	bool				useTypeCreate;
51 	VkSemaphoreType		semaphoreType;
52 	SynchronizationType type;
53 };
54 
55 static const int basicChainLength	= 32768;
56 
createTestSemaphore(Context & context,const DeviceInterface & vk,const VkDevice device,const TestConfig & config)57 Move<VkSemaphore> createTestSemaphore(Context& context, const DeviceInterface& vk, const VkDevice device, const TestConfig& config)
58 {
59 	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
60 		TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
61 
62 	return Move<VkSemaphore>(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) : createSemaphore(vk, device));
63 }
64 
65 #define FENCE_WAIT	~0ull
66 
basicOneQueueCase(Context & context,const TestConfig config)67 tcu::TestStatus basicOneQueueCase (Context& context, const TestConfig config)
68 {
69 	const DeviceInterface&			vk							= context.getDeviceInterface();
70 	const VkDevice					device						= context.getDevice();
71 	const VkQueue					queue						= context.getUniversalQueue();
72 	const deUint32					queueFamilyIndex			= context.getUniversalQueueFamilyIndex();
73 	const Unique<VkSemaphore>		semaphore					(createTestSemaphore(context, vk, device, config));
74 	const Unique<VkCommandPool>		cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
75 	const Unique<VkCommandBuffer>	cmdBuffer					(makeCommandBuffer(vk, device, *cmdPool));
76 	const VkCommandBufferBeginInfo	info						{
77 																	VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
78 																	DE_NULL,										// const void*                              pNext;
79 																	VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
80 																	DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
81 																};
82 	const deUint64					timelineValue				= 1u;
83 	const Unique<VkFence>			fence						(createFence(vk, device));
84 	bool							usingTimelineSemaphores		= config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR;
85 	VkCommandBufferSubmitInfoKHR	commandBufferInfo			= makeCommonCommandBufferSubmitInfo(*cmdBuffer);
86 	SynchronizationWrapperPtr		synchronizationWrapper		= getSynchronizationWrapper(config.type, vk, usingTimelineSemaphores, 2u);
87 	VkSemaphoreSubmitInfoKHR		signalSemaphoreSubmitInfo	= makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
88 	VkSemaphoreSubmitInfoKHR		waitSemaphoreSubmitInfo		= makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
89 
90 	synchronizationWrapper->addSubmitInfo(
91 		0u,												// deUint32								waitSemaphoreInfoCount
92 		DE_NULL,										// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
93 		1u,												// deUint32								commandBufferInfoCount
94 		&commandBufferInfo,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
95 		1u,												// deUint32								signalSemaphoreInfoCount
96 		&signalSemaphoreSubmitInfo,						// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
97 		DE_FALSE,
98 		usingTimelineSemaphores
99 	);
100 	synchronizationWrapper->addSubmitInfo(
101 		1u,												// deUint32								waitSemaphoreInfoCount
102 		&waitSemaphoreSubmitInfo,						// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
103 		1u,												// deUint32								commandBufferInfoCount
104 		&commandBufferInfo,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
105 		0u,												// deUint32								signalSemaphoreInfoCount
106 		DE_NULL,										// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
107 		usingTimelineSemaphores,
108 		DE_FALSE
109 	);
110 
111 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
112 	endCommandBuffer(vk, *cmdBuffer);
113 	VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
114 
115 	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
116 		return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
117 
118 	return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
119 }
120 
basicChainCase(Context & context,TestConfig config)121 tcu::TestStatus basicChainCase(Context & context, TestConfig config)
122 {
123 	VkResult								err							= VK_SUCCESS;
124 	const DeviceInterface&					vk							= context.getDeviceInterface();
125 	const VkDevice&							device						= context.getDevice();
126 	const VkQueue							queue						= context.getUniversalQueue();
127 	VkSemaphoreCreateInfo					sci							= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
128 	VkFenceCreateInfo						fci							= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
129 	VkFence									fence;
130 	std::vector<VkSemaphoreSubmitInfoKHR>	waitSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
131 	std::vector<VkSemaphoreSubmitInfoKHR>	signalSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
132 	VkSemaphoreSubmitInfoKHR*				pWaitSemaphoreInfo			= DE_NULL;
133 	VkSemaphoreSubmitInfoKHR*				pSignalSemaphoreInfo		= signalSemaphoreSubmitInfos.data();
134 
135 	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
136 	{
137 		if (i % (basicChainLength/4) == 0) context.getTestContext().touchWatchdog();
138 
139 		err = vk.createSemaphore(device, &sci, DE_NULL, &pSignalSemaphoreInfo->semaphore);
140 		if (err != VK_SUCCESS)
141 			continue;
142 
143 		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
144 		synchronizationWrapper->addSubmitInfo(
145 			!!pWaitSemaphoreInfo,						// deUint32								waitSemaphoreInfoCount
146 			pWaitSemaphoreInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
147 			0u,											// deUint32								commandBufferInfoCount
148 			DE_NULL,									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
149 			1u,											// deUint32								signalSemaphoreInfoCount
150 			pSignalSemaphoreInfo						// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
151 		);
152 
153 		err = synchronizationWrapper->queueSubmit(queue, 0);
154 		pWaitSemaphoreInfo				= &waitSemaphoreSubmitInfos[i];
155 		pWaitSemaphoreInfo->semaphore	= pSignalSemaphoreInfo->semaphore;
156 		pSignalSemaphoreInfo++;
157 	}
158 
159 
160 	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
161 
162 	{
163 		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
164 		synchronizationWrapper->addSubmitInfo(1, pWaitSemaphoreInfo, 0, DE_NULL, 0, DE_NULL);
165 		VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
166 	}
167 
168 	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
169 	vk.destroyFence(device, fence, DE_NULL);
170 
171 	for (const auto& s : signalSemaphoreSubmitInfos)
172 		vk.destroySemaphore(device, s.semaphore, DE_NULL);
173 
174 	if (err == VK_SUCCESS)
175 		return tcu::TestStatus::pass("Basic semaphore chain test passed");
176 
177 	return tcu::TestStatus::fail("Basic semaphore chain test failed");
178 }
179 
basicChainTimelineCase(Context & context,TestConfig config)180 tcu::TestStatus basicChainTimelineCase (Context& context, TestConfig config)
181 {
182 	VkResult					err			= VK_SUCCESS;
183 	const DeviceInterface&		vk			= context.getDeviceInterface();
184 	const VkDevice&				device		= context.getDevice();
185 	const VkQueue				queue		= context.getUniversalQueue();
186 	VkSemaphoreTypeCreateInfo	scti		= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 };
187 	VkSemaphoreCreateInfo		sci			= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
188 	VkFenceCreateInfo			fci			= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
189 	VkSemaphore					semaphore;
190 	VkFence						fence;
191 
192 	VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore));
193 
194 	std::vector<VkSemaphoreSubmitInfoKHR>	waitSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
195 	std::vector<VkSemaphoreSubmitInfoKHR>	signalSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
196 	VkSemaphoreSubmitInfoKHR*				pWaitSemaphoreInfo			= DE_NULL;
197 	VkSemaphoreSubmitInfoKHR*				pSignalSemaphoreInfo		= signalSemaphoreSubmitInfos.data();
198 
199 	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
200 	{
201 		if (i % (basicChainLength/4) == 0) context.getTestContext().touchWatchdog();
202 
203 		pSignalSemaphoreInfo->value = static_cast<deUint64>(i+1);
204 
205 		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
206 		synchronizationWrapper->addSubmitInfo(
207 			!!pWaitSemaphoreInfo,					// deUint32								waitSemaphoreInfoCount
208 			pWaitSemaphoreInfo,						// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
209 			0u,										// deUint32								commandBufferInfoCount
210 			DE_NULL,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
211 			1u,										// deUint32								signalSemaphoreInfoCount
212 			pSignalSemaphoreInfo,					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
213 			!!pWaitSemaphoreInfo,
214 			DE_TRUE
215 		);
216 
217 		err = synchronizationWrapper->queueSubmit(queue, 0);
218 
219 		pWaitSemaphoreInfo			= &waitSemaphoreSubmitInfos[i];
220 		pWaitSemaphoreInfo->value	= static_cast<deUint64>(i);
221 		pSignalSemaphoreInfo++;
222 	}
223 
224 	pWaitSemaphoreInfo->value = basicChainLength;
225 	SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
226 	synchronizationWrapper->addSubmitInfo(
227 		1u,											// deUint32								waitSemaphoreInfoCount
228 		pWaitSemaphoreInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
229 		0u,											// deUint32								commandBufferInfoCount
230 		DE_NULL,									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
231 		0u,											// deUint32								signalSemaphoreInfoCount
232 		DE_NULL,									// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
233 		DE_TRUE
234 	);
235 
236 	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
237 	VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
238 	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
239 
240 	vk.destroyFence(device, fence, DE_NULL);
241 	vk.destroySemaphore(device, semaphore, DE_NULL);
242 
243 	if (err == VK_SUCCESS)
244 		return tcu::TestStatus::pass("Basic semaphore chain test passed");
245 
246 	return tcu::TestStatus::fail("Basic semaphore chain test failed");
247 }
248 
basicThreadTimelineCase(Context & context,TestConfig)249 tcu::TestStatus basicThreadTimelineCase(Context& context, TestConfig)
250 {
251 	const DeviceInterface&				vk				= context.getDeviceInterface();
252 	const VkDevice&						device			= context.getDevice();
253 	const VkSemaphoreTypeCreateInfo		scti			= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 };
254 	const VkSemaphoreCreateInfo			sci				= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
255 	const VkFenceCreateInfo				fci				= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
256 	const vk::Unique<vk::VkSemaphore>	semaphore		(createSemaphore(vk, device, &sci));
257 	const Unique<VkFence>				fence			(createFence(vk, device, &fci));
258 	const deUint64						waitTimeout		= 50ull * 1000000ull;		// miliseconds
259 	VkResult							threadResult	= VK_SUCCESS;
260 
261 	// helper creating VkSemaphoreSignalInfo
262 	auto makeSemaphoreSignalInfo = [&semaphore](deUint64 value) -> VkSemaphoreSignalInfo
263 	{
264 		return
265 		{
266 			VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,		// VkStructureType				sType
267 			DE_NULL,										// const void*					pNext
268 			*semaphore,										// VkSemaphore					semaphore
269 			value											// deUint64						value
270 		};
271 	};
272 
273 	// helper creating VkSemaphoreWaitInfo
274 	auto makeSemaphoreWaitInfo = [&semaphore](deUint64* valuePtr) -> VkSemaphoreWaitInfo
275 	{
276 		return
277 		{
278 			VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,			// VkStructureType				sType
279 			DE_NULL,										// const void*					pNext
280 			VK_SEMAPHORE_WAIT_ANY_BIT,						// VkSemaphoreWaitFlags			flags;
281 			1u,												// deUint32						semaphoreCount;
282 			&*semaphore,									// const VkSemaphore*			pSemaphores;
283 			valuePtr										// const deUint64*				pValues;
284 		};
285 	};
286 
287 	// start thread - semaphore has value 0
288 	de::MovePtr<std::thread> thread(new std::thread([=, &vk, &threadResult]
289 	{
290 		// wait till semaphore has value 1
291 		deUint64 waitValue = 1;
292 		VkSemaphoreWaitInfo waitOne = makeSemaphoreWaitInfo(&waitValue);
293 		threadResult = vk.waitSemaphores(device, &waitOne, waitTimeout);
294 
295 		if (threadResult == VK_SUCCESS)
296 		{
297 			// signal semaphore with value 2
298 			VkSemaphoreSignalInfo signalTwo = makeSemaphoreSignalInfo(2);
299 			threadResult = vk.signalSemaphore(device, &signalTwo);
300 		}
301 	}));
302 
303 	// wait some time to give thread chance to start
304 	deSleep(1);		// milisecond
305 
306 	// signal semaphore with value 1
307 	VkSemaphoreSignalInfo signalOne = makeSemaphoreSignalInfo(1);
308 	vk.signalSemaphore(device, &signalOne);
309 
310 	// wait till semaphore has value 2
311 	deUint64				waitValue	= 2;
312 	VkSemaphoreWaitInfo		waitTwo		= makeSemaphoreWaitInfo(&waitValue);
313 	VkResult				mainResult	= vk.waitSemaphores(device, &waitTwo, waitTimeout);
314 
315 	thread->join();
316 
317 	if (mainResult == VK_SUCCESS)
318 		return tcu::TestStatus::pass("Pass");
319 
320 	if ((mainResult == VK_TIMEOUT) || (threadResult == VK_TIMEOUT))
321 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Reached wait timeout");
322 
323 	return tcu::TestStatus::fail("Fail");
324 }
325 
basicMultiQueueCase(Context & context,TestConfig config)326 tcu::TestStatus basicMultiQueueCase(Context& context, TestConfig config)
327 {
328 	enum { NO_MATCH_FOUND = ~((deUint32)0) };
329 	enum QueuesIndexes { FIRST = 0, SECOND, COUNT };
330 
331 	struct Queues
332 	{
333 		VkQueue		queue;
334 		deUint32	queueFamilyIndex;
335 	};
336 
337 	const DeviceInterface&					vk						= context.getDeviceInterface();
338 	const InstanceInterface&				instance				= context.getInstanceInterface();
339 	const VkPhysicalDevice					physicalDevice			= context.getPhysicalDevice();
340 	vk::Move<vk::VkDevice>					logicalDevice;
341 	std::vector<VkQueueFamilyProperties>	queueFamilyProperties;
342 	VkDeviceCreateInfo						deviceInfo;
343 	VkPhysicalDeviceFeatures				deviceFeatures;
344 	const float								queuePriorities[COUNT]	= { 1.0f, 1.0f };
345 	VkDeviceQueueCreateInfo					queueInfos[COUNT];
346 	Queues									queues[COUNT] =
347 	{
348 		{DE_NULL, (deUint32)NO_MATCH_FOUND},
349 		{DE_NULL, (deUint32)NO_MATCH_FOUND}
350 	};
351 	const VkCommandBufferBeginInfo			info =
352 	{
353 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
354 		DE_NULL,										// const void*                              pNext;
355 		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
356 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
357 	};
358 	Move<VkSemaphore>						semaphore;
359 	Move<VkCommandPool>						cmdPool[COUNT];
360 	Move<VkCommandBuffer>					cmdBuffer[COUNT];
361 	deUint64								timelineValues[COUNT] = { 1ull, 2ull };
362 	Move<VkFence>							fence[COUNT];
363 	bool									isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR;
364 
365 	queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
366 
367 	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
368 	{
369 		if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
370 			queues[FIRST].queueFamilyIndex = queueNdx;
371 
372 		if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
373 		{
374 			queues[SECOND].queueFamilyIndex = queueNdx;
375 			break;
376 		}
377 	}
378 
379 	if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
380 		TCU_THROW(NotSupportedError, "Queues couldn't be created");
381 
382 	for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
383 	{
384 		VkDeviceQueueCreateInfo queueInfo;
385 		deMemset(&queueInfo, 0, sizeof(queueInfo));
386 
387 		queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
388 		queueInfo.pNext = DE_NULL;
389 		queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
390 		queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
391 		queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
392 		queueInfo.pQueuePriorities = queuePriorities;
393 
394 		queueInfos[queueNdx] = queueInfo;
395 
396 		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
397 			break;
398 	}
399 
400 	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
401 	instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
402 
403 	VkPhysicalDeviceFeatures2					createPhysicalFeature		{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, deviceFeatures };
404 	VkPhysicalDeviceTimelineSemaphoreFeatures	timelineSemaphoreFeatures	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE };
405 	VkPhysicalDeviceSynchronization2FeaturesKHR	synchronization2Features	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE };
406 	void**										nextPtr						= &createPhysicalFeature.pNext;
407 
408 	std::vector<const char*> deviceExtensions;
409 	if (isTimelineSemaphore)
410 	{
411 		deviceExtensions.push_back("VK_KHR_timeline_semaphore");
412 		addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
413 	}
414 	if (config.type == SynchronizationType::SYNCHRONIZATION2)
415 	{
416 		deviceExtensions.push_back("VK_KHR_synchronization2");
417 		addToChainVulkanStructure(&nextPtr, synchronization2Features);
418 	}
419 
420 	deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
421 	deviceInfo.pNext = &createPhysicalFeature;
422 	deviceInfo.enabledExtensionCount = static_cast<deUint32>(deviceExtensions.size());
423 	deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : deviceExtensions.data();
424 	deviceInfo.enabledLayerCount = 0u;
425 	deviceInfo.ppEnabledLayerNames = DE_NULL;
426 	deviceInfo.pEnabledFeatures = 0u;
427 	deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
428 	deviceInfo.pQueueCreateInfos = queueInfos;
429 
430 	logicalDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo);
431 
432 	for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
433 	{
434 		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
435 			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
436 		else
437 			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
438 	}
439 
440 	semaphore			= (createTestSemaphore(context, vk, *logicalDevice, config));
441 	cmdPool[FIRST]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
442 	cmdPool[SECOND]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
443 	cmdBuffer[FIRST]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
444 	cmdBuffer[SECOND]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
445 
446 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
447 	endCommandBuffer(vk, *cmdBuffer[FIRST]);
448 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
449 	endCommandBuffer(vk, *cmdBuffer[SECOND]);
450 
451 	fence[FIRST] = (createFence(vk, *logicalDevice));
452 	fence[SECOND] = (createFence(vk, *logicalDevice));
453 
454 	VkCommandBufferSubmitInfoKHR commandBufferInfo[]
455 	{
456 		makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]),
457 		makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND])
458 	};
459 
460 	VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[]
461 	{
462 		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR),
463 		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)
464 	};
465 	VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
466 		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
467 
468 	{
469 		SynchronizationWrapperPtr synchronizationWrapper[]
470 		{
471 			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
472 			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
473 		};
474 		synchronizationWrapper[FIRST]->addSubmitInfo(
475 			0u,													// deUint32								waitSemaphoreInfoCount
476 			DE_NULL,											// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
477 			1u,													// deUint32								commandBufferInfoCount
478 			&commandBufferInfo[FIRST],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
479 			1u,													// deUint32								signalSemaphoreInfoCount
480 			&signalSemaphoreSubmitInfo[FIRST],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
481 			DE_FALSE,
482 			isTimelineSemaphore
483 		);
484 		synchronizationWrapper[SECOND]->addSubmitInfo(
485 			1u,													// deUint32								waitSemaphoreInfoCount
486 			&waitSemaphoreSubmitInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
487 			1u,													// deUint32								commandBufferInfoCount
488 			&commandBufferInfo[SECOND],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
489 			1u,													// deUint32								signalSemaphoreInfoCount
490 			&signalSemaphoreSubmitInfo[SECOND],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
491 			isTimelineSemaphore,
492 			isTimelineSemaphore
493 		);
494 		VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
495 		VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
496 	}
497 
498 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
499 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
500 
501 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
502 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
503 
504 	if (isTimelineSemaphore)
505 	{
506 		signalSemaphoreSubmitInfo[FIRST].value	= 3ull;
507 		signalSemaphoreSubmitInfo[SECOND].value	= 4ull;
508 		waitSemaphoreSubmitInfo.value			= 3ull;
509 	}
510 
511 	// swap semaphore info compared to above submits
512 	{
513 		SynchronizationWrapperPtr synchronizationWrapper[]
514 		{
515 			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
516 			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
517 		};
518 		synchronizationWrapper[FIRST]->addSubmitInfo(
519 			1u,													// deUint32								waitSemaphoreInfoCount
520 			&waitSemaphoreSubmitInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
521 			1u,													// deUint32								commandBufferInfoCount
522 			&commandBufferInfo[FIRST],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
523 			1u,													// deUint32								signalSemaphoreInfoCount
524 			&signalSemaphoreSubmitInfo[SECOND],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
525 			isTimelineSemaphore,
526 			isTimelineSemaphore
527 		);
528 		synchronizationWrapper[SECOND]->addSubmitInfo(
529 			isTimelineSemaphore ? 0u : 1u,								// deUint32								waitSemaphoreInfoCount
530 			isTimelineSemaphore ? DE_NULL : &waitSemaphoreSubmitInfo,	// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
531 			1u,															// deUint32								commandBufferInfoCount
532 			&commandBufferInfo[SECOND],									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
533 			1u,															// deUint32								signalSemaphoreInfoCount
534 			&signalSemaphoreSubmitInfo[FIRST],							// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
535 			DE_FALSE,
536 			isTimelineSemaphore
537 		);
538 
539 		VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
540 		VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
541 		VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
542 		VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
543 	}
544 
545 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
546 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
547 
548 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
549 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
550 
551 	return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
552 }
553 
checkSupport(Context & context,TestConfig config)554 void checkSupport(Context& context, TestConfig config)
555 {
556 	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR)
557 		context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
558 
559 	if (config.type == SynchronizationType::SYNCHRONIZATION2)
560 		context.requireDeviceFunctionality("VK_KHR_synchronization2");
561 }
562 
563 } // anonymous
564 
createBasicBinarySemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type)565 tcu::TestCaseGroup* createBasicBinarySemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type)
566 {
567 	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore", "Basic semaphore tests"));
568 
569 	TestConfig config =
570 	{
571 		0,
572 		VK_SEMAPHORE_TYPE_BINARY_KHR,
573 		type,
574 	};
575 	for (deUint32 typedCreate = 0; typedCreate < 2; typedCreate++)
576 	{
577 		config.useTypeCreate = (typedCreate != 0);
578 		const std::string createName = config.useTypeCreate ? "_typed" : "";
579 
580 		addFunctionCase(basicTests.get(), "one_queue" + createName,		"Basic binary semaphore tests with one queue",		checkSupport, basicOneQueueCase, config);
581 		addFunctionCase(basicTests.get(), "multi_queue" + createName,	"Basic binary semaphore tests with multi queue",	checkSupport, basicMultiQueueCase, config);
582 	}
583 
584 	addFunctionCase(basicTests.get(), "chain", "Binary semaphore chain test", checkSupport, basicChainCase, config);
585 
586 	return basicTests.release();
587 }
588 
createBasicTimelineSemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type)589 tcu::TestCaseGroup* createBasicTimelineSemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type)
590 {
591 	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore", "Basic timeline semaphore tests"));
592 	const TestConfig				config =
593 	{
594 		true,
595 		VK_SEMAPHORE_TYPE_TIMELINE_KHR,
596 		type,
597 	};
598 
599 	addFunctionCase(basicTests.get(), "one_queue",		"Basic timeline semaphore tests with one queue",	checkSupport, basicOneQueueCase, config);
600 	addFunctionCase(basicTests.get(), "multi_queue",	"Basic timeline semaphore tests with multi queue",	checkSupport, basicMultiQueueCase, config);
601 	addFunctionCase(basicTests.get(), "chain",			"Timeline semaphore chain test",					checkSupport, basicChainTimelineCase, config);
602 
603 	// dont repeat this test for synchronization2
604 	if (type == SynchronizationType::LEGACY)
605 		addFunctionCase(basicTests.get(), "two_threads","Timeline semaphore used by two threads",			checkSupport, basicThreadTimelineCase, config);
606 
607 	return basicTests.release();
608 }
609 
610 } // synchronization
611 } // vkt
612