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