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