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