diff options
| author | Quentin LADEVIE <qladevie@wanadev.fr> | 2022-02-17 18:29:40 +0100 |
|---|---|---|
| committer | Quentin LADEVIE <qladevie@wanadev.fr> | 2022-02-17 18:29:40 +0100 |
| commit | 5b87100b8ca9953832086f392ee60e1421654b3b (patch) | |
| tree | 5ce2c36ebd4abab6cf9e71e0807aef7c9906a498 | |
| parent | 21684829d4817ebc7d26f2454e4b15052ec94bd7 (diff) | |
Select a physical based on supported vulkan features
| -rw-r--r-- | include/vk-context.hpp | 8 | ||||
| -rw-r--r-- | include/vulkan-loader.hpp | 2 | ||||
| -rw-r--r-- | src/vk-context.cpp | 110 |
3 files changed, 107 insertions, 13 deletions
diff --git a/include/vk-context.hpp b/include/vk-context.hpp index 405cd83..7b7f6bf 100644 --- a/include/vk-context.hpp +++ b/include/vk-context.hpp @@ -1,6 +1,8 @@ #ifndef __VK_CONTEXT_HPP_ #define __VK_CONTEXT_HPP_ +#include <vector> + #include "vulkan-loader.hpp" #include "thirdparty/vk_mem_alloc.h" @@ -33,6 +35,12 @@ class vkcontext { void select_queue(); + void check_available_instance_layers(std::vector<const char*>& needed_layers); + + void check_available_instance_extensions(std::vector<const char*>& available_layers, std::vector<const char*>& needed_extensions); + + bool support_required_features(VkPhysicalDevice physical_device); + VkDebugUtilsMessengerEXT debugMessenger; }; diff --git a/include/vulkan-loader.hpp b/include/vulkan-loader.hpp index 6bdf54f..16df7a6 100644 --- a/include/vulkan-loader.hpp +++ b/include/vulkan-loader.hpp @@ -49,7 +49,9 @@ X(vkDestroyInstance) \ X(vkEnumeratePhysicalDevices) \ X(vkGetPhysicalDeviceProperties) \ + X(vkGetPhysicalDeviceProperties2) \ X(vkGetPhysicalDeviceFeatures) \ + X(vkGetPhysicalDeviceFeatures2) \ X(vkGetPhysicalDeviceQueueFamilyProperties) \ X(vkGetPhysicalDeviceMemoryProperties) \ X(vkCreateDevice) \ diff --git a/src/vk-context.cpp b/src/vk-context.cpp index d68dca9..52edc09 100644 --- a/src/vk-context.cpp +++ b/src/vk-context.cpp @@ -1,8 +1,8 @@ -#include <vector> #include <iostream> #include <cassert> #include "vk-context.hpp" +#include "vulkan-loader.hpp" #define VMA_IMPLEMENTATION #include "thirdparty/vk_mem_alloc.h" @@ -28,6 +28,8 @@ vkcontext::vkcontext() { create_instance(); create_device(); + create_debugger(); + create_memory_allocator(); } vkcontext::~vkcontext() { @@ -47,11 +49,15 @@ void vkcontext::create_instance() { app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); app_info.apiVersion = VK_API_VERSION_1_2; - - std::vector<const char*> layers = { + std::vector<const char*> needed_layers = { +#if defined(_DEBUG) "VK_LAYER_KHRONOS_validation", +#endif }; - std::vector<const char*> extensions = { + + check_available_instance_layers(needed_layers); + + std::vector<const char*> needed_extensions = { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, "VK_KHR_surface", #if defined(LINUX) @@ -63,20 +69,20 @@ void vkcontext::create_instance() { #endif }; + check_available_instance_extensions(needed_layers, needed_extensions); + VkInstanceCreateInfo instance_create_info = {}; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.pApplicationInfo = &app_info; - instance_create_info.enabledLayerCount = layers.size(); - instance_create_info.ppEnabledLayerNames = layers.data(); - instance_create_info.enabledExtensionCount = extensions.size(); - instance_create_info.ppEnabledExtensionNames = extensions.data(); + instance_create_info.enabledLayerCount = needed_layers.size(); + instance_create_info.ppEnabledLayerNames = needed_layers.data(); + instance_create_info.enabledExtensionCount = needed_extensions.size(); + instance_create_info.ppEnabledExtensionNames = needed_extensions.data(); VKRESULT(vkCreateInstance(&instance_create_info, nullptr, &instance)) load_instance_functions(instance); - create_debugger(); - std::cerr << "Instance ready" << std::endl; } @@ -146,8 +152,6 @@ void vkcontext::create_device() { vkGetDeviceQueue(device, queue_index, 0, &queue); - create_memory_allocator(); - std::cerr << "Device ready" << std::endl; } @@ -175,7 +179,14 @@ void vkcontext::select_physical_device() { std::vector<VkPhysicalDevice> physical_devices { physical_devices_count }; vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data()); - physical_device = physical_devices[0]; + + for (auto& physical_device: physical_devices) { + if (support_required_features(physical_device)) { + this->physical_device = physical_device; + } + } + + assert(physical_device != VK_NULL_HANDLE); } void vkcontext::select_queue() { @@ -196,3 +207,76 @@ void vkcontext::select_queue() { exit(1); } +void vkcontext::check_available_instance_layers(std::vector<const char*>& needed_layers) { + uint32_t property_count = 0; + vkEnumerateInstanceLayerProperties(&property_count, VK_NULL_HANDLE); + + std::vector<VkLayerProperties> layer_properties { property_count }; + vkEnumerateInstanceLayerProperties(&property_count, layer_properties.data()); + + uint32_t available_needed_layers_count = 0; + + std::vector<const char*> available_layers; + for (auto& layer_property: layer_properties) { + for (auto& needed_layer: needed_layers) { + if (strcmp(layer_property.layerName, needed_layer) == 0) { + available_layers.push_back(needed_layer); + available_needed_layers_count++; + } + } + } + + assert(available_needed_layers_count == needed_layers.size()); +} + +void vkcontext::check_available_instance_extensions(std::vector<const char*>& available_layers, std::vector<const char*>& needed_extensions) { + uint32_t vulkan_extensions_count = 0; + vkEnumerateInstanceExtensionProperties(VK_NULL_HANDLE, &vulkan_extensions_count, VK_NULL_HANDLE); + + std::vector<VkExtensionProperties> vulkan_extensions_properties { vulkan_extensions_count }; + vkEnumerateInstanceExtensionProperties(VK_NULL_HANDLE, &vulkan_extensions_count, vulkan_extensions_properties.data()); + + uint32_t available_needed_extensions_count = 0; + + std::vector<const char*> available_extensions; + for (auto& extension: vulkan_extensions_properties) { + for (auto& needed_extension: needed_extensions) { + if (strcmp(extension.extensionName, needed_extension) == 0) { + available_extensions.push_back(needed_extension); + available_needed_extensions_count++; + } + } + } + + assert(available_needed_extensions_count == needed_extensions.size()); +} + +bool vkcontext::support_required_features(VkPhysicalDevice physical_device) { + VkPhysicalDeviceProperties physical_device_properties = {}; + + vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties); + + VkPhysicalDeviceVulkan12Features vulkan_12_features = {}; + vulkan_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + + VkPhysicalDeviceFeatures2 physical_device_features = {}; + physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + physical_device_features.pNext = &vulkan_12_features; + + vkGetPhysicalDeviceFeatures2(physical_device, &physical_device_features); + + if (vulkan_12_features.bufferDeviceAddress == VK_TRUE && + vulkan_12_features.runtimeDescriptorArray == VK_TRUE && + vulkan_12_features.shaderStorageImageArrayNonUniformIndexing == VK_TRUE && + vulkan_12_features.shaderSampledImageArrayNonUniformIndexing == VK_TRUE && + vulkan_12_features.descriptorBindingPartiallyBound == VK_TRUE && + vulkan_12_features.descriptorBindingPartiallyBound == VK_TRUE && + vulkan_12_features.descriptorBindingUpdateUnusedWhilePending == VK_TRUE) { + std::cerr << "Using physical device " << physical_device_properties.deviceName << std::endl; + return true; + } else { + std::cerr << "Physical device " << physical_device_properties.deviceName << " is missing some features" << std::endl; + return false; + } +} + |
