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