void VulkanExampleBase::initVulkan(bool enableValidation) { VkResult err; // Vulkan instance err = createInstance(enableValidation); if (err) { vkTools::exitFatal("Could not create Vulkan instance : \n" + vkTools::errorString(err), "Fatal error"); } #if defined(__ANDROID__) loadVulkanFunctions(instance); #endif // Physical device uint32_t gpuCount = 0; // Get number of available physical devices err = vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr); assert(!err); assert(gpuCount > 0); // Enumerate devices std::vector<VkPhysicalDevice> physicalDevices(gpuCount); err = vkEnumeratePhysicalDevices(instance, &gpuCount, physicalDevices.data()); if (err) { vkTools::exitFatal("Could not enumerate phyiscal devices : \n" + vkTools::errorString(err), "Fatal error"); } // Note : // This example will always use the first physical device reported, // change the vector index if you have multiple Vulkan devices installed // and want to use another one physicalDevice = physicalDevices[0]; // Find a queue that supports graphics operations uint32_t graphicsQueueIndex = 0; uint32_t queueCount; vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL); assert(queueCount >= 1); std::vector<VkQueueFamilyProperties> queueProps; queueProps.resize(queueCount); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data()); for (graphicsQueueIndex = 0; graphicsQueueIndex < queueCount; graphicsQueueIndex++) { if (queueProps[graphicsQueueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) break; } assert(graphicsQueueIndex < queueCount); // Vulkan device std::array<float, 1> queuePriorities = { 0.0f }; VkDeviceQueueCreateInfo queueCreateInfo = {}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = graphicsQueueIndex; queueCreateInfo.queueCount = 1; queueCreateInfo.pQueuePriorities = queuePriorities.data(); err = createDevice(queueCreateInfo, enableValidation); assert(!err); // Store properties (including limits) and features of the phyiscal device // So examples can check against them and see if a feature is actually supported vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); #if defined(__ANDROID__) LOGD(deviceProperties.deviceName); #endif // Gather physical device memory properties vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); // Get the graphics queue vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue); // Find a suitable depth format VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &depthFormat); assert(validDepthFormat); swapChain.connect(instance, physicalDevice, device); // Create synchronization objects VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo(); // Create a semaphore used to synchronize image presentation // Ensures that the image is displayed before we start submitting new commands to the queu err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.presentComplete); assert(!err); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands have been sumbitted and executed err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.renderComplete); assert(!err); // Set up submit info structure // Semaphores will stay the same during application lifetime // Command buffer submission info is set by each example submitInfo = vkTools::initializers::submitInfo(); submitInfo.pWaitDstStageMask = &submitPipelineStages; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &semaphores.presentComplete; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &semaphores.renderComplete; }
Context::Context() { if(!loadVulkanLibrary()) { CV_Error(Error::StsError, "loadVulkanLibrary failed"); return; } else if (!loadVulkanEntry()) { CV_Error(Error::StsError, "loadVulkanEntry failed"); return; } else if (!loadVulkanGlobalFunctions()) { CV_Error(Error::StsError, "loadVulkanGlobalFunctions failed"); return; } // create VkInstance, VkPhysicalDevice std::vector<const char *> enabledExtensions; if (enableValidationLayers) { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, NULL); std::vector<VkLayerProperties> layerProperties(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, layerProperties.data()); bool foundLayer = false; for (VkLayerProperties prop : layerProperties) { if (strcmp("VK_LAYER_LUNARG_standard_validation", prop.layerName) == 0) { foundLayer = true; break; } } if (!foundLayer) { throw std::runtime_error("Layer VK_LAYER_LUNARG_standard_validation not supported\n"); } kEnabledLayers.push_back("VK_LAYER_LUNARG_standard_validation"); uint32_t extensionCount; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, NULL); std::vector<VkExtensionProperties> extensionProperties(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensionProperties.data()); bool foundExtension = false; for (VkExtensionProperties prop : extensionProperties) { if (strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, prop.extensionName) == 0) { foundExtension = true; break; } } if (!foundExtension) { throw std::runtime_error("Extension VK_EXT_DEBUG_REPORT_EXTENSION_NAME not supported\n"); } enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } VkApplicationInfo applicationInfo = {}; applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; applicationInfo.pApplicationName = "VkCom Library"; applicationInfo.applicationVersion = 0; applicationInfo.pEngineName = "vkcom"; applicationInfo.engineVersion = 0; applicationInfo.apiVersion = VK_API_VERSION_1_0;; VkInstanceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.flags = 0; createInfo.pApplicationInfo = &applicationInfo; // Give our desired layers and extensions to vulkan. createInfo.enabledLayerCount = kEnabledLayers.size(); createInfo.ppEnabledLayerNames = kEnabledLayers.data(); createInfo.enabledExtensionCount = enabledExtensions.size(); createInfo.ppEnabledExtensionNames = enabledExtensions.data(); VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &kInstance)); if (!loadVulkanFunctions(kInstance)) { CV_Error(Error::StsError, "loadVulkanFunctions failed"); return; } if (enableValidationLayers && vkCreateDebugReportCallbackEXT) { VkDebugReportCallbackCreateInfoEXT createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; createInfo.pfnCallback = &debugReportCallbackFn; // Create and register callback. VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(kInstance, &createInfo, NULL, &kDebugReportCallback)); } // find physical device uint32_t deviceCount; vkEnumeratePhysicalDevices(kInstance, &deviceCount, NULL); if (deviceCount == 0) { throw std::runtime_error("could not find a device with vulkan support"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(kInstance, &deviceCount, devices.data()); for (VkPhysicalDevice device : devices) { if (true) { kPhysicalDevice = device; break; } } kQueueFamilyIndex = getComputeQueueFamilyIndex(); // create device, queue, command pool VkDeviceQueueCreateInfo queueCreateInfo = {}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = kQueueFamilyIndex; queueCreateInfo.queueCount = 1; // create one queue in this family. We don't need more. float queuePriorities = 1.0; // we only have one queue, so this is not that imporant. queueCreateInfo.pQueuePriorities = &queuePriorities; VkDeviceCreateInfo deviceCreateInfo = {}; // Specify any desired device features here. We do not need any for this application, though. VkPhysicalDeviceFeatures deviceFeatures = {}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.enabledLayerCount = kEnabledLayers.size(); deviceCreateInfo.ppEnabledLayerNames = kEnabledLayers.data(); deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pEnabledFeatures = &deviceFeatures; VK_CHECK_RESULT(vkCreateDevice(kPhysicalDevice, &deviceCreateInfo, NULL, &kDevice)); // Get a handle to the only member of the queue family. vkGetDeviceQueue(kDevice, kQueueFamilyIndex, 0, &kQueue); // create command pool VkCommandPoolCreateInfo commandPoolCreateInfo = {}; commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // the queue family of this command pool. All command buffers allocated from this command pool, // must be submitted to queues of this family ONLY. commandPoolCreateInfo.queueFamilyIndex = kQueueFamilyIndex; VK_CHECK_RESULT(vkCreateCommandPool(kDevice, &commandPoolCreateInfo, NULL, &kCmdPool)); }