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
28 #include "vkDefs.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkCmdUtil.hpp"
32
33
34 #include "vkRef.hpp"
35
36 namespace vkt
37 {
38 namespace synchronization
39 {
40 namespace
41 {
42
43 using namespace vk;
44
45 #define FENCE_WAIT ~0ull
46
basicOneQueueCase(Context & context)47 tcu::TestStatus basicOneQueueCase (Context& context)
48 {
49 const DeviceInterface& vk = context.getDeviceInterface();
50 const VkDevice device = context.getDevice();
51 const VkQueue queue = context.getUniversalQueue();
52 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
53 const Unique<VkSemaphore> semaphore (createSemaphore (vk, device));
54 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
55 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
56 const VkCommandBufferBeginInfo info =
57 {
58 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
59 DE_NULL, // const void* pNext;
60 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
61 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
62 };
63 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
64 const VkSubmitInfo submitInfo[2] =
65 {
66 {
67 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
68 DE_NULL, // const void* pNext;
69 0u, // deUint32 waitSemaphoreCount;
70 DE_NULL, // const VkSemaphore* pWaitSemaphores;
71 (const VkPipelineStageFlags*)DE_NULL,
72 1u, // deUint32 commandBufferCount;
73 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
74 1u, // deUint32 signalSemaphoreCount;
75 &semaphore.get(), // const VkSemaphore* pSignalSemaphores;
76 },
77 {
78 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
79 DE_NULL, // const void* pNext;
80 1u, // deUint32 waitSemaphoreCount;
81 &semaphore.get(), // const VkSemaphore* pWaitSemaphores;
82 stageBits, // const VkPipelineStageFlags* pWaitDstStageMask;
83 1u, // deUint32 commandBufferCount;
84 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
85 0u, // deUint32 signalSemaphoreCount;
86 DE_NULL, // const VkSemaphore* pSignalSemaphores;
87 }
88 };
89 const Unique<VkFence> fence (createFence(vk, device));
90
91 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
92 endCommandBuffer(vk, *cmdBuffer);
93 VK_CHECK(vk.queueSubmit(queue, 2u, submitInfo, *fence));
94
95 if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
96 return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");
97
98 return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
99 }
100
basicChainCase(Context & context)101 tcu::TestStatus basicChainCase (Context& context)
102 {
103 VkResult err = VK_SUCCESS;
104 const DeviceInterface& vk = context.getDeviceInterface();
105 const VkDevice& device = context.getDevice();
106 const VkQueue queue = context.getUniversalQueue();
107 const int chainLength = 32768;
108 VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
109 VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
110 VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
111 std::vector<VkSemaphore> semaphores;
112 VkFence fence;
113
114 for (int i = 0; err == VK_SUCCESS && i < chainLength; i++)
115 {
116 VkSemaphore semaphore;
117 err = vk.createSemaphore(device, &sci, DE_NULL, &semaphore);
118 if (err == VK_SUCCESS)
119 {
120 semaphores.push_back(semaphore);
121
122 VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
123 DE_NULL,
124 semaphores.size() > 1 ? 1u : 0u,
125 semaphores.size() > 1 ? &semaphores[semaphores.size() - 2] : DE_NULL,
126 &flags,
127 0,
128 DE_NULL,
129 1,
130 &semaphores[semaphores.size() - 1] };
131 err = vk.queueSubmit(queue, 1, &si, 0);
132 }
133 }
134
135 VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));
136
137 VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 1, &semaphores.back(), &flags, 0, DE_NULL, 0, DE_NULL };
138 VK_CHECK(vk.queueSubmit(queue, 1, &si, fence));
139
140 vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));
141
142 vk.destroyFence(device, fence, DE_NULL);
143
144 for (unsigned int i = 0; i < semaphores.size(); i++)
145 vk.destroySemaphore(device, semaphores[i], DE_NULL);
146
147 if (err == VK_SUCCESS)
148 return tcu::TestStatus::pass("Basic semaphore chain test passed");
149
150 return tcu::TestStatus::fail("Basic semaphore chain test failed");
151 }
152
basicMultiQueueCase(Context & context)153 tcu::TestStatus basicMultiQueueCase (Context& context)
154 {
155 enum {NO_MATCH_FOUND = ~((deUint32)0)};
156 enum QueuesIndexes {FIRST = 0, SECOND, COUNT};
157
158 struct Queues
159 {
160 VkQueue queue;
161 deUint32 queueFamilyIndex;
162 };
163
164
165 const DeviceInterface& vk = context.getDeviceInterface();
166 const InstanceInterface& instance = context.getInstanceInterface();
167 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
168 vk::Move<vk::VkDevice> logicalDevice;
169 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
170 VkDeviceCreateInfo deviceInfo;
171 VkPhysicalDeviceFeatures deviceFeatures;
172 const float queuePriorities[COUNT] = {1.0f, 1.0f};
173 VkDeviceQueueCreateInfo queueInfos[COUNT];
174 Queues queues[COUNT] =
175 {
176 {DE_NULL, (deUint32)NO_MATCH_FOUND},
177 {DE_NULL, (deUint32)NO_MATCH_FOUND}
178 };
179 const VkCommandBufferBeginInfo info =
180 {
181 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
182 DE_NULL, // const void* pNext;
183 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags;
184 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
185 };
186 Move<VkSemaphore> semaphore;
187 Move<VkCommandPool> cmdPool[COUNT];
188 Move<VkCommandBuffer> cmdBuffer[COUNT];
189 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
190 VkSubmitInfo submitInfo[COUNT];
191 Move<VkFence> fence[COUNT];
192
193 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
194
195 for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
196 {
197 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
198 queues[FIRST].queueFamilyIndex = queueNdx;
199
200 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
201 {
202 queues[SECOND].queueFamilyIndex = queueNdx;
203 break;
204 }
205 }
206
207 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
208 TCU_THROW(NotSupportedError, "Queues couldn't be created");
209
210 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
211 {
212 VkDeviceQueueCreateInfo queueInfo;
213 deMemset(&queueInfo, 0, sizeof(queueInfo));
214
215 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
216 queueInfo.pNext = DE_NULL;
217 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
218 queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex;
219 queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
220 queueInfo.pQueuePriorities = queuePriorities;
221
222 queueInfos[queueNdx] = queueInfo;
223
224 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
225 break;
226 }
227
228 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
229 instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
230
231 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
232 deviceInfo.pNext = DE_NULL;
233 deviceInfo.enabledExtensionCount = 0u;
234 deviceInfo.ppEnabledExtensionNames = DE_NULL;
235 deviceInfo.enabledLayerCount = 0u;
236 deviceInfo.ppEnabledLayerNames = DE_NULL;
237 deviceInfo.pEnabledFeatures = &deviceFeatures;
238 deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
239 deviceInfo.pQueueCreateInfos = queueInfos;
240
241 logicalDevice = vk::createDevice(context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo);
242
243 for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
244 {
245 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
246 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
247 else
248 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
249 }
250
251 semaphore = (createSemaphore (vk, *logicalDevice));
252 cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
253 cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
254 cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
255 cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));
256
257 submitInfo[FIRST].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
258 submitInfo[FIRST].pNext = DE_NULL;
259 submitInfo[FIRST].waitSemaphoreCount = 0u;
260 submitInfo[FIRST].pWaitSemaphores = DE_NULL;
261 submitInfo[FIRST].pWaitDstStageMask = (const VkPipelineStageFlags*)DE_NULL;
262 submitInfo[FIRST].commandBufferCount = 1u;
263 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
264 submitInfo[FIRST].signalSemaphoreCount = 1u;
265 submitInfo[FIRST].pSignalSemaphores = &semaphore.get();
266
267 submitInfo[SECOND].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
268 submitInfo[SECOND].pNext = DE_NULL;
269 submitInfo[SECOND].waitSemaphoreCount = 1u;
270 submitInfo[SECOND].pWaitSemaphores = &semaphore.get();
271 submitInfo[SECOND].pWaitDstStageMask = stageBits;
272 submitInfo[SECOND].commandBufferCount = 1u;
273 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
274 submitInfo[SECOND].signalSemaphoreCount = 0u;
275 submitInfo[SECOND].pSignalSemaphores = DE_NULL;
276
277 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
278 endCommandBuffer(vk, *cmdBuffer[FIRST]);
279 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
280 endCommandBuffer(vk, *cmdBuffer[SECOND]);
281
282 fence[FIRST] = (createFence(vk, *logicalDevice));
283 fence[SECOND] = (createFence(vk, *logicalDevice));
284
285 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
286 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
287
288 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
289 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
290
291 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
292 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
293
294 {
295 VkSubmitInfo swapInfo = submitInfo[SECOND];
296 submitInfo[SECOND] = submitInfo[FIRST];
297 submitInfo[FIRST] = swapInfo;
298 submitInfo[SECOND].pCommandBuffers = &cmdBuffer[SECOND].get();
299 submitInfo[FIRST].pCommandBuffers = &cmdBuffer[FIRST].get();
300 }
301
302 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
303 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));
304
305 VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
306 VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
307
308 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
309 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
310
311 if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
312 return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");
313
314 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
315 }
316
317 } // anonymous
318
createBasicSemaphoreTests(tcu::TestContext & testCtx)319 tcu::TestCaseGroup* createBasicSemaphoreTests (tcu::TestContext& testCtx)
320 {
321 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "semaphore", "Basic semaphore tests"));
322 addFunctionCase(basicTests.get(), "one_queue", "Basic semaphore tests with one queue", basicOneQueueCase);
323 addFunctionCase(basicTests.get(), "multi_queue", "Basic semaphore tests with multi queue", basicMultiQueueCase);
324 addFunctionCase(basicTests.get(), "chain", "Semaphore chain test", basicChainCase);
325
326 return basicTests.release();
327 }
328
329 } // synchronization
330 } // vkt
331