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 semaphore basic tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationBasicSemaphoreTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktSynchronizationUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkRef.hpp"
34
35 #include <thread>
36
37 #include "tcuCommandLine.hpp"
38
39 namespace vkt
40 {
41 namespace synchronization
42 {
43 namespace
44 {
45
46 using namespace vk;
47
48 struct TestConfig
49 {
50 bool useTypeCreate;
51 VkSemaphoreType semaphoreType;
52 SynchronizationType type;
53 };
54
55 static const int basicChainLength = 32768;
56
createTestSemaphore(Context & context,const DeviceInterface & vk,const VkDevice device,const TestConfig & config)57 Move<VkSemaphore> createTestSemaphore(Context& context, const DeviceInterface& vk, const VkDevice device, const TestConfig& config)
58 {
59 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
60 TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
61
62 return Move<VkSemaphore>(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) : createSemaphore(vk, device));
63 }
64
65 #define FENCE_WAIT ~0ull
66
basicOneQueueCase(Context & context,const TestConfig config)67 tcu::TestStatus basicOneQueueCase (Context& context, const TestConfig config)
68 {
69 const DeviceInterface& vk = context.getDeviceInterface();
70 const VkDevice device = context.getDevice();
71 const VkQueue queue = context.getUniversalQueue();
72 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
73 const Unique<VkSemaphore> semaphore (createTestSemaphore(context, vk, device, config));
74 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
75 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
76 const VkCommandBufferBeginInfo info {
77 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
78 DE_NULL, // const void* pNext;
79 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
80 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
81 };
82 const deUint64 timelineValue = 1u;
83 const Unique<VkFence> fence (createFence(vk, device));
84 bool usingTimelineSemaphores = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR;
85 VkCommandBufferSubmitInfoKHR commandBufferInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer);
86 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, usingTimelineSemaphores, 2u);
87 VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
88 VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
89
90 synchronizationWrapper->addSubmitInfo(
91 0u, // deUint32 waitSemaphoreInfoCount
92 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
93 1u, // deUint32 commandBufferInfoCount
94 &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
95 1u, // deUint32 signalSemaphoreInfoCount
96 &signalSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
97 DE_FALSE,
98 usingTimelineSemaphores
99 );
100 synchronizationWrapper->addSubmitInfo(
101 1u, // deUint32 waitSemaphoreInfoCount
102 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
103 1u, // deUint32 commandBufferInfoCount
104 &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
105 0u, // deUint32 signalSemaphoreInfoCount
106 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
107 usingTimelineSemaphores,
108 DE_FALSE
109 );
110
111 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
112 endCommandBuffer(vk, *cmdBuffer);
113 VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
114
115 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
116 return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
117
118 return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
119 }
120
basicChainCase(Context & context,TestConfig config)121 tcu::TestStatus basicChainCase(Context & context, TestConfig config)
122 {
123 VkResult err = VK_SUCCESS;
124 const DeviceInterface& vk = context.getDeviceInterface();
125 const VkDevice& device = context.getDevice();
126 const VkQueue queue = context.getUniversalQueue();
127 VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
128 VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
129 VkFence fence;
130 std::vector<VkSemaphoreSubmitInfoKHR> waitSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
131 std::vector<VkSemaphoreSubmitInfoKHR> signalSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
132 VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfo = DE_NULL;
133 VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data();
134
135 for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
136 {
137 err = vk.createSemaphore(device, &sci, DE_NULL, &pSignalSemaphoreInfo->semaphore);
138 if (err != VK_SUCCESS)
139 continue;
140
141 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
142 synchronizationWrapper->addSubmitInfo(
143 !!pWaitSemaphoreInfo, // deUint32 waitSemaphoreInfoCount
144 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
145 0u, // deUint32 commandBufferInfoCount
146 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
147 1u, // deUint32 signalSemaphoreInfoCount
148 pSignalSemaphoreInfo // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
149 );
150
151 err = synchronizationWrapper->queueSubmit(queue, 0);
152 pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i];
153 pWaitSemaphoreInfo->semaphore = pSignalSemaphoreInfo->semaphore;
154 pSignalSemaphoreInfo++;
155 }
156
157
158 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
159
160 {
161 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
162 synchronizationWrapper->addSubmitInfo(1, pWaitSemaphoreInfo, 0, DE_NULL, 0, DE_NULL);
163 VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
164 }
165
166 vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
167 vk.destroyFence(device, fence, DE_NULL);
168
169 for (const auto& s : signalSemaphoreSubmitInfos)
170 vk.destroySemaphore(device, s.semaphore, DE_NULL);
171
172 if (err == VK_SUCCESS)
173 return tcu::TestStatus::pass("Basic semaphore chain test passed");
174
175 return tcu::TestStatus::fail("Basic semaphore chain test failed");
176 }
177
basicChainTimelineCase(Context & context,TestConfig config)178 tcu::TestStatus basicChainTimelineCase (Context& context, TestConfig config)
179 {
180 VkResult err = VK_SUCCESS;
181 const DeviceInterface& vk = context.getDeviceInterface();
182 const VkDevice& device = context.getDevice();
183 const VkQueue queue = context.getUniversalQueue();
184 VkSemaphoreTypeCreateInfo scti = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 };
185 VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
186 VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
187 VkSemaphore semaphore;
188 VkFence fence;
189
190 VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore));
191
192 std::vector<VkSemaphoreSubmitInfoKHR> waitSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
193 std::vector<VkSemaphoreSubmitInfoKHR> signalSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
194 VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfo = DE_NULL;
195 VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data();
196
197 for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
198 {
199 pSignalSemaphoreInfo->value = static_cast<deUint64>(i+1);
200
201 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
202 synchronizationWrapper->addSubmitInfo(
203 !!pWaitSemaphoreInfo, // deUint32 waitSemaphoreInfoCount
204 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
205 0u, // deUint32 commandBufferInfoCount
206 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
207 1u, // deUint32 signalSemaphoreInfoCount
208 pSignalSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
209 !!pWaitSemaphoreInfo,
210 DE_TRUE
211 );
212
213 err = synchronizationWrapper->queueSubmit(queue, 0);
214
215 pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i];
216 pWaitSemaphoreInfo->value = static_cast<deUint64>(i);
217 pSignalSemaphoreInfo++;
218 }
219
220 pWaitSemaphoreInfo->value = basicChainLength;
221 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE);
222 synchronizationWrapper->addSubmitInfo(
223 1u, // deUint32 waitSemaphoreInfoCount
224 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
225 0u, // deUint32 commandBufferInfoCount
226 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
227 0u, // deUint32 signalSemaphoreInfoCount
228 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
229 DE_TRUE
230 );
231
232 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
233 VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
234 vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
235
236 vk.destroyFence(device, fence, DE_NULL);
237 vk.destroySemaphore(device, semaphore, DE_NULL);
238
239 if (err == VK_SUCCESS)
240 return tcu::TestStatus::pass("Basic semaphore chain test passed");
241
242 return tcu::TestStatus::fail("Basic semaphore chain test failed");
243 }
244
basicThreadTimelineCase(Context & context,TestConfig)245 tcu::TestStatus basicThreadTimelineCase(Context& context, TestConfig)
246 {
247 const DeviceInterface& vk = context.getDeviceInterface();
248 const VkDevice& device = context.getDevice();
249 const VkSemaphoreTypeCreateInfo scti = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 };
250 const VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
251 const VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
252 const vk::Unique<vk::VkSemaphore> semaphore (createSemaphore(vk, device, &sci));
253 const Unique<VkFence> fence (createFence(vk, device, &fci));
254 const deUint64 waitTimeout = 50ull * 1000000ull; // miliseconds
255 VkResult threadResult = VK_SUCCESS;
256
257 // helper creating VkSemaphoreSignalInfo
258 auto makeSemaphoreSignalInfo = [&semaphore](deUint64 value) -> VkSemaphoreSignalInfo
259 {
260 return
261 {
262 VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType
263 DE_NULL, // const void* pNext
264 *semaphore, // VkSemaphore semaphore
265 value // deUint64 value
266 };
267 };
268
269 // helper creating VkSemaphoreWaitInfo
270 auto makeSemaphoreWaitInfo = [&semaphore](deUint64* valuePtr) -> VkSemaphoreWaitInfo
271 {
272 return
273 {
274 VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, // VkStructureType sType
275 DE_NULL, // const void* pNext
276 VK_SEMAPHORE_WAIT_ANY_BIT, // VkSemaphoreWaitFlags flags;
277 1u, // deUint32 semaphoreCount;
278 &*semaphore, // const VkSemaphore* pSemaphores;
279 valuePtr // const deUint64* pValues;
280 };
281 };
282
283 // start thread - semaphore has value 0
284 de::MovePtr<std::thread> thread(new std::thread([=, &vk, &threadResult]
285 {
286 // wait till semaphore has value 1
287 deUint64 waitValue = 1;
288 VkSemaphoreWaitInfo waitOne = makeSemaphoreWaitInfo(&waitValue);
289 threadResult = vk.waitSemaphores(device, &waitOne, waitTimeout);
290
291 if (threadResult == VK_SUCCESS)
292 {
293 // signal semaphore with value 2
294 VkSemaphoreSignalInfo signalTwo = makeSemaphoreSignalInfo(2);
295 threadResult = vk.signalSemaphore(device, &signalTwo);
296 }
297 }));
298
299 // wait some time to give thread chance to start
300 deSleep(1); // milisecond
301
302 // signal semaphore with value 1
303 VkSemaphoreSignalInfo signalOne = makeSemaphoreSignalInfo(1);
304 vk.signalSemaphore(device, &signalOne);
305
306 // wait till semaphore has value 2
307 deUint64 waitValue = 2;
308 VkSemaphoreWaitInfo waitTwo = makeSemaphoreWaitInfo(&waitValue);
309 VkResult mainResult = vk.waitSemaphores(device, &waitTwo, waitTimeout);
310
311 thread->join();
312
313 if (mainResult == VK_SUCCESS)
314 return tcu::TestStatus::pass("Pass");
315
316 if ((mainResult == VK_TIMEOUT) || (threadResult == VK_TIMEOUT))
317 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Reached wait timeout");
318
319 return tcu::TestStatus::fail("Fail");
320 }
321
basicMultiQueueCase(Context & context,TestConfig config)322 tcu::TestStatus basicMultiQueueCase(Context& context, TestConfig config)
323 {
324 enum { NO_MATCH_FOUND = ~((deUint32)0) };
325 enum QueuesIndexes { FIRST = 0, SECOND, COUNT };
326
327 struct Queues
328 {
329 VkQueue queue;
330 deUint32 queueFamilyIndex;
331 };
332
333 const DeviceInterface& vk = context.getDeviceInterface();
334 const InstanceInterface& instance = context.getInstanceInterface();
335 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
336 vk::Move<vk::VkDevice> logicalDevice;
337 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
338 VkDeviceCreateInfo deviceInfo;
339 VkPhysicalDeviceFeatures deviceFeatures;
340 const float queuePriorities[COUNT] = { 1.0f, 1.0f };
341 VkDeviceQueueCreateInfo queueInfos[COUNT];
342 Queues queues[COUNT] =
343 {
344 {DE_NULL, (deUint32)NO_MATCH_FOUND},
345 {DE_NULL, (deUint32)NO_MATCH_FOUND}
346 };
347 const VkCommandBufferBeginInfo info =
348 {
349 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
350 DE_NULL, // const void* pNext;
351 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
352 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
353 };
354 Move<VkSemaphore> semaphore;
355 Move<VkCommandPool> cmdPool[COUNT];
356 Move<VkCommandBuffer> cmdBuffer[COUNT];
357 deUint64 timelineValues[COUNT] = { 1ull, 2ull };
358 Move<VkFence> fence[COUNT];
359 bool isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR;
360
361 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
362
363 for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
364 {
365 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
366 queues[FIRST].queueFamilyIndex = queueNdx;
367
368 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
369 {
370 queues[SECOND].queueFamilyIndex = queueNdx;
371 break;
372 }
373 }
374
375 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
376 TCU_THROW(NotSupportedError, "Queues couldn't be created");
377
378 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
379 {
380 VkDeviceQueueCreateInfo queueInfo;
381 deMemset(&queueInfo, 0, sizeof(queueInfo));
382
383 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
384 queueInfo.pNext = DE_NULL;
385 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
386 queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
387 queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
388 queueInfo.pQueuePriorities = queuePriorities;
389
390 queueInfos[queueNdx] = queueInfo;
391
392 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
393 break;
394 }
395
396 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
397 instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
398
399 VkPhysicalDeviceFeatures2 createPhysicalFeature { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, deviceFeatures };
400 VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE };
401 VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE };
402 void** nextPtr = &createPhysicalFeature.pNext;
403
404 std::vector<const char*> deviceExtensions;
405 if (isTimelineSemaphore)
406 {
407 deviceExtensions.push_back("VK_KHR_timeline_semaphore");
408 addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
409 }
410 if (config.type == SynchronizationType::SYNCHRONIZATION2)
411 {
412 deviceExtensions.push_back("VK_KHR_synchronization2");
413 addToChainVulkanStructure(&nextPtr, synchronization2Features);
414 }
415
416 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
417 deviceInfo.pNext = &createPhysicalFeature;
418 deviceInfo.enabledExtensionCount = static_cast<deUint32>(deviceExtensions.size());
419 deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : deviceExtensions.data();
420 deviceInfo.enabledLayerCount = 0u;
421 deviceInfo.ppEnabledLayerNames = DE_NULL;
422 deviceInfo.pEnabledFeatures = 0u;
423 deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
424 deviceInfo.pQueueCreateInfos = queueInfos;
425
426 logicalDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo);
427
428 for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
429 {
430 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
431 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
432 else
433 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
434 }
435
436 semaphore = (createTestSemaphore(context, vk, *logicalDevice, config));
437 cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
438 cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
439 cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
440 cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
441
442 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
443 endCommandBuffer(vk, *cmdBuffer[FIRST]);
444 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
445 endCommandBuffer(vk, *cmdBuffer[SECOND]);
446
447 fence[FIRST] = (createFence(vk, *logicalDevice));
448 fence[SECOND] = (createFence(vk, *logicalDevice));
449
450 VkCommandBufferSubmitInfoKHR commandBufferInfo[]
451 {
452 makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]),
453 makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND])
454 };
455
456 VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[]
457 {
458 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR),
459 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)
460 };
461 VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
462 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
463
464 {
465 SynchronizationWrapperPtr synchronizationWrapper[]
466 {
467 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
468 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
469 };
470 synchronizationWrapper[FIRST]->addSubmitInfo(
471 0u, // deUint32 waitSemaphoreInfoCount
472 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
473 1u, // deUint32 commandBufferInfoCount
474 &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
475 1u, // deUint32 signalSemaphoreInfoCount
476 &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
477 DE_FALSE,
478 isTimelineSemaphore
479 );
480 synchronizationWrapper[SECOND]->addSubmitInfo(
481 1u, // deUint32 waitSemaphoreInfoCount
482 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
483 1u, // deUint32 commandBufferInfoCount
484 &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
485 1u, // deUint32 signalSemaphoreInfoCount
486 &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
487 isTimelineSemaphore,
488 isTimelineSemaphore
489 );
490 VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
491 VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
492 }
493
494 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
495 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
496
497 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
498 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
499
500 if (isTimelineSemaphore)
501 {
502 signalSemaphoreSubmitInfo[FIRST].value = 3ull;
503 signalSemaphoreSubmitInfo[SECOND].value = 4ull;
504 waitSemaphoreSubmitInfo.value = 3ull;
505 }
506
507 // swap semaphore info compared to above submits
508 {
509 SynchronizationWrapperPtr synchronizationWrapper[]
510 {
511 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
512 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)
513 };
514 synchronizationWrapper[FIRST]->addSubmitInfo(
515 1u, // deUint32 waitSemaphoreInfoCount
516 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
517 1u, // deUint32 commandBufferInfoCount
518 &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
519 1u, // deUint32 signalSemaphoreInfoCount
520 &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
521 isTimelineSemaphore,
522 isTimelineSemaphore
523 );
524 synchronizationWrapper[SECOND]->addSubmitInfo(
525 isTimelineSemaphore ? 0u : 1u, // deUint32 waitSemaphoreInfoCount
526 isTimelineSemaphore ? DE_NULL : &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
527 1u, // deUint32 commandBufferInfoCount
528 &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
529 1u, // deUint32 signalSemaphoreInfoCount
530 &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
531 DE_FALSE,
532 isTimelineSemaphore
533 );
534
535 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
536 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
537 VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
538 VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
539 }
540
541 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
542 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
543
544 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
545 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
546
547 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
548 }
549
checkSupport(Context & context,TestConfig config)550 void checkSupport(Context& context, TestConfig config)
551 {
552 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR)
553 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
554
555 if (config.type == SynchronizationType::SYNCHRONIZATION2)
556 context.requireDeviceFunctionality("VK_KHR_synchronization2");
557 }
558
559 } // anonymous
560
createBasicBinarySemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type)561 tcu::TestCaseGroup* createBasicBinarySemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type)
562 {
563 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore", "Basic semaphore tests"));
564
565 TestConfig config =
566 {
567 0,
568 VK_SEMAPHORE_TYPE_BINARY_KHR,
569 type,
570 };
571 for (deUint32 typedCreate = 0; typedCreate < 2; typedCreate++)
572 {
573 config.useTypeCreate = (typedCreate != 0);
574 const std::string createName = config.useTypeCreate ? "_typed" : "";
575
576 addFunctionCase(basicTests.get(), "one_queue" + createName, "Basic binary semaphore tests with one queue", checkSupport, basicOneQueueCase, config);
577 addFunctionCase(basicTests.get(), "multi_queue" + createName, "Basic binary semaphore tests with multi queue", checkSupport, basicMultiQueueCase, config);
578 }
579
580 addFunctionCase(basicTests.get(), "chain", "Binary semaphore chain test", checkSupport, basicChainCase, config);
581
582 return basicTests.release();
583 }
584
createBasicTimelineSemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type)585 tcu::TestCaseGroup* createBasicTimelineSemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type)
586 {
587 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore", "Basic timeline semaphore tests"));
588 const TestConfig config =
589 {
590 true,
591 VK_SEMAPHORE_TYPE_TIMELINE_KHR,
592 type,
593 };
594
595 addFunctionCase(basicTests.get(), "one_queue", "Basic timeline semaphore tests with one queue", checkSupport, basicOneQueueCase, config);
596 addFunctionCase(basicTests.get(), "multi_queue", "Basic timeline semaphore tests with multi queue", checkSupport, basicMultiQueueCase, config);
597 addFunctionCase(basicTests.get(), "chain", "Timeline semaphore chain test", checkSupport, basicChainTimelineCase, config);
598
599 // dont repeat this test for synchronization2
600 if (type == SynchronizationType::LEGACY)
601 addFunctionCase(basicTests.get(), "two_threads","Timeline semaphore used by two threads", checkSupport, basicThreadTimelineCase, config);
602
603 return basicTests.release();
604 }
605
606 } // synchronization
607 } // vkt
608