• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 fence basic tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSynchronizationBasicFenceTests.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 #include <vector>
34 #include <algorithm>
35 #include <iterator>
36 
37 namespace vkt
38 {
39 namespace synchronization
40 {
41 namespace
42 {
43 using namespace vk;
44 
45 static const deUint64	SHORT_FENCE_WAIT	= 1000ull;			// 1us
46 static const deUint64	LONG_FENCE_WAIT		= 1000000000ull;	// 1s
47 
basicOneFenceCase(Context & context)48 tcu::TestStatus basicOneFenceCase (Context& context)
49 {
50 	const DeviceInterface&			vk					= context.getDeviceInterface();
51 	const VkDevice					device				= context.getDevice();
52 	const VkQueue					queue				= context.getUniversalQueue();
53 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
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 
57 	const VkFenceCreateInfo			fenceInfo			=
58 	{
59 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType      sType;
60 		DE_NULL,								// const void*          pNext;
61 		0u,										// VkFenceCreateFlags   flags;
62 	};
63 
64 	const Unique<VkFence>			fence				(createFence(vk, device, &fenceInfo));
65 
66 	const VkSubmitInfo				submitInfo			=
67 	{
68 		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType                sType;
69 		DE_NULL,								// const void*                    pNext;
70 		0u,										// deUint32                       waitSemaphoreCount;
71 		DE_NULL,								// const VkSemaphore*             pWaitSemaphores;
72 		(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*    pWaitDstStageMask;
73 		1u,										// deUint32                       commandBufferCount;
74 		&cmdBuffer.get(),						// const VkCommandBuffer*         pCommandBuffers;
75 		0u,										// deUint32                       signalSemaphoreCount;
76 		DE_NULL,								// const VkSemaphore*             pSignalSemaphores;
77 	};
78 
79 	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
80 		return tcu::TestStatus::fail("Created fence should be in unsignaled state");
81 
82 	if (VK_TIMEOUT != vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, SHORT_FENCE_WAIT))
83 		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT");
84 
85 	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
86 		return tcu::TestStatus::fail("Created fence should be in unsignaled state");
87 
88 	beginCommandBuffer(vk, *cmdBuffer);
89 	endCommandBuffer(vk, *cmdBuffer);
90 
91 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
92 
93 	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
94 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
95 
96 	if (VK_SUCCESS != vk.getFenceStatus(device, *fence))
97 		return tcu::TestStatus::fail("Fence should be in signaled state");
98 
99 	if (VK_SUCCESS != vk.resetFences(device, 1u, &fence.get()))
100 		return tcu::TestStatus::fail("Couldn't reset the fence");
101 
102 	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
103 		return tcu::TestStatus::fail("Fence after reset should be in unsignaled state");
104 
105 	return tcu::TestStatus::pass("Basic one fence tests passed");
106 }
107 
basicSignaledCase(Context & context,uint32_t numFences)108 tcu::TestStatus basicSignaledCase (Context& context, uint32_t numFences)
109 {
110 	const auto&		vkd			= context.getDeviceInterface();
111 	const auto		device		= context.getDevice();
112 
113 	std::vector<Move<VkFence>> fences;
114 	fences.reserve(numFences);
115 
116 	const VkFenceCreateInfo fenceCreateInfo =
117 	{
118 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	//	VkStructureType		sType;
119 		nullptr,								//	const void*			pNext;
120 		VK_FENCE_CREATE_SIGNALED_BIT,			//	VkFenceCreateFlags	flags;
121 	};
122 
123 	for (uint32_t i = 0u; i < numFences; ++i)
124 	{
125 		fences.push_back(createFence(vkd, device, &fenceCreateInfo));
126 		if (vkd.getFenceStatus(device, fences.back().get()) != VK_SUCCESS)
127 			TCU_FAIL("Fence was not created signaled");
128 	}
129 
130 	std::vector<VkFence> rawFences;
131 	std::transform(begin(fences), end(fences), std::back_inserter(rawFences), [](const Move<VkFence>& f) { return f.get(); });
132 
133 	const auto waitResult = vkd.waitForFences(device, static_cast<uint32_t>(rawFences.size()), de::dataOrNull(rawFences), VK_TRUE, LONG_FENCE_WAIT);
134 	if (waitResult != VK_SUCCESS)
135 		TCU_FAIL("vkWaitForFences failed with exit status " + std::to_string(waitResult));
136 
137 	return tcu::TestStatus::pass("Pass");
138 }
139 
basicMultiFenceCase(Context & context)140 tcu::TestStatus basicMultiFenceCase (Context& context)
141 {
142 	enum
143 	{
144 		FIRST_FENCE = 0,
145 		SECOND_FENCE
146 	};
147 
148 	const DeviceInterface&			vk					= context.getDeviceInterface();
149 	const VkDevice					device				= context.getDevice();
150 	const VkQueue					queue				= context.getUniversalQueue();
151 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
152 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,  queueFamilyIndex));
153 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
154 
155 	const VkFenceCreateInfo			fenceInfo			=
156 	{
157 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType      sType;
158 		DE_NULL,								// const void*          pNext;
159 		0u,										// VkFenceCreateFlags   flags;
160 	};
161 
162 	const Move<VkFence>				ptrFence[2]			=
163 	{
164 		createFence(vk, device, &fenceInfo),
165 		createFence(vk, device, &fenceInfo)
166 	};
167 
168 	const VkFence					fence[2]			=
169 	{
170 		*ptrFence[FIRST_FENCE],
171 		*ptrFence[SECOND_FENCE]
172 	};
173 
174 	const VkCommandBufferBeginInfo	info				=
175 	{
176 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
177 		DE_NULL,										// const void*                              pNext;
178 		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
179 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
180 	};
181 
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 		(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*    pWaitDstStageMask;
189 		1u,										// deUint32                       commandBufferCount;
190 		&cmdBuffer.get(),						// const VkCommandBuffer*         pCommandBuffers;
191 		0u,										// deUint32                       signalSemaphoreCount;
192 		DE_NULL,								// const VkSemaphore*             pSignalSemaphores;
193 	};
194 
195 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
196 	endCommandBuffer(vk, *cmdBuffer);
197 
198 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
199 
200 	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
201 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
202 
203 	if (VK_SUCCESS != vk.resetFences(device, 1u, &fence[FIRST_FENCE]))
204 		return tcu::TestStatus::fail("Couldn't reset the fence");
205 
206 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
207 
208 	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
209 		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT");
210 
211 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));
212 
213 	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, LONG_FENCE_WAIT))
214 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
215 
216 	return tcu::TestStatus::pass("Basic multi fence tests passed");
217 }
218 
emptySubmitCase(Context & context)219 tcu::TestStatus emptySubmitCase (Context& context)
220 {
221 	const DeviceInterface&			vk					= context.getDeviceInterface();
222 	const VkDevice					device				= context.getDevice();
223 	const VkQueue					queue				= context.getUniversalQueue();
224 
225 	const VkFenceCreateInfo			fenceCreateInfo		=
226 	{
227 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType       sType;
228 		DE_NULL,								// const void*           pNext;
229 		(VkFenceCreateFlags)0,					// VkFenceCreateFlags    flags;
230 	};
231 
232 	const Unique<VkFence>			fence				(createFence(vk, device, &fenceCreateInfo));
233 
234 	VK_CHECK(vk.queueSubmit(queue, 0u, DE_NULL, *fence));
235 
236 	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
237 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
238 
239 	return tcu::TestStatus::pass("OK");
240 }
241 
basicMultiFenceWaitAllFalseCase(Context & context)242 tcu::TestStatus basicMultiFenceWaitAllFalseCase (Context& context)
243 {
244 	enum
245 	{
246 		FIRST_FENCE = 0,
247 		SECOND_FENCE
248 	};
249 
250 	const DeviceInterface&			vk					= context.getDeviceInterface();
251 	const VkDevice					device				= context.getDevice();
252 	const VkQueue					queue				= context.getUniversalQueue();
253 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
254 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
255 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
256 
257 	const VkFenceCreateInfo			fenceInfo			=
258 	{
259 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType     sType;
260 		DE_NULL,								// const void*         pNext;
261 		0u,										// VkFenceCreateFlags  flags;
262 	};
263 
264 	const Move<VkFence>				ptrFence[2]			=
265 	{
266 		createFence(vk, device, &fenceInfo),
267 		createFence(vk, device, &fenceInfo)
268 	};
269 
270 	const VkFence					fence[2]			=
271 	{
272 		*ptrFence[FIRST_FENCE],
273 		*ptrFence[SECOND_FENCE]
274 	};
275 
276 	const VkCommandBufferBeginInfo	info				=
277 	{
278 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
279 		DE_NULL,										// const void*                              pNext;
280 		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
281 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
282 	};
283 
284 	const VkSubmitInfo				submitInfo			=
285 	{
286 		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType                sType;
287 		DE_NULL,								// const void*                    pNext;
288 		0u,										// deUint32                       waitSemaphoreCount;
289 		DE_NULL,								// const VkSemaphore*             pWaitSemaphores;
290 		(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*    pWaitDstStageMask;
291 		1u,										// deUint32                       commandBufferCount;
292 		&cmdBuffer.get(),						// const VkCommandBuffer*         pCommandBuffers;
293 		0u,										// deUint32                       signalSemaphoreCount;
294 		DE_NULL,								// const VkSemaphore*             pSignalSemaphores;
295 	};
296 
297 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
298 	endCommandBuffer(vk, *cmdBuffer);
299 
300 
301 	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, SHORT_FENCE_WAIT))
302 		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for any fence (No fence has been signaled)");
303 
304 	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
305 		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (No fence has been signaled)");
306 
307 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));
308 
309 	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
310 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (Only second fence signaled)");
311 
312 	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
313 		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (Only second fence signaled)");
314 
315 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
316 
317 	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
318 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (All fences signaled)");
319 
320 	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, LONG_FENCE_WAIT))
321 		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for all fences (All fences signaled)");
322 
323 	return tcu::TestStatus::pass("Basic multi fence test without waitAll passed");
324 }
325 
326 } // anonymous
327 
createBasicFenceTests(tcu::TestContext & testCtx)328 tcu::TestCaseGroup* createBasicFenceTests (tcu::TestContext& testCtx)
329 {
330 	de::MovePtr<tcu::TestCaseGroup> basicFenceTests(new tcu::TestCaseGroup(testCtx, "fence", "Basic fence tests"));
331 	addFunctionCase(basicFenceTests.get(),	"one",					"Basic one fence tests",							basicOneFenceCase);
332 	addFunctionCase(basicFenceTests.get(),	"multi",				"Basic multi fence tests",							basicMultiFenceCase);
333 	addFunctionCase(basicFenceTests.get(),	"empty_submit",			"Signal a fence after an empty queue submission",	emptySubmitCase);
334 	addFunctionCase(basicFenceTests.get(),	"multi_waitall_false",	"Basic multi fence test without waitAll",			basicMultiFenceWaitAllFalseCase);
335 	addFunctionCase(basicFenceTests.get(),	"one_signaled",			"Create a single signaled fence and wait on it",	basicSignaledCase, 1u);
336 	addFunctionCase(basicFenceTests.get(),	"multiple_signaled",	"Create multiple signaled fences and wait on them",	basicSignaledCase, 10u);
337 
338 	return basicFenceTests.release();
339 }
340 
341 } // synchronization
342 } // vkt
343