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