Cleanup and asserts for VkPhysicalDeviceFeatures2.

This commit is contained in:
Cody Goodson 2021-04-18 13:26:08 -05:00 committed by Charles Giessen
parent 6ee81abdd3
commit 5ac038b778
2 changed files with 40 additions and 32 deletions

View File

@ -908,7 +908,6 @@ bool supports_features(VkPhysicalDeviceFeatures supported,
if (requested.inheritedQueries && !supported.inheritedQueries) return false; if (requested.inheritedQueries && !supported.inheritedQueries) return false;
for(auto i = 0; i < extension_requested.size(); ++i) { 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]); auto res = GenericFeaturesPNextNode::match(extension_requested[i], extension_supported[i]);
if(!res) return false; if(!res) return false;
} }
@ -1411,21 +1410,47 @@ detail::Result<Device> DeviceBuilder::build() const {
extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME });
bool has_phys_dev_features_2 = false; bool has_phys_dev_features_2 = false;
bool user_defined_phys_dev_features_2 = false;
std::vector<VkBaseOutStructure*> final_pnext_chain; std::vector<VkBaseOutStructure*> final_pnext_chain;
VkDeviceCreateInfo device_create_info = {};
#if defined(VK_API_VERSION_1_1) #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{}; VkPhysicalDeviceFeatures2 local_features2{};
local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
auto physical_device_extension_features_copy = physical_device.extended_features_chain;
if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0)) { if(!user_defined_phys_dev_features_2) {
has_phys_dev_features_2 = true; if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0)) {
for(auto& features_node : physical_device_extension_features_copy) { local_features2.features = physical_device.features;
final_pnext_chain.push_back(reinterpret_cast<VkBaseOutStructure*>(&features_node)); final_pnext_chain.push_back(reinterpret_cast<VkBaseOutStructure*>(&local_features2));
has_phys_dev_features_2 = true;
for (auto& features_node : physical_device_extension_features_copy) {
final_pnext_chain.push_back(reinterpret_cast<VkBaseOutStructure*>(&features_node));
}
} }
} }
if(!user_defined_phys_dev_features_2 && !has_phys_dev_features_2) {
device_create_info.pEnabledFeatures = &physical_device.features;
}
#endif #endif
VkDeviceCreateInfo device_create_info = {}; 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);
}
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.flags = info.flags; device_create_info.flags = info.flags;
device_create_info.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()); device_create_info.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
@ -1433,30 +1458,10 @@ detail::Result<Device> DeviceBuilder::build() const {
device_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); device_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
device_create_info.ppEnabledExtensionNames = extensions.data(); device_create_info.ppEnabledExtensionNames = extensions.data();
for(auto& pnext : info.pNext_chain) { if(!final_pnext_chain.empty()) {
final_pnext_chain.push_back(pnext); device_create_info.pNext = final_pnext_chain.front();
} }
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; Device device;
VkResult res = detail::vulkan_functions().fp_vkCreateDevice( VkResult res = detail::vulkan_functions().fp_vkCreateDevice(

View File

@ -124,18 +124,18 @@ struct GenericFeaturesPNextNode {
VkStructureType sType = static_cast<VkStructureType>(0); VkStructureType sType = static_cast<VkStructureType>(0);
void* pNext = nullptr; void* pNext = nullptr;
VkBool32 fields[256]; static const uint32_t field_capacity = 256;
VkBool32 fields[field_capacity];
template <typename T> template <typename T>
void set(T const& features) { void set(T const& features) {
GenericFeaturesPNextNode node;
*reinterpret_cast<T*>(this) = features; *reinterpret_cast<T*>(this) = features;
} }
static bool match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) { static bool match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) {
assert(requested.sType == supported.sType && assert(requested.sType == supported.sType &&
"Non-matching sTypes in features nodes!"); "Non-matching sTypes in features nodes!");
for (uint32_t i = 0; i < (sizeof(fields) / sizeof(VkBool32)); i++) { for (uint32_t i = 0; i < field_capacity; i++) {
if (requested.fields[i] && !supported.fields[i]) return false; if (requested.fields[i] && !supported.fields[i]) return false;
} }
return true; return true;
@ -362,6 +362,7 @@ struct PhysicalDevice {
VkPhysicalDevice physical_device = VK_NULL_HANDLE; VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = 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{}; VkPhysicalDeviceFeatures features{};
VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceProperties properties{};
VkPhysicalDeviceMemoryProperties memory_properties{}; VkPhysicalDeviceMemoryProperties memory_properties{};
@ -450,6 +451,8 @@ class PhysicalDeviceSelector {
PhysicalDeviceSelector& add_required_extension_features(T const& features) { PhysicalDeviceSelector& add_required_extension_features(T const& features) {
assert(features.sType != 0 && assert(features.sType != 0 &&
"Features struct sType must be filled with the struct's corresponding VkStructureType enum"); "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; detail::GenericFeaturesPNextNode node;
node.set(features); node.set(features);
criteria.extended_features_chain.push_back(node); criteria.extended_features_chain.push_back(node);