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 event basic tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationBasicEventTests.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 namespace vkt
34 {
35 namespace synchronization
36 {
37 namespace
38 {
39
40 using namespace vk;
41 #define SHORT_FENCE_WAIT 1000ull
42 #define LONG_FENCE_WAIT ~0ull
43
44 struct TestConfig
45 {
46 SynchronizationType type;
47 VkEventCreateFlags flags;
48 };
49
hostResetSetEventCase(Context & context,TestConfig config)50 tcu::TestStatus hostResetSetEventCase (Context& context, TestConfig config)
51 {
52 const DeviceInterface& vk = context.getDeviceInterface();
53 const VkDevice device = context.getDevice();
54 const VkEventCreateInfo eventInfo =
55 {
56 VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
57 DE_NULL,
58 0
59 };
60 VkEvent event;
61 Move<VkEvent> ptrEvent;
62
63 DE_UNREF(config);
64
65 if (VK_SUCCESS != vk.createEvent(device, &eventInfo, DE_NULL, &event))
66 return tcu::TestStatus::fail("Couldn't create event");
67
68 ptrEvent = Move<VkEvent>(check<VkEvent>(event), Deleter<VkEvent>(vk, device, DE_NULL));
69
70 if (VK_EVENT_RESET != vk.getEventStatus(device, event))
71 return tcu::TestStatus::fail("Created event should be in unsignaled state");
72
73 if (VK_SUCCESS != vk.setEvent(device, event))
74 return tcu::TestStatus::fail("Couldn't set event");
75
76 if (VK_EVENT_SET != vk.getEventStatus(device, event))
77 return tcu::TestStatus::fail("Event should be in signaled state after set");
78
79 if (VK_SUCCESS != vk.resetEvent(device, event))
80 return tcu::TestStatus::fail("Couldn't reset event");
81
82 if (VK_EVENT_RESET != vk.getEventStatus(device, event))
83 return tcu::TestStatus::fail("Event should be in unsignaled state after reset");
84
85 return tcu::TestStatus::pass("Tests set and reset event on host pass");
86 }
87
deviceResetSetEventCase(Context & context,TestConfig config)88 tcu::TestStatus deviceResetSetEventCase (Context& context, TestConfig config)
89 {
90 const DeviceInterface& vk = context.getDeviceInterface();
91 const VkDevice device = context.getDevice();
92 const VkQueue queue = context.getUniversalQueue();
93 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
94 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
95 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
96 const Unique<VkEvent> event (createEvent(vk, device));
97 const VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(cmdBuffer.get());
98 const VkMemoryBarrier2KHR memoryBarrier2 =
99 {
100 VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, // VkStructureType sType
101 DE_NULL, // const void* pNext
102 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
103 VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR srcAccessMask
104 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
105 VK_ACCESS_2_HOST_READ_BIT_KHR // VkAccessFlags2KHR dstAccessMask
106 };
107 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(&memoryBarrier2);
108
109 {
110 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
111
112 beginCommandBuffer(vk, *cmdBuffer);
113 synchronizationWrapper->cmdSetEvent(*cmdBuffer, *event, &dependencyInfo);
114 endCommandBuffer(vk, *cmdBuffer);
115
116 synchronizationWrapper->addSubmitInfo(
117 0u, // deUint32 waitSemaphoreInfoCount
118 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
119 1u, // deUint32 commandBufferInfoCount
120 &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
121 0u, // deUint32 signalSemaphoreInfoCount
122 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
123 );
124
125 VK_CHECK(synchronizationWrapper->queueSubmit(queue, DE_NULL));
126 }
127
128 VK_CHECK(vk.queueWaitIdle(queue));
129
130 if (VK_EVENT_SET != vk.getEventStatus(device, *event))
131 return tcu::TestStatus::fail("Event should be in signaled state after set");
132
133 {
134 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
135
136 beginCommandBuffer(vk, *cmdBuffer);
137 synchronizationWrapper->cmdResetEvent(*cmdBuffer, *event, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
138 endCommandBuffer(vk, *cmdBuffer);
139
140 synchronizationWrapper->addSubmitInfo(
141 0u, // deUint32 waitSemaphoreInfoCount
142 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
143 1u, // deUint32 commandBufferInfoCount
144 &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
145 0u, // deUint32 signalSemaphoreInfoCount
146 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
147 );
148
149 VK_CHECK(synchronizationWrapper->queueSubmit(queue, DE_NULL));
150 }
151
152 VK_CHECK(vk.queueWaitIdle(queue));
153
154 if (VK_EVENT_RESET != vk.getEventStatus(device, *event))
155 return tcu::TestStatus::fail("Event should be in unsignaled state after set");
156
157 return tcu::TestStatus::pass("Device set and reset event tests pass");
158 }
159
singleSubmissionCase(Context & context,TestConfig config)160 tcu::TestStatus singleSubmissionCase (Context& context, TestConfig config)
161 {
162 enum {SET=0, WAIT, COUNT};
163 const DeviceInterface& vk = context.getDeviceInterface();
164 const VkDevice device = context.getDevice();
165 const VkQueue queue = context.getUniversalQueue();
166 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
167 const Unique<VkFence> fence (createFence(vk, device));
168 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
169 const Move<VkCommandBuffer> ptrCmdBuffer[COUNT] = { makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool) };
170 VkCommandBuffer cmdBuffers[COUNT] = {*ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT]};
171 const Unique<VkEvent> event (createEvent(vk, device, config.flags));
172 VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo[] {
173 makeCommonCommandBufferSubmitInfo(cmdBuffers[SET]),
174 makeCommonCommandBufferSubmitInfo(cmdBuffers[WAIT])
175 };
176 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo();
177 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
178
179 synchronizationWrapper->addSubmitInfo(
180 0u, // deUint32 waitSemaphoreInfoCount
181 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
182 2u, // deUint32 commandBufferInfoCount
183 commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
184 0u, // deUint32 signalSemaphoreInfoCount
185 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
186 );
187
188 beginCommandBuffer(vk, cmdBuffers[SET]);
189 synchronizationWrapper->cmdSetEvent(cmdBuffers[SET], *event, &dependencyInfo);
190 endCommandBuffer(vk, cmdBuffers[SET]);
191
192 beginCommandBuffer(vk, cmdBuffers[WAIT]);
193 synchronizationWrapper->cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(), &dependencyInfo);
194 endCommandBuffer(vk, cmdBuffers[WAIT]);
195
196 VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
197
198 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
199 return tcu::TestStatus::fail("Queue should end execution");
200
201 return tcu::TestStatus::pass("Wait and set even on device single submission tests pass");
202 }
203
multiSubmissionCase(Context & context,TestConfig config)204 tcu::TestStatus multiSubmissionCase(Context& context, TestConfig config)
205 {
206 enum { SET = 0, WAIT, COUNT };
207 const DeviceInterface& vk = context.getDeviceInterface();
208 const VkDevice device = context.getDevice();
209 const VkQueue queue = context.getUniversalQueue();
210 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
211 const Move<VkFence> ptrFence[COUNT] = { createFence(vk, device), createFence(vk, device) };
212 VkFence fence[COUNT] = { *ptrFence[SET], *ptrFence[WAIT] };
213 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
214 const Move<VkCommandBuffer> ptrCmdBuffer[COUNT] = { makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool) };
215 VkCommandBuffer cmdBuffers[COUNT] = { *ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT] };
216 const Unique<VkEvent> event (createEvent(vk, device, config.flags));
217 VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo[] =
218 {
219 makeCommonCommandBufferSubmitInfo(cmdBuffers[SET]),
220 makeCommonCommandBufferSubmitInfo(cmdBuffers[WAIT])
221 };
222 SynchronizationWrapperPtr synchronizationWrapper[] =
223 {
224 getSynchronizationWrapper(config.type, vk, DE_FALSE),
225 getSynchronizationWrapper(config.type, vk, DE_FALSE)
226 };
227 VkDependencyInfoKHR dependencyInfos[] =
228 {
229 makeCommonDependencyInfo(),
230 makeCommonDependencyInfo()
231 };
232
233 synchronizationWrapper[SET]->addSubmitInfo(
234 0u, // deUint32 waitSemaphoreInfoCount
235 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
236 1u, // deUint32 commandBufferInfoCount
237 &commandBufferSubmitInfo[SET], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
238 0u, // deUint32 signalSemaphoreInfoCount
239 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
240 );
241
242 synchronizationWrapper[WAIT]->addSubmitInfo(
243 0u, // deUint32 waitSemaphoreInfoCount
244 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
245 1u, // deUint32 commandBufferInfoCount
246 &commandBufferSubmitInfo[WAIT], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
247 0u, // deUint32 signalSemaphoreInfoCount
248 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
249 );
250
251 beginCommandBuffer(vk, cmdBuffers[SET]);
252 synchronizationWrapper[SET]->cmdSetEvent(cmdBuffers[SET], *event, &dependencyInfos[SET]);
253 endCommandBuffer(vk, cmdBuffers[SET]);
254
255 beginCommandBuffer(vk, cmdBuffers[WAIT]);
256 synchronizationWrapper[WAIT]->cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(), &dependencyInfos[WAIT]);
257 endCommandBuffer(vk, cmdBuffers[WAIT]);
258
259 VK_CHECK(synchronizationWrapper[SET]->queueSubmit(queue, fence[SET]));
260 VK_CHECK(synchronizationWrapper[WAIT]->queueSubmit(queue, fence[WAIT]));
261
262 if (VK_SUCCESS != vk.waitForFences(device, 2u, fence, DE_TRUE, LONG_FENCE_WAIT))
263 return tcu::TestStatus::fail("Queue should end execution");
264
265 return tcu::TestStatus::pass("Wait and set even on device multi submission tests pass");
266 }
267
secondaryCommandBufferCase(Context & context,TestConfig config)268 tcu::TestStatus secondaryCommandBufferCase (Context& context, TestConfig config)
269 {
270 enum {SET=0, WAIT, COUNT};
271 const DeviceInterface& vk = context.getDeviceInterface();
272 const VkDevice device = context.getDevice();
273 const VkQueue queue = context.getUniversalQueue();
274 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
275 const Unique<VkFence> fence (createFence(vk, device));
276 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
277 const Move<VkCommandBuffer> primaryCmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
278 const VkCommandBufferAllocateInfo cmdBufferInfo =
279 {
280 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
281 DE_NULL, // const void* pNext;
282 *cmdPool, // VkCommandPool commandPool;
283 VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
284 1u, // deUint32 commandBufferCount;
285 };
286 const Move<VkCommandBuffer> prtCmdBuffers[COUNT] = {allocateCommandBuffer (vk, device, &cmdBufferInfo), allocateCommandBuffer (vk, device, &cmdBufferInfo)};
287 VkCommandBuffer secondaryCmdBuffers[] = {*prtCmdBuffers[SET], *prtCmdBuffers[WAIT]};
288 const Unique<VkEvent> event (createEvent(vk, device, config.flags));
289
290 const VkCommandBufferInheritanceInfo secCmdBufInheritInfo =
291 {
292 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, //VkStructureType sType;
293 DE_NULL, //const void* pNext;
294 DE_NULL, //VkRenderPass renderPass;
295 0u, //deUint32 subpass;
296 DE_NULL, //VkFramebuffer framebuffer;
297 VK_FALSE, //VkBool32 occlusionQueryEnable;
298 (VkQueryControlFlags)0u, //VkQueryControlFlags queryFlags;
299 (VkQueryPipelineStatisticFlags)0u, //VkQueryPipelineStatisticFlags pipelineStatistics;
300 };
301 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
302 {
303 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
304 DE_NULL, // const void* pNext;
305 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
306 &secCmdBufInheritInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
307 };
308 VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(*primaryCmdBuffer);
309 VkDependencyInfoKHR dependencyInfos[] =
310 {
311 makeCommonDependencyInfo(),
312 makeCommonDependencyInfo()
313 };
314 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
315
316 synchronizationWrapper->addSubmitInfo(
317 0u, // deUint32 waitSemaphoreInfoCount
318 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
319 1u, // deUint32 commandBufferInfoCount
320 &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
321 0u, // deUint32 signalSemaphoreInfoCount
322 DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
323 );
324
325 VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[SET], &cmdBufferBeginInfo));
326 synchronizationWrapper->cmdSetEvent(secondaryCmdBuffers[SET], *event, &dependencyInfos[SET]);
327 endCommandBuffer(vk, secondaryCmdBuffers[SET]);
328
329 VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[WAIT], &cmdBufferBeginInfo));
330 synchronizationWrapper->cmdWaitEvents(secondaryCmdBuffers[WAIT], 1u, &event.get(), &dependencyInfos[WAIT]);
331 endCommandBuffer(vk, secondaryCmdBuffers[WAIT]);
332
333 beginCommandBuffer(vk, *primaryCmdBuffer);
334 vk.cmdExecuteCommands(*primaryCmdBuffer, 2u, secondaryCmdBuffers);
335 endCommandBuffer(vk, *primaryCmdBuffer);
336
337 VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
338
339 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
340 return tcu::TestStatus::fail("Queue should end execution");
341
342 return tcu::TestStatus::pass("Wait and set even on device using secondary command buffers tests pass");
343 }
344
checkSupport(Context & context,TestConfig config)345 void checkSupport(Context& context, TestConfig config)
346 {
347 if (config.type == SynchronizationType::SYNCHRONIZATION2)
348 context.requireDeviceFunctionality("VK_KHR_synchronization2");
349
350 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
351 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
352 }
353
354 } // anonymous
355
createBasicEventTests(tcu::TestContext & testCtx)356 tcu::TestCaseGroup* createBasicEventTests (tcu::TestContext& testCtx)
357 {
358 TestConfig config
359 {
360 SynchronizationType::LEGACY,
361 0U
362 };
363
364 de::MovePtr<tcu::TestCaseGroup> basicTests (new tcu::TestCaseGroup(testCtx, "event", "Basic event tests"));
365
366 addFunctionCase(basicTests.get(), "host_set_reset", "Basic event tests set and reset on host", checkSupport, hostResetSetEventCase, config);
367 addFunctionCase(basicTests.get(), "device_set_reset", "Basic event tests set and reset on device", checkSupport, deviceResetSetEventCase, config);
368 addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer", "Wait and set event single submission on device", checkSupport, singleSubmissionCase, config);
369 addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer", "Wait and set event mutli submission on device", checkSupport, multiSubmissionCase, config);
370 addFunctionCase(basicTests.get(), "multi_secondary_command_buffer", "Event used on secondary command buffer ", checkSupport, secondaryCommandBufferCase, config);
371
372 return basicTests.release();
373 }
374
createSynchronization2BasicEventTests(tcu::TestContext & testCtx)375 tcu::TestCaseGroup* createSynchronization2BasicEventTests (tcu::TestContext& testCtx)
376 {
377 TestConfig config
378 {
379 SynchronizationType::SYNCHRONIZATION2,
380 0U
381 };
382
383 de::MovePtr<tcu::TestCaseGroup> basicTests (new tcu::TestCaseGroup(testCtx, "event", "Basic event tests"));
384
385 addFunctionCase(basicTests.get(), "device_set_reset", "Basic event tests set and reset on device", checkSupport, deviceResetSetEventCase, config);
386 addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer", "Wait and set event single submission on device", checkSupport, singleSubmissionCase, config);
387 addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer", "Wait and set event mutli submission on device", checkSupport, multiSubmissionCase, config);
388 addFunctionCase(basicTests.get(), "multi_secondary_command_buffer", "Event used on secondary command buffer ", checkSupport, secondaryCommandBufferCase, config);
389
390 config.flags = VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR;
391 addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer_device_only", "Wait and set GPU-only event single submission", checkSupport, singleSubmissionCase, config);
392 addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer_device_only", "Wait and set GPU-only event mutli submission", checkSupport, multiSubmissionCase, config);
393 addFunctionCase(basicTests.get(), "multi_secondary_command_buffer_device_only", "GPU-only event used on secondary command buffer ", checkSupport, secondaryCommandBufferCase, config);
394
395 return basicTests.release();
396
397 }
398
399 } // synchronization
400 } // vkt
401