Don't pass an instance in for pre-instance functions.

A recent loader change results in NULL being returned for pre-instance functions
if the instance handle passed into vkGetInstanceProcAddr isn't NULL. This was
reverted but going forward this change will require updating applications.
This commit is contained in:
Charles Giessen 2021-12-08 15:49:44 -07:00
parent e761a6f67b
commit 6bf383778b
2 changed files with 41 additions and 25 deletions

View File

@ -109,10 +109,14 @@ class VulkanFunctions {
} }
void init_pre_instance_funcs() { void init_pre_instance_funcs() {
get_inst_proc_addr(fp_vkEnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties"); fp_vkEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
get_inst_proc_addr(fp_vkEnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties"); ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"));
get_inst_proc_addr(fp_vkEnumerateInstanceVersion, "vkEnumerateInstanceVersion"); fp_vkEnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
get_inst_proc_addr(fp_vkCreateInstance, "vkCreateInstance"); ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"));
fp_vkEnumerateInstanceVersion = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion"));
fp_vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(
ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance"));
} }
public: public:
@ -488,7 +492,9 @@ detail::Result<SystemInfo> SystemInfo::get_system_info() {
detail::Result<SystemInfo> SystemInfo::get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { detail::Result<SystemInfo> SystemInfo::get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) {
// Using externally provided function pointers, assume the loader is available // Using externally provided function pointers, assume the loader is available
detail::vulkan_functions().init_vulkan_funcs(fp_vkGetInstanceProcAddr); if (!detail::vulkan_functions().init_vulkan_funcs(fp_vkGetInstanceProcAddr)) {
return make_error_code(InstanceError::vulkan_unavailable);
}
return SystemInfo(); return SystemInfo();
} }
@ -551,9 +557,7 @@ void destroy_instance(Instance instance) {
} }
} }
Instance::operator VkInstance() const { Instance::operator VkInstance() const { return this->instance; }
return this->instance;
}
InstanceBuilder::InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { InstanceBuilder::InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) {
info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr;
@ -699,9 +703,11 @@ detail::Result<Instance> InstanceBuilder::build() const {
VkInstanceCreateInfo instance_create_info = {}; VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
detail::setup_pNext_chain(instance_create_info, pNext_chain); detail::setup_pNext_chain(instance_create_info, pNext_chain);
#if !defined(NDEBUG)
for (auto& node : pNext_chain) { for (auto& node : pNext_chain) {
assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO);
} }
#endif
instance_create_info.flags = info.flags; instance_create_info.flags = info.flags;
instance_create_info.pApplicationInfo = &app_info; instance_create_info.pApplicationInfo = &app_info;
instance_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); instance_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
@ -1351,9 +1357,7 @@ std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families() const
return queue_families; return queue_families;
} }
PhysicalDevice::operator VkPhysicalDevice() const { PhysicalDevice::operator VkPhysicalDevice() const { return this->physical_device; }
return this->physical_device;
}
// ---- Queues ---- // // ---- Queues ---- //
@ -1425,9 +1429,7 @@ DispatchTable Device::make_table() const { return { device, fp_vkGetDeviceProcAd
// ---- Device ---- // // ---- Device ---- //
Device::operator VkDevice() const { Device::operator VkDevice() const { return this->device; }
return this->device;
}
CustomQueueDescription::CustomQueueDescription(uint32_t index, uint32_t count, std::vector<float> priorities) CustomQueueDescription::CustomQueueDescription(uint32_t index, uint32_t count, std::vector<float> priorities)
: index(index), count(count), priorities(priorities) { : index(index), count(count), priorities(priorities) {
@ -1507,10 +1509,11 @@ detail::Result<Device> DeviceBuilder::build() const {
} }
detail::setup_pNext_chain(device_create_info, final_pnext_chain); detail::setup_pNext_chain(device_create_info, final_pnext_chain);
#if !defined(NDEBUG)
for (auto& node : final_pnext_chain) { for (auto& node : final_pnext_chain) {
assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO);
} }
#endif
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());
@ -1757,9 +1760,11 @@ detail::Result<Swapchain> SwapchainBuilder::build() const {
VkSwapchainCreateInfoKHR swapchain_create_info = {}; VkSwapchainCreateInfoKHR swapchain_create_info = {};
swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
detail::setup_pNext_chain(swapchain_create_info, info.pNext_chain); detail::setup_pNext_chain(swapchain_create_info, info.pNext_chain);
#if !defined(NDEBUG)
for (auto& node : info.pNext_chain) { for (auto& node : info.pNext_chain) {
assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO);
} }
#endif
swapchain_create_info.flags = info.create_flags; swapchain_create_info.flags = info.create_flags;
swapchain_create_info.surface = info.surface; swapchain_create_info.surface = info.surface;
swapchain_create_info.minImageCount = image_count; swapchain_create_info.minImageCount = image_count;
@ -1856,9 +1861,7 @@ void Swapchain::destroy_image_views(std::vector<VkImageView> const& image_views)
internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks); internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks);
} }
} }
Swapchain::operator VkSwapchainKHR() const { Swapchain::operator VkSwapchainKHR() const { return this->swapchain; }
return this->swapchain;
}
SwapchainBuilder& SwapchainBuilder::set_old_swapchain(VkSwapchainKHR old_swapchain) { SwapchainBuilder& SwapchainBuilder::set_old_swapchain(VkSwapchainKHR old_swapchain) {
info.old_swapchain = old_swapchain; info.old_swapchain = old_swapchain;
return *this; return *this;

View File

@ -68,6 +68,17 @@ TEST_CASE("Instance with surface", "[VkBootstrap.bootstrap]") {
vkb::destroy_instance(instance); vkb::destroy_instance(instance);
destroy_window_glfw(window); destroy_window_glfw(window);
} }
GIVEN("Two Instances") {
vkb::InstanceBuilder instance_builder1;
auto instance_ret1 = instance_builder1.use_default_debug_messenger().build();
REQUIRE(instance_ret1);
vkb::InstanceBuilder instance_builder2;
auto instance_ret2 = instance_builder2.use_default_debug_messenger().build();
REQUIRE(instance_ret2);
vkb::destroy_instance(instance_ret1.value());
vkb::destroy_instance(instance_ret2.value());
}
} }
TEST_CASE("instance configuration", "[VkBootstrap.bootstrap]") { TEST_CASE("instance configuration", "[VkBootstrap.bootstrap]") {
@ -496,15 +507,16 @@ TEST_CASE("Passing vkb classes to Vulkan handles", "[VkBootstrap.pass_class_to_h
auto instance = get_instance(); auto instance = get_instance();
// Check if we can get instance functions. // Check if we can get instance functions.
PFN_vkVoidFunction instanceFunction = instance.fp_vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"); // validation layers should be provided. PFN_vkVoidFunction instanceFunction = instance.fp_vkGetInstanceProcAddr(
instance, "vkSetDebugUtilsObjectNameEXT"); // validation layers should be provided.
REQUIRE(instanceFunction != NULL); REQUIRE(instanceFunction != NULL);
auto window = create_window_glfw("Conversion operators"); auto window = create_window_glfw("Conversion operators");
auto surface = create_surface_glfw(instance, window); auto surface = create_surface_glfw(instance, window);
vkb::PhysicalDeviceSelector physicalDeviceSelector(instance); vkb::PhysicalDeviceSelector physicalDeviceSelector(instance);
auto physicalDevice = physicalDeviceSelector auto physicalDevice =
.add_required_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME) physicalDeviceSelector.add_required_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)
.set_surface(surface) .set_surface(surface)
.select(); .select();
REQUIRE(physicalDevice.has_value()); REQUIRE(physicalDevice.has_value());
@ -513,7 +525,8 @@ TEST_CASE("Passing vkb classes to Vulkan handles", "[VkBootstrap.pass_class_to_h
REQUIRE(device.has_value()); REQUIRE(device.has_value());
// Check if we can get a device function address, passing vkb::Device to the function. // Check if we can get a device function address, passing vkb::Device to the function.
PFN_vkVoidFunction deviceFunction = instance.fp_vkGetDeviceProcAddr(device.value(), "vkAcquireNextImageKHR"); PFN_vkVoidFunction deviceFunction =
instance.fp_vkGetDeviceProcAddr(device.value(), "vkAcquireNextImageKHR");
REQUIRE(deviceFunction != NULL); REQUIRE(deviceFunction != NULL);
} }
} }