diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index bbd3b6b..b738735 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -844,7 +844,10 @@ std::vector check_device_extension_support( } // clang-format off -bool supports_features(VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeatures requested) { +bool supports_features(VkPhysicalDeviceFeatures supported, + VkPhysicalDeviceFeatures requested, + const std::vector& extension_supported, + const std::vector& extension_requested) { if (requested.robustBufferAccess && !supported.robustBufferAccess) return false; if (requested.fullDrawIndexUint32 && !supported.fullDrawIndexUint32) return false; if (requested.imageCubeArray && !supported.imageCubeArray) return false; @@ -900,75 +903,14 @@ bool supports_features(VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeatu if (requested.sparseResidencyAliased && !supported.sparseResidencyAliased) return false; if (requested.variableMultisampleRate && !supported.variableMultisampleRate) return false; if (requested.inheritedQueries && !supported.inheritedQueries) return false; - return true; -} -#if defined(VK_API_VERSION_1_2) -bool supports_features_11(VkPhysicalDeviceVulkan11Features supported, VkPhysicalDeviceVulkan11Features requested){ - if (requested.storageBuffer16BitAccess && !supported.storageBuffer16BitAccess) return false; - if (requested.uniformAndStorageBuffer16BitAccess && !supported.uniformAndStorageBuffer16BitAccess) return false; - if (requested.storagePushConstant16 && !supported.storagePushConstant16) return false; - if (requested.storageInputOutput16 && !supported.storageInputOutput16) return false; - if (requested.multiview && !supported.multiview) return false; - if (requested.multiviewGeometryShader && !supported.multiviewGeometryShader) return false; - if (requested.multiviewTessellationShader && !supported.multiviewTessellationShader) return false; - if (requested.variablePointersStorageBuffer && !supported.variablePointersStorageBuffer) return false; - if (requested.variablePointers && !supported.variablePointers) return false; - if (requested.protectedMemory && !supported.protectedMemory) return false; - if (requested.samplerYcbcrConversion && !supported.samplerYcbcrConversion) return false; - if (requested.shaderDrawParameters && !supported.shaderDrawParameters) return false; + + for(auto i = 0; i < extension_requested.size(); ++i) { + auto res = extension_requested[i].match(extension_supported[i]); + if(!res) return false; + } + return true; } -bool supports_features_12(VkPhysicalDeviceVulkan12Features supported, VkPhysicalDeviceVulkan12Features requested){ - if(requested.samplerMirrorClampToEdge && !supported.samplerMirrorClampToEdge) return false; - if(requested.drawIndirectCount && !supported.drawIndirectCount) return false; - if(requested.storageBuffer8BitAccess && !supported.storageBuffer8BitAccess) return false; - if(requested.uniformAndStorageBuffer8BitAccess && !supported.uniformAndStorageBuffer8BitAccess) return false; - if(requested.storagePushConstant8 && !supported.storagePushConstant8) return false; - if(requested.shaderBufferInt64Atomics && !supported.shaderBufferInt64Atomics) return false; - if(requested.shaderSharedInt64Atomics && !supported.shaderSharedInt64Atomics) return false; - if(requested.shaderFloat16 && !supported.shaderFloat16) return false; - if(requested.shaderInt8 && !supported.shaderInt8) return false; - if(requested.descriptorIndexing && !supported.descriptorIndexing) return false; - if(requested.shaderInputAttachmentArrayDynamicIndexing && !supported.shaderInputAttachmentArrayDynamicIndexing) return false; - if(requested.shaderUniformTexelBufferArrayDynamicIndexing && !supported.shaderUniformTexelBufferArrayDynamicIndexing) return false; - if(requested.shaderStorageTexelBufferArrayDynamicIndexing && !supported.shaderStorageTexelBufferArrayDynamicIndexing) return false; - if(requested.shaderUniformBufferArrayNonUniformIndexing && !supported.shaderUniformBufferArrayNonUniformIndexing) return false; - if(requested.shaderSampledImageArrayNonUniformIndexing && !supported.shaderSampledImageArrayNonUniformIndexing) return false; - if(requested.shaderStorageBufferArrayNonUniformIndexing && !supported.shaderStorageBufferArrayNonUniformIndexing) return false; - if(requested.shaderStorageImageArrayNonUniformIndexing && !supported.shaderStorageImageArrayNonUniformIndexing) return false; - if(requested.shaderInputAttachmentArrayNonUniformIndexing && !supported.shaderInputAttachmentArrayNonUniformIndexing) return false; - if(requested.shaderUniformTexelBufferArrayNonUniformIndexing && !supported.shaderUniformTexelBufferArrayNonUniformIndexing) return false; - if(requested.shaderStorageTexelBufferArrayNonUniformIndexing && !supported.shaderStorageTexelBufferArrayNonUniformIndexing) return false; - if(requested.descriptorBindingUniformBufferUpdateAfterBind && !supported.descriptorBindingUniformBufferUpdateAfterBind) return false; - if(requested.descriptorBindingSampledImageUpdateAfterBind && !supported.descriptorBindingSampledImageUpdateAfterBind) return false; - if(requested.descriptorBindingStorageImageUpdateAfterBind && !supported.descriptorBindingStorageImageUpdateAfterBind) return false; - if(requested.descriptorBindingStorageBufferUpdateAfterBind && !supported.descriptorBindingStorageBufferUpdateAfterBind) return false; - if(requested.descriptorBindingUniformTexelBufferUpdateAfterBind && !supported.descriptorBindingUniformTexelBufferUpdateAfterBind) return false; - if(requested.descriptorBindingStorageTexelBufferUpdateAfterBind && !supported.descriptorBindingStorageTexelBufferUpdateAfterBind) return false; - if(requested.descriptorBindingUpdateUnusedWhilePending && !supported.descriptorBindingUpdateUnusedWhilePending) return false; - if(requested.descriptorBindingPartiallyBound && !supported.descriptorBindingPartiallyBound) return false; - if(requested.descriptorBindingVariableDescriptorCount && !supported.descriptorBindingVariableDescriptorCount) return false; - if(requested.runtimeDescriptorArray && !supported.runtimeDescriptorArray) return false; - if(requested.samplerFilterMinmax && !supported.samplerFilterMinmax) return false; - if(requested.scalarBlockLayout && !supported.scalarBlockLayout) return false; - if(requested.imagelessFramebuffer && !supported.imagelessFramebuffer) return false; - if(requested.uniformBufferStandardLayout && !supported.uniformBufferStandardLayout) return false; - if(requested.shaderSubgroupExtendedTypes && !supported.shaderSubgroupExtendedTypes) return false; - if(requested.separateDepthStencilLayouts && !supported.separateDepthStencilLayouts) return false; - if(requested.hostQueryReset && !supported.hostQueryReset) return false; - if(requested.timelineSemaphore && !supported.timelineSemaphore) return false; - if(requested.bufferDeviceAddress && !supported.bufferDeviceAddress) return false; - if(requested.bufferDeviceAddressCaptureReplay && !supported.bufferDeviceAddressCaptureReplay) return false; - if(requested.bufferDeviceAddressMultiDevice && !supported.bufferDeviceAddressMultiDevice) return false; - if(requested.vulkanMemoryModel && !supported.vulkanMemoryModel) return false; - if(requested.vulkanMemoryModelDeviceScope && !supported.vulkanMemoryModelDeviceScope) return false; - if(requested.vulkanMemoryModelAvailabilityVisibilityChains && !supported.vulkanMemoryModelAvailabilityVisibilityChains) return false; - if(requested.shaderOutputViewportIndex && !supported.shaderOutputViewportIndex) return false; - if(requested.shaderOutputLayer && !supported.shaderOutputLayer) return false; - if(requested.subgroupBroadcastDynamicId && !supported.subgroupBroadcastDynamicId) return false; - return true; -} -#endif // clang-format on // finds the first queue which supports graphics operations. returns QUEUE_INDEX_MAX_VALUE if none is found uint32_t get_graphics_queue_index(std::vector const& families) { @@ -1049,7 +991,8 @@ uint32_t get_present_queue_index(VkPhysicalDevice const phys_device, PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details( - uint32_t instance_version, VkPhysicalDevice phys_device) const { + uint32_t instance_version, VkPhysicalDevice phys_device, + std::vector extension_features_as_template) const { PhysicalDeviceSelector::PhysicalDeviceDesc desc{}; desc.phys_device = phys_device; auto queue_families = detail::get_vector_noerror( @@ -1062,16 +1005,20 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi #if defined(VK_API_VERSION_1_1) desc.device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - -#if defined(VK_API_VERSION_1_2) - desc.device_features_11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; - desc.device_features_12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; - desc.device_features2.pNext = &desc.device_features_11; - desc.device_features_11.pNext = &desc.device_features_12; -#endif - if (instance_version >= VK_API_VERSION_1_1) { - detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &desc.device_features2); - } + desc.extension_features = extension_features_as_template; + if (instance_version >= VK_API_VERSION_1_1) { + ExtensionFeatures* prev = nullptr; + for(auto& extension : desc.extension_features) { + if(prev != nullptr) { + prev->structure->pNext = extension.structure; + } + prev = &extension; + } + if(desc.extension_features.size() > 0) { + desc.device_features2.pNext = &desc.extension_features[0].structure; + } + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &desc.device_features2); + } #endif return desc; } @@ -1112,7 +1059,6 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable(Phys if (desired_extensions_supported.size() != criteria.desired_extensions.size()) suitable = Suitable::partial; - bool swapChainAdequate = false; if (criteria.defer_surface_initialization) { swapChainAdequate = true; @@ -1142,21 +1088,10 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable(Phys return Suitable::no; } - bool required_features_supported = detail::supports_features(pd.device_features, criteria.required_features); + bool required_features_supported = detail::supports_features(pd.device_features, criteria.required_features, + pd.extension_features, criteria.extension_features); if (!required_features_supported) return Suitable::no; -#if defined(VK_API_VERSION_1_2) - if (instance_info.version >= VK_API_VERSION_1_2) { - bool required_features_11_supported = - detail::supports_features_11(pd.device_features_11, criteria.required_features_11); - if (!required_features_11_supported) return Suitable::no; - - bool required_features_12_supported = - detail::supports_features_12(pd.device_features_12, criteria.required_features_12); - if (!required_features_12_supported) return Suitable::no; - } -#endif - bool has_required_memory = false; bool has_preferred_memory = false; for (uint32_t i = 0; i < pd.mem_properties.memoryHeapCount; i++) { @@ -1205,7 +1140,9 @@ detail::Result PhysicalDeviceSelector::select() const { std::vector phys_device_descriptions; for (auto& phys_device : physical_devices) { - phys_device_descriptions.push_back(populate_device_details(instance_info.version, phys_device)); + phys_device_descriptions.push_back(populate_device_details(instance_info.version, + phys_device, + criteria.extension_features)); } PhysicalDeviceDesc selected_device{}; @@ -1231,12 +1168,7 @@ detail::Result PhysicalDeviceSelector::select() const { out_device.physical_device = selected_device.phys_device; out_device.surface = instance_info.surface; out_device.features = criteria.required_features; -#if defined(VK_API_VERSION_1_2) - out_device.features_11 = criteria.required_features_11; - out_device.features_11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; - out_device.features_12 = criteria.required_features_12; - out_device.features_12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; -#endif + out_device.extension_features = criteria.extension_features; out_device.properties = selected_device.device_properties; out_device.memory_properties = selected_device.mem_properties; out_device.queue_families = selected_device.queue_families; @@ -1321,20 +1253,17 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::set_desired_version(uint32_t maj criteria.desired_version = VK_MAKE_VERSION(major, minor, 0); return *this; } -PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features(VkPhysicalDeviceFeatures const& features) { - criteria.required_features = features; - return *this; -} #if defined(VK_API_VERSION_1_2) +// Just calls add_required_features PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_11( VkPhysicalDeviceVulkan11Features const& features_11) { - criteria.required_features_11 = features_11; - return *this; + add_required_features(features_11); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_12( VkPhysicalDeviceVulkan12Features const& features_12) { - criteria.required_features_12 = features_12; - return *this; + add_required_features(features_12); + return *this; } #endif PhysicalDeviceSelector& PhysicalDeviceSelector::defer_surface_initialization() { @@ -1467,63 +1396,40 @@ detail::Result DeviceBuilder::build() const { if (physical_device.surface != VK_NULL_HANDLE || physical_device.defer_surface_initialization) extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); - std::vector pNext_chain = info.pNext_chain; + bool has_phys_dev_features_2 = false; - // check if certain structs were added in the pNext chain by the user - bool has_phys_dev_features_2 = false; - bool has_phys_dev_vulkan_features_11 = false; - bool has_phys_dev_vulkan_features_12 = false; - for (auto& pNext_struct : pNext_chain) { - if (pNext_struct->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { - has_phys_dev_features_2 = true; - } - if (pNext_struct->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES) { - has_phys_dev_vulkan_features_11 = true; - } - if (pNext_struct->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES) { - has_phys_dev_vulkan_features_12 = true; - } - } - -// Add the correct structs to the pNext chain if api is 1.1/1.2 and aren't already present -// This is to guard against users who were already doing that +// Setup the pNexts of all the extension features #if defined(VK_API_VERSION_1_1) - VkPhysicalDeviceFeatures2 local_features2{}; - if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0) && !has_phys_dev_features_2) { - local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - local_features2.features = physical_device.features; - pNext_chain.push_back(reinterpret_cast(&local_features2)); - has_phys_dev_features_2 = true; - } -#if defined(VK_API_VERSION_1_2) - VkPhysicalDeviceVulkan11Features local_features_11 = physical_device.features_11; - VkPhysicalDeviceVulkan12Features local_features_12 = physical_device.features_12; - if (physical_device.instance_version >= VK_MAKE_VERSION(1, 2, 0)) { - if (!has_phys_dev_vulkan_features_11) { - pNext_chain.push_back(reinterpret_cast(&local_features_11)); - has_phys_dev_vulkan_features_11 = true; - } - if (!has_phys_dev_vulkan_features_12) { - pNext_chain.push_back(reinterpret_cast(&local_features_12)); - has_phys_dev_vulkan_features_12 = true; - } - } -#endif + VkPhysicalDeviceFeatures2 local_features2{}; + if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0) && + physical_device.extension_features.size() > 0) { + ExtensionFeatures* prev = nullptr; + for(auto& extension : physical_device.extension_features) { + if(prev != nullptr) { + prev->structure->pNext = extension.structure; + } + prev = &extension; + } + local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + local_features2.features = physical_device.features; + local_features2.pNext = physical_device.extension_features[0].structure; + has_phys_dev_features_2 = true; + } #endif VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - detail::setup_pNext_chain(device_create_info, pNext_chain); device_create_info.flags = info.flags; device_create_info.queueCreateInfoCount = static_cast(queueCreateInfos.size()); device_create_info.pQueueCreateInfos = queueCreateInfos.data(); device_create_info.enabledExtensionCount = static_cast(extensions.size()); device_create_info.ppEnabledExtensionNames = extensions.data(); // VUID-VkDeviceCreateInfo-pNext-00373 - don't add pEnabledFeatures if the phys_dev_features_2 is present - if (!has_phys_dev_features_2) { - device_create_info.pEnabledFeatures = &physical_device.features; - } - + if (!has_phys_dev_features_2) { + device_create_info.pEnabledFeatures = &physical_device.features; + } else { + device_create_info.pNext = &local_features2; + } Device device; VkResult res = detail::vulkan_functions().fp_vkCreateDevice( diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 10baba2..ac47e42 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -195,6 +195,105 @@ struct SystemInfo { class InstanceBuilder; class PhysicalDeviceSelector; +struct ExtensionFeatures { + + using DeleteProc = void(*)(ExtensionFeatures&); + using CopyProc = void(*)(const ExtensionFeatures&, ExtensionFeatures&); + + ExtensionFeatures() = default; + + ExtensionFeatures (const ExtensionFeatures& other) : delete_proc(other.delete_proc), copy_proc(other.copy_proc) { + if(copy_proc) { copy_proc(other, *this); } + } + + ExtensionFeatures (ExtensionFeatures&& other) : delete_proc(std::exchange(other.delete_proc, nullptr)), + copy_proc(std::exchange(other.copy_proc, nullptr)), + structure(std::exchange(other.structure, nullptr)), + fields(std::exchange(other.fields, {})) {} + + ExtensionFeatures& operator=(const ExtensionFeatures& other) { + delete_proc = other.delete_proc; + copy_proc = other.copy_proc; + if(copy_proc) { copy_proc(other, *this); } + return *this; + } + + ExtensionFeatures& operator=(ExtensionFeatures&& other) { + delete_proc = std::exchange(other.delete_proc, nullptr); + copy_proc = std::exchange(other.copy_proc, nullptr); + structure = std::exchange(other.structure, nullptr); + fields = std::exchange(other.fields, {}); + return *this; + } + + template + static ExtensionFeatures make(T src) { + + ExtensionFeatures extension_features; + T* new_features_structure = new T; + *new_features_structure = src; + extension_features.structure = reinterpret_cast(new_features_structure); + + auto structure_field_count = + (sizeof(T) - (sizeof(VkStructureType) + sizeof(void*))) / sizeof(VkBool32); + extension_features.fields.resize(structure_field_count); + memcpy(extension_features.fields.data(), + reinterpret_cast(extension_features.structure) + + (sizeof(VkStructureType) + sizeof(void*)), + sizeof(VkBool32) * extension_features.fields.size()); + + extension_features.delete_proc = [](ExtensionFeatures& features) { + + features.fields = {}; + if(features.structure) { + auto casted = reinterpret_cast(features.structure); + delete casted; + } + + }; + + extension_features.copy_proc = [](const ExtensionFeatures& src, ExtensionFeatures& dst) { + + if(dst.structure) { + auto casted = reinterpret_cast(dst.structure); + delete casted; + } + T* new_features_structure = new T; + *new_features_structure = *reinterpret_cast(src.structure); + dst.structure = reinterpret_cast(new_features_structure); + dst.fields = src.fields; + + }; + + return extension_features; + } + + bool match(const ExtensionFeatures& other) const { + + if(!structure || !other.structure || structure->sType != other.structure->sType) { return false; } + + for(auto i = 0; i < fields.size(); ++i) { + if(fields[i] == VK_TRUE && other.fields[i] == VK_FALSE) { + return false; + } + } + + return true; + } + + ~ExtensionFeatures() { + + if(delete_proc) { delete_proc(*this); } + + } + + VkBaseOutStructure* structure = nullptr; + std::vector fields; + private: + DeleteProc delete_proc = {}; + CopyProc copy_proc = {}; +}; + struct Instance { VkInstance instance = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; @@ -335,10 +434,6 @@ struct PhysicalDevice { VkSurfaceKHR surface = VK_NULL_HANDLE; VkPhysicalDeviceFeatures features{}; -#if defined(VK_API_VERSION_1_2) - VkPhysicalDeviceVulkan11Features features_11{}; - VkPhysicalDeviceVulkan12Features features_12{}; -#endif VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceMemoryProperties memory_properties{}; @@ -359,6 +454,7 @@ struct PhysicalDevice { uint32_t instance_version = VK_MAKE_VERSION(1, 0, 0); std::vector extensions_to_enable; std::vector queue_families; + mutable std::vector extension_features; bool defer_surface_initialization = false; friend class PhysicalDeviceSelector; friend class DeviceBuilder; @@ -419,16 +515,26 @@ class PhysicalDeviceSelector { // Require a physical device that supports a (major, minor) version of vulkan. PhysicalDeviceSelector& set_minimum_version(uint32_t major, uint32_t minor); - // Require a physical device which supports the features in VkPhysicalDeviceFeatures. - PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features); - +// Require a physical device which supports a specific set of general/extension features. + template + PhysicalDeviceSelector& add_required_features(T const& features) { +#if defined(VK_API_VERSION_1_1) + criteria.extension_features.push_back(ExtensionFeatures::make(features)); +#endif + return *this; + } + template<> + PhysicalDeviceSelector& add_required_features(VkPhysicalDeviceFeatures const& features) { + criteria.required_features = features; + return *this; + } #if defined(VK_API_VERSION_1_2) - // Require a physical device which supports the features in VkPhysicalDeviceVulkan11Features. - // Must have vulkan version 1.2 - This is due to the VkPhysicalDeviceVulkan11Features struct being added in 1.2, not 1.1 - PhysicalDeviceSelector& set_required_features_11(VkPhysicalDeviceVulkan11Features const& features_11); - // Require a physical device which supports the features in VkPhysicalDeviceVulkan12Features. - // Must have vulkan version 1.2 - PhysicalDeviceSelector& set_required_features_12(VkPhysicalDeviceVulkan12Features const& features_12); + // Require a physical device which supports the features in VkPhysicalDeviceVulkan11Features. + // Must have vulkan version 1.2 - This is due to the VkPhysicalDeviceVulkan11Features struct being added in 1.2, not 1.1 + PhysicalDeviceSelector& set_required_features_11(VkPhysicalDeviceVulkan11Features const& features_11); + // Require a physical device which supports the features in VkPhysicalDeviceVulkan12Features. + // Must have vulkan version 1.2 + PhysicalDeviceSelector& set_required_features_12(VkPhysicalDeviceVulkan12Features const& features_12); #endif // Used when surface creation happens after physical device selection. @@ -456,13 +562,16 @@ class PhysicalDeviceSelector { VkPhysicalDeviceMemoryProperties mem_properties{}; #if defined(VK_API_VERSION_1_1) VkPhysicalDeviceFeatures2 device_features2{}; -#endif -#if defined(VK_API_VERSION_1_2) - VkPhysicalDeviceVulkan11Features device_features_11{}; - VkPhysicalDeviceVulkan12Features device_features_12{}; + std::vector extension_features; #endif }; - PhysicalDeviceDesc populate_device_details(uint32_t instance_version, VkPhysicalDevice phys_device) const; + + // We copy the extension features stored in the selector criteria under the prose of a "template" to + // ensure that after fetching everything is compared 1:1 during a match. + + PhysicalDeviceDesc populate_device_details(uint32_t instance_version, + VkPhysicalDevice phys_device, + std::vector extension_features_as_template) const; struct SelectionCriteria { PreferredDeviceType preferred_type = PreferredDeviceType::discrete; @@ -484,13 +593,8 @@ class PhysicalDeviceSelector { VkPhysicalDeviceFeatures required_features{}; #if defined(VK_API_VERSION_1_1) VkPhysicalDeviceFeatures2 required_features2{}; + std::vector extension_features; #endif - -#if defined(VK_API_VERSION_1_2) - VkPhysicalDeviceVulkan11Features required_features_11{}; - VkPhysicalDeviceVulkan12Features required_features_12{}; -#endif - bool defer_surface_initialization = false; bool use_first_gpu_unconditionally = false; } criteria; @@ -547,13 +651,6 @@ class DeviceBuilder { // If a custom queue setup is provided, getting the queues and queue indexes is up to the application. DeviceBuilder& custom_queue_setup(std::vector queue_descriptions); - // Add a structure to the pNext chain of VkDeviceCreateInfo. - // The structure must be valid when DeviceBuilder::build() is called. - template DeviceBuilder& add_pNext(T* structure) { - info.pNext_chain.push_back(reinterpret_cast(structure)); - return *this; - } - // Provide custom allocation callbacks. DeviceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); @@ -561,8 +658,6 @@ class DeviceBuilder { PhysicalDevice physical_device; struct DeviceInfo { VkDeviceCreateFlags flags = 0; - std::vector pNext_chain; - std::vector queue_descriptions; VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; } info;