diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 4f9b3b2..8d5607a 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -1010,17 +1010,14 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi detail::ExtensionFeatures* prev = nullptr; for(auto& extension : desc.extension_features) { if(prev != nullptr) { - prev->structure->pNext = extension.structure; + prev->structure.header->pNext = extension.structure.header; } prev = &extension; } if(desc.extension_features.size() > 0) { - desc.device_features2.pNext = desc.extension_features[0].structure; + desc.device_features2.pNext = desc.extension_features.front().structure.header; } detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &desc.device_features2); - for(auto& extension : desc.extension_features) { - extension.update(); - } } #endif return desc; @@ -1407,20 +1404,20 @@ detail::Result DeviceBuilder::build() const { // Setup the pNexts of all the extension features std::vector match = physical_device.extension_features; VkPhysicalDeviceFeatures2 local_features2{}; - VkBaseOutStructure* tail = nullptr; + //VkBaseOutStructure* tail = nullptr; if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0) && match.size() > 0) { detail::ExtensionFeatures* prev = nullptr; for(auto& extension : match) { if(prev != nullptr) { - prev->structure->pNext = extension.structure; + prev->structure.header->pNext = extension.structure.header; } prev = &extension; - tail = prev->structure; + //tail = prev->structure; } local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; local_features2.features = physical_device.features; - local_features2.pNext = match.front().structure; + local_features2.pNext = match.front().structure.header; has_phys_dev_features_2 = true; } #endif @@ -1440,7 +1437,7 @@ detail::Result DeviceBuilder::build() const { if (has_phys_dev_features_2) { device_create_info.pNext = &local_features2; if(info.pNext_chain.size() > 0) { - match.back().structure->pNext = info.pNext_chain.front(); + match.back().structure.header->pNext = info.pNext_chain.front(); } } else { device_create_info.pEnabledFeatures = &physical_device.features; diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 3efc232..86b3c3a 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -117,38 +117,73 @@ template class Result { struct ExtensionFeatures { - using DeleteProc = void(*)(ExtensionFeatures&); - using UpdateProc = void(*)(ExtensionFeatures&); - using CopyProc = void(*)(const ExtensionFeatures&, ExtensionFeatures&); + struct StructureContainer { + + struct Header { + VkStructureType sType; + void* pNext; + }; + + StructureContainer() = default; + + StructureContainer (StructureContainer const& other) { copy(other); } + + StructureContainer (StructureContainer&& other) { copy(other); } + + StructureContainer& operator=(StructureContainer const& other) { copy(other); return *this; } + + StructureContainer& operator=(StructureContainer&& other) { copy(other); return *this; } + + template + void set(T const& features) { + data.resize(sizeof(T)); + *reinterpret_cast(data.data()) = features; + count = (sizeof(T) - sizeof(Header)) / sizeof(VkBool32); + header = reinterpret_cast(data.data()); + fields = reinterpret_cast(data.data() + sizeof(Header)); + } + + bool match(StructureContainer const& other) const { + if(!header || !other.header || header->sType != other.header->sType) { return false; } + for(auto i = 0; i < count; ++i) { + if(fields[i] == VK_TRUE && other.fields[i] == VK_FALSE) { + return false; + } + } + return true; + } + + Header* header = nullptr; + private: + + // Just to avoid having it copied in 4 places + void copy(StructureContainer const& other) { + data = other.data; + count = other.count; + header = reinterpret_cast(data.data()); + fields = reinterpret_cast(data.data() + sizeof(Header)); + } + + std::vector data; + VkBool32* fields = nullptr; + void* extend = nullptr; // Future proofing + int count = 0; + + }; ExtensionFeatures() = default; - ExtensionFeatures (const ExtensionFeatures& other) : delete_proc(other.delete_proc), - update_proc(other.update_proc), - copy_proc(other.copy_proc) { - if(copy_proc) { copy_proc(other, *this); } - } + ExtensionFeatures (ExtensionFeatures const& other) : structure(other.structure) {} - ExtensionFeatures (ExtensionFeatures&& other) : delete_proc(std::exchange(other.delete_proc, nullptr)), - update_proc(std::exchange(other.update_proc, nullptr)), - copy_proc(std::exchange(other.copy_proc, nullptr)), - structure(std::exchange(other.structure, nullptr)), - fields(std::exchange(other.fields, {})) {} + ExtensionFeatures (ExtensionFeatures&& other) : structure(std::exchange(other.structure, {})) {} - ExtensionFeatures& operator=(const ExtensionFeatures& other) { - delete_proc = other.delete_proc; - update_proc = other.update_proc; - copy_proc = other.copy_proc; - if(copy_proc) { copy_proc(other, *this); } + ExtensionFeatures& operator=(ExtensionFeatures const& other) { + structure = other.structure; return *this; } ExtensionFeatures& operator=(ExtensionFeatures&& other) { - delete_proc = std::exchange(other.delete_proc, nullptr); - update_proc = std::exchange(other.update_proc, nullptr); - copy_proc = std::exchange(other.copy_proc, nullptr); - structure = std::exchange(other.structure, nullptr); - fields = std::exchange(other.fields, {}); + structure = std::exchange(other.structure, {}); return *this; } @@ -156,81 +191,15 @@ struct ExtensionFeatures { 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); - - extension_features.delete_proc = [](ExtensionFeatures& features) { - - features.fields = {}; - if(features.structure) { - auto casted = reinterpret_cast(features.structure); - delete casted; - } - - }; - - extension_features.update_proc = [](ExtensionFeatures& features) { - - auto structure_field_count = (sizeof(T) - (sizeof(void*) * 2)) / sizeof(VkBool32); - features.fields.resize(structure_field_count); - memcpy(features.fields.data(), - reinterpret_cast(features.structure) + (sizeof(void*) * 2), - sizeof(VkBool32) * features.fields.size()); - - }; - - 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; - - }; - - extension_features.update(); - + extension_features.structure.set(src); return extension_features; - } - - void update() { - - if(update_proc) { - update_proc(*this); - } - - } - - 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 = nullptr; - UpdateProc update_proc = nullptr; - CopyProc copy_proc = nullptr; + bool match(const ExtensionFeatures& other) const { return structure.match(other.structure); } + + StructureContainer structure; + }; } // namespace detail