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 #include "vkRef.hpp"
31 #include "vkCmdUtil.hpp"
32 
33 namespace vkt
34 {
35 namespace synchronization
36 {
37 namespace
38 {
39 
40 using namespace vk;
41 #define SHORT_FENCE_WAIT	1000ull
42 #define LONG_FENCE_WAIT		~0ull
43 
hostResetSetEventCase(Context & context)44 tcu::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 
deviceResetSetEventCase(Context & context)80 tcu::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 
deviceWaitForEventCase(Context & context)125 tcu::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 
singleSubmissionCase(Context & context)171 tcu::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 
multiSubmissionCase(Context & context)211 tcu::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 
secondaryCommandBufferCase(Context & context)271 tcu::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 
createBasicEventTests(tcu::TestContext & testCtx)345 tcu::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