diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 60c1bfc..f366207 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -908,6 +908,7 @@ bool supports_features(VkPhysicalDeviceFeatures supported, if (requested.inheritedQueries && !supported.inheritedQueries) return false; for(auto i = 0; i < extension_requested.size(); ++i) { + //auto res = extension_requested[i].match(extension_supported[i]); auto res = GenericFeaturesPNextNode::match(extension_requested[i], extension_supported[i]); if(!res) return false; } @@ -1410,47 +1411,21 @@ detail::Result DeviceBuilder::build() const { extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); bool has_phys_dev_features_2 = false; - bool user_defined_phys_dev_features_2 = false; std::vector final_pnext_chain; - VkDeviceCreateInfo device_create_info = {}; #if defined(VK_API_VERSION_1_1) - for(auto& pnext : info.pNext_chain) { - if(pnext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { - user_defined_phys_dev_features_2 = true; - break; - } - } - - auto physical_device_extension_features_copy = physical_device.extended_features_chain; VkPhysicalDeviceFeatures2 local_features2{}; local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - - if(!user_defined_phys_dev_features_2) { - if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0)) { - local_features2.features = physical_device.features; - final_pnext_chain.push_back(reinterpret_cast(&local_features2)); - has_phys_dev_features_2 = true; - for (auto& features_node : physical_device_extension_features_copy) { - final_pnext_chain.push_back(reinterpret_cast(&features_node)); - } + auto physical_device_extension_features_copy = physical_device.extended_features_chain; + if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0)) { + has_phys_dev_features_2 = true; + for(auto& features_node : physical_device_extension_features_copy) { + final_pnext_chain.push_back(reinterpret_cast(&features_node)); } } - - if(!user_defined_phys_dev_features_2 && !has_phys_dev_features_2) { - device_create_info.pEnabledFeatures = &physical_device.features; - } #endif - for(auto& pnext : info.pNext_chain) { - final_pnext_chain.push_back(pnext); - } - - detail::setup_pNext_chain(device_create_info, final_pnext_chain); - for(auto& node : final_pnext_chain) { - assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); - } - + VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.flags = info.flags; device_create_info.queueCreateInfoCount = static_cast(queueCreateInfos.size()); @@ -1458,10 +1433,30 @@ detail::Result DeviceBuilder::build() const { device_create_info.enabledExtensionCount = static_cast(extensions.size()); device_create_info.ppEnabledExtensionNames = extensions.data(); - if(!final_pnext_chain.empty()) { - device_create_info.pNext = final_pnext_chain.front(); + for(auto& pnext : info.pNext_chain) { + final_pnext_chain.push_back(pnext); } + detail::setup_pNext_chain(device_create_info, final_pnext_chain); + for(auto& node : final_pnext_chain) { + assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); + } + +#if defined(VK_API_VERSION_1_1) + // 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.pNext = &local_features2; + if(!final_pnext_chain.empty()) { + local_features2.pNext = final_pnext_chain.front(); + } + device_create_info.pEnabledFeatures = nullptr; + } else { + device_create_info.pEnabledFeatures = &physical_device.features; + } +#else + device_create_info.pEnabledFeatures = &physical_device.features; +#endif + Device device; VkResult res = detail::vulkan_functions().fp_vkCreateDevice( diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index f9f2630..c9a2ec6 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -124,18 +124,18 @@ struct GenericFeaturesPNextNode { VkStructureType sType = static_cast(0); void* pNext = nullptr; - static const uint32_t field_capacity = 256; - VkBool32 fields[field_capacity]; + VkBool32 fields[256]; template void set(T const& features) { + GenericFeaturesPNextNode node; *reinterpret_cast(this) = features; } static bool match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) { assert(requested.sType == supported.sType && "Non-matching sTypes in features nodes!"); - for (uint32_t i = 0; i < field_capacity; i++) { + for (uint32_t i = 0; i < (sizeof(fields) / sizeof(VkBool32)); i++) { if (requested.fields[i] && !supported.fields[i]) return false; } return true; @@ -362,7 +362,6 @@ struct PhysicalDevice { VkPhysicalDevice physical_device = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE; - // Note that this reflects selected features carried over from required features, not all features the physical device supports. VkPhysicalDeviceFeatures features{}; VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceMemoryProperties memory_properties{}; @@ -451,8 +450,6 @@ class PhysicalDeviceSelector { PhysicalDeviceSelector& add_required_extension_features(T const& features) { assert(features.sType != 0 && "Features struct sType must be filled with the struct's corresponding VkStructureType enum"); - assert(features.sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 && - "Do not pass VkPhysicalDeviceFeatures2 as a required extension feature structure. An instance of this is managed internally for selection criteria and device creation."); detail::GenericFeaturesPNextNode node; node.set(features); criteria.extended_features_chain.push_back(node);