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 
28 #include "vkDefs.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 
33 
34 #include "vkRef.hpp"
35 
36 namespace vkt
37 {
38 namespace synchronization
39 {
40 namespace
41 {
42 
43 using namespace vk;
44 
45 #define FENCE_WAIT	~0ull
46 
basicOneQueueCase(Context & context)47 tcu::TestStatus basicOneQueueCase (Context& context)
48 {
49 	const DeviceInterface&			vk					= context.getDeviceInterface();
50 	const VkDevice					device				= context.getDevice();
51 	const VkQueue					queue				= context.getUniversalQueue();
52 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
53 	const Unique<VkSemaphore>		semaphore			(createSemaphore (vk, device));
54 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
55 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
56 	const VkCommandBufferBeginInfo	info				=
57 														{
58 															VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
59 															DE_NULL,										// const void*                              pNext;
60 															VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
61 															DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
62 														};
63 	const VkPipelineStageFlags		stageBits[]			= { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
64 	const VkSubmitInfo				submitInfo[2]		=
65 														{
66 															{
67 																VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType			sType;
68 																DE_NULL,							// const void*				pNext;
69 																0u,									// deUint32					waitSemaphoreCount;
70 																DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
71 																(const VkPipelineStageFlags*)DE_NULL,
72 																1u,									// deUint32					commandBufferCount;
73 																&cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
74 																1u,									// deUint32					signalSemaphoreCount;
75 																&semaphore.get(),					// const VkSemaphore*		pSignalSemaphores;
76 															},
77 															{
78 																VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType				sType;
79 																DE_NULL,							// const void*					pNext;
80 																1u,									// deUint32						waitSemaphoreCount;
81 																&semaphore.get(),					// const VkSemaphore*			pWaitSemaphores;
82 																stageBits,							// const VkPipelineStageFlags*	pWaitDstStageMask;
83 																1u,									// deUint32						commandBufferCount;
84 																&cmdBuffer.get(),					// const VkCommandBuffer*		pCommandBuffers;
85 																0u,									// deUint32						signalSemaphoreCount;
86 																DE_NULL,							// const VkSemaphore*			pSignalSemaphores;
87 															}
88 														};
89 	const Unique<VkFence>			fence				(createFence(vk, device));
90 
91 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
92 	endCommandBuffer(vk, *cmdBuffer);
93 	VK_CHECK(vk.queueSubmit(queue, 2u, submitInfo, *fence));
94 
95 	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
96 		return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
97 
98 	return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
99 }
100 
basicChainCase(Context & context)101 tcu::TestStatus basicChainCase (Context& context)
102 {
103 	VkResult					err			= VK_SUCCESS;
104 	const DeviceInterface&		vk			= context.getDeviceInterface();
105 	const VkDevice&				device		= context.getDevice();
106 	const VkQueue				queue		= context.getUniversalQueue();
107 	const int					chainLength = 32768;
108 	VkPipelineStageFlags		flags		= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
109 	VkSemaphoreCreateInfo		sci			= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
110 	VkFenceCreateInfo			fci			= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
111 	std::vector<VkSemaphore>	semaphores;
112 	VkFence						fence;
113 
114 	for (int i = 0; err == VK_SUCCESS && i < chainLength; i++)
115 	{
116 		VkSemaphore				semaphore;
117 		err = vk.createSemaphore(device, &sci, DE_NULL, &semaphore);
118 		if (err == VK_SUCCESS)
119 		{
120 			semaphores.push_back(semaphore);
121 
122 			VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
123 				DE_NULL,
124 				semaphores.size() > 1 ? 1u : 0u,
125 				semaphores.size() > 1 ? &semaphores[semaphores.size() - 2] : DE_NULL,
126 				&flags,
127 				0,
128 				DE_NULL,
129 				1,
130 				&semaphores[semaphores.size() - 1] };
131 			err = vk.queueSubmit(queue, 1, &si, 0);
132 		}
133 	}
134 
135 	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
136 
137 	VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 1, &semaphores.back(), &flags, 0, DE_NULL, 0, DE_NULL };
138 	VK_CHECK(vk.queueSubmit(queue, 1, &si, fence));
139 
140 	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
141 
142 	vk.destroyFence(device, fence, DE_NULL);
143 
144 	for (unsigned int i = 0; i < semaphores.size(); i++)
145 		vk.destroySemaphore(device, semaphores[i], DE_NULL);
146 
147 	if (err == VK_SUCCESS)
148 		return tcu::TestStatus::pass("Basic semaphore chain test passed");
149 
150 	return tcu::TestStatus::fail("Basic semaphore chain test failed");
151 }
152 
basicMultiQueueCase(Context & context)153 tcu::TestStatus basicMultiQueueCase (Context& context)
154 {
155 	enum {NO_MATCH_FOUND = ~((deUint32)0)};
156 	enum QueuesIndexes {FIRST = 0, SECOND, COUNT};
157 
158 	struct Queues
159 	{
160 		VkQueue		queue;
161 		deUint32	queueFamilyIndex;
162 	};
163 
164 
165 	const DeviceInterface&					vk							= context.getDeviceInterface();
166 	const InstanceInterface&				instance					= context.getInstanceInterface();
167 	const VkPhysicalDevice					physicalDevice				= context.getPhysicalDevice();
168 	vk::Move<vk::VkDevice>					logicalDevice;
169 	std::vector<VkQueueFamilyProperties>	queueFamilyProperties;
170 	VkDeviceCreateInfo						deviceInfo;
171 	VkPhysicalDeviceFeatures				deviceFeatures;
172 	const float								queuePriorities[COUNT]		= {1.0f, 1.0f};
173 	VkDeviceQueueCreateInfo					queueInfos[COUNT];
174 	Queues									queues[COUNT]				=
175 																		{
176 																			{DE_NULL, (deUint32)NO_MATCH_FOUND},
177 																			{DE_NULL, (deUint32)NO_MATCH_FOUND}
178 																		};
179 	const VkCommandBufferBeginInfo			info						=
180 																		{
181 																			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
182 																			DE_NULL,										// const void*                              pNext;
183 																			VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
184 																			DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
185 																		};
186 	Move<VkSemaphore>						semaphore;
187 	Move<VkCommandPool>						cmdPool[COUNT];
188 	Move<VkCommandBuffer>					cmdBuffer[COUNT];
189 	const VkPipelineStageFlags				stageBits[]					= { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
190 	VkSubmitInfo							submitInfo[COUNT];
191 	Move<VkFence>							fence[COUNT];
192 
193 	queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
194 
195 	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
196 	{
197 		if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
198 			queues[FIRST].queueFamilyIndex = queueNdx;
199 
200 		if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
201 		{
202 			queues[SECOND].queueFamilyIndex = queueNdx;
203 			break;
204 		}
205 	}
206 
207 	if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
208 		TCU_THROW(NotSupportedError, "Queues couldn't be created");
209 
210 	for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
211 	{
212 		VkDeviceQueueCreateInfo queueInfo;
213 		deMemset(&queueInfo, 0, sizeof(queueInfo));
214 
215 		queueInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
216 		queueInfo.pNext				= DE_NULL;
217 		queueInfo.flags				= (VkDeviceQueueCreateFlags)0u;
218 		queueInfo.queueFamilyIndex	= queues[queueNdx].queueFamilyIndex;
219 		queueInfo.queueCount		= (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
220 		queueInfo.pQueuePriorities	= queuePriorities;
221 
222 		queueInfos[queueNdx]		= queueInfo;
223 
224 		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
225 			break;
226 	}
227 
228 	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
229 	instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
230 
231 	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
232 	deviceInfo.pNext					= DE_NULL;
233 	deviceInfo.enabledExtensionCount	= 0u;
234 	deviceInfo.ppEnabledExtensionNames	= DE_NULL;
235 	deviceInfo.enabledLayerCount		= 0u;
236 	deviceInfo.ppEnabledLayerNames		= DE_NULL;
237 	deviceInfo.pEnabledFeatures			= &deviceFeatures;
238 	deviceInfo.queueCreateInfoCount		= (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
239 	deviceInfo.pQueueCreateInfos		= queueInfos;
240 
241 	logicalDevice = vk::createDevice(context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo);
242 
243 	for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
244 	{
245 		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
246 			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
247 		else
248 			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
249 	}
250 
251 	semaphore			= (createSemaphore (vk, *logicalDevice));
252 	cmdPool[FIRST]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
253 	cmdPool[SECOND]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
254 	cmdBuffer[FIRST]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
255 	cmdBuffer[SECOND]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
256 
257 	submitInfo[FIRST].sType					= VK_STRUCTURE_TYPE_SUBMIT_INFO;
258 	submitInfo[FIRST].pNext					= DE_NULL;
259 	submitInfo[FIRST].waitSemaphoreCount	= 0u;
260 	submitInfo[FIRST].pWaitSemaphores		= DE_NULL;
261 	submitInfo[FIRST].pWaitDstStageMask		= (const VkPipelineStageFlags*)DE_NULL;
262 	submitInfo[FIRST].commandBufferCount	= 1u;
263 	submitInfo[FIRST].pCommandBuffers		= &cmdBuffer[FIRST].get();
264 	submitInfo[FIRST].signalSemaphoreCount	= 1u;
265 	submitInfo[FIRST].pSignalSemaphores		= &semaphore.get();
266 
267 	submitInfo[SECOND].sType					= VK_STRUCTURE_TYPE_SUBMIT_INFO;
268 	submitInfo[SECOND].pNext					= DE_NULL;
269 	submitInfo[SECOND].waitSemaphoreCount		= 1u;
270 	submitInfo[SECOND].pWaitSemaphores			= &semaphore.get();
271 	submitInfo[SECOND].pWaitDstStageMask		= stageBits;
272 	submitInfo[SECOND].commandBufferCount		= 1u;
273 	submitInfo[SECOND].pCommandBuffers			= &cmdBuffer[SECOND].get();
274 	submitInfo[SECOND].signalSemaphoreCount		= 0u;
275 	submitInfo[SECOND].pSignalSemaphores		= DE_NULL;
276 
277 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
278 	endCommandBuffer(vk, *cmdBuffer[FIRST]);
279 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
280 	endCommandBuffer(vk, *cmdBuffer[SECOND]);
281 
282 	fence[FIRST]  = (createFence(vk, *logicalDevice));
283 	fence[SECOND] = (createFence(vk, *logicalDevice));
284 
285 	VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
286 	VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
287 
288 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
289 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
290 
291 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
292 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
293 
294 	{
295 		VkSubmitInfo swapInfo				= submitInfo[SECOND];
296 		submitInfo[SECOND]					= submitInfo[FIRST];
297 		submitInfo[FIRST]					= swapInfo;
298 		submitInfo[SECOND].pCommandBuffers	= &cmdBuffer[SECOND].get();
299 		submitInfo[FIRST].pCommandBuffers	= &cmdBuffer[FIRST].get();
300 	}
301 
302 	VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
303 	VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
304 
305 	VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
306 	VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
307 
308 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
309 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
310 
311 	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
312 		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
313 
314 	return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
315 }
316 
317 } // anonymous
318 
createBasicSemaphoreTests(tcu::TestContext & testCtx)319 tcu::TestCaseGroup* createBasicSemaphoreTests (tcu::TestContext& testCtx)
320 {
321 	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "semaphore", "Basic semaphore tests"));
322 	addFunctionCase(basicTests.get(), "one_queue",   "Basic semaphore tests with one queue",   basicOneQueueCase);
323 	addFunctionCase(basicTests.get(), "multi_queue", "Basic semaphore tests with multi queue", basicMultiQueueCase);
324 	addFunctionCase(basicTests.get(), "chain", "Semaphore chain test", basicChainCase);
325 
326 	return basicTests.release();
327 }
328 
329 } // synchronization
330 } // vkt
331