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