1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Synchronization semaphore basic tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktSynchronizationBasicSemaphoreTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktSynchronizationUtil.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkQueryUtil.hpp"
37 namespace synchronization
44 #define FENCE_WAIT ~0ull
46 tcu::TestStatus basicOneQueueCase (Context& context)
48 const DeviceInterface& vk = context.getDeviceInterface();
49 const VkDevice device = context.getDevice();
50 const VkQueue queue = context.getUniversalQueue();
51 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
52 const Unique<VkSemaphore> semaphore (createSemaphore (vk, device));
53 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
54 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
55 const VkCommandBufferBeginInfo info =
57 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
58 DE_NULL, // const void* pNext;
59 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
60 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
62 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
63 const VkSubmitInfo submitInfo[2] =
66 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
67 DE_NULL, // const void* pNext;
68 0u, // deUint32 waitSemaphoreCount;
69 DE_NULL, // const VkSemaphore* pWaitSemaphores;
70 (const VkPipelineStageFlags*)DE_NULL,
71 1u, // deUint32 commandBufferCount;
72 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
73 1u, // deUint32 signalSemaphoreCount;
74 &semaphore.get(), // const VkSemaphore* pSignalSemaphores;
77 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
78 DE_NULL, // const void* pNext;
79 1u, // deUint32 waitSemaphoreCount;
80 &semaphore.get(), // const VkSemaphore* pWaitSemaphores;
81 stageBits, // const VkPipelineStageFlags* pWaitDstStageMask;
82 1u, // deUint32 commandBufferCount;
83 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
84 0u, // deUint32 signalSemaphoreCount;
85 DE_NULL, // const VkSemaphore* pSignalSemaphores;
88 const Unique<VkFence> fence (createFence(vk, device));
90 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
91 endCommandBuffer(vk, *cmdBuffer);
92 VK_CHECK(vk.queueSubmit(queue, 2u, submitInfo, *fence));
94 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
95 return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
97 return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
100 tcu::TestStatus basicChainCase (Context& context)
102 VkResult err = VK_SUCCESS;
103 const DeviceInterface& vk = context.getDeviceInterface();
104 const VkDevice& device = context.getDevice();
105 const VkQueue queue = context.getUniversalQueue();
106 const int chainLength = 32768;
107 VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
108 VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
109 VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
110 std::vector<VkSemaphore> semaphores;
113 for (int i = 0; err == VK_SUCCESS && i < chainLength; i++)
115 VkSemaphore semaphore;
116 err = vk.createSemaphore(device, &sci, DE_NULL, &semaphore);
117 if (err == VK_SUCCESS)
119 semaphores.push_back(semaphore);
121 VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
123 semaphores.size() > 1 ? 1u : 0u,
124 semaphores.size() > 1 ? &semaphores[semaphores.size() - 2] : DE_NULL,
129 &semaphores[semaphores.size() - 1] };
130 err = vk.queueSubmit(queue, 1, &si, 0);
134 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
136 VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 1, &semaphores.back(), &flags, 0, DE_NULL, 0, DE_NULL };
137 VK_CHECK(vk.queueSubmit(queue, 1, &si, fence));
139 vk.waitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
141 vk.destroyFence(device, fence, DE_NULL);
143 for (unsigned int i = 0; i < semaphores.size(); i++)
144 vk.destroySemaphore(device, semaphores[i], DE_NULL);
146 if (err == VK_SUCCESS)
147 return tcu::TestStatus::pass("Basic semaphore chain test passed");
149 return tcu::TestStatus::fail("Basic semaphore chain test failed");
152 tcu::TestStatus basicMultiQueueCase (Context& context)
154 enum {NO_MATCH_FOUND = ~((deUint32)0)};
155 enum QueuesIndexes {FIRST = 0, SECOND, COUNT};
160 deUint32 queueFamilyIndex;
164 const DeviceInterface& vk = context.getDeviceInterface();
165 const InstanceInterface& instance = context.getInstanceInterface();
166 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
167 vk::Move<vk::VkDevice> logicalDevice;
168 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
169 VkDeviceCreateInfo deviceInfo;
170 VkPhysicalDeviceFeatures deviceFeatures;
171 const float queuePriorities[COUNT] = {1.0f, 1.0f};
172 VkDeviceQueueCreateInfo queueInfos[COUNT];
173 Queues queues[COUNT] =
175 {DE_NULL, (deUint32)NO_MATCH_FOUND},
176 {DE_NULL, (deUint32)NO_MATCH_FOUND}
178 const VkCommandBufferBeginInfo info =
180 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
181 DE_NULL, // const void* pNext;
182 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
183 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
185 Move<VkSemaphore> semaphore;
186 Move<VkCommandPool> cmdPool[COUNT];
187 Move<VkCommandBuffer> cmdBuffer[COUNT];
188 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
189 VkSubmitInfo submitInfo[COUNT];
190 Move<VkFence> fence[COUNT];
192 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
194 for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
196 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
197 queues[FIRST].queueFamilyIndex = queueNdx;
199 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
201 queues[SECOND].queueFamilyIndex = queueNdx;
206 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
207 TCU_THROW(NotSupportedError, "Queues couldn't be created");
209 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
211 VkDeviceQueueCreateInfo queueInfo;
212 deMemset(&queueInfo, 0, sizeof(queueInfo));
214 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
215 queueInfo.pNext = DE_NULL;
216 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
217 queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
218 queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
219 queueInfo.pQueuePriorities = queuePriorities;
221 queueInfos[queueNdx] = queueInfo;
223 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
227 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
228 instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
230 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
231 deviceInfo.pNext = DE_NULL;
232 deviceInfo.enabledExtensionCount = 0u;
233 deviceInfo.ppEnabledExtensionNames = DE_NULL;
234 deviceInfo.enabledLayerCount = 0u;
235 deviceInfo.ppEnabledLayerNames = DE_NULL;
236 deviceInfo.pEnabledFeatures = &deviceFeatures;
237 deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
238 deviceInfo.pQueueCreateInfos = queueInfos;
240 logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo);
242 for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
244 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
245 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
247 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
250 semaphore = (createSemaphore (vk, *logicalDevice));
251 cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
252 cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
253 cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
254 cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
256 submitInfo[FIRST].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
257 submitInfo[FIRST].pNext = DE_NULL;
258 submitInfo[FIRST].waitSemaphoreCount = 0u;
259 submitInfo[FIRST].pWaitSemaphores = DE_NULL;
260 submitInfo[FIRST].pWaitDstStageMask = (const VkPipelineStageFlags*)DE_NULL;
261 submitInfo[FIRST].commandBufferCount = 1u;
262 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
263 submitInfo[FIRST].signalSemaphoreCount = 1u;
264 submitInfo[FIRST].pSignalSemaphores = &semaphore.get();
266 submitInfo[SECOND].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
267 submitInfo[SECOND].pNext = DE_NULL;
268 submitInfo[SECOND].waitSemaphoreCount = 1u;
269 submitInfo[SECOND].pWaitSemaphores = &semaphore.get();
270 submitInfo[SECOND].pWaitDstStageMask = stageBits;
271 submitInfo[SECOND].commandBufferCount = 1u;
272 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
273 submitInfo[SECOND].signalSemaphoreCount = 0u;
274 submitInfo[SECOND].pSignalSemaphores = DE_NULL;
276 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
277 endCommandBuffer(vk, *cmdBuffer[FIRST]);
278 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
279 endCommandBuffer(vk, *cmdBuffer[SECOND]);
281 fence[FIRST] = (createFence(vk, *logicalDevice));
282 fence[SECOND] = (createFence(vk, *logicalDevice));
284 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
285 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
287 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
288 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
290 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
291 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
294 VkSubmitInfo swapInfo = submitInfo[SECOND];
295 submitInfo[SECOND] = submitInfo[FIRST];
296 submitInfo[FIRST] = swapInfo;
297 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
298 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
301 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
302 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
304 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
305 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
307 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
308 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
310 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
311 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
313 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
318 tcu::TestCaseGroup* createBasicSemaphoreTests (tcu::TestContext& testCtx)
320 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "semaphore", "Basic semaphore tests"));
321 addFunctionCase(basicTests.get(), "one_queue", "Basic semaphore tests with one queue", basicOneQueueCase);
322 addFunctionCase(basicTests.get(), "multi_queue", "Basic semaphore tests with multi queue", basicMultiQueueCase);
323 addFunctionCase(basicTests.get(), "chain", "Semaphore chain test", basicChainCase);
325 return basicTests.release();