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 35namespace vkt 36{ 37namespace synchronization 38{ 39namespace 40{ 41 42using namespace vk; 43 44#define FENCE_WAIT ~0ull 45 46tcu::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 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 = 56 { 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; 61 }; 62 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT }; 63 const VkSubmitInfo submitInfo[2] = 64 { 65 { 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; 75 }, 76 { 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; 86 } 87 }; 88 const Unique<VkFence> fence (createFence(vk, device)); 89 90 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info)); 91 endCommandBuffer(vk, *cmdBuffer); 92 VK_CHECK(vk.queueSubmit(queue, 2u, submitInfo, *fence)); 93 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"); 96 97 return tcu::TestStatus::pass("Basic semaphore tests with one queue passed"); 98} 99 100tcu::TestStatus basicMultiQueueCase (Context& context) 101{ 102 enum {NO_MATCH_FOUND = ~((deUint32)0)}; 103 enum QueuesIndexes {FIRST = 0, SECOND, COUNT}; 104 105 struct Queues 106 { 107 VkQueue queue; 108 deUint32 queueFamilyIndex; 109 }; 110 111 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] = 122 { 123 {DE_NULL, (deUint32)NO_MATCH_FOUND}, 124 {DE_NULL, (deUint32)NO_MATCH_FOUND} 125 }; 126 const VkCommandBufferBeginInfo info = 127 { 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; 132 }; 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]; 139 140 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice); 141 142 for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx) 143 { 144 if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex) 145 queues[FIRST].queueFamilyIndex = queueNdx; 146 147 if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u) 148 { 149 queues[SECOND].queueFamilyIndex = queueNdx; 150 break; 151 } 152 } 153 154 if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND) 155 TCU_THROW(NotSupportedError, "Queues couldn't be created"); 156 157 for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx) 158 { 159 VkDeviceQueueCreateInfo queueInfo; 160 deMemset(&queueInfo, 0, sizeof(queueInfo)); 161 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; 168 169 queueInfos[queueNdx] = queueInfo; 170 171 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) 172 break; 173 } 174 175 deMemset(&deviceInfo, 0, sizeof(deviceInfo)); 176 instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); 177 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; 187 188 logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo); 189 190 for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx) 191 { 192 if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) 193 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue); 194 else 195 vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue); 196 } 197 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])); 203 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(); 213 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; 223 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]); 228 229 fence[FIRST] = (createFence(vk, *logicalDevice)); 230 fence[SECOND] = (createFence(vk, *logicalDevice)); 231 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])); 234 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"); 237 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"); 240 241 { 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(); 247 } 248 249 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get())); 250 VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get())); 251 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])); 254 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"); 257 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"); 260 261 return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed"); 262} 263 264} // anonymous 265 266tcu::TestCaseGroup* createBasicSemaphoreTests (tcu::TestContext& testCtx) 267{ 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); 271 272 return basicTests.release(); 273} 274 275} // synchronization 276} // vkt 277