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 uint64_t SHORT_FENCE_WAIT = 1000ull; // 1us
47 static const uint64_t 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(
58 config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
59 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
60 const VkDevice device = getSyncDevice(videoDevice, context);
61 const VkQueue queue = getSyncQueue(videoDevice, context);
62 const uint32_t queueFamilyIndex = getSyncQueueFamilyIndex(videoDevice, context);
63 const Unique<VkCommandPool> cmdPool(
64 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
65 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
66
67 const VkFenceCreateInfo fenceInfo = {
68 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
69 DE_NULL, // const void* pNext;
70 0u, // VkFenceCreateFlags flags;
71 };
72
73 const Unique<VkFence> fence(createFence(vk, device, &fenceInfo));
74
75 const VkSubmitInfo submitInfo = {
76 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
77 DE_NULL, // const void* pNext;
78 0u, // uint32_t waitSemaphoreCount;
79 DE_NULL, // const VkSemaphore* pWaitSemaphores;
80 (const VkPipelineStageFlags *)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
81 1u, // uint32_t commandBufferCount;
82 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
83 0u, // uint32_t 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(), 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(
135 config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
136 const DeviceInterface &vkd = getSyncDeviceInterface(videoDevice, context);
137 const VkDevice device = getSyncDevice(videoDevice, context);
138
139 std::vector<Move<VkFence>> fences;
140 fences.reserve(config.numFences);
141
142 const VkFenceCreateInfo fenceCreateInfo = {
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),
157 [](const Move<VkFence> &f) { return f.get(); });
158
159 const auto waitResult = vkd.waitForFences(device, static_cast<uint32_t>(rawFences.size()),
160 de::dataOrNull(rawFences), VK_TRUE, LONG_FENCE_WAIT);
161 if (waitResult != VK_SUCCESS)
162 TCU_FAIL("vkWaitForFences failed with exit status " + std::to_string(waitResult));
163
164 return tcu::TestStatus::pass("Pass");
165 }
166
basicMultiFenceCase(Context & context,FenceConfig config)167 tcu::TestStatus basicMultiFenceCase(Context &context, FenceConfig config)
168 {
169 enum
170 {
171 FIRST_FENCE = 0,
172 SECOND_FENCE
173 };
174
175 de::MovePtr<VideoDevice> videoDevice(
176 config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
177 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
178 const VkDevice device = getSyncDevice(videoDevice, context);
179 const VkQueue queue = getSyncQueue(videoDevice, context);
180 const uint32_t queueFamilyIndex = getSyncQueueFamilyIndex(videoDevice, context);
181 const Unique<VkCommandPool> cmdPool(
182 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
183 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
184
185 const VkFenceCreateInfo fenceInfo = {
186 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
187 DE_NULL, // const void* pNext;
188 0u, // VkFenceCreateFlags flags;
189 };
190
191 const Move<VkFence> ptrFence[2] = {createFence(vk, device, &fenceInfo), createFence(vk, device, &fenceInfo)};
192
193 const VkFence fence[2] = {*ptrFence[FIRST_FENCE], *ptrFence[SECOND_FENCE]};
194
195 const VkCommandBufferBeginInfo info = {
196 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
197 DE_NULL, // const void* pNext;
198 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
199 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
200 };
201
202 const VkSubmitInfo submitInfo = {
203 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
204 DE_NULL, // const void* pNext;
205 0u, // uint32_t waitSemaphoreCount;
206 DE_NULL, // const VkSemaphore* pWaitSemaphores;
207 (const VkPipelineStageFlags *)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
208 1u, // uint32_t commandBufferCount;
209 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
210 0u, // uint32_t signalSemaphoreCount;
211 DE_NULL, // const VkSemaphore* pSignalSemaphores;
212 };
213
214 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
215 endCommandBuffer(vk, *cmdBuffer);
216
217 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
218
219 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence[FIRST_FENCE], false, LONG_FENCE_WAIT))
220 return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
221
222 if (VK_SUCCESS != vk.resetFences(device, 1u, &fence[FIRST_FENCE]))
223 return tcu::TestStatus::fail("Couldn't reset the fence");
224
225 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
226
227 if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], true, SHORT_FENCE_WAIT))
228 return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT");
229
230 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));
231
232 if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], true, LONG_FENCE_WAIT))
233 return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
234
235 return tcu::TestStatus::pass("Basic multi fence tests passed");
236 }
237
emptySubmitCase(Context & context,FenceConfig config)238 tcu::TestStatus emptySubmitCase(Context &context, FenceConfig config)
239 {
240 de::MovePtr<VideoDevice> videoDevice(
241 config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
242 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
243 const VkDevice device = getSyncDevice(videoDevice, context);
244 const VkQueue queue = getSyncQueue(videoDevice, context);
245
246 const VkFenceCreateInfo fenceCreateInfo = {
247 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
248 DE_NULL, // const void* pNext;
249 (VkFenceCreateFlags)0, // VkFenceCreateFlags flags;
250 };
251
252 const Unique<VkFence> fence(createFence(vk, device, &fenceCreateInfo));
253
254 VK_CHECK(vk.queueSubmit(queue, 0u, DE_NULL, *fence));
255
256 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), true, LONG_FENCE_WAIT))
257 return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");
258
259 return tcu::TestStatus::pass("OK");
260 }
261
basicMultiFenceWaitAllFalseCase(Context & context,FenceConfig config)262 tcu::TestStatus basicMultiFenceWaitAllFalseCase(Context &context, FenceConfig config)
263 {
264 enum
265 {
266 FIRST_FENCE = 0,
267 SECOND_FENCE
268 };
269
270 de::MovePtr<VideoDevice> videoDevice(
271 config.videoCodecOperationFlags != 0 ? new VideoDevice(context, config.videoCodecOperationFlags) : DE_NULL);
272 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
273 const VkDevice device = getSyncDevice(videoDevice, context);
274 const VkQueue queue = getSyncQueue(videoDevice, context);
275 const uint32_t queueFamilyIndex = getSyncQueueFamilyIndex(videoDevice, context);
276 const Unique<VkCommandPool> cmdPool(
277 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
278 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
279
280 const VkFenceCreateInfo fenceInfo = {
281 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
282 DE_NULL, // const void* pNext;
283 0u, // VkFenceCreateFlags flags;
284 };
285
286 const Move<VkFence> ptrFence[2] = {createFence(vk, device, &fenceInfo), createFence(vk, device, &fenceInfo)};
287
288 const VkFence fence[2] = {*ptrFence[FIRST_FENCE], *ptrFence[SECOND_FENCE]};
289
290 const VkCommandBufferBeginInfo info = {
291 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
292 DE_NULL, // const void* pNext;
293 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
294 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
295 };
296
297 const VkSubmitInfo submitInfo = {
298 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
299 DE_NULL, // const void* pNext;
300 0u, // uint32_t waitSemaphoreCount;
301 DE_NULL, // const VkSemaphore* pWaitSemaphores;
302 (const VkPipelineStageFlags *)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
303 1u, // uint32_t commandBufferCount;
304 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
305 0u, // uint32_t signalSemaphoreCount;
306 DE_NULL, // const VkSemaphore* pSignalSemaphores;
307 };
308
309 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
310 endCommandBuffer(vk, *cmdBuffer);
311
312 if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], false, SHORT_FENCE_WAIT))
313 return tcu::TestStatus::fail(
314 "vkWaitForFences should return VK_TIMEOUT for case: Wait for any fence (No fence has been signaled)");
315
316 if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], true, SHORT_FENCE_WAIT))
317 return tcu::TestStatus::fail(
318 "vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (No fence has been signaled)");
319
320 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));
321
322 if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], false, LONG_FENCE_WAIT))
323 return tcu::TestStatus::fail(
324 "vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (Only second fence signaled)");
325
326 if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], true, SHORT_FENCE_WAIT))
327 return tcu::TestStatus::fail(
328 "vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (Only second fence signaled)");
329
330 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));
331
332 if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], false, LONG_FENCE_WAIT))
333 return tcu::TestStatus::fail(
334 "vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (All fences signaled)");
335
336 if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], true, LONG_FENCE_WAIT))
337 return tcu::TestStatus::fail(
338 "vkWaitForFences should return VK_SUCCESS for case: Wait for all fences (All fences signaled)");
339
340 return tcu::TestStatus::pass("Basic multi fence test without waitAll passed");
341 }
342
343 } // namespace
344
createBasicFenceTests(tcu::TestContext & testCtx,VideoCodecOperationFlags videoCodecOperationFlags)345 tcu::TestCaseGroup *createBasicFenceTests(tcu::TestContext &testCtx, VideoCodecOperationFlags videoCodecOperationFlags)
346 {
347 // Basic fence tests
348 de::MovePtr<tcu::TestCaseGroup> basicFenceTests(new tcu::TestCaseGroup(testCtx, "fence"));
349
350 // Basic one fence tests
351 addFunctionCase(basicFenceTests.get(), "one", checkVideoSupport, basicOneFenceCase,
352 FenceConfig{0u, videoCodecOperationFlags});
353 // Basic multi fence tests
354 addFunctionCase(basicFenceTests.get(), "multi", checkCommandBufferSimultaneousUseSupport, basicMultiFenceCase,
355 FenceConfig{0u, videoCodecOperationFlags});
356 // Signal a fence after an empty queue submission
357 addFunctionCase(basicFenceTests.get(), "empty_submit", checkVideoSupport, emptySubmitCase,
358 FenceConfig{0u, videoCodecOperationFlags});
359 // Basic multi fence test without waitAll
360 addFunctionCase(basicFenceTests.get(), "multi_waitall_false", checkCommandBufferSimultaneousUseSupport,
361 basicMultiFenceWaitAllFalseCase, FenceConfig{0u, videoCodecOperationFlags});
362 // Create a single signaled fence and wait on it
363 addFunctionCase(basicFenceTests.get(), "one_signaled", checkVideoSupport, basicSignaledCase,
364 FenceConfig{1u, videoCodecOperationFlags});
365 // Create multiple signaled fences and wait on them
366 addFunctionCase(basicFenceTests.get(), "multiple_signaled", checkCommandBufferSimultaneousUseSupport,
367 basicSignaledCase, FenceConfig{10u, videoCodecOperationFlags});
368
369 return basicFenceTests.release();
370 }
371
372 } // namespace synchronization
373 } // namespace vkt
374