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 event basic tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSynchronizationBasicEventTests.hpp"
25#include "vktTestCaseUtil.hpp"
26#include "vktSynchronizationUtil.hpp"
27
28#include "vkDefs.hpp"
29#include "vkPlatform.hpp"
30
31#include "vkRef.hpp"
32
33namespace vkt
34{
35namespace synchronization
36{
37namespace
38{
39
40using namespace vk;
41#define SHORT_FENCE_WAIT	1000ull
42#define LONG_FENCE_WAIT		~0ull
43
44tcu::TestStatus hostResetSetEventCase (Context& context)
45{
46	const DeviceInterface&		vk			= context.getDeviceInterface();
47	const VkDevice				device		= context.getDevice();
48	const VkEventCreateInfo		eventInfo	=
49											{
50												VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
51												DE_NULL,
52												0
53											};
54	VkEvent						event;
55	Move<VkEvent>				ptrEvent;
56
57	if (VK_SUCCESS != vk.createEvent(device, &eventInfo, DE_NULL, &event))
58		return tcu::TestStatus::fail("Couldn't create event");
59
60	ptrEvent = Move<VkEvent>(check<VkEvent>(event), Deleter<VkEvent>(vk, device, DE_NULL));
61
62	if (VK_EVENT_RESET != vk.getEventStatus(device, event))
63		return tcu::TestStatus::fail("Created event should be in unsignaled state");
64
65	if (VK_SUCCESS != vk.setEvent(device, event))
66		return tcu::TestStatus::fail("Couldn't set event");
67
68	if (VK_EVENT_SET != vk.getEventStatus(device, event))
69		return tcu::TestStatus::fail("Event should be in signaled state after set");
70
71	if (VK_SUCCESS != vk.resetEvent(device, event))
72		return tcu::TestStatus::fail("Couldn't reset event");
73
74	if (VK_EVENT_RESET != vk.getEventStatus(device, event))
75		return tcu::TestStatus::fail("Event should be in unsignaled state after reset");
76
77	return tcu::TestStatus::pass("Tests set and reset event on host pass");
78}
79
80tcu::TestStatus deviceResetSetEventCase (Context& context)
81{
82	const DeviceInterface&			vk					= context.getDeviceInterface();
83	const VkDevice					device				= context.getDevice();
84	const VkQueue					queue				= context.getUniversalQueue();
85	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
86	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
87	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
88	const VkSubmitInfo				submitInfo			=
89														{
90															VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
91															DE_NULL,						// const void*					pNext;
92															0u,								// deUint32						waitSemaphoreCount;
93															DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
94															DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
95															1u,								// deUint32						commandBufferCount;
96															&cmdBuffer.get(),				// const VkCommandBuffer*		pCommandBuffers;
97															0u,								// deUint32						signalSemaphoreCount;
98															DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
99														};
100	const Unique<VkEvent>			event				(createEvent(vk, device));
101
102	beginCommandBuffer(vk, *cmdBuffer);
103	vk.cmdSetEvent(*cmdBuffer, *event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
104	endCommandBuffer(vk, *cmdBuffer);
105
106	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
107	VK_CHECK(vk.queueWaitIdle(queue));
108
109	if (VK_EVENT_SET != vk.getEventStatus(device, *event))
110		return tcu::TestStatus::fail("Event should be in signaled state after set");
111
112	beginCommandBuffer(vk, *cmdBuffer);
113	vk.cmdResetEvent(*cmdBuffer, *event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
114	endCommandBuffer(vk, *cmdBuffer);
115
116	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
117	VK_CHECK(vk.queueWaitIdle(queue));
118
119	if (VK_EVENT_RESET != vk.getEventStatus(device, *event))
120		return tcu::TestStatus::fail("Event should be in unsignaled state after set");
121
122	return tcu::TestStatus::pass("Device set and reset event tests pass");
123}
124
125tcu::TestStatus deviceWaitForEventCase (Context& context)
126{
127	const DeviceInterface&			vk					= context.getDeviceInterface();
128	const VkDevice					device				= context.getDevice();
129	const VkQueue					queue				= context.getUniversalQueue();
130	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
131	const Unique<VkFence>			fence				(createFence(vk, device));
132	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
133	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
134	const VkSubmitInfo				submitInfo			=
135														{
136															VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
137															DE_NULL,						// const void*					pNext;
138															0u,								// deUint32						waitSemaphoreCount;
139															DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
140															DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
141															1u,								// deUint32						commandBufferCount;
142															&cmdBuffer.get(),				// const VkCommandBuffer*		pCommandBuffers;
143															0u,								// deUint32						signalSemaphoreCount;
144															DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
145														};
146	const VkEventCreateInfo			eventInfo			=
147														{
148															VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
149															DE_NULL,
150															0
151														};
152	const Unique<VkEvent>			event				(createEvent(vk, device, &eventInfo, DE_NULL));
153
154	beginCommandBuffer(vk, *cmdBuffer);
155	vk.cmdWaitEvents(*cmdBuffer, 1u, &event.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
156	endCommandBuffer(vk, *cmdBuffer);
157
158	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
159	if (VK_TIMEOUT != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, SHORT_FENCE_WAIT))
160		return tcu::TestStatus::fail("Queue should not end execution");
161
162	if (VK_SUCCESS != vk.setEvent(device, *event))
163		return tcu::TestStatus::fail("Couldn't set event");
164
165	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
166		return tcu::TestStatus::fail("Queue should end execution");
167
168	return tcu::TestStatus::pass("Device wait for event tests pass");
169}
170
171tcu::TestStatus singleSubmissionCase (Context& context)
172{
173	enum {SET=0, WAIT, COUNT};
174	const DeviceInterface&			vk					= context.getDeviceInterface();
175	const VkDevice					device				= context.getDevice();
176	const VkQueue					queue				= context.getUniversalQueue();
177	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
178	const Unique<VkFence>			fence				(createFence(vk, device));
179	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
180	const Move<VkCommandBuffer>		ptrCmdBuffer[COUNT]	= {makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool)};
181	VkCommandBuffer					cmdBuffers[COUNT]	= {*ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT]};
182	const VkSubmitInfo				submitInfo			=
183														{
184															VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
185															DE_NULL,						// const void*					pNext;
186															0u,								// deUint32						waitSemaphoreCount;
187															DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
188															DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
189															2u,								// deUint32						commandBufferCount;
190															cmdBuffers,						// const VkCommandBuffer*		pCommandBuffers;
191															0u,								// deUint32						signalSemaphoreCount;
192															DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
193														};
194	const Unique<VkEvent>			event				(createEvent(vk, device));
195
196	beginCommandBuffer(vk, cmdBuffers[SET]);
197	vk.cmdSetEvent(cmdBuffers[SET], *event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
198	endCommandBuffer(vk, cmdBuffers[SET]);
199
200	beginCommandBuffer(vk, cmdBuffers[WAIT]);
201	vk.cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(),VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
202	endCommandBuffer(vk, cmdBuffers[WAIT]);
203
204	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
205	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
206		return tcu::TestStatus::fail("Queue should end execution");
207
208	return tcu::TestStatus::pass("Wait and set even on device single submission tests pass");
209}
210
211tcu::TestStatus multiSubmissionCase (Context& context)
212{
213	enum {SET=0, WAIT, COUNT};
214	const DeviceInterface&			vk					= context.getDeviceInterface();
215	const VkDevice					device				= context.getDevice();
216	const VkQueue					queue				= context.getUniversalQueue();
217	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
218	const Move<VkFence>				ptrFence[COUNT]		=
219	{
220		createFence(vk, device),
221		createFence(vk, device)
222	};
223	VkFence							fence[COUNT]		= {*ptrFence[SET], *ptrFence[WAIT]};
224	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
225	const Move<VkCommandBuffer>		ptrCmdBuffer[COUNT]	= {makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool)};
226	VkCommandBuffer					cmdBuffers[COUNT]	= {*ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT]};
227	const VkSubmitInfo				submitInfo[COUNT]	=
228														{
229															{
230																VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
231																DE_NULL,						// const void*					pNext;
232																0u,								// deUint32						waitSemaphoreCount;
233																DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
234																DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
235																1u,								// deUint32						commandBufferCount;
236																&cmdBuffers[SET],				// const VkCommandBuffer*		pCommandBuffers;
237																0u,								// deUint32						signalSemaphoreCount;
238																DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
239															},
240															{
241																VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
242																DE_NULL,						// const void*					pNext;
243																0u,								// deUint32						waitSemaphoreCount;
244																DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
245																DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
246																1u,								// deUint32						commandBufferCount;
247																&cmdBuffers[WAIT],				// const VkCommandBuffer*		pCommandBuffers;
248																0u,								// deUint32						signalSemaphoreCount;
249																DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
250															}
251														};
252	const Unique<VkEvent>			event				(createEvent(vk, device));
253
254	beginCommandBuffer(vk, cmdBuffers[SET]);
255	vk.cmdSetEvent(cmdBuffers[SET], *event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
256	endCommandBuffer(vk, cmdBuffers[SET]);
257
258	beginCommandBuffer(vk, cmdBuffers[WAIT]);
259	vk.cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
260	endCommandBuffer(vk, cmdBuffers[WAIT]);
261
262	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo[SET], fence[SET]));
263	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo[WAIT], fence[WAIT]));
264
265	if (VK_SUCCESS != vk.waitForFences(device, 2u, fence, DE_TRUE, LONG_FENCE_WAIT))
266		return tcu::TestStatus::fail("Queue should end execution");
267
268	return tcu::TestStatus::pass("Wait and set even on device multi submission tests pass");
269}
270
271tcu::TestStatus secondaryCommandBufferCase (Context& context)
272{
273	enum {SET=0, WAIT, COUNT};
274	const DeviceInterface&					vk						= context.getDeviceInterface();
275	const VkDevice							device					= context.getDevice();
276	const VkQueue							queue					= context.getUniversalQueue();
277	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
278	const Unique<VkFence>					fence					(createFence(vk, device));
279	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
280	const Move<VkCommandBuffer>				primaryCmdBuffer		(makeCommandBuffer(vk, device, *cmdPool));
281	const VkCommandBufferAllocateInfo		cmdBufferInfo			=
282																	{
283																		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
284																		DE_NULL,											// const void*			pNext;
285																		*cmdPool,											// VkCommandPool		commandPool;
286																		VK_COMMAND_BUFFER_LEVEL_SECONDARY,					// VkCommandBufferLevel	level;
287																		1u,													// deUint32				commandBufferCount;
288																	};
289	const Move<VkCommandBuffer>				prtCmdBuffers[COUNT]	= {allocateCommandBuffer (vk, device, &cmdBufferInfo), allocateCommandBuffer (vk, device, &cmdBufferInfo)};
290	VkCommandBuffer							secondaryCmdBuffers[]	= {*prtCmdBuffers[SET], *prtCmdBuffers[WAIT]};
291	const VkSubmitInfo						submitInfo				=
292																	{
293																		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
294																		DE_NULL,						// const void*					pNext;
295																		0u,								// deUint32						waitSemaphoreCount;
296																		DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
297																		DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
298																		1u,								// deUint32						commandBufferCount;
299																		&primaryCmdBuffer.get(),		// const VkCommandBuffer*		pCommandBuffers;
300																		0u,								// deUint32						signalSemaphoreCount;
301																		DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
302																	};
303	const Unique<VkEvent>					event					(createEvent(vk, device));
304
305	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
306																	{
307																		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,	//VkStructureType					sType;
308																		DE_NULL,											//const void*						pNext;
309																		DE_NULL,											//VkRenderPass					renderPass;
310																		0u,													//deUint32						subpass;
311																		DE_NULL,											//VkFramebuffer					framebuffer;
312																		VK_FALSE,											//VkBool32						occlusionQueryEnable;
313																		(VkQueryControlFlags)0u,							//VkQueryControlFlags				queryFlags;
314																		(VkQueryPipelineStatisticFlags)0u,					//VkQueryPipelineStatisticFlags	pipelineStatistics;
315																	};
316	const VkCommandBufferBeginInfo			cmdBufferBeginInfo		=
317																	{
318																		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
319																		DE_NULL,										// const void*                              pNext;
320																		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags                flags;
321																		&secCmdBufInheritInfo,							// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
322																	};
323
324	VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[SET], &cmdBufferBeginInfo));
325	vk.cmdSetEvent(secondaryCmdBuffers[SET], *event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
326	endCommandBuffer(vk, secondaryCmdBuffers[SET]);
327
328	VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[WAIT], &cmdBufferBeginInfo));
329	vk.cmdWaitEvents(secondaryCmdBuffers[WAIT], 1u, &event.get(),VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
330	endCommandBuffer(vk, secondaryCmdBuffers[WAIT]);
331
332	beginCommandBuffer(vk, *primaryCmdBuffer);
333	vk.cmdExecuteCommands(*primaryCmdBuffer, 2u, secondaryCmdBuffers);
334	endCommandBuffer(vk, *primaryCmdBuffer);
335
336	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
337	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
338		return tcu::TestStatus::fail("Queue should end execution");
339
340	return tcu::TestStatus::pass("Wait and set even on device using secondary command buffers tests pass");
341}
342
343} // anonymous
344
345tcu::TestCaseGroup* createBasicEventTests (tcu::TestContext& testCtx)
346{
347	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "event", "Basic event tests"));
348	addFunctionCase(basicTests.get(), "host_set_reset",   "Basic event tests set and reset on host", hostResetSetEventCase);
349	addFunctionCase(basicTests.get(), "device_set_reset", "Basic event tests set and reset on device", deviceResetSetEventCase);
350	addFunctionCase(basicTests.get(), "host_set_device_wait", "Wait for event on device test", deviceWaitForEventCase);
351	addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer", "Wait and set event single submission on device", singleSubmissionCase);
352	addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer", "Wait and set event mutli submission on device", multiSubmissionCase);
353	addFunctionCase(basicTests.get(), "multi_secondary_command_buffer", "Event used on secondary command buffer ", secondaryCommandBufferCase);
354
355	return basicTests.release();
356}
357
358} // synchronization
359} // vkt
360