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 "vkDeviceUtil.hpp"
34 #include "vkRef.hpp"
35 #include "vkSafetyCriticalUtil.hpp"
36
37 #include <thread>
38
39 #include "tcuCommandLine.hpp"
40
41 namespace vkt
42 {
43 namespace synchronization
44 {
45 namespace
46 {
47
48 using namespace vk;
49 using vkt::synchronization::VideoCodecOperationFlags;
50
51 struct TestConfig
52 {
53 bool useTypeCreate;
54 VkSemaphoreType semaphoreType;
55 SynchronizationType type;
56 VideoCodecOperationFlags videoCodecOperationFlags;
57 };
58
59 #ifdef CTS_USES_VULKANSC
60 static const int basicChainLength = 1024;
61 #else
62 static const int basicChainLength = 32768;
63 #endif
64
createTestSemaphore(Context & context,const DeviceInterface & vk,const VkDevice device,const TestConfig & config)65 Move<VkSemaphore> createTestSemaphore(Context &context, const DeviceInterface &vk, const VkDevice device,
66 const TestConfig &config)
67 {
68 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
69 TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
70
71 return Move<VkSemaphore>(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) :
72 createSemaphore(vk, device));
73 }
74
75 #define FENCE_WAIT ~0ull
76
getVideoDevice(Context & context,bool usingTimelineSemaphores,VideoCodecOperationFlags videoCodecOperationFlags)77 VideoDevice *getVideoDevice(Context &context, bool usingTimelineSemaphores,
78 VideoCodecOperationFlags videoCodecOperationFlags)
79 {
80 DE_ASSERT(videoCodecOperationFlags != 0);
81
82 VideoDevice::VideoDeviceFlags videoFlags = VideoDevice::VideoDeviceFlagBits::VIDEO_DEVICE_FLAG_NONE;
83 if (usingTimelineSemaphores)
84 videoFlags |= VideoDevice::VideoDeviceFlagBits::VIDEO_DEVICE_FLAG_REQUIRE_TIMELINE_OR_NOT_SUPPORTED;
85
86 return new VideoDevice(context, videoCodecOperationFlags, videoFlags);
87 }
88
basicOneQueueCase(Context & context,const TestConfig config)89 tcu::TestStatus basicOneQueueCase(Context &context, const TestConfig config)
90 {
91 bool usingTimelineSemaphores = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
92
93 de::MovePtr<VideoDevice> videoDevice(
94 config.videoCodecOperationFlags != 0 ?
95 getVideoDevice(context, usingTimelineSemaphores, config.videoCodecOperationFlags) :
96 DE_NULL);
97 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
98 const VkDevice device = getSyncDevice(videoDevice, context);
99 const VkQueue queue = getSyncQueue(videoDevice, context);
100 const uint32_t queueFamilyIndex = getSyncQueueFamilyIndex(videoDevice, context);
101 const Unique<VkSemaphore> semaphore(createTestSemaphore(context, vk, device, config));
102 const Unique<VkCommandPool> cmdPool(
103 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
104 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
105 const VkCommandBufferBeginInfo info{
106 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
107 DE_NULL, // const void* pNext;
108 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
109 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
110 };
111 const uint64_t timelineValue = 1u;
112 const Unique<VkFence> fence(createFence(vk, device));
113 VkCommandBufferSubmitInfoKHR commandBufferInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer);
114 SynchronizationWrapperPtr synchronizationWrapper =
115 getSynchronizationWrapper(config.type, vk, usingTimelineSemaphores, 2u);
116 VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo =
117 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
118 VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
119 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
120
121 synchronizationWrapper->addSubmitInfo(
122 0u, // uint32_t waitSemaphoreInfoCount
123 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
124 1u, // uint32_t commandBufferInfoCount
125 &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
126 1u, // uint32_t signalSemaphoreInfoCount
127 &signalSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
128 false, usingTimelineSemaphores);
129 synchronizationWrapper->addSubmitInfo(
130 1u, // uint32_t waitSemaphoreInfoCount
131 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
132 1u, // uint32_t commandBufferInfoCount
133 &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
134 0u, // uint32_t signalSemaphoreInfoCount
135 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
136 usingTimelineSemaphores, false);
137
138 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
139 endCommandBuffer(vk, *cmdBuffer);
140 VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
141
142 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), true, FENCE_WAIT))
143 return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
144
145 return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
146 }
147
noneWaitSubmitTest(Context & context,const TestConfig config)148 tcu::TestStatus noneWaitSubmitTest(Context &context, const TestConfig config)
149 {
150 const DeviceInterface &vk = context.getDeviceInterface();
151 const VkDevice device = context.getDevice();
152 const VkQueue queue = context.getUniversalQueue();
153 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
154
155 const Unique<VkSemaphore> semaphore(createTestSemaphore(context, vk, device, config));
156 const Unique<VkCommandPool> cmdPool(
157 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
158
159 const Unique<VkCommandBuffer> firstbuffer(makeCommandBuffer(vk, device, *cmdPool));
160 const Unique<VkCommandBuffer> secondBuffer(makeCommandBuffer(vk, device, *cmdPool));
161
162 const VkCommandBufferBeginInfo info{
163 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
164 DE_NULL, // const void* pNext;
165 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
166 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
167 };
168 const Unique<VkFence> fence1(createFence(vk, device));
169 const Unique<VkFence> fence2(createFence(vk, device));
170 const Unique<VkEvent> event(createEvent(vk, device));
171
172 VK_CHECK(vk.beginCommandBuffer(*firstbuffer, &info));
173 endCommandBuffer(vk, *firstbuffer);
174
175 const VkSubmitInfo firstSubmitInfo{
176 VK_STRUCTURE_TYPE_SUBMIT_INFO, //VkStructureType sType
177 DE_NULL, //const void* pNext
178 0u, //uint32_t waitSemaphoreCount
179 DE_NULL, //const VkSemaphore* pWaitSemaphores
180 DE_NULL, //const VkPipelineStageFlags* pWaitDstStageMask
181 1u, //uint32_t commandBufferCount
182 &firstbuffer.get(), //const VkCommandBuffer* pCommandBuffers
183 1, //uint32_t signalSemaphoreCount
184 &semaphore.get() //const VkSemaphore* pSignalSemaphores
185 };
186
187 //check if waiting on an event in the none stage works as expected
188 VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_NONE_KHR};
189
190 const VkSubmitInfo secondSubmitInfo{
191 VK_STRUCTURE_TYPE_SUBMIT_INFO, //VkStructureType sType
192 DE_NULL, //const void* pNext
193 1u, //uint32_t waitSemaphoreCount
194 &semaphore.get(), //const VkSemaphore* pWaitSemaphores
195 waitStages, //const VkPipelineStageFlags* pWaitDstStageMask
196 1u, //uint32_t commandBufferCount
197 &secondBuffer.get(), //const VkCommandBuffer* pCommandBuffers
198 0, //uint32_t signalSemaphoreCount
199 DE_NULL //const VkSemaphore* pSignalSemaphores
200 };
201
202 VK_CHECK(vk.beginCommandBuffer(*secondBuffer, &info));
203 vk.cmdSetEvent(*secondBuffer, event.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
204 endCommandBuffer(vk, *secondBuffer);
205
206 VK_CHECK(vk.queueSubmit(queue, 1, &firstSubmitInfo, fence1.get()));
207 VK_CHECK(vk.queueSubmit(queue, 1, &secondSubmitInfo, fence2.get()));
208 VK_CHECK(vk.queueWaitIdle(queue));
209
210 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence1.get(), true, FENCE_WAIT))
211 return tcu::TestStatus::fail("None stage test failed, failed to wait for fence");
212
213 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence2.get(), true, FENCE_WAIT))
214 return tcu::TestStatus::fail("None stage test failed, failed to wait for the second fence");
215
216 if (vk.getEventStatus(device, event.get()) != VK_EVENT_SET)
217 return tcu::TestStatus::fail("None stage test failed, event isn't set");
218
219 return tcu::TestStatus::pass("Pass");
220 }
221
basicChainCase(Context & context,TestConfig config)222 tcu::TestStatus basicChainCase(Context &context, TestConfig config)
223 {
224 VkResult err = VK_SUCCESS;
225 bool usingTimelineSemaphores = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
226
227 de::MovePtr<VideoDevice> videoDevice(
228 config.videoCodecOperationFlags != 0 ?
229 getVideoDevice(context, usingTimelineSemaphores, config.videoCodecOperationFlags) :
230 DE_NULL);
231
232 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
233 const VkDevice device = getSyncDevice(videoDevice, context);
234 const VkQueue queue = getSyncQueue(videoDevice, context);
235 VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0};
236 VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0};
237 VkFence fence;
238 std::vector<VkSemaphoreSubmitInfoKHR> waitSemaphoreSubmitInfos(
239 basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
240 std::vector<VkSemaphoreSubmitInfoKHR> signalSemaphoreSubmitInfos(
241 basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
242 VkSemaphoreSubmitInfoKHR *pWaitSemaphoreInfo = DE_NULL;
243 VkSemaphoreSubmitInfoKHR *pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data();
244
245 for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
246 {
247 if (i % (basicChainLength / 4) == 0)
248 context.getTestContext().touchWatchdog();
249
250 err = vk.createSemaphore(device, &sci, DE_NULL, &pSignalSemaphoreInfo->semaphore);
251 if (err != VK_SUCCESS)
252 continue;
253
254 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, false);
255 synchronizationWrapper->addSubmitInfo(
256 !!pWaitSemaphoreInfo, // uint32_t waitSemaphoreInfoCount
257 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
258 0u, // uint32_t commandBufferInfoCount
259 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
260 1u, // uint32_t signalSemaphoreInfoCount
261 pSignalSemaphoreInfo // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
262 );
263
264 err = synchronizationWrapper->queueSubmit(queue, 0);
265 pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i];
266 pWaitSemaphoreInfo->semaphore = pSignalSemaphoreInfo->semaphore;
267 pSignalSemaphoreInfo++;
268 }
269
270 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
271
272 {
273 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, false);
274 synchronizationWrapper->addSubmitInfo(1, pWaitSemaphoreInfo, 0, DE_NULL, 0, DE_NULL);
275 VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
276 }
277
278 vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
279 vk.destroyFence(device, fence, DE_NULL);
280
281 for (const auto &s : signalSemaphoreSubmitInfos)
282 vk.destroySemaphore(device, s.semaphore, DE_NULL);
283
284 if (err == VK_SUCCESS)
285 return tcu::TestStatus::pass("Basic semaphore chain test passed");
286
287 return tcu::TestStatus::fail("Basic semaphore chain test failed");
288 }
289
basicChainTimelineCase(Context & context,TestConfig config)290 tcu::TestStatus basicChainTimelineCase(Context &context, TestConfig config)
291 {
292 VkResult err = VK_SUCCESS;
293 de::MovePtr<VideoDevice> videoDevice(config.videoCodecOperationFlags != 0 ?
294 getVideoDevice(context, true, config.videoCodecOperationFlags) :
295 DE_NULL);
296
297 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
298 const VkDevice device = getSyncDevice(videoDevice, context);
299 const VkQueue queue = getSyncQueue(videoDevice, context);
300 VkSemaphoreTypeCreateInfo scti = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE,
301 0};
302 VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0};
303 VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0};
304 VkSemaphore semaphore;
305 VkFence fence;
306
307 VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore));
308
309 std::vector<VkSemaphoreSubmitInfoKHR> waitSemaphoreSubmitInfos(
310 basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR));
311 std::vector<VkSemaphoreSubmitInfoKHR> signalSemaphoreSubmitInfos(
312 basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR));
313 VkSemaphoreSubmitInfoKHR *pWaitSemaphoreInfo = DE_NULL;
314 VkSemaphoreSubmitInfoKHR *pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data();
315
316 for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
317 {
318 if (i % (basicChainLength / 4) == 0)
319 context.getTestContext().touchWatchdog();
320
321 pSignalSemaphoreInfo->value = static_cast<uint64_t>(i + 1);
322
323 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, true);
324 synchronizationWrapper->addSubmitInfo(
325 !!pWaitSemaphoreInfo, // uint32_t waitSemaphoreInfoCount
326 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
327 0u, // uint32_t commandBufferInfoCount
328 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
329 1u, // uint32_t signalSemaphoreInfoCount
330 pSignalSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
331 !!pWaitSemaphoreInfo, true);
332
333 err = synchronizationWrapper->queueSubmit(queue, 0);
334
335 pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i];
336 pWaitSemaphoreInfo->value = static_cast<uint64_t>(i);
337 pSignalSemaphoreInfo++;
338 }
339
340 pWaitSemaphoreInfo->value = basicChainLength;
341 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, true);
342 synchronizationWrapper->addSubmitInfo(
343 1u, // uint32_t waitSemaphoreInfoCount
344 pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
345 0u, // uint32_t commandBufferInfoCount
346 DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
347 0u, // uint32_t signalSemaphoreInfoCount
348 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
349 true);
350
351 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
352 VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence));
353 vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
354
355 vk.destroyFence(device, fence, DE_NULL);
356 vk.destroySemaphore(device, semaphore, DE_NULL);
357
358 if (err == VK_SUCCESS)
359 return tcu::TestStatus::pass("Basic semaphore chain test passed");
360
361 return tcu::TestStatus::fail("Basic semaphore chain test failed");
362 }
363
basicThreadTimelineCase(Context & context,TestConfig config)364 tcu::TestStatus basicThreadTimelineCase(Context &context, TestConfig config)
365 {
366 const VkSemaphoreTypeCreateInfo scti = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL,
367 VK_SEMAPHORE_TYPE_TIMELINE, 0};
368 de::MovePtr<VideoDevice> videoDevice(config.videoCodecOperationFlags != 0 ?
369 getVideoDevice(context, true, config.videoCodecOperationFlags) :
370 DE_NULL);
371 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
372 const VkDevice device = getSyncDevice(videoDevice, context);
373 const VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0};
374 const VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0};
375 const vk::Unique<vk::VkSemaphore> semaphore(createSemaphore(vk, device, &sci));
376 const Unique<VkFence> fence(createFence(vk, device, &fci));
377 const uint64_t waitTimeout = 50ull * 1000000ull; // miliseconds
378 VkResult threadResult = VK_SUCCESS;
379
380 // helper creating VkSemaphoreSignalInfo
381 auto makeSemaphoreSignalInfo = [&semaphore](uint64_t value) -> VkSemaphoreSignalInfo
382 {
383 return {
384 VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType
385 DE_NULL, // const void* pNext
386 *semaphore, // VkSemaphore semaphore
387 value // uint64_t value
388 };
389 };
390
391 // helper creating VkSemaphoreWaitInfo
392 auto makeSemaphoreWaitInfo = [&semaphore](uint64_t *valuePtr) -> VkSemaphoreWaitInfo
393 {
394 return {
395 VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, // VkStructureType sType
396 DE_NULL, // const void* pNext
397 VK_SEMAPHORE_WAIT_ANY_BIT, // VkSemaphoreWaitFlags flags;
398 1u, // uint32_t semaphoreCount;
399 &*semaphore, // const VkSemaphore* pSemaphores;
400 valuePtr // const uint64_t* pValues;
401 };
402 };
403
404 // start thread - semaphore has value 0
405 de::MovePtr<std::thread> thread(new std::thread(
406 [=, &vk, &threadResult]
407 {
408 // wait till semaphore has value 1
409 uint64_t waitValue = 1;
410 VkSemaphoreWaitInfo waitOne = makeSemaphoreWaitInfo(&waitValue);
411 threadResult = vk.waitSemaphores(device, &waitOne, waitTimeout);
412
413 if (threadResult == VK_SUCCESS)
414 {
415 // signal semaphore with value 2
416 VkSemaphoreSignalInfo signalTwo = makeSemaphoreSignalInfo(2);
417 threadResult = vk.signalSemaphore(device, &signalTwo);
418 }
419 }));
420
421 // wait some time to give thread chance to start
422 deSleep(1); // milisecond
423
424 // signal semaphore with value 1
425 VkSemaphoreSignalInfo signalOne = makeSemaphoreSignalInfo(1);
426 vk.signalSemaphore(device, &signalOne);
427
428 // wait till semaphore has value 2
429 uint64_t waitValue = 2;
430 VkSemaphoreWaitInfo waitTwo = makeSemaphoreWaitInfo(&waitValue);
431 VkResult mainResult = vk.waitSemaphores(device, &waitTwo, waitTimeout);
432
433 thread->join();
434
435 if (mainResult == VK_SUCCESS)
436 return tcu::TestStatus::pass("Pass");
437
438 if ((mainResult == VK_TIMEOUT) || (threadResult == VK_TIMEOUT))
439 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Reached wait timeout");
440
441 return tcu::TestStatus::fail("Fail");
442 }
443
basicWaitForTimelineValueHelper(Context & context,TestConfig config,VkSemaphoreWaitFlags wait_flags,uint64_t signal_value,uint64_t wait_value)444 VkResult basicWaitForTimelineValueHelper(Context &context, TestConfig config, VkSemaphoreWaitFlags wait_flags,
445 uint64_t signal_value, uint64_t wait_value)
446 {
447 const VkSemaphoreTypeCreateInfo scti = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, DE_NULL,
448 VK_SEMAPHORE_TYPE_TIMELINE, 0};
449 de::MovePtr<VideoDevice> videoDevice(config.videoCodecOperationFlags != 0 ?
450 getVideoDevice(context, true, config.videoCodecOperationFlags) :
451 DE_NULL);
452 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
453 const VkDevice device = getSyncDevice(videoDevice, context);
454 const VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0};
455 const VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0};
456 const vk::Unique<vk::VkSemaphore> semaphore(createSemaphore(vk, device, &sci));
457 const Unique<VkFence> fence(createFence(vk, device, &fci));
458 const uint64_t waitTimeout = 0; // return immediately
459
460 // helper creating VkSemaphoreSignalInfo
461 auto makeSemaphoreSignalInfo = [&semaphore](uint64_t value) -> VkSemaphoreSignalInfo
462 {
463 return {
464 VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType
465 DE_NULL, // const void* pNext
466 *semaphore, // VkSemaphore semaphore
467 value // uint64_t value
468 };
469 };
470
471 // helper creating VkSemaphoreWaitInfo
472 auto makeSemaphoreWaitInfo = [&semaphore](VkSemaphoreWaitFlags flags, uint64_t *valuePtr) -> VkSemaphoreWaitInfo
473 {
474 return {
475 VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, // VkStructureType sType
476 DE_NULL, // const void* pNext
477 flags, // VkSemaphoreWaitFlags flags;
478 1u, // uint32_t semaphoreCount;
479 &*semaphore, // const VkSemaphore* pSemaphores;
480 valuePtr // const uint64_t* pValues;
481 };
482 };
483
484 VkSemaphoreSignalInfo signalTheValue = makeSemaphoreSignalInfo(signal_value);
485 vk.signalSemaphore(device, &signalTheValue);
486
487 VkSemaphoreWaitInfo waitForTheValue = makeSemaphoreWaitInfo(wait_flags, &wait_value);
488 return vk.waitSemaphores(device, &waitForTheValue, waitTimeout);
489 }
490
basicWaitForAnyCurrentTimelineValueCase(Context & context,TestConfig config)491 tcu::TestStatus basicWaitForAnyCurrentTimelineValueCase(Context &context, TestConfig config)
492 {
493 VkResult mainResult = basicWaitForTimelineValueHelper(context, config, VK_SEMAPHORE_WAIT_ANY_BIT, 1, 1);
494 if (mainResult == VK_SUCCESS)
495 return tcu::TestStatus::pass("Pass");
496
497 return tcu::TestStatus::fail("Fail");
498 }
499
basicWaitForAnyLesserTimelineValueCase(Context & context,TestConfig config)500 tcu::TestStatus basicWaitForAnyLesserTimelineValueCase(Context &context, TestConfig config)
501 {
502 VkResult mainResult = basicWaitForTimelineValueHelper(context, config, VK_SEMAPHORE_WAIT_ANY_BIT, 4, 1);
503 if (mainResult == VK_SUCCESS)
504 return tcu::TestStatus::pass("Pass");
505
506 return tcu::TestStatus::fail("Fail");
507 }
508
basicWaitForAllCurrentTimelineValueCase(Context & context,TestConfig config)509 tcu::TestStatus basicWaitForAllCurrentTimelineValueCase(Context &context, TestConfig config)
510 {
511 VkResult mainResult = basicWaitForTimelineValueHelper(context, config, 0, 1, 1);
512 if (mainResult == VK_SUCCESS)
513 return tcu::TestStatus::pass("Pass");
514
515 return tcu::TestStatus::fail("Fail");
516 }
517
basicWaitForAllLesserTimelineValueCase(Context & context,TestConfig config)518 tcu::TestStatus basicWaitForAllLesserTimelineValueCase(Context &context, TestConfig config)
519 {
520 VkResult mainResult = basicWaitForTimelineValueHelper(context, config, 0, 4, 1);
521 if (mainResult == VK_SUCCESS)
522 return tcu::TestStatus::pass("Pass");
523
524 return tcu::TestStatus::fail("Fail");
525 }
526
basicMultiQueueCase(Context & context,TestConfig config)527 tcu::TestStatus basicMultiQueueCase(Context &context, TestConfig config)
528 {
529 enum
530 {
531 NO_MATCH_FOUND = ~((uint32_t)0)
532 };
533 enum QueuesIndexes
534 {
535 FIRST = 0,
536 SECOND,
537 COUNT
538 };
539
540 struct Queues
541 {
542 VkQueue queue;
543 uint32_t queueFamilyIndex;
544 };
545
546 #ifndef CTS_USES_VULKANSC
547 const VkInstance instance = context.getInstance();
548 const InstanceInterface &instanceInterface = context.getInstanceInterface();
549 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
550 bool usingTimelineSemaphores = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
551
552 de::MovePtr<VideoDevice> videoDevice(
553 config.videoCodecOperationFlags != 0 ?
554 getVideoDevice(context, usingTimelineSemaphores, config.videoCodecOperationFlags) :
555 DE_NULL);
556
557 const DeviceInterface &vk = getSyncDeviceInterface(videoDevice, context);
558 std::vector<VkQueueFamilyVideoPropertiesKHR> videoQueueFamilyProperties2;
559 #else
560 const CustomInstance instance(createCustomInstanceFromContext(context));
561 const InstanceDriver &instanceDriver(instance.getDriver());
562 const VkPhysicalDevice physicalDevice =
563 chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
564 const InstanceInterface &instanceInterface = instanceDriver;
565 // const DeviceInterface& vk = context.getDeviceInterface();
566 // const InstanceInterface& instance = context.getInstanceInterface();
567 // const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
568 #endif // CTS_USES_VULKANSC
569 vk::Move<vk::VkDevice> logicalDevice;
570 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
571 std::vector<VkQueueFamilyProperties2> queueFamilyProperties2;
572 VkDeviceCreateInfo deviceInfo;
573 VkPhysicalDeviceFeatures deviceFeatures;
574 const float queuePriorities[COUNT] = {1.0f, 1.0f};
575 VkDeviceQueueCreateInfo queueInfos[COUNT];
576 Queues queues[COUNT] = {{DE_NULL, (uint32_t)NO_MATCH_FOUND}, {DE_NULL, (uint32_t)NO_MATCH_FOUND}};
577 const VkCommandBufferBeginInfo info = {
578 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
579 DE_NULL, // const void* pNext;
580 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
581 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
582 };
583
584 const bool isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
585
586 if (config.videoCodecOperationFlags != 0)
587 {
588 #ifndef CTS_USES_VULKANSC
589 uint32_t queueFamilyPropertiesCount = 0;
590
591 instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
592
593 if (queueFamilyPropertiesCount > 0)
594 {
595 queueFamilyProperties2.resize(queueFamilyPropertiesCount);
596 videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
597
598 for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
599 {
600 queueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
601 queueFamilyProperties2[ndx].pNext = &videoQueueFamilyProperties2[ndx];
602 videoQueueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
603 videoQueueFamilyProperties2[ndx].pNext = DE_NULL;
604 videoQueueFamilyProperties2[ndx].videoCodecOperations = 0;
605 }
606
607 instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount,
608 queueFamilyProperties2.data());
609
610 if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
611 TCU_FAIL("Device returns less queue families than initially reported");
612
613 queueFamilyProperties.reserve(queueFamilyPropertiesCount);
614
615 for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
616 queueFamilyProperties.push_back(queueFamilyProperties2[ndx].queueFamilyProperties);
617 }
618 #endif // CTS_USES_VULKANSC
619 }
620 else
621 {
622 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceInterface, physicalDevice);
623 }
624
625 for (uint32_t queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
626 {
627 #ifndef CTS_USES_VULKANSC
628 const bool usableQueue =
629 videoQueueFamilyProperties2.empty() ||
630 (videoQueueFamilyProperties2[queueNdx].videoCodecOperations & config.videoCodecOperationFlags) != 0;
631
632 if (!usableQueue)
633 continue;
634 #endif // CTS_USES_VULKANSC
635
636 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
637 queues[FIRST].queueFamilyIndex = queueNdx;
638
639 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
640 {
641 queues[SECOND].queueFamilyIndex = queueNdx;
642 break;
643 }
644 }
645
646 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
647 TCU_THROW(NotSupportedError, "Queues couldn't be created");
648
649 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
650 {
651 VkDeviceQueueCreateInfo queueInfo;
652 deMemset(&queueInfo, 0, sizeof(queueInfo));
653
654 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
655 queueInfo.pNext = DE_NULL;
656 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
657 queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
658 queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
659 queueInfo.pQueuePriorities = queuePriorities;
660
661 queueInfos[queueNdx] = queueInfo;
662
663 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
664 break;
665 }
666
667 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
668 instanceInterface.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
669
670 VkPhysicalDeviceFeatures2 createPhysicalFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL,
671 deviceFeatures};
672 VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures{
673 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, true};
674 VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features{
675 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, true};
676 void **nextPtr = &createPhysicalFeature.pNext;
677
678 std::vector<const char *> deviceExtensions;
679
680 if (config.videoCodecOperationFlags != 0)
681 VideoDevice::addVideoDeviceExtensions(deviceExtensions, context.getUsedApiVersion(),
682 VideoDevice::getQueueFlags(config.videoCodecOperationFlags),
683 config.videoCodecOperationFlags);
684
685 if (isTimelineSemaphore)
686 {
687 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_timeline_semaphore"))
688 deviceExtensions.push_back("VK_KHR_timeline_semaphore");
689 addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
690 }
691 if (config.type == SynchronizationType::SYNCHRONIZATION2)
692 {
693 deviceExtensions.push_back("VK_KHR_synchronization2");
694 addToChainVulkanStructure(&nextPtr, synchronization2Features);
695 }
696
697 void *pNext = &createPhysicalFeature;
698 #ifdef CTS_USES_VULKANSC
699 VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ?
700 context.getResourceInterface()->getStatMax() :
701 resetDeviceObjectReservationCreateInfo();
702 memReservationInfo.pNext = pNext;
703 pNext = &memReservationInfo;
704
705 VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
706 sc10Features.pNext = pNext;
707 pNext = &sc10Features;
708
709 VkPipelineCacheCreateInfo pcCI;
710 std::vector<VkPipelinePoolSize> poolSizes;
711 if (context.getTestContext().getCommandLine().isSubProcess())
712 {
713 if (context.getResourceInterface()->getCacheDataSize() > 0)
714 {
715 pcCI = {
716 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
717 DE_NULL, // const void* pNext;
718 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
719 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
720 context.getResourceInterface()->getCacheDataSize(), // uintptr_t initialDataSize;
721 context.getResourceInterface()->getCacheData() // const void* pInitialData;
722 };
723 memReservationInfo.pipelineCacheCreateInfoCount = 1;
724 memReservationInfo.pPipelineCacheCreateInfos = &pcCI;
725 }
726
727 poolSizes = context.getResourceInterface()->getPipelinePoolSizes();
728 if (!poolSizes.empty())
729 {
730 memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
731 memReservationInfo.pPipelinePoolSizes = poolSizes.data();
732 }
733 }
734 #endif // CTS_USES_VULKANSC
735
736 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
737 deviceInfo.pNext = pNext;
738 deviceInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
739 deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : deviceExtensions.data();
740 deviceInfo.enabledLayerCount = 0u;
741 deviceInfo.ppEnabledLayerNames = DE_NULL;
742 deviceInfo.pEnabledFeatures = 0u;
743 deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
744 deviceInfo.pQueueCreateInfos = queueInfos;
745
746 logicalDevice =
747 createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
748 context.getPlatformInterface(), instance, instanceInterface, physicalDevice, &deviceInfo);
749
750 #ifndef CTS_USES_VULKANSC
751 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(
752 new DeviceDriver(context.getPlatformInterface(), instance, *logicalDevice, context.getUsedApiVersion(),
753 context.getTestContext().getCommandLine()));
754 #else
755 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver =
756 de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(
757 new DeviceDriverSC(context.getPlatformInterface(), instance, *logicalDevice,
758 context.getTestContext().getCommandLine(), context.getResourceInterface(),
759 context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(),
760 context.getUsedApiVersion()),
761 vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *logicalDevice));
762 const DeviceInterface &vk = *deviceDriver;
763 #endif // CTS_USES_VULKANSC
764
765 for (uint32_t queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
766 {
767 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
768 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx,
769 &queues[queueReqNdx].queue);
770 else
771 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
772 }
773
774 Move<VkSemaphore> semaphore;
775 Move<VkCommandPool> cmdPool[COUNT];
776 Move<VkCommandBuffer> cmdBuffer[COUNT];
777 uint64_t timelineValues[COUNT] = {1ull, 2ull};
778 Move<VkFence> fence[COUNT];
779
780 semaphore = (createTestSemaphore(context, vk, *logicalDevice, config));
781 cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
782 queues[FIRST].queueFamilyIndex));
783 cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
784 queues[SECOND].queueFamilyIndex));
785 cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
786 cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
787
788 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
789 endCommandBuffer(vk, *cmdBuffer[FIRST]);
790 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
791 endCommandBuffer(vk, *cmdBuffer[SECOND]);
792
793 fence[FIRST] = (createFence(vk, *logicalDevice));
794 fence[SECOND] = (createFence(vk, *logicalDevice));
795
796 VkCommandBufferSubmitInfoKHR commandBufferInfo[]{makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]),
797 makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND])};
798
799 VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[]{
800 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST],
801 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR),
802 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND],
803 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)};
804 VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
805 makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
806
807 {
808 SynchronizationWrapperPtr synchronizationWrapper[]{
809 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
810 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)};
811 synchronizationWrapper[FIRST]->addSubmitInfo(
812 0u, // uint32_t waitSemaphoreInfoCount
813 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
814 1u, // uint32_t commandBufferInfoCount
815 &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
816 1u, // uint32_t signalSemaphoreInfoCount
817 &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
818 false, isTimelineSemaphore);
819 synchronizationWrapper[SECOND]->addSubmitInfo(
820 1u, // uint32_t waitSemaphoreInfoCount
821 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
822 1u, // uint32_t commandBufferInfoCount
823 &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
824 1u, // uint32_t signalSemaphoreInfoCount
825 &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
826 isTimelineSemaphore, isTimelineSemaphore);
827 VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
828 VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
829 }
830
831 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), true, FENCE_WAIT))
832 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
833
834 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), true, FENCE_WAIT))
835 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
836
837 if (isTimelineSemaphore)
838 {
839 signalSemaphoreSubmitInfo[FIRST].value = 3ull;
840 signalSemaphoreSubmitInfo[SECOND].value = 4ull;
841 waitSemaphoreSubmitInfo.value = 3ull;
842 }
843
844 // swap semaphore info compared to above submits
845 {
846 SynchronizationWrapperPtr synchronizationWrapper[]{
847 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
848 getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)};
849 synchronizationWrapper[FIRST]->addSubmitInfo(
850 1u, // uint32_t waitSemaphoreInfoCount
851 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
852 1u, // uint32_t commandBufferInfoCount
853 &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
854 1u, // uint32_t signalSemaphoreInfoCount
855 &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
856 isTimelineSemaphore, isTimelineSemaphore);
857 synchronizationWrapper[SECOND]->addSubmitInfo(
858 isTimelineSemaphore ? 0u : 1u, // uint32_t waitSemaphoreInfoCount
859 isTimelineSemaphore ?
860 DE_NULL :
861 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
862 1u, // uint32_t commandBufferInfoCount
863 &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
864 1u, // uint32_t signalSemaphoreInfoCount
865 &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
866 false, isTimelineSemaphore);
867
868 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
869 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
870 VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
871 VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
872 }
873
874 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), true, FENCE_WAIT))
875 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
876
877 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), true, FENCE_WAIT))
878 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
879
880 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
881 }
882
checkSupport(Context & context,TestConfig config)883 void checkSupport(Context &context, TestConfig config)
884 {
885 if (config.videoCodecOperationFlags != 0)
886 VideoDevice::checkSupport(context, config.videoCodecOperationFlags);
887
888 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
889 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
890
891 if (config.type == SynchronizationType::SYNCHRONIZATION2)
892 context.requireDeviceFunctionality("VK_KHR_synchronization2");
893 }
894
checkCommandBufferSimultaneousUseSupport(Context & context,TestConfig config)895 void checkCommandBufferSimultaneousUseSupport(Context &context, TestConfig config)
896 {
897 checkSupport(context, config);
898
899 #ifdef CTS_USES_VULKANSC
900 if (context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
901 TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
902 #endif
903 }
904
905 } // namespace
906
createBasicBinarySemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type,VideoCodecOperationFlags videoCodecOperationFlags)907 tcu::TestCaseGroup *createBasicBinarySemaphoreTests(tcu::TestContext &testCtx, SynchronizationType type,
908 VideoCodecOperationFlags videoCodecOperationFlags)
909 {
910 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore"));
911
912 TestConfig config = {
913 0,
914 VK_SEMAPHORE_TYPE_BINARY,
915 type,
916 videoCodecOperationFlags,
917 };
918 for (uint32_t typedCreate = 0; typedCreate < 2; typedCreate++)
919 {
920 config.useTypeCreate = (typedCreate != 0);
921 const std::string createName = config.useTypeCreate ? "_typed" : "";
922
923 // Basic binary semaphore tests with one queue
924 addFunctionCase(basicTests.get(), "one_queue" + createName, checkCommandBufferSimultaneousUseSupport,
925 basicOneQueueCase, config);
926 // Basic binary semaphore tests with multi queue
927 addFunctionCase(basicTests.get(), "multi_queue" + createName, checkCommandBufferSimultaneousUseSupport,
928 basicMultiQueueCase, config);
929 }
930
931 if (type == SynchronizationType::SYNCHRONIZATION2)
932 // Test waiting on the none pipeline stage
933 addFunctionCase(basicTests.get(), "none_wait_submit", checkCommandBufferSimultaneousUseSupport,
934 noneWaitSubmitTest, config);
935
936 // Binary semaphore chain test
937 addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainCase, config);
938
939 return basicTests.release();
940 }
941
createBasicTimelineSemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type,VideoCodecOperationFlags videoCodecOperationFlags)942 tcu::TestCaseGroup *createBasicTimelineSemaphoreTests(tcu::TestContext &testCtx, SynchronizationType type,
943 VideoCodecOperationFlags videoCodecOperationFlags)
944 {
945 // Basic timeline semaphore tests
946 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore"));
947 const TestConfig config = {
948 true,
949 VK_SEMAPHORE_TYPE_TIMELINE,
950 type,
951 videoCodecOperationFlags,
952 };
953
954 // Basic timeline semaphore tests with one queue
955 addFunctionCase(basicTests.get(), "one_queue", checkCommandBufferSimultaneousUseSupport, basicOneQueueCase, config);
956 // Basic timeline semaphore tests with multi queue
957 addFunctionCase(basicTests.get(), "multi_queue", checkCommandBufferSimultaneousUseSupport, basicMultiQueueCase,
958 config);
959 // Timeline semaphore chain test
960 addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainTimelineCase, config);
961
962 // dont repeat this test for synchronization2
963 if (type == SynchronizationType::LEGACY)
964 {
965 // Timeline semaphore used by two threads
966 addFunctionCase(basicTests.get(), "two_threads", checkSupport, basicThreadTimelineCase, config);
967 // Wait for the currently signalled timeline semaphore value (wait for any)
968 addFunctionCase(basicTests.get(), "wait_for_any_current_value", checkSupport,
969 basicWaitForAnyCurrentTimelineValueCase, config);
970 // Wait for a value less than the currently signalled timeline semaphore value (wait for any)
971 addFunctionCase(basicTests.get(), "wait_for_any_lesser_value", checkSupport,
972 basicWaitForAnyLesserTimelineValueCase, config);
973 // Wait for the currently signalled timeline semaphore value (wait for all)
974 addFunctionCase(basicTests.get(), "wait_for_all_current_value", checkSupport,
975 basicWaitForAllCurrentTimelineValueCase, config);
976 // Wait for a value less than the currently signalled timeline semaphore value (wait for all)
977 addFunctionCase(basicTests.get(), "wait_for_all_lesser_value", checkSupport,
978 basicWaitForAllLesserTimelineValueCase, config);
979 }
980
981 return basicTests.release();
982 }
983
984 } // namespace synchronization
985 } // namespace vkt
986