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