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