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 "vkDeviceUtil.hpp"
34#include "vkRef.hpp"
35#include "vkSafetyCriticalUtil.hpp"
36
37#include <thread>
38
39#include "tcuCommandLine.hpp"
40
41namespace vkt
42{
43namespace synchronization
44{
45namespace
46{
47
48using namespace vk;
49using vkt::synchronization::VideoCodecOperationFlags;
50
51struct TestConfig
52{
53	bool						useTypeCreate;
54	VkSemaphoreType				semaphoreType;
55	SynchronizationType			type;
56	VideoCodecOperationFlags	videoCodecOperationFlags;
57};
58
59#ifdef CTS_USES_VULKANSC
60static const int basicChainLength	= 1024;
61#else
62static const int basicChainLength	= 32768;
63#endif
64
65Move<VkSemaphore> createTestSemaphore(Context& context, const DeviceInterface& vk, const VkDevice device, const TestConfig& config)
66{
67	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
68		TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
69
70	return Move<VkSemaphore>(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) : createSemaphore(vk, device));
71}
72
73#define FENCE_WAIT	~0ull
74
75tcu::TestStatus basicOneQueueCase (Context& context, const TestConfig config)
76{
77	de::MovePtr<VideoDevice>		videoDevice					(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
78	const DeviceInterface&			vk							= getSyncDeviceInterface(videoDevice, context);
79	const VkDevice					device						= getSyncDevice(videoDevice, context);
80	const VkQueue					queue						= getSyncQueue(videoDevice, context);
81	const deUint32					queueFamilyIndex			= getSyncQueueFamilyIndex(videoDevice, context);
82	const Unique<VkSemaphore>		semaphore					(createTestSemaphore(context, vk, device, config));
83	const Unique<VkCommandPool>		cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
84	const Unique<VkCommandBuffer>	cmdBuffer					(makeCommandBuffer(vk, device, *cmdPool));
85	const VkCommandBufferBeginInfo	info						{
86																	VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
87																	DE_NULL,										// const void*                              pNext;
88																	VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
89																	DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
90																};
91	const deUint64					timelineValue				= 1u;
92	const Unique<VkFence>			fence						(createFence(vk, device));
93	bool							usingTimelineSemaphores		= config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
94	VkCommandBufferSubmitInfoKHR	commandBufferInfo			= makeCommonCommandBufferSubmitInfo(*cmdBuffer);
95	SynchronizationWrapperPtr		synchronizationWrapper		= getSynchronizationWrapper(config.type, vk, usingTimelineSemaphores, 2u);
96	VkSemaphoreSubmitInfoKHR		signalSemaphoreSubmitInfo	= makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
97	VkSemaphoreSubmitInfoKHR		waitSemaphoreSubmitInfo		= makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
98
99	synchronizationWrapper->addSubmitInfo(
100		0u,												// deUint32								waitSemaphoreInfoCount
101		DE_NULL,										// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
102		1u,												// deUint32								commandBufferInfoCount
103		&commandBufferInfo,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
104		1u,												// deUint32								signalSemaphoreInfoCount
105		&signalSemaphoreSubmitInfo,						// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
106		DE_FALSE,
107		usingTimelineSemaphores
108	);
109	synchronizationWrapper->addSubmitInfo(
110		1u,												// deUint32								waitSemaphoreInfoCount
111		&waitSemaphoreSubmitInfo,						// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
112		1u,												// deUint32								commandBufferInfoCount
113		&commandBufferInfo,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
114		0u,												// deUint32								signalSemaphoreInfoCount
115		DE_NULL,										// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
116		usingTimelineSemaphores,
117		DE_FALSE
118	);
119
120	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
121	endCommandBuffer(vk, *cmdBuffer);
122	VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
123
124	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
125		return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
126
127	return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
128}
129
130tcu::TestStatus noneWaitSubmitTest (Context& context, const TestConfig config)
131{
132	const DeviceInterface&			vk										= context.getDeviceInterface();
133	const VkDevice							device								= context.getDevice();
134	const VkQueue								queue									= context.getUniversalQueue();
135	const deUint32							queueFamilyIndex			= context.getUniversalQueueFamilyIndex();
136
137	const Unique<VkSemaphore>			semaphore					(createTestSemaphore(context, vk, device, config));
138	const Unique<VkCommandPool>		cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
139
140		const Unique<VkCommandBuffer>	firstbuffer					(makeCommandBuffer(vk, device, *cmdPool));
141	const Unique<VkCommandBuffer>	secondBuffer				(makeCommandBuffer(vk, device, *cmdPool));
142
143	const VkCommandBufferBeginInfo	info						{
144																	VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
145																	DE_NULL,																			// const void*                              pNext;
146																	VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
147																	DE_NULL,																			// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
148																};
149	const Unique<VkFence>			fence1					(createFence(vk, device));
150	const Unique<VkFence>			fence2					(createFence(vk, device));
151	const Unique<VkEvent>			event						(createEvent(vk, device));
152
153	VK_CHECK(vk.beginCommandBuffer(*firstbuffer, &info));
154	endCommandBuffer(vk, *firstbuffer);
155
156	const VkSubmitInfo firstSubmitInfo {
157		VK_STRUCTURE_TYPE_SUBMIT_INFO,	//VkStructureType sType
158		DE_NULL,												//const void* pNext
159		0u,															//uint32_t waitSemaphoreCount
160		DE_NULL,												//const VkSemaphore* pWaitSemaphores
161		DE_NULL,												//const VkPipelineStageFlags* pWaitDstStageMask
162		1u,															//uint32_t commandBufferCount
163		&firstbuffer.get(),							//const VkCommandBuffer* pCommandBuffers
164		1,															//uint32_t signalSemaphoreCount
165		&semaphore.get()								//const VkSemaphore* pSignalSemaphores
166	};
167
168	//check if waiting on an event in the none stage works as expected
169	VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_NONE_KHR};
170
171	const VkSubmitInfo secondSubmitInfo {
172		VK_STRUCTURE_TYPE_SUBMIT_INFO,  //VkStructureType sType
173		DE_NULL,												//const void* pNext
174		1u,															//uint32_t waitSemaphoreCount
175		&semaphore.get(),								//const VkSemaphore* pWaitSemaphores
176		waitStages,											//const VkPipelineStageFlags* pWaitDstStageMask
177		1u,															//uint32_t commandBufferCount
178		&secondBuffer.get(),							//const VkCommandBuffer* pCommandBuffers
179		0,															//uint32_t signalSemaphoreCount
180		DE_NULL													//const VkSemaphore* pSignalSemaphores
181	};
182
183	VK_CHECK(vk.beginCommandBuffer(*secondBuffer, &info));
184	vk.cmdSetEvent(*secondBuffer, event.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
185	endCommandBuffer(vk, *secondBuffer);
186
187	VK_CHECK(vk.queueSubmit(queue, 1, &firstSubmitInfo,  fence1.get()));
188	VK_CHECK(vk.queueSubmit(queue, 1, &secondSubmitInfo, fence2.get()));
189	VK_CHECK(vk.queueWaitIdle(queue));
190
191	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence1.get(), DE_TRUE, FENCE_WAIT))
192		return tcu::TestStatus::fail("None stage test failed, failed to wait for fence");
193
194	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence2.get(), DE_TRUE, FENCE_WAIT))
195		return tcu::TestStatus::fail("None stage test failed, failed to wait for the second fence");
196
197	if (vk.getEventStatus(device, event.get()) != VK_EVENT_SET)
198		return tcu::TestStatus::fail("None stage test failed, event isn't set");
199
200	return tcu::TestStatus::pass("Pass");
201}
202
203tcu::TestStatus basicChainCase(Context & context, TestConfig config)
204{
205	VkResult								err							= VK_SUCCESS;
206	de::MovePtr<VideoDevice>				videoDevice					(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
207	const DeviceInterface&					vk							= getSyncDeviceInterface(videoDevice, context);
208	const VkDevice							device						= getSyncDevice(videoDevice, context);
209	const VkQueue							queue						= getSyncQueue(videoDevice, context);
210	VkSemaphoreCreateInfo					sci							= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
211	VkFenceCreateInfo						fci							= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
212	VkFence									fence;
213	std::vector<VkSemaphoreSubmitInfoKHR>	waitSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
214	std::vector<VkSemaphoreSubmitInfoKHR>	signalSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
215	VkSemaphoreSubmitInfoKHR*				pWaitSemaphoreInfo			= DE_NULL;
216	VkSemaphoreSubmitInfoKHR*				pSignalSemaphoreInfo		= signalSemaphoreSubmitInfos.data();
217
218	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
219	{
220		if (i % (basicChainLength/4) == 0) context.getTestContext().touchWatchdog();
221
222		err = vk.createSemaphore(device, &sci, DE_NULL, &pSignalSemaphoreInfo->semaphore);
223		if (err != VK_SUCCESS)
224			continue;
225
226		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
227		synchronizationWrapper->addSubmitInfo(
228			!!pWaitSemaphoreInfo,						// deUint32								waitSemaphoreInfoCount
229			pWaitSemaphoreInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
230			0u,											// deUint32								commandBufferInfoCount
231			DE_NULL,									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
232			1u,											// deUint32								signalSemaphoreInfoCount
233			pSignalSemaphoreInfo						// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
234		);
235
236		err = synchronizationWrapper->queueSubmit(queue, 0);
237		pWaitSemaphoreInfo				= &waitSemaphoreSubmitInfos[i];
238		pWaitSemaphoreInfo->semaphore	= pSignalSemaphoreInfo->semaphore;
239		pSignalSemaphoreInfo++;
240	}
241
242
243	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
244
245	{
246		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
247		synchronizationWrapper->addSubmitInfo(1, pWaitSemaphoreInfo, 0, DE_NULL, 0, DE_NULL);
248		VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
249	}
250
251	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
252	vk.destroyFence(device, fence, DE_NULL);
253
254	for (const auto& s : signalSemaphoreSubmitInfos)
255		vk.destroySemaphore(device, s.semaphore, DE_NULL);
256
257	if (err == VK_SUCCESS)
258		return tcu::TestStatus::pass("Basic semaphore chain test passed");
259
260	return tcu::TestStatus::fail("Basic semaphore chain test failed");
261}
262
263tcu::TestStatus basicChainTimelineCase (Context& context, TestConfig config)
264{
265	VkResult					err			= VK_SUCCESS;
266	de::MovePtr<VideoDevice>	videoDevice	(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
267	const DeviceInterface&		vk			= getSyncDeviceInterface(videoDevice, context);
268	const VkDevice				device		= getSyncDevice(videoDevice, context);
269	const VkQueue				queue		= getSyncQueue(videoDevice, context);
270	VkSemaphoreTypeCreateInfo	scti		= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE, 0 };
271	VkSemaphoreCreateInfo		sci			= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
272	VkFenceCreateInfo			fci			= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
273	VkSemaphore					semaphore;
274	VkFence						fence;
275
276	VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore));
277
278	std::vector<VkSemaphoreSubmitInfoKHR>	waitSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
279	std::vector<VkSemaphoreSubmitInfoKHR>	signalSemaphoreSubmitInfos	(basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
280	VkSemaphoreSubmitInfoKHR*				pWaitSemaphoreInfo			= DE_NULL;
281	VkSemaphoreSubmitInfoKHR*				pSignalSemaphoreInfo		= signalSemaphoreSubmitInfos.data();
282
283	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
284	{
285		if (i % (basicChainLength/4) == 0) context.getTestContext().touchWatchdog();
286
287		pSignalSemaphoreInfo->value = static_cast<deUint64>(i+1);
288
289		SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
290		synchronizationWrapper->addSubmitInfo(
291			!!pWaitSemaphoreInfo,					// deUint32								waitSemaphoreInfoCount
292			pWaitSemaphoreInfo,						// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
293			0u,										// deUint32								commandBufferInfoCount
294			DE_NULL,								// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
295			1u,										// deUint32								signalSemaphoreInfoCount
296			pSignalSemaphoreInfo,					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
297			!!pWaitSemaphoreInfo,
298			DE_TRUE
299		);
300
301		err = synchronizationWrapper->queueSubmit(queue, 0);
302
303		pWaitSemaphoreInfo			= &waitSemaphoreSubmitInfos[i];
304		pWaitSemaphoreInfo->value	= static_cast<deUint64>(i);
305		pSignalSemaphoreInfo++;
306	}
307
308	pWaitSemaphoreInfo->value = basicChainLength;
309	SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
310	synchronizationWrapper->addSubmitInfo(
311		1u,											// deUint32								waitSemaphoreInfoCount
312		pWaitSemaphoreInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
313		0u,											// deUint32								commandBufferInfoCount
314		DE_NULL,									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
315		0u,											// deUint32								signalSemaphoreInfoCount
316		DE_NULL,									// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
317		DE_TRUE
318	);
319
320	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
321	VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
322	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
323
324	vk.destroyFence(device, fence, DE_NULL);
325	vk.destroySemaphore(device, semaphore, DE_NULL);
326
327	if (err == VK_SUCCESS)
328		return tcu::TestStatus::pass("Basic semaphore chain test passed");
329
330	return tcu::TestStatus::fail("Basic semaphore chain test failed");
331}
332
333tcu::TestStatus basicThreadTimelineCase(Context& context, TestConfig config)
334{
335	const VkSemaphoreTypeCreateInfo		scti			= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE, 0 };
336	de::MovePtr<VideoDevice>			videoDevice		(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
337	const DeviceInterface&				vk				= getSyncDeviceInterface(videoDevice, context);
338	const VkDevice						device			= getSyncDevice(videoDevice, context);
339	const VkSemaphoreCreateInfo			sci				= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
340	const VkFenceCreateInfo				fci				= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
341	const vk::Unique<vk::VkSemaphore>	semaphore		(createSemaphore(vk, device, &sci));
342	const Unique<VkFence>				fence			(createFence(vk, device, &fci));
343	const deUint64						waitTimeout		= 50ull * 1000000ull;		// miliseconds
344	VkResult							threadResult	= VK_SUCCESS;
345
346	// helper creating VkSemaphoreSignalInfo
347	auto makeSemaphoreSignalInfo = [&semaphore](deUint64 value) -> VkSemaphoreSignalInfo
348	{
349		return
350		{
351			VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,		// VkStructureType				sType
352			DE_NULL,										// const void*					pNext
353			*semaphore,										// VkSemaphore					semaphore
354			value											// deUint64						value
355		};
356	};
357
358	// helper creating VkSemaphoreWaitInfo
359	auto makeSemaphoreWaitInfo = [&semaphore](deUint64* valuePtr) -> VkSemaphoreWaitInfo
360	{
361		return
362		{
363			VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,			// VkStructureType				sType
364			DE_NULL,										// const void*					pNext
365			VK_SEMAPHORE_WAIT_ANY_BIT,						// VkSemaphoreWaitFlags			flags;
366			1u,												// deUint32						semaphoreCount;
367			&*semaphore,									// const VkSemaphore*			pSemaphores;
368			valuePtr										// const deUint64*				pValues;
369		};
370	};
371
372	// start thread - semaphore has value 0
373	de::MovePtr<std::thread> thread(new std::thread([=, &vk, &threadResult]
374	{
375		// wait till semaphore has value 1
376		deUint64 waitValue = 1;
377		VkSemaphoreWaitInfo waitOne = makeSemaphoreWaitInfo(&waitValue);
378		threadResult = vk.waitSemaphores(device, &waitOne, waitTimeout);
379
380		if (threadResult == VK_SUCCESS)
381		{
382			// signal semaphore with value 2
383			VkSemaphoreSignalInfo signalTwo = makeSemaphoreSignalInfo(2);
384			threadResult = vk.signalSemaphore(device, &signalTwo);
385		}
386	}));
387
388	// wait some time to give thread chance to start
389	deSleep(1);		// milisecond
390
391	// signal semaphore with value 1
392	VkSemaphoreSignalInfo signalOne = makeSemaphoreSignalInfo(1);
393	vk.signalSemaphore(device, &signalOne);
394
395	// wait till semaphore has value 2
396	deUint64				waitValue	= 2;
397	VkSemaphoreWaitInfo		waitTwo		= makeSemaphoreWaitInfo(&waitValue);
398	VkResult				mainResult	= vk.waitSemaphores(device, &waitTwo, waitTimeout);
399
400	thread->join();
401
402	if (mainResult == VK_SUCCESS)
403		return tcu::TestStatus::pass("Pass");
404
405	if ((mainResult == VK_TIMEOUT) || (threadResult == VK_TIMEOUT))
406		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Reached wait timeout");
407
408	return tcu::TestStatus::fail("Fail");
409}
410
411VkResult basicWaitForTimelineValueHelper(Context& context, TestConfig config, VkSemaphoreWaitFlags wait_flags, deUint64 signal_value, deUint64 wait_value) {
412	const VkSemaphoreTypeCreateInfo		scti			= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE, 0 };
413	de::MovePtr<VideoDevice>			videoDevice		(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
414	const DeviceInterface&				vk				= getSyncDeviceInterface(videoDevice, context);
415	const VkDevice						device			= getSyncDevice(videoDevice, context);
416	const VkSemaphoreCreateInfo			sci				= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
417	const VkFenceCreateInfo				fci				= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
418	const vk::Unique<vk::VkSemaphore>	semaphore		(createSemaphore(vk, device, &sci));
419	const Unique<VkFence>				fence			(createFence(vk, device, &fci));
420	const deUint64						waitTimeout		= 0;		// return immediately
421
422	// helper creating VkSemaphoreSignalInfo
423	auto makeSemaphoreSignalInfo = [&semaphore](deUint64 value) -> VkSemaphoreSignalInfo
424	{
425		return
426		{
427			VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,		// VkStructureType				sType
428			DE_NULL,										// const void*					pNext
429			*semaphore,										// VkSemaphore					semaphore
430			value											// deUint64						value
431		};
432	};
433
434	// helper creating VkSemaphoreWaitInfo
435	auto makeSemaphoreWaitInfo = [&semaphore](VkSemaphoreWaitFlags flags, deUint64* valuePtr) -> VkSemaphoreWaitInfo
436	{
437		return
438		{
439			VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,			// VkStructureType				sType
440			DE_NULL,										// const void*					pNext
441			flags,											// VkSemaphoreWaitFlags			flags;
442			1u,												// deUint32						semaphoreCount;
443			&*semaphore,									// const VkSemaphore*			pSemaphores;
444			valuePtr										// const deUint64*				pValues;
445		};
446	};
447
448	VkSemaphoreSignalInfo signalTheValue = makeSemaphoreSignalInfo(signal_value);
449	vk.signalSemaphore(device, &signalTheValue);
450
451    VkSemaphoreWaitInfo waitForTheValue = makeSemaphoreWaitInfo(wait_flags, &wait_value);
452    return vk.waitSemaphores(device, &waitForTheValue, waitTimeout);
453}
454
455tcu::TestStatus basicWaitForAnyCurrentTimelineValueCase(Context& context, TestConfig config)
456{
457  VkResult mainResult = basicWaitForTimelineValueHelper(context, config, VK_SEMAPHORE_WAIT_ANY_BIT, 1, 1);
458  if (mainResult == VK_SUCCESS)
459    return tcu::TestStatus::pass("Pass");
460
461  return tcu::TestStatus::fail("Fail");
462}
463
464tcu::TestStatus basicWaitForAnyLesserTimelineValueCase(Context& context, TestConfig config)
465{
466  VkResult mainResult = basicWaitForTimelineValueHelper(context, config, VK_SEMAPHORE_WAIT_ANY_BIT, 4, 1);
467  if (mainResult == VK_SUCCESS)
468    return tcu::TestStatus::pass("Pass");
469
470  return tcu::TestStatus::fail("Fail");
471}
472
473tcu::TestStatus basicWaitForAllCurrentTimelineValueCase(Context& context, TestConfig config)
474{
475  VkResult mainResult = basicWaitForTimelineValueHelper(context, config, 0, 1, 1);
476  if (mainResult == VK_SUCCESS)
477    return tcu::TestStatus::pass("Pass");
478
479  return tcu::TestStatus::fail("Fail");
480}
481
482tcu::TestStatus basicWaitForAllLesserTimelineValueCase(Context& context, TestConfig config)
483{
484  VkResult mainResult = basicWaitForTimelineValueHelper(context, config, 0, 4, 1);
485  if (mainResult == VK_SUCCESS)
486    return tcu::TestStatus::pass("Pass");
487
488  return tcu::TestStatus::fail("Fail");
489}
490
491tcu::TestStatus basicMultiQueueCase (Context& context, TestConfig config)
492{
493	enum { NO_MATCH_FOUND = ~((deUint32)0) };
494	enum QueuesIndexes { FIRST = 0, SECOND, COUNT };
495
496	struct Queues
497	{
498		VkQueue		queue;
499		deUint32	queueFamilyIndex;
500	};
501
502#ifndef CTS_USES_VULKANSC
503	const VkInstance								instance						= context.getInstance();
504	const InstanceInterface&						instanceInterface				= context.getInstanceInterface();
505	const VkPhysicalDevice							physicalDevice					= context.getPhysicalDevice();
506	de::MovePtr<VideoDevice>						videoDevice						(config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
507	const DeviceInterface&							vk								= getSyncDeviceInterface(videoDevice, context);
508	std::vector<VkQueueFamilyVideoPropertiesKHR>	videoQueueFamilyProperties2;
509#else
510	const CustomInstance							instance						(createCustomInstanceFromContext(context));
511	const InstanceDriver&							instanceDriver					(instance.getDriver());
512	const VkPhysicalDevice							physicalDevice					= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
513	const InstanceInterface&						instanceInterface				= instanceDriver;
514//	const DeviceInterface&							vk								= context.getDeviceInterface();
515//	const InstanceInterface&						instance						= context.getInstanceInterface();
516//	const VkPhysicalDevice							physicalDevice					= context.getPhysicalDevice();
517#endif // CTS_USES_VULKANSC
518	vk::Move<vk::VkDevice>							logicalDevice;
519	std::vector<VkQueueFamilyProperties>			queueFamilyProperties;
520	std::vector<VkQueueFamilyProperties2>			queueFamilyProperties2;
521	VkDeviceCreateInfo								deviceInfo;
522	VkPhysicalDeviceFeatures						deviceFeatures;
523	const float										queuePriorities[COUNT]	= { 1.0f, 1.0f };
524	VkDeviceQueueCreateInfo							queueInfos[COUNT];
525	Queues											queues[COUNT] =
526	{
527		{DE_NULL, (deUint32)NO_MATCH_FOUND},
528		{DE_NULL, (deUint32)NO_MATCH_FOUND}
529	};
530	const VkCommandBufferBeginInfo			info =
531	{
532		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
533		DE_NULL,										// const void*                              pNext;
534		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
535		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
536	};
537
538	const bool								isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
539
540	if (config.videoCodecOperationFlags != 0)
541	{
542#ifndef CTS_USES_VULKANSC
543		uint32_t	queueFamilyPropertiesCount	= 0;
544
545		instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
546
547		if (queueFamilyPropertiesCount > 0)
548		{
549			queueFamilyProperties2.resize(queueFamilyPropertiesCount);
550			videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
551
552			for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
553			{
554				queueFamilyProperties2[ndx].sType						= vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
555				queueFamilyProperties2[ndx].pNext						= &videoQueueFamilyProperties2[ndx];
556				videoQueueFamilyProperties2[ndx].sType					= vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
557				videoQueueFamilyProperties2[ndx].pNext					= DE_NULL;
558				videoQueueFamilyProperties2[ndx].videoCodecOperations	= 0;
559			}
560
561			instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, queueFamilyProperties2.data());
562
563			if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
564				TCU_FAIL("Device returns less queue families than initially reported");
565
566			queueFamilyProperties.reserve(queueFamilyPropertiesCount);
567
568			for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
569				queueFamilyProperties.push_back(queueFamilyProperties2[ndx].queueFamilyProperties);
570		}
571#endif // CTS_USES_VULKANSC
572	}
573	else
574	{
575		queueFamilyProperties	= getPhysicalDeviceQueueFamilyProperties(instanceInterface, physicalDevice);
576	}
577
578	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
579	{
580#ifndef CTS_USES_VULKANSC
581		const bool usableQueue	=  videoQueueFamilyProperties2.empty()
582								|| (videoQueueFamilyProperties2[queueNdx].videoCodecOperations & config.videoCodecOperationFlags) != 0;
583
584		if (!usableQueue)
585			continue;
586#endif // CTS_USES_VULKANSC
587
588		if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
589			queues[FIRST].queueFamilyIndex = queueNdx;
590
591		if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
592		{
593			queues[SECOND].queueFamilyIndex = queueNdx;
594			break;
595		}
596	}
597
598	if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
599		TCU_THROW(NotSupportedError, "Queues couldn't be created");
600
601	for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
602	{
603		VkDeviceQueueCreateInfo queueInfo;
604		deMemset(&queueInfo, 0, sizeof(queueInfo));
605
606		queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
607		queueInfo.pNext = DE_NULL;
608		queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
609		queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
610		queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
611		queueInfo.pQueuePriorities = queuePriorities;
612
613		queueInfos[queueNdx] = queueInfo;
614
615		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
616			break;
617	}
618
619	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
620	instanceInterface.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
621
622	VkPhysicalDeviceFeatures2					createPhysicalFeature		{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, deviceFeatures };
623	VkPhysicalDeviceTimelineSemaphoreFeatures	timelineSemaphoreFeatures	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE };
624	VkPhysicalDeviceSynchronization2FeaturesKHR	synchronization2Features	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE };
625	void**										nextPtr						= &createPhysicalFeature.pNext;
626
627	std::vector<const char*> deviceExtensions;
628
629	if (config.videoCodecOperationFlags != 0)
630		VideoDevice::addVideoDeviceExtensions(deviceExtensions, context.getUsedApiVersion(), VideoDevice::getQueueFlags(config.videoCodecOperationFlags), config.videoCodecOperationFlags);
631
632	if (isTimelineSemaphore)
633	{
634		if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_timeline_semaphore"))
635			deviceExtensions.push_back("VK_KHR_timeline_semaphore");
636		addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
637	}
638	if (config.type == SynchronizationType::SYNCHRONIZATION2)
639	{
640		deviceExtensions.push_back("VK_KHR_synchronization2");
641		addToChainVulkanStructure(&nextPtr, synchronization2Features);
642	}
643
644	void* pNext												= &createPhysicalFeature;
645#ifdef CTS_USES_VULKANSC
646	VkDeviceObjectReservationCreateInfo memReservationInfo	= context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
647	memReservationInfo.pNext								= pNext;
648	pNext													= &memReservationInfo;
649
650	VkPhysicalDeviceVulkanSC10Features sc10Features			= createDefaultSC10Features();
651	sc10Features.pNext										= pNext;
652	pNext													= &sc10Features;
653
654	VkPipelineCacheCreateInfo			pcCI;
655	std::vector<VkPipelinePoolSize>		poolSizes;
656	if (context.getTestContext().getCommandLine().isSubProcess())
657	{
658		if (context.getResourceInterface()->getCacheDataSize() > 0)
659		{
660			pcCI =
661			{
662				VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,		// VkStructureType				sType;
663				DE_NULL,											// const void*					pNext;
664				VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
665					VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
666				context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
667				context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
668			};
669			memReservationInfo.pipelineCacheCreateInfoCount		= 1;
670			memReservationInfo.pPipelineCacheCreateInfos		= &pcCI;
671		}
672
673		poolSizes							= context.getResourceInterface()->getPipelinePoolSizes();
674		if (!poolSizes.empty())
675		{
676			memReservationInfo.pipelinePoolSizeCount			= deUint32(poolSizes.size());
677			memReservationInfo.pPipelinePoolSizes				= poolSizes.data();
678		}
679	}
680#endif // CTS_USES_VULKANSC
681
682	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
683	deviceInfo.pNext					= pNext;
684	deviceInfo.enabledExtensionCount	= static_cast<deUint32>(deviceExtensions.size());
685	deviceInfo.ppEnabledExtensionNames	= deviceExtensions.empty() ? DE_NULL : deviceExtensions.data();
686	deviceInfo.enabledLayerCount		= 0u;
687	deviceInfo.ppEnabledLayerNames		= DE_NULL;
688	deviceInfo.pEnabledFeatures			= 0u;
689	deviceInfo.queueCreateInfoCount		= (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
690	deviceInfo.pQueueCreateInfos		= queueInfos;
691
692	logicalDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instance, instanceInterface, physicalDevice, &deviceInfo);
693
694#ifndef CTS_USES_VULKANSC
695	de::MovePtr<vk::DeviceDriver>								deviceDriver	= de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instance, *logicalDevice, context.getUsedApiVersion()));
696#else
697	de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>	deviceDriver	= de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instance, *logicalDevice, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(), context.getUsedApiVersion()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *logicalDevice));
698	const DeviceInterface&										vk				= *deviceDriver;
699#endif // CTS_USES_VULKANSC
700
701	for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
702	{
703		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
704			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
705		else
706			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
707	}
708
709	Move<VkSemaphore>						semaphore;
710	Move<VkCommandPool>						cmdPool[COUNT];
711	Move<VkCommandBuffer>					cmdBuffer[COUNT];
712	deUint64								timelineValues[COUNT] = { 1ull, 2ull };
713	Move<VkFence>							fence[COUNT];
714
715	semaphore			= (createTestSemaphore(context, vk, *logicalDevice, config));
716	cmdPool[FIRST]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
717	cmdPool[SECOND]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
718	cmdBuffer[FIRST]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
719	cmdBuffer[SECOND]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
720
721	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
722	endCommandBuffer(vk, *cmdBuffer[FIRST]);
723	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
724	endCommandBuffer(vk, *cmdBuffer[SECOND]);
725
726	fence[FIRST] = (createFence(vk, *logicalDevice));
727	fence[SECOND] = (createFence(vk, *logicalDevice));
728
729	VkCommandBufferSubmitInfoKHR commandBufferInfo[]
730	{
731		makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]),
732		makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND])
733	};
734
735	VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[]
736	{
737		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR),
738		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)
739	};
740	VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
741		makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
742
743	{
744		SynchronizationWrapperPtr synchronizationWrapper[]
745		{
746			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
747			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
748		};
749		synchronizationWrapper[FIRST]->addSubmitInfo(
750			0u,													// deUint32								waitSemaphoreInfoCount
751			DE_NULL,											// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
752			1u,													// deUint32								commandBufferInfoCount
753			&commandBufferInfo[FIRST],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
754			1u,													// deUint32								signalSemaphoreInfoCount
755			&signalSemaphoreSubmitInfo[FIRST],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
756			DE_FALSE,
757			isTimelineSemaphore
758		);
759		synchronizationWrapper[SECOND]->addSubmitInfo(
760			1u,													// deUint32								waitSemaphoreInfoCount
761			&waitSemaphoreSubmitInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
762			1u,													// deUint32								commandBufferInfoCount
763			&commandBufferInfo[SECOND],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
764			1u,													// deUint32								signalSemaphoreInfoCount
765			&signalSemaphoreSubmitInfo[SECOND],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
766			isTimelineSemaphore,
767			isTimelineSemaphore
768		);
769		VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
770		VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
771	}
772
773	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
774		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
775
776	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
777		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
778
779	if (isTimelineSemaphore)
780	{
781		signalSemaphoreSubmitInfo[FIRST].value	= 3ull;
782		signalSemaphoreSubmitInfo[SECOND].value	= 4ull;
783		waitSemaphoreSubmitInfo.value			= 3ull;
784	}
785
786	// swap semaphore info compared to above submits
787	{
788		SynchronizationWrapperPtr synchronizationWrapper[]
789		{
790			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
791			getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
792		};
793		synchronizationWrapper[FIRST]->addSubmitInfo(
794			1u,													// deUint32								waitSemaphoreInfoCount
795			&waitSemaphoreSubmitInfo,							// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
796			1u,													// deUint32								commandBufferInfoCount
797			&commandBufferInfo[FIRST],							// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
798			1u,													// deUint32								signalSemaphoreInfoCount
799			&signalSemaphoreSubmitInfo[SECOND],					// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
800			isTimelineSemaphore,
801			isTimelineSemaphore
802		);
803		synchronizationWrapper[SECOND]->addSubmitInfo(
804			isTimelineSemaphore ? 0u : 1u,								// deUint32								waitSemaphoreInfoCount
805			isTimelineSemaphore ? DE_NULL : &waitSemaphoreSubmitInfo,	// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
806			1u,															// deUint32								commandBufferInfoCount
807			&commandBufferInfo[SECOND],									// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
808			1u,															// deUint32								signalSemaphoreInfoCount
809			&signalSemaphoreSubmitInfo[FIRST],							// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
810			DE_FALSE,
811			isTimelineSemaphore
812		);
813
814		VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
815		VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
816		VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
817		VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
818	}
819
820	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
821		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
822
823	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
824		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
825
826	return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
827}
828
829void checkSupport (Context& context, TestConfig config)
830{
831	if (config.videoCodecOperationFlags != 0)
832		VideoDevice::checkSupport(context, config.videoCodecOperationFlags);
833
834	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
835		context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
836
837	if (config.type == SynchronizationType::SYNCHRONIZATION2)
838		context.requireDeviceFunctionality("VK_KHR_synchronization2");
839}
840
841void checkCommandBufferSimultaneousUseSupport (Context& context, TestConfig config)
842{
843	checkSupport(context, config);
844
845#ifdef CTS_USES_VULKANSC
846	if (context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
847		TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
848#endif
849}
850
851} // anonymous
852
853tcu::TestCaseGroup* createBasicBinarySemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type, VideoCodecOperationFlags videoCodecOperationFlags)
854{
855	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore"));
856
857	TestConfig config =
858	{
859		0,
860		VK_SEMAPHORE_TYPE_BINARY,
861		type,
862		videoCodecOperationFlags,
863	};
864	for (deUint32 typedCreate = 0; typedCreate < 2; typedCreate++)
865	{
866		config.useTypeCreate = (typedCreate != 0);
867		const std::string createName = config.useTypeCreate ? "_typed" : "";
868
869		// Basic binary semaphore tests with one queue
870		addFunctionCase(basicTests.get(), "one_queue" + createName, checkCommandBufferSimultaneousUseSupport,	basicOneQueueCase, config);
871		// Basic binary semaphore tests with multi queue
872		addFunctionCase(basicTests.get(), "multi_queue" + createName, checkCommandBufferSimultaneousUseSupport,	basicMultiQueueCase, config);
873	}
874
875	if (type == SynchronizationType::SYNCHRONIZATION2)
876		// Test waiting on the none pipeline stage
877		addFunctionCase(basicTests.get(), "none_wait_submit", checkCommandBufferSimultaneousUseSupport, noneWaitSubmitTest, config);
878
879	// Binary semaphore chain test
880	addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainCase, config);
881
882	return basicTests.release();
883}
884
885tcu::TestCaseGroup* createBasicTimelineSemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type, VideoCodecOperationFlags videoCodecOperationFlags)
886{
887	// Basic timeline semaphore tests
888	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore"));
889	const TestConfig				config =
890	{
891		true,
892		VK_SEMAPHORE_TYPE_TIMELINE,
893		type,
894		videoCodecOperationFlags,
895	};
896
897	// Basic timeline semaphore tests with one queue
898	addFunctionCase(basicTests.get(), "one_queue", checkCommandBufferSimultaneousUseSupport,	basicOneQueueCase, config);
899	// Basic timeline semaphore tests with multi queue
900	addFunctionCase(basicTests.get(), "multi_queue", checkCommandBufferSimultaneousUseSupport,	basicMultiQueueCase, config);
901	// Timeline semaphore chain test
902	addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainTimelineCase, config);
903
904	// dont repeat this test for synchronization2
905	if (type == SynchronizationType::LEGACY) {
906		// Timeline semaphore used by two threads
907		addFunctionCase(basicTests.get(), "two_threads", checkSupport, basicThreadTimelineCase, config);
908		// Wait for the currently signalled timeline semaphore value (wait for any)
909		addFunctionCase(basicTests.get(), "wait_for_any_current_value", checkSupport, basicWaitForAnyCurrentTimelineValueCase, config);
910		// Wait for a value less than the currently signalled timeline semaphore value (wait for any)
911		addFunctionCase(basicTests.get(), "wait_for_any_lesser_value", checkSupport, basicWaitForAnyLesserTimelineValueCase, config);
912		// Wait for the currently signalled timeline semaphore value (wait for all)
913		addFunctionCase(basicTests.get(), "wait_for_all_current_value", checkSupport, basicWaitForAllCurrentTimelineValueCase, config);
914		// Wait for a value less than the currently signalled timeline semaphore value (wait for all)
915		addFunctionCase(basicTests.get(), "wait_for_all_lesser_value", checkSupport, basicWaitForAllLesserTimelineValueCase, config);
916    }
917
918	return basicTests.release();
919}
920
921} // synchronization
922} // vkt
923