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