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     std::vector<VkQueueFamilyVideoPropertiesKHR> videoQueueFamilyProperties2;
553 #else
554     const CustomInstance instance(createCustomInstanceFromContext(context));
555     const InstanceDriver &instanceDriver(instance.getDriver());
556     const VkPhysicalDevice physicalDevice =
557         chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
558     const InstanceInterface &instanceInterface = instanceDriver;
559 // const DeviceInterface& vk = context.getDeviceInterface();
560 // const InstanceInterface& instance = context.getInstanceInterface();
561 // const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
562 #endif // CTS_USES_VULKANSC
563     vk::Move<vk::VkDevice> logicalDevice;
564     std::vector<VkQueueFamilyProperties> queueFamilyProperties;
565     std::vector<VkQueueFamilyProperties2> queueFamilyProperties2;
566     VkDeviceCreateInfo deviceInfo;
567     VkPhysicalDeviceFeatures deviceFeatures;
568     const float queuePriorities[COUNT] = {1.0f, 1.0f};
569     VkDeviceQueueCreateInfo queueInfos[COUNT];
570     Queues queues[COUNT]                = {{DE_NULL, (uint32_t)NO_MATCH_FOUND}, {DE_NULL, (uint32_t)NO_MATCH_FOUND}};
571     const VkCommandBufferBeginInfo info = {
572         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,  // VkStructureType                          sType;
573         DE_NULL,                                      // const void*                              pNext;
574         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags                flags;
575         DE_NULL,                                      // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
576     };
577 
578     const bool isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
579 
580     if (config.videoCodecOperationFlags != 0)
581     {
582 #ifndef CTS_USES_VULKANSC
583         uint32_t queueFamilyPropertiesCount = 0;
584 
585         instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
586 
587         if (queueFamilyPropertiesCount > 0)
588         {
589             queueFamilyProperties2.resize(queueFamilyPropertiesCount);
590             videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
591 
592             for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
593             {
594                 queueFamilyProperties2[ndx].sType      = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
595                 queueFamilyProperties2[ndx].pNext      = &videoQueueFamilyProperties2[ndx];
596                 videoQueueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
597                 videoQueueFamilyProperties2[ndx].pNext = DE_NULL;
598                 videoQueueFamilyProperties2[ndx].videoCodecOperations = 0;
599             }
600 
601             instanceInterface.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount,
602                                                                       queueFamilyProperties2.data());
603 
604             if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
605                 TCU_FAIL("Device returns less queue families than initially reported");
606 
607             queueFamilyProperties.reserve(queueFamilyPropertiesCount);
608 
609             for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
610                 queueFamilyProperties.push_back(queueFamilyProperties2[ndx].queueFamilyProperties);
611         }
612 #endif // CTS_USES_VULKANSC
613     }
614     else
615     {
616         queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceInterface, physicalDevice);
617     }
618 
619     for (uint32_t queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
620     {
621 #ifndef CTS_USES_VULKANSC
622         const bool usableQueue =
623             videoQueueFamilyProperties2.empty() ||
624             (videoQueueFamilyProperties2[queueNdx].videoCodecOperations & config.videoCodecOperationFlags) != 0;
625 
626         if (!usableQueue)
627             continue;
628 #endif // CTS_USES_VULKANSC
629 
630         if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
631             queues[FIRST].queueFamilyIndex = queueNdx;
632 
633         if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
634         {
635             queues[SECOND].queueFamilyIndex = queueNdx;
636             break;
637         }
638     }
639 
640     if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
641         TCU_THROW(NotSupportedError, "Queues couldn't be created");
642 
643     for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
644     {
645         VkDeviceQueueCreateInfo queueInfo;
646         deMemset(&queueInfo, 0, sizeof(queueInfo));
647 
648         queueInfo.sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
649         queueInfo.pNext            = DE_NULL;
650         queueInfo.flags            = (VkDeviceQueueCreateFlags)0u;
651         queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
652         queueInfo.queueCount       = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
653         queueInfo.pQueuePriorities = queuePriorities;
654 
655         queueInfos[queueNdx] = queueInfo;
656 
657         if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
658             break;
659     }
660 
661     deMemset(&deviceInfo, 0, sizeof(deviceInfo));
662     instanceInterface.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
663 
664     VkPhysicalDeviceFeatures2 createPhysicalFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL,
665                                                     deviceFeatures};
666     VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures{
667         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, true};
668     VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features{
669         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, true};
670     void **nextPtr = &createPhysicalFeature.pNext;
671 
672     std::vector<const char *> deviceExtensions;
673 
674     if (config.videoCodecOperationFlags != 0)
675         VideoDevice::addVideoDeviceExtensions(deviceExtensions, context.getUsedApiVersion(),
676                                               VideoDevice::getQueueFlags(config.videoCodecOperationFlags),
677                                               config.videoCodecOperationFlags);
678 
679     if (isTimelineSemaphore)
680     {
681         if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_timeline_semaphore"))
682             deviceExtensions.push_back("VK_KHR_timeline_semaphore");
683         addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
684     }
685     if (config.type == SynchronizationType::SYNCHRONIZATION2)
686     {
687         deviceExtensions.push_back("VK_KHR_synchronization2");
688         addToChainVulkanStructure(&nextPtr, synchronization2Features);
689     }
690 
691     void *pNext = &createPhysicalFeature;
692 #ifdef CTS_USES_VULKANSC
693     VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ?
694                                                                  context.getResourceInterface()->getStatMax() :
695                                                                  resetDeviceObjectReservationCreateInfo();
696     memReservationInfo.pNext                               = pNext;
697     pNext                                                  = &memReservationInfo;
698 
699     VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
700     sc10Features.pNext                              = pNext;
701     pNext                                           = &sc10Features;
702 
703     VkPipelineCacheCreateInfo pcCI;
704     std::vector<VkPipelinePoolSize> poolSizes;
705     if (context.getTestContext().getCommandLine().isSubProcess())
706     {
707         if (context.getResourceInterface()->getCacheDataSize() > 0)
708         {
709             pcCI = {
710                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
711                 DE_NULL,                                      // const void* pNext;
712                 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
713                     VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
714                 context.getResourceInterface()->getCacheDataSize(),       // uintptr_t initialDataSize;
715                 context.getResourceInterface()->getCacheData()            // const void* pInitialData;
716             };
717             memReservationInfo.pipelineCacheCreateInfoCount = 1;
718             memReservationInfo.pPipelineCacheCreateInfos    = &pcCI;
719         }
720 
721         poolSizes = context.getResourceInterface()->getPipelinePoolSizes();
722         if (!poolSizes.empty())
723         {
724             memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
725             memReservationInfo.pPipelinePoolSizes    = poolSizes.data();
726         }
727     }
728 #endif // CTS_USES_VULKANSC
729 
730     deviceInfo.sType                   = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
731     deviceInfo.pNext                   = pNext;
732     deviceInfo.enabledExtensionCount   = static_cast<uint32_t>(deviceExtensions.size());
733     deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : deviceExtensions.data();
734     deviceInfo.enabledLayerCount       = 0u;
735     deviceInfo.ppEnabledLayerNames     = DE_NULL;
736     deviceInfo.pEnabledFeatures        = 0u;
737     deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
738     deviceInfo.pQueueCreateInfos    = queueInfos;
739 
740     logicalDevice =
741         createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
742                            context.getPlatformInterface(), instance, instanceInterface, physicalDevice, &deviceInfo);
743 
744 #ifndef CTS_USES_VULKANSC
745     de::MovePtr<VideoDevice> videoDevice(
746         config.videoCodecOperationFlags != 0 ?
747             getVideoDevice(context, usingTimelineSemaphores, config.videoCodecOperationFlags) :
748             DE_NULL);
749 
750     de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(
751         new DeviceDriver(context.getPlatformInterface(), instance, *logicalDevice, context.getUsedApiVersion(),
752                          context.getTestContext().getCommandLine()));
753 
754     const DeviceInterface &vk = (videoDevice != DE_NULL) ? getSyncDeviceInterface(videoDevice, context) : *deviceDriver;
755 
756 #else
757     de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver =
758         de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(
759             new DeviceDriverSC(context.getPlatformInterface(), instance, *logicalDevice,
760                                context.getTestContext().getCommandLine(), context.getResourceInterface(),
761                                context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(),
762                                context.getUsedApiVersion()),
763             vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *logicalDevice));
764     const DeviceInterface &vk = *deviceDriver;
765 #endif // CTS_USES_VULKANSC
766 
767     for (uint32_t queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
768     {
769         if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
770             vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx,
771                               &queues[queueReqNdx].queue);
772         else
773             vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
774     }
775 
776     Move<VkSemaphore> semaphore;
777     Move<VkCommandPool> cmdPool[COUNT];
778     Move<VkCommandBuffer> cmdBuffer[COUNT];
779     uint64_t timelineValues[COUNT] = {1ull, 2ull};
780     Move<VkFence> fence[COUNT];
781 
782     semaphore         = (createTestSemaphore(context, vk, *logicalDevice, config));
783     cmdPool[FIRST]    = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
784                                            queues[FIRST].queueFamilyIndex));
785     cmdPool[SECOND]   = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
786                                            queues[SECOND].queueFamilyIndex));
787     cmdBuffer[FIRST]  = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
788     cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
789 
790     VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
791     endCommandBuffer(vk, *cmdBuffer[FIRST]);
792     VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
793     endCommandBuffer(vk, *cmdBuffer[SECOND]);
794 
795     fence[FIRST]  = (createFence(vk, *logicalDevice));
796     fence[SECOND] = (createFence(vk, *logicalDevice));
797 
798     VkCommandBufferSubmitInfoKHR commandBufferInfo[]{makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]),
799                                                      makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND])};
800 
801     VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[]{
802         makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST],
803                                       VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR),
804         makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND],
805                                       VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)};
806     VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
807         makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
808 
809     {
810         SynchronizationWrapperPtr synchronizationWrapper[]{
811             getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
812             getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)};
813         synchronizationWrapper[FIRST]->addSubmitInfo(
814             0u,                                // uint32_t                                waitSemaphoreInfoCount
815             DE_NULL,                           // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
816             1u,                                // uint32_t                                commandBufferInfoCount
817             &commandBufferInfo[FIRST],         // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
818             1u,                                // uint32_t                                signalSemaphoreInfoCount
819             &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
820             false, isTimelineSemaphore);
821         synchronizationWrapper[SECOND]->addSubmitInfo(
822             1u,                                 // uint32_t                                waitSemaphoreInfoCount
823             &waitSemaphoreSubmitInfo,           // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
824             1u,                                 // uint32_t                                commandBufferInfoCount
825             &commandBufferInfo[SECOND],         // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
826             1u,                                 // uint32_t                                signalSemaphoreInfoCount
827             &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
828             isTimelineSemaphore, isTimelineSemaphore);
829         VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
830         VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
831     }
832 
833     if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), true, FENCE_WAIT))
834         return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
835 
836     if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), true, FENCE_WAIT))
837         return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
838 
839     if (isTimelineSemaphore)
840     {
841         signalSemaphoreSubmitInfo[FIRST].value  = 3ull;
842         signalSemaphoreSubmitInfo[SECOND].value = 4ull;
843         waitSemaphoreSubmitInfo.value           = 3ull;
844     }
845 
846     // swap semaphore info compared to above submits
847     {
848         SynchronizationWrapperPtr synchronizationWrapper[]{
849             getSynchronizationWrapper(config.type, vk, isTimelineSemaphore),
850             getSynchronizationWrapper(config.type, vk, isTimelineSemaphore)};
851         synchronizationWrapper[FIRST]->addSubmitInfo(
852             1u,                                 // uint32_t                                waitSemaphoreInfoCount
853             &waitSemaphoreSubmitInfo,           // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
854             1u,                                 // uint32_t                                commandBufferInfoCount
855             &commandBufferInfo[FIRST],          // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
856             1u,                                 // uint32_t                                signalSemaphoreInfoCount
857             &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
858             isTimelineSemaphore, isTimelineSemaphore);
859         synchronizationWrapper[SECOND]->addSubmitInfo(
860             isTimelineSemaphore ? 0u : 1u, // uint32_t                                waitSemaphoreInfoCount
861             isTimelineSemaphore ?
862                 DE_NULL :
863                 &waitSemaphoreSubmitInfo,      // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
864             1u,                                // uint32_t                                commandBufferInfoCount
865             &commandBufferInfo[SECOND],        // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
866             1u,                                // uint32_t                                signalSemaphoreInfoCount
867             &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
868             false, isTimelineSemaphore);
869 
870         VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
871         VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
872         VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND]));
873         VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST]));
874     }
875 
876     if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), true, FENCE_WAIT))
877         return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
878 
879     if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), true, FENCE_WAIT))
880         return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
881 
882     return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
883 }
884 
checkSupport(Context & context,TestConfig config)885 void checkSupport(Context &context, TestConfig config)
886 {
887     if (config.videoCodecOperationFlags != 0)
888         VideoDevice::checkSupport(context, config.videoCodecOperationFlags);
889 
890     if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
891         context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
892 
893     if (config.type == SynchronizationType::SYNCHRONIZATION2)
894         context.requireDeviceFunctionality("VK_KHR_synchronization2");
895 }
896 
checkCommandBufferSimultaneousUseSupport(Context & context,TestConfig config)897 void checkCommandBufferSimultaneousUseSupport(Context &context, TestConfig config)
898 {
899     checkSupport(context, config);
900 
901 #ifdef CTS_USES_VULKANSC
902     if (context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
903         TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
904 #endif
905 }
906 
907 } // namespace
908 
createBasicBinarySemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type,VideoCodecOperationFlags videoCodecOperationFlags)909 tcu::TestCaseGroup *createBasicBinarySemaphoreTests(tcu::TestContext &testCtx, SynchronizationType type,
910                                                     VideoCodecOperationFlags videoCodecOperationFlags)
911 {
912     de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore"));
913 
914     TestConfig config = {
915         0,
916         VK_SEMAPHORE_TYPE_BINARY,
917         type,
918         videoCodecOperationFlags,
919     };
920     for (uint32_t typedCreate = 0; typedCreate < 2; typedCreate++)
921     {
922         config.useTypeCreate         = (typedCreate != 0);
923         const std::string createName = config.useTypeCreate ? "_typed" : "";
924 
925         // Basic binary semaphore tests with one queue
926         addFunctionCase(basicTests.get(), "one_queue" + createName, checkCommandBufferSimultaneousUseSupport,
927                         basicOneQueueCase, config);
928         // Basic binary semaphore tests with multi queue
929         addFunctionCase(basicTests.get(), "multi_queue" + createName, checkCommandBufferSimultaneousUseSupport,
930                         basicMultiQueueCase, config);
931     }
932 
933     if (type == SynchronizationType::SYNCHRONIZATION2)
934         // Test waiting on the none pipeline stage
935         addFunctionCase(basicTests.get(), "none_wait_submit", checkCommandBufferSimultaneousUseSupport,
936                         noneWaitSubmitTest, config);
937 
938     // Binary semaphore chain test
939     addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainCase, config);
940 
941     return basicTests.release();
942 }
943 
createBasicTimelineSemaphoreTests(tcu::TestContext & testCtx,SynchronizationType type,VideoCodecOperationFlags videoCodecOperationFlags)944 tcu::TestCaseGroup *createBasicTimelineSemaphoreTests(tcu::TestContext &testCtx, SynchronizationType type,
945                                                       VideoCodecOperationFlags videoCodecOperationFlags)
946 {
947     // Basic timeline semaphore tests
948     de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore"));
949     const TestConfig config = {
950         true,
951         VK_SEMAPHORE_TYPE_TIMELINE,
952         type,
953         videoCodecOperationFlags,
954     };
955 
956     // Basic timeline semaphore tests with one queue
957     addFunctionCase(basicTests.get(), "one_queue", checkCommandBufferSimultaneousUseSupport, basicOneQueueCase, config);
958     // Basic timeline semaphore tests with multi queue
959     addFunctionCase(basicTests.get(), "multi_queue", checkCommandBufferSimultaneousUseSupport, basicMultiQueueCase,
960                     config);
961     // Timeline semaphore chain test
962     addFunctionCase(basicTests.get(), "chain", checkSupport, basicChainTimelineCase, config);
963 
964     // dont repeat this test for synchronization2
965     if (type == SynchronizationType::LEGACY)
966     {
967         // Timeline semaphore used by two threads
968         addFunctionCase(basicTests.get(), "two_threads", checkSupport, basicThreadTimelineCase, config);
969         // Wait for the currently signalled timeline semaphore value (wait for any)
970         addFunctionCase(basicTests.get(), "wait_for_any_current_value", checkSupport,
971                         basicWaitForAnyCurrentTimelineValueCase, config);
972         // Wait for a value less than the currently signalled timeline semaphore value (wait for any)
973         addFunctionCase(basicTests.get(), "wait_for_any_lesser_value", checkSupport,
974                         basicWaitForAnyLesserTimelineValueCase, config);
975         // Wait for the currently signalled timeline semaphore value (wait for all)
976         addFunctionCase(basicTests.get(), "wait_for_all_current_value", checkSupport,
977                         basicWaitForAllCurrentTimelineValueCase, config);
978         // Wait for a value less than the currently signalled timeline semaphore value (wait for all)
979         addFunctionCase(basicTests.get(), "wait_for_all_lesser_value", checkSupport,
980                         basicWaitForAllLesserTimelineValueCase, config);
981     }
982 
983     return basicTests.release();
984 }
985 
986 } // namespace synchronization
987 } // namespace vkt
988