bool VulkanContext::SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface, bool enable_validation_layer) { u32 extension_count = 0; VkResult res = vkEnumerateDeviceExtensionProperties(m_physical_device, nullptr, &extension_count, nullptr); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkEnumerateDeviceExtensionProperties failed: "); return false; } if (extension_count == 0) { ERROR_LOG(VIDEO, "Vulkan: No extensions supported by device."); return false; } std::vector<VkExtensionProperties> available_extension_list(extension_count); res = vkEnumerateDeviceExtensionProperties(m_physical_device, nullptr, &extension_count, available_extension_list.data()); _assert_(res == VK_SUCCESS); for (const auto& extension_properties : available_extension_list) INFO_LOG(VIDEO, "Available extension: %s", extension_properties.extensionName); auto CheckForExtension = [&](const char* name, bool required) -> bool { if (std::find_if(available_extension_list.begin(), available_extension_list.end(), [&](const VkExtensionProperties& properties) { return !strcmp(name, properties.extensionName); }) != available_extension_list.end()) { INFO_LOG(VIDEO, "Enabling extension: %s", name); extension_list->push_back(name); return true; } if (required) { ERROR_LOG(VIDEO, "Vulkan: Missing required extension %s.", name); return false; } return true; }; if (enable_surface && !CheckForExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true)) { return false; } return true; }
void checkDeviceExtensionPresent(VkPhysicalDevice physicalDevice, const char* extensionName) { uint32_t extensionCount = 0; std::vector<VkExtensionProperties> extensions; vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, NULL); extensions.resize(extensionCount); vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, extensions.data()); for (auto& ext : extensions) { if (!strcmp(extensionName, ext.extensionName)) { return; } } cerr << "ERROR: cannot find extension: " << extensionName << endl; exit(1); }
VkBool32 VKTS_APIENTRY wsiGatherNeededDeviceExtensions(const VkPhysicalDevice physicalDevice) { if (!physicalDevice) { return VK_FALSE; } VkResult result; // uint32_t propertyCount = 0; result = vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &propertyCount, nullptr); if (result != VK_SUCCESS || propertyCount == 0) { return VK_FALSE; } std::vector<VkExtensionProperties> allDeviceExtensionProperties( propertyCount); result = vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &propertyCount, &allDeviceExtensionProperties[0]); if (result != VK_SUCCESS) { return VK_FALSE; } // VkBool32 extensionFound = VK_FALSE; for (uint32_t i = 0; i < propertyCount; i++) { if (strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, allDeviceExtensionProperties[i].extensionName) == 0) { if (!_extensionAddDeviceExtensions(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { return VK_FALSE; } extensionFound = VK_TRUE; break; } } return extensionFound; }
// Pass layerName == nullptr to get the extension list for the device. VkResult VulkanContext::GetDeviceLayerExtensionList(const char *layerName, std::vector<VkExtensionProperties> &extensions) { VkResult res; do { uint32_t device_extension_count; res = vkEnumerateDeviceExtensionProperties(physical_devices_[physical_device_], layerName, &device_extension_count, nullptr); if (res != VK_SUCCESS) return res; if (!device_extension_count) return VK_SUCCESS; extensions.resize(device_extension_count); res = vkEnumerateDeviceExtensionProperties(physical_devices_[physical_device_], layerName, &device_extension_count, extensions.data()); } while (res == VK_INCOMPLETE); return res; }
bool checkDeviceExtensionSupport(VkPhysicalDevice device) { uint32_t extensionCount; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); std::vector<VkExtensionProperties> availableExtensions(extensionCount); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); for (const auto& extension : availableExtensions) { requiredExtensions.erase(extension.extensionName); } return requiredExtensions.empty(); }
VkBool32 checkDeviceExtensionPresent(VkPhysicalDevice physicalDevice, const char* extensionName) { uint32_t extensionCount = 0; std::vector<VkExtensionProperties> extensions; vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, NULL); extensions.resize(extensionCount); vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, extensions.data()); for (auto& ext : extensions) { if (!strcmp(extensionName, ext.extensionName)) { return true; } } return false; }
/* * Return list of PhysicalDevice extensions provided by the specified layer * If pLayerName is NULL, will return extensions for ICD / loader. */ std::vector<VkExtensionProperties> PhysicalDevice::extensions(const char *pLayerName) const { std::vector<VkExtensionProperties> exts; VkResult err; do { uint32_t extCount = 0; err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName, &extCount, NULL); if (err == VK_SUCCESS) { exts.resize(extCount); err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName, &extCount, exts.data()); } } while (err == VK_INCOMPLETE); assert(err == VK_SUCCESS); return exts; }
// Move this up void vulkan_device_check_extensions(const std::vector<const char*>& extensions, VkPhysicalDevice physicalDevice) { uint32_t extensions_count = 0; Assert(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensions_count, nullptr) == VK_SUCCESS); Assert(extensions_count > 0); std::vector<VkExtensionProperties> available_extensions(extensions_count); Assert(vkEnumerateDeviceExtensionProperties( physicalDevice, nullptr, &extensions_count, (extensions_count > 0 ? &available_extensions[0] : nullptr)) == VK_SUCCESS); for (size_t i = 0; i < extensions.size(); ++i) { bool found = false; for (size_t j = 0; j < available_extensions.size(); ++j) { if (std::strcmp(available_extensions[j].extensionName, extensions[i]) == 0) found = true; } Assert(found, fmt::format("vulkan: extension '{}' not supported by the device", extensions[i])); } }
TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for(uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_NE(std::find_if( &properties[0], &properties[count], [](VkExtensionProperties const& properties) { return strcmp(properties.extensionName, "VK_KHR_swapchain") == 0; }), &properties[count]); } vkDestroyInstance(instance, nullptr); }
TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for(uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if(count < 2u) { continue; } std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]); count = 1; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } vkDestroyInstance(instance, nullptr); }
// Devices void Renderer::_InitDevice() { { uint32_t gpu_count = 0; // Read number of GPU's vkEnumeratePhysicalDevices(_instance, &gpu_count, nullptr); std::vector<VkPhysicalDevice> gpu_list(gpu_count); // Populate list vkEnumeratePhysicalDevices(_instance, &gpu_count, gpu_list.data()); _gpu = gpu_list[0]; // Get the first available list vkGetPhysicalDeviceProperties(_gpu, &_gpu_properties); vkGetPhysicalDeviceMemoryProperties(_gpu, &_gpu_memory_properties); } { uint32_t family_count = 0; // Read number of GPU queue family properties vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_property_list(family_count); // Populate list vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, family_property_list.data()); // Find the graphics family bool found = false; for (uint32_t i = 0; i < family_count; ++i) { if (family_property_list[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { found = true; _graphics_family_index = i; } } if (!found) { assert(0 && "Vulkan ERROR: Queue family supporting graphics not found."); std::exit(-1); } } // Instance Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateInstanceLayerProperties(&layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateInstanceLayerProperties(&layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Instance Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } // Device Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateDeviceLayerProperties(_gpu, &layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateDeviceLayerProperties(_gpu, &layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Device Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } float queue_priorities[] {1.0f}; VkDeviceQueueCreateInfo device_queue_create_info {}; device_queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; device_queue_create_info.queueFamilyIndex = _graphics_family_index; device_queue_create_info.queueCount = 1; device_queue_create_info.pQueuePriorities = queue_priorities; VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.queueCreateInfoCount = 1; device_create_info.pQueueCreateInfos = &device_queue_create_info; device_create_info.enabledLayerCount = (uint32_t) _device_layer_list.size(); device_create_info.ppEnabledLayerNames = _device_layer_list.data(); device_create_info.enabledExtensionCount = (uint32_t) _device_extension_list.size(); device_create_info.ppEnabledExtensionNames = _device_extension_list.data(); ErrorCheck(vkCreateDevice(_gpu, &device_create_info, nullptr, &_device)); vkGetDeviceQueue(_device, _graphics_family_index, 0, &_queue); }
int main(int argc, char** argv) { g_validationLayers = std::vector<const char*> { "VK_LAYER_LUNARG_mem_tracker", "VK_LAYER_GOOGLE_unique_objects", }; // Init GLFW { // Handle GLFW errors glfwSetErrorCallback([](int error, const char* description) { std::cout << "GLFW error: " << error << " - " << description << std::endl; }); // Initialize GLFW if (!glfwInit()) error("Cannot initialize GLFW."); // Check Vulkan support if (!glfwVulkanSupported()) error("Cannot find compatible Vulkan client driver."); } // Get Validation layers { uint32_t numInstanceLayers = 0; // Get numInstanceLayers if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, nullptr)) error("Vulkan: Could not enumerate instance layer properties."); if (numInstanceLayers > 0) { std::vector<VkLayerProperties> instanceLayers(numInstanceLayers); if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, instanceLayers.data())) error("Vulkan: Could not enumerate instance layer properties."); // Print layers: std::cout << "Validation layers: " << std::endl; for (int i = 0; i < numInstanceLayers; ++i) { std::cout << "\t" << instanceLayers[i].layerName << std::endl; std::cout << "\t\t" << instanceLayers[i].description << std::endl; std::cout << std::endl; } std::cout << std::endl; } else std::cout << "No validation layers found!" << std::endl; // TODO: Check Layers } // Check instance extensions { int numRequiredExtensions; const char** requiredExtensions; // Get required extensions from GLFW { requiredExtensions = glfwGetRequiredInstanceExtensions((int*)&numRequiredExtensions); if (numRequiredExtensions > 0) { // Write to global g_extensions for (int i = 0; i < numRequiredExtensions; ++i) g_extensions.push_back(requiredExtensions[i]); // Print std::cout << "Required Instance Extensions(GLFW):" << std::endl; for (int i = 0; i < numRequiredExtensions; ++i) { std::cout << "\t" << requiredExtensions[i] << std::endl; } std::cout << std::endl; } // TODO: Check extensions } // Get Instance extensions { VkResult err; uint32_t numInstanceExtensions; err = vkEnumerateInstanceExtensionProperties(nullptr, &numInstanceExtensions, nullptr); if (numInstanceExtensions > 0) { std::vector<VkExtensionProperties> instanceExtensions(numInstanceExtensions); err = vkEnumerateInstanceExtensionProperties(NULL, &numInstanceExtensions, instanceExtensions.data()); // Print std::cout << "Instance Extensions: " << std::endl; for (int i = 0; i < numInstanceExtensions; ++i) { std::cout << "\t" <<instanceExtensions[i].extensionName << std::endl; std::cout << "\t\t" << instanceExtensions[i].specVersion << std::endl; std::cout << std::endl; } std::cout << std::endl; } // TODO: Check instance extensions(with required instance extensions) } } // Create Vulkan Instance { VkApplicationInfo app; { app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pNext = nullptr; app.pApplicationName = "Vulkan test 1"; app.applicationVersion = 0; app.pEngineName = "Vulkan test 1"; app.engineVersion = 0; app.apiVersion = VK_API_VERSION; } VkInstanceCreateInfo instanceInfo; { instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceInfo.pNext = nullptr; instanceInfo.pApplicationInfo = &app; instanceInfo.enabledLayerCount = g_validationLayers.size(); instanceInfo.ppEnabledLayerNames = g_validationLayers.data(); instanceInfo.enabledExtensionCount = g_extensions.size(); instanceInfo.ppEnabledExtensionNames = g_extensions.data(); } // TODO: Aligned allocators VkAllocationCallbacks allocator; { allocator.pUserData = nullptr; allocator.pfnAllocation = [](void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)->void* { return malloc(size); }; allocator.pfnFree = [](void* pUserData, void* pMemory) { free(pMemory); }; allocator.pfnReallocation = [](void* pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) { free(pOriginal); return malloc(size); }; allocator.pfnInternalAllocation = nullptr; allocator.pfnInternalFree = nullptr; allocator.pfnReallocation = nullptr; } // Create vulkan instance VkResult vkError = vkCreateInstance(&instanceInfo, &allocator, &g_vkInstance); // Handle errors switch (vkError) { case VK_ERROR_INCOMPATIBLE_DRIVER: error("Drivers do not support vulkan. Drivers could be outdated."); break; case VK_ERROR_EXTENSION_NOT_PRESENT: error("Cannot find specified extension."); break; case VK_SUCCESS: // Succes! (prevent default from catching success as error) std::cout << "Vulkan instance created!" << std::endl; break; default: error("Could not create vulkan Instance. Drivers could be outdated."); break; } } // Look for GPU device { uint32_t numGPUs; VkResult vkError = vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, nullptr); if (numGPUs < 0) error("vkEnumeratePhysicalDevices could not find any GPU devices."); if (vkError) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); if (numGPUs > 0) { std::vector<VkPhysicalDevice> physicalDevices(numGPUs); if (vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, physicalDevices.data())) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); g_vkGPU = physicalDevices[0]; std::cout << numGPUs << " GPUs found!" << std::endl; } } // Get queue properties { uint32_t numQueues; vkGetPhysicalDeviceProperties(g_vkGPU, &g_vkGPUProperties); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, nullptr); if (numQueues == 0) error("vkGetPhysicalDeviceQueueFamilyProperties could not find any queues."); g_vkQueueProperties = std::vector<VkQueueFamilyProperties>(numQueues); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, g_vkQueueProperties.data()); } // Look for device layers (Unecessary code that does nothing) { uint32_t numDeviceLayers; if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, nullptr)) error("vkEnumerateDeviceLayerProperties failed!"); if (numDeviceLayers > 0) { std::vector<VkLayerProperties> deviceLayers(numDeviceLayers); if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, deviceLayers.data())) error("vkEnumerateDeviceLayerProperties failed!"); // TODO: Check device layers. } } // Look for device extensions (swapchain extension) { uint32_t numDeviceExtensions; bool extensionSwapChainFound = false; if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, nullptr)) error("vkEnumerateDeviceExtensionProperties failed!"); if (numDeviceExtensions > 0) { std::vector<VkExtensionProperties> deviceExtensions(numDeviceExtensions); if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, deviceExtensions.data())) error("vkEnumerateDeviceExtensionProperties failed!"); // Search for swapchain extension for (VkExtensionProperties extension : deviceExtensions) { if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) extensionSwapChainFound = true; } // Print std::cout << std::endl << "Extensions:" << std::endl; for (VkExtensionProperties extension : deviceExtensions) { std::cout << extension.extensionName << "(" << extension.specVersion << ")" << std::endl; } std::cout << std::endl; } if (!extensionSwapChainFound) error("Failed to find the " VK_KHR_SWAPCHAIN_EXTENSION_NAME " extension!"); } // TODO: Validate // Get instance function adresses { GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceFormatsKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceSupportKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, CreateSwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, DestroySwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetSwapchainImagesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, AcquireNextImageKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, QueuePresentKHR); } // Create window { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); g_window = glfwCreateWindow(g_width, g_height, "Vulkan test", NULL, NULL); if (!g_window) error("Could not create window!"); glfwSetWindowRefreshCallback(g_window, [](GLFWwindow* window) { // TODO: draw(); }); glfwSetFramebufferSizeCallback(g_window, [](GLFWwindow* window, int width, int height) { g_width = width; g_height = height; // TODO: resize(); }); } // Init swapchain { glfwCreateWindowSurface(g_vkInstance, g_window, nullptr, &g_vkSurface); std::vector<VkBool32> supportsPresent(g_vkQueueProperties.size()); for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) g_vkFPGetPhysicalDeviceSurfaceSupportKHR(g_vkGPU, i, g_vkSurface, &supportsPresent[i]); uint32_t graphicsQueueNodeIndex = UINT32_MAX; uint32_t presentQueueNodeIndex = UINT32_MAX; for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { if (graphicsQueueNodeIndex == UINT32_MAX) { graphicsQueueNodeIndex = i; } if (supportsPresent[i] == VK_TRUE) { graphicsQueueNodeIndex = i; presentQueueNodeIndex = i; break; } } //if (presentQueueNodeIndex == UINT32_MAX) { // for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { // if (supportsPresent[i] == VK_TRUE) { // presentQueueNodeIndex = i; // } // } //} if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) error("Could not find a graphics and a present queue."); if (graphicsQueueNodeIndex != presentQueueNodeIndex) error("Could not find a common graphics and present queue."); g_vkGraphicsQueueNodeIndex = graphicsQueueNodeIndex; //TODO: init device { float queuePriotities = 0.f; VkDeviceQueueCreateInfo queue; { queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue.pNext = NULL; queue.queueFamilyIndex = g_vkGraphicsQueueNodeIndex; queue.queueCount = 1; queue.pQueuePriorities = &queuePriotities; } } //vkGetDeviceQueue(g_vkDevice, g_vkGraphicsQueueNodeIndex, 0, g_vkQueue); } std::cin.get(); return 0; }
int main() { //Настроем вывод. setlocale(LC_ALL, "Russian"); //Подготовим данные приложения VkApplicationInfo app_info; memset(&app_info, 0, sizeof(app_info)); app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = app_name; #ifdef VK_API_VERSION_1_0 app_info.apiVersion = VK_API_VERSION_1_0; #else app_info.apiVersion = VK_API_VERSION; #endif app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 25); VkResult res; //заранее подготовим переменную для результата, она нам понадобится несколько раз. //Данные экземпляра VkInstanceCreateInfo instance_info; memset(&instance_info, 0, sizeof(instance_info)); instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_info.pApplicationInfo = &app_info; uint32_t available_instance_layer_count = 0; //узнаём кол-во установленных слоёв. res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, nullptr); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_instance_layers(available_instance_layer_count); //Получаем слои res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, available_instance_layers.data()); if (available_instance_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои экземпляра:\n"; for (uint32_t i = 0; i < available_instance_layer_count; i++) { VkLayerProperties &properties = available_instance_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; std::vector<const char *> instance_layers; instance_layers.push_back("VK_LAYER_LUNARG_standard_validation"); //И затем отправим их в стурктуру с информацией. instance_info.enabledLayerCount = instance_layers.size(); instance_info.ppEnabledLayerNames = instance_layers.data(); //Кол-во расширений. uint32_t available_instance_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, nullptr); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_instance_extensions(available_instance_extension_count); //Получаем расширения res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, available_instance_extensions.data()); if (available_instance_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения экземпляра:\n"; for (uint32_t i = 0; i < available_instance_extensions.size(); i++) { VkExtensionProperties &properties = available_instance_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } //Настройка расширений std::vector<const char *> instance_extensions; instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); instance_info.enabledExtensionCount = instance_extensions.size(); instance_info.ppEnabledExtensionNames = instance_extensions.data(); VkInstance instance = VK_NULL_HANDLE; res = vkCreateInstance(&instance_info, NULL, &instance); if (res != VK_SUCCESS) //С проверками особо заморачиваться не будем. { std::wcerr << L"Что-то не так...\n"; return -1; } else std::wcout << L"Экземпляр Vulkan создан.\n"; //Создадим указатели на функции таким образом. PFN_vkCreateDebugReportCallbackEXT fvkCreateDebugReportCallbackEXT = NULL; PFN_vkDestroyDebugReportCallbackEXT fvkDestroyDebugReportCallbackEXT = NULL; //И получим их. fvkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); fvkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"); /* Отлично, мы получили эти функции! Теперь, нам нужно подготовить информацию для callback'ов, а также * оставить хэндл, который мы конечно же потом уничтожим. */ //Структура, которую мы должны заполнить VkDebugReportCallbackCreateInfoEXT debug_report_callback_info; memset(&debug_report_callback_info, 0, sizeof(debug_report_callback_info)); debug_report_callback_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; debug_report_callback_info.flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; // Настало время прикрепить наш прототип здесь: debug_report_callback_info.pfnCallback = DebugReportCallback; VkDebugReportCallbackEXT debug_report_callback = VK_NULL_HANDLE; //И наконец-таки привзяываем наш Callback: res = fvkCreateDebugReportCallbackEXT(instance, &debug_report_callback_info, NULL, &debug_report_callback); if (res != VK_SUCCESS) { std::wcerr << L"Не удалось создать debug-report callback.\n"; return -1; } std::vector<VkPhysicalDevice> gpu_list; //здесь будем хранить физические устройства. uint32_t gpu_count; //кол-во девайсов //получаем колв-о девайсов и сразу проверяем на удачу. if (vkEnumeratePhysicalDevices(instance, &gpu_count, VK_NULL_HANDLE) != VK_SUCCESS) { std::wcerr << L"Посчитать физические устройства не удалось :(\n"; return -1; } gpu_list.resize(gpu_count); //заранее изменим размер под самый оптимальный. //Забираем физические девайсы if (vkEnumeratePhysicalDevices(instance, &gpu_count, gpu_list.data()) != VK_SUCCESS) { std::wcerr << L"Заполучить твои физические устройства не удалось, но я приду за ними в следующий раз!\n"; return -1; } //Выбираем видеокарту VkPhysicalDevice gpu = gpu_list[0]; //Теперь, семейства. uint32_t family_count = 0; //кол-во семейтсв vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_properties_list(family_count); vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, family_properties_list.data()); //Листаем семейтсва и получаем нужное. uint32_t valid_family_index = (uint32_t) -1; //значение -1 будем использовать как "не найдено, 404". for (uint32_t i = 0; i < family_count; i++) //листаем все семейства. { VkQueueFamilyProperties &properties = family_properties_list[i]; if (properties.queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (valid_family_index == (uint32_t) -1) valid_family_index = i; } } //И если наш индекс всё ещё не перезаписан, то.. if (valid_family_index == (uint32_t) -1) return -1; //Описываем очереди. VkDeviceQueueCreateInfo device_queue_info; memset(&device_queue_info, 0, sizeof(device_queue_info)); device_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; float device_queue_priority[] = {1.0f}; device_queue_info.queueCount = 1; device_queue_info.queueFamilyIndex = valid_family_index; device_queue_info.pQueuePriorities = device_queue_priority; VkDeviceCreateInfo device_info; memset(&device_info, 0, sizeof(device_info)); device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &device_queue_info; uint32_t available_device_layer_count = 0; res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_device_layers(available_device_layer_count); res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, available_device_layers.data()); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить слои.\n"; return -1; } if (available_device_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои устройства:\n"; for (uint32_t i = 0; i < available_device_layer_count; i++) { //Сделаем красивый вывод для имени и описания слоя. VkLayerProperties &properties = available_device_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; //Кол-во расширений. uint32_t available_device_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_device_extensions(available_device_extension_count); //Получаем расширения res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, available_device_extensions.data()); if (available_device_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения устройства:\n"; for (uint32_t i = 0; i < available_device_extensions.size(); i++) { VkExtensionProperties &properties = available_device_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } std::vector<const char *> device_layers = instance_layers; //Расширения и слои device_info.enabledLayerCount = device_layers.size(); device_info.ppEnabledLayerNames = device_layers.data(); //А расширения устройства оставим и на сей раз пустым. std::vector<const char *> device_extensions; device_info.enabledExtensionCount = device_extensions.size(); device_info.ppEnabledExtensionNames = device_extensions.data(); VkDevice device = VK_NULL_HANDLE; if (vkCreateDevice(gpu, &device_info, NULL, &device) != VK_SUCCESS) return -1; vkDestroyDevice(device, NULL); fvkDestroyDebugReportCallbackEXT(instance, debug_report_callback, NULL); vkDestroyInstance(instance, NULL); std::wcout << L"Пожарено!\n"; return 0; }
gboolean gst_vulkan_device_open (GstVulkanDevice * device, GError ** error) { const char *extension_names[64]; uint32_t enabled_extension_count = 0; uint32_t device_extension_count = 0; VkExtensionProperties *device_extensions = NULL; uint32_t enabled_layer_count = 0; gchar **enabled_layers; uint32_t device_layer_count = 0; VkLayerProperties *device_layers; gboolean have_swapchain_ext; VkPhysicalDevice gpu; VkResult err; guint i; g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), FALSE); GST_OBJECT_LOCK (device); if (device->priv->opened) { GST_OBJECT_UNLOCK (device); return TRUE; } if (!_physical_device_info (device, error)) goto error; gpu = gst_vulkan_device_get_physical_device (device); /* Look for validation layers */ err = vkEnumerateDeviceLayerProperties (gpu, &device_layer_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceLayerProperties") < 0) goto error; device_layers = g_new0 (VkLayerProperties, device_layer_count); err = vkEnumerateDeviceLayerProperties (gpu, &device_layer_count, device_layers); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceLayerProperties") < 0) { g_free (device_layers); goto error; } _check_for_all_layers (G_N_ELEMENTS (device_validation_layers), device_validation_layers, device_layer_count, device_layers, &enabled_layer_count, &enabled_layers); g_free (device_layers); device_layers = NULL; err = vkEnumerateDeviceExtensionProperties (gpu, NULL, &device_extension_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceExtensionProperties") < 0) { g_strfreev (enabled_layers); goto error; } GST_DEBUG_OBJECT (device, "Found %u extensions", device_extension_count); have_swapchain_ext = 0; enabled_extension_count = 0; memset (extension_names, 0, sizeof (extension_names)); device_extensions = g_new0 (VkExtensionProperties, device_extension_count); err = vkEnumerateDeviceExtensionProperties (gpu, NULL, &device_extension_count, device_extensions); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateDeviceExtensionProperties") < 0) { g_strfreev (enabled_layers); g_free (device_extensions); goto error; } for (uint32_t i = 0; i < device_extension_count; i++) { GST_TRACE_OBJECT (device, "checking device extension %s", device_extensions[i].extensionName); if (!strcmp (VK_KHR_SWAPCHAIN_EXTENSION_NAME, device_extensions[i].extensionName)) { have_swapchain_ext = TRUE; extension_names[enabled_extension_count++] = (gchar *) VK_KHR_SWAPCHAIN_EXTENSION_NAME; } g_assert (enabled_extension_count < 64); } if (!have_swapchain_ext) { g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_EXTENSION_NOT_PRESENT, "Failed to find required extension, \"" VK_KHR_SWAPCHAIN_EXTENSION_NAME "\""); g_strfreev (enabled_layers); goto error; } g_free (device_extensions); vkGetPhysicalDeviceProperties (gpu, &device->gpu_props); vkGetPhysicalDeviceMemoryProperties (gpu, &device->memory_properties); vkGetPhysicalDeviceFeatures (gpu, &device->gpu_features); vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families, NULL); g_assert (device->n_queue_families >= 1); device->queue_family_props = g_new0 (VkQueueFamilyProperties, device->n_queue_families); vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families, device->queue_family_props); /* FIXME: allow overriding/selecting */ for (i = 0; i < device->n_queue_families; i++) { if (device->queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) break; } if (i >= device->n_queue_families) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to find a compatible queue family"); g_strfreev (enabled_layers); goto error; } device->queue_family_id = i; device->n_queues = 1; { VkDeviceQueueCreateInfo queue_info = { 0, }; VkDeviceCreateInfo device_info = { 0, }; gfloat queue_priority = 0.5; queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info.pNext = NULL; queue_info.queueFamilyIndex = device->queue_family_id; queue_info.queueCount = device->n_queues; queue_info.pQueuePriorities = &queue_priority; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.pNext = NULL; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; device_info.enabledLayerCount = enabled_layer_count; device_info.ppEnabledLayerNames = (const char *const *) enabled_layers; device_info.enabledExtensionCount = enabled_extension_count; device_info.ppEnabledExtensionNames = (const char *const *) extension_names; device_info.pEnabledFeatures = NULL; err = vkCreateDevice (gpu, &device_info, NULL, &device->device); if (gst_vulkan_error_to_g_error (err, error, "vkCreateDevice") < 0) { g_strfreev (enabled_layers); goto error; } } g_strfreev (enabled_layers); { VkCommandPoolCreateInfo cmd_pool_info = { 0, }; cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmd_pool_info.pNext = NULL; cmd_pool_info.queueFamilyIndex = device->queue_family_id; cmd_pool_info.flags = 0; err = vkCreateCommandPool (device->device, &cmd_pool_info, NULL, &device->cmd_pool); if (gst_vulkan_error_to_g_error (err, error, "vkCreateCommandPool") < 0) goto error; } GST_OBJECT_UNLOCK (device); return TRUE; error: { GST_OBJECT_UNLOCK (device); return FALSE; } }
bool VulkanCommon::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { uint32_t extensions_count = 0; if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || (extensions_count == 0) ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<VkExtensionProperties> available_extensions( extensions_count ); if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<const char*> device_extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; for( size_t i = 0; i < device_extensions.size(); ++i ) { if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; return false; } } VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties( physical_device, &device_properties ); vkGetPhysicalDeviceFeatures( physical_device, &device_features ); uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); if( (major_version < 1) && (device_properties.limits.maxImageDimension2D < 4096) ) { std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; return false; } uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); if( queue_families_count == 0 ) { std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; return false; } std::vector<VkQueueFamilyProperties> queue_family_properties( queue_families_count ); std::vector<VkBool32> queue_present_support( queue_families_count ); vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for( uint32_t i = 0; i < queue_families_count; ++i ) { vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); if( (queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { // Select first queue that supports graphics if( graphics_queue_family_index == UINT32_MAX ) { graphics_queue_family_index = i; } // If there is queue that supports both graphics and present - prefer it if( queue_present_support[i] ) { selected_graphics_queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have queue that supports both graphics and present so we have to use separate queues for( uint32_t i = 0; i < queue_families_count; ++i ) { if( queue_present_support[i] ) { present_queue_family_index = i; break; } } // If this device doesn't support queues with graphics and present capabilities don't use it if( (graphics_queue_family_index == UINT32_MAX) || (present_queue_family_index == UINT32_MAX) ) { std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; return false; } selected_graphics_queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }
bool check_physical_device_properties(VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index, const std::vector<const char *> &device_extensions) { uint32_t extensions_count = 0; if ((vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, nullptr) != VK_SUCCESS) || (extensions_count == 0)) { SET_ERROR (LOG_TYPE, "Error occurred during physical device %d extensions enumeration!", physical_device); return false; } std::vector<VkExtensionProperties> available_extensions(extensions_count); if (vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, &available_extensions[0]) != VK_SUCCESS) { SET_ERROR (LOG_TYPE, "Error occurred during physical device %d extensions enumeration!", physical_device); return false; } for (size_t i = 0; i < device_extensions.size(); ++i) { if (!utils::check_extension(device_extensions[i], available_extensions)) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't support extension named \"%s\"!", physical_device, device_extensions[i]); return false; } } VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties(physical_device, &device_properties); vkGetPhysicalDeviceFeatures(physical_device, &device_features); uint32_t major_version = VK_VERSION_MAJOR(device_properties.apiVersion); if ((major_version < 1) && (device_properties.limits.maxImageDimension2D < 4096)) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't support required parameters!", physical_device); return false; } uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr); if (queue_families_count == 0) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't have any handle families!", physical_device); return false; } std::vector<VkQueueFamilyProperties> queue_family_properties(queue_families_count); std::vector<VkBool32> queue_present_support(queue_families_count); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, &queue_family_properties[0]); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for (uint32_t i = 0; i < queue_families_count; ++i) { vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, vk_globals::surface, &queue_present_support[i]); if ((queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { // Select first handle that supports graphics if (graphics_queue_family_index == UINT32_MAX) { graphics_queue_family_index = i; } // If there is handle that supports both graphics and present - prefer it if (queue_present_support[i]) { selected_graphics_queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have handle that supports both graphics and present so we have to use separate queues for (uint32_t i = 0; i < queue_families_count; ++i) { if (queue_present_support[i]) { present_queue_family_index = i; break; } } // If this device doesn't support queues with graphics and present capabilities don't use it if ((graphics_queue_family_index == UINT32_MAX) || (present_queue_family_index == UINT32_MAX)) { SET_ERROR (LOG_TYPE, "Could not find handle families with required properties on physical device %d!", physical_device); return false; } selected_graphics_queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }
bool select_device(std::vector<VkPhysicalDevice> &devices, VkPhysicalDevice &chosen_device) { bool suitable_dev_found = false; unsigned int best_score = 0; for (const auto& device : devices) { unsigned int score = 0; VkPhysicalDeviceProperties deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceProperties(device, &deviceProperties); vkGetPhysicalDeviceFeatures(device, &deviceFeatures); if(deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU){score+= 1000;} if(!deviceFeatures.geometryShader){score-= 1000000;} uint32_t queueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); /*checks that all the needed queue families are supported */ bool graphics_found = false, present_found = false; int i = 0; for(const auto& queueFamily : queueFamilies) { if (!graphics_found && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { graphics_found = true; graphics_queue_family_index = i; } VkBool32 presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); if (!present_found && queueFamily.queueCount > 0 && presentSupport) { present_found = true; present_queue_family_index = i; } if(present_found && graphics_found){break;}//if it finds both there is no point in keeping looking for queue families i++; } if(!(graphics_found && present_found)){continue;}//if it didn't find both cues go to next device /*checking for device specific extnsions support*/ uint32_t extensionCount; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); std::vector<VkExtensionProperties> availableExtensions(extensionCount); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); std::set<std::string> requiredExtensions(device_extensions.begin(), device_extensions.end()); for (const auto& extension : availableExtensions) { requiredExtensions.erase(extension.extensionName); } if(!requiredExtensions.empty()){continue;} /*checks that swap chains are supported*/ bool swapChainAdequate = false; SwapChainSupportDetails swapChainSupport = query_swap_chain_support(device); swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); if(score >= best_score) { chosen_device = device; suitable_dev_found = true; best_score = score; } if(!swapChainAdequate){continue;} } return suitable_dev_found; //if no device is found }