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 basicMultiQueueCase (Context& context)
102 enum {NO_MATCH_FOUND = ~((deUint32)0)};
103 enum QueuesIndexes {FIRST = 0, SECOND, COUNT};
108 deUint32 queueFamilyIndex;
112 const DeviceInterface& vk = context.getDeviceInterface();
113 const InstanceInterface& instance = context.getInstanceInterface();
114 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
115 vk::Move<vk::VkDevice> logicalDevice;
116 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
117 VkDeviceCreateInfo deviceInfo;
118 VkPhysicalDeviceFeatures deviceFeatures;
119 const float queuePriorities[COUNT] = {1.0f, 1.0f};
120 VkDeviceQueueCreateInfo queueInfos[COUNT];
121 Queues queues[COUNT] =
123 {DE_NULL, (deUint32)NO_MATCH_FOUND},
124 {DE_NULL, (deUint32)NO_MATCH_FOUND}
126 const VkCommandBufferBeginInfo info =
128 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
129 DE_NULL, // const void* pNext;
130 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
131 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
133 Move<VkSemaphore> semaphore;
134 Move<VkCommandPool> cmdPool[COUNT];
135 Move<VkCommandBuffer> cmdBuffer[COUNT];
136 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
137 VkSubmitInfo submitInfo[COUNT];
138 Move<VkFence> fence[COUNT];
140 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
142 for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
144 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
145 queues[FIRST].queueFamilyIndex = queueNdx;
147 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
149 queues[SECOND].queueFamilyIndex = queueNdx;
154 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
155 TCU_THROW(NotSupportedError, "Queues couldn't be created");
157 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
159 VkDeviceQueueCreateInfo queueInfo;
160 deMemset(&queueInfo, 0, sizeof(queueInfo));
162 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
163 queueInfo.pNext = DE_NULL;
164 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
165 queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
166 queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
167 queueInfo.pQueuePriorities = queuePriorities;
169 queueInfos[queueNdx] = queueInfo;
171 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
175 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
176 instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
178 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
179 deviceInfo.pNext = DE_NULL;
180 deviceInfo.enabledExtensionCount = 0u;
181 deviceInfo.ppEnabledExtensionNames = DE_NULL;
182 deviceInfo.enabledLayerCount = 0u;
183 deviceInfo.ppEnabledLayerNames = DE_NULL;
184 deviceInfo.pEnabledFeatures = &deviceFeatures;
185 deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
186 deviceInfo.pQueueCreateInfos = queueInfos;
188 logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo);
190 for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
192 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
193 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
195 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
198 semaphore = (createSemaphore (vk, *logicalDevice));
199 cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
200 cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
201 cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
202 cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
204 submitInfo[FIRST].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
205 submitInfo[FIRST].pNext = DE_NULL;
206 submitInfo[FIRST].waitSemaphoreCount = 0u;
207 submitInfo[FIRST].pWaitSemaphores = DE_NULL;
208 submitInfo[FIRST].pWaitDstStageMask = (const VkPipelineStageFlags*)DE_NULL;
209 submitInfo[FIRST].commandBufferCount = 1u;
210 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
211 submitInfo[FIRST].signalSemaphoreCount = 1u;
212 submitInfo[FIRST].pSignalSemaphores = &semaphore.get();
214 submitInfo[SECOND].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
215 submitInfo[SECOND].pNext = DE_NULL;
216 submitInfo[SECOND].waitSemaphoreCount = 1u;
217 submitInfo[SECOND].pWaitSemaphores = &semaphore.get();
218 submitInfo[SECOND].pWaitDstStageMask = stageBits;
219 submitInfo[SECOND].commandBufferCount = 1u;
220 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
221 submitInfo[SECOND].signalSemaphoreCount = 0u;
222 submitInfo[SECOND].pSignalSemaphores = DE_NULL;
224 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
225 endCommandBuffer(vk, *cmdBuffer[FIRST]);
226 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
227 endCommandBuffer(vk, *cmdBuffer[SECOND]);
229 fence[FIRST] = (createFence(vk, *logicalDevice));
230 fence[SECOND] = (createFence(vk, *logicalDevice));
232 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
233 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
235 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
236 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
238 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
239 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
242 VkSubmitInfo swapInfo = submitInfo[SECOND];
243 submitInfo[SECOND] = submitInfo[FIRST];
244 submitInfo[FIRST] = swapInfo;
245 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
246 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
249 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
250 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
252 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
253 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
255 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
256 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
258 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
259 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
261 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
266 tcu::TestCaseGroup* createBasicSemaphoreTests (tcu::TestContext& testCtx)
268 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "semaphore", "Basic semaphore tests"));
269 addFunctionCase(basicTests.get(), "one_queue", "Basic semaphore tests with one queue", basicOneQueueCase);
270 addFunctionCase(basicTests.get(), "multi_queue", "Basic semaphore tests with multi queue", basicMultiQueueCase);
272 return basicTests.release();