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