From 8df2c26952f6748d964d146d1ac592931ef61bda Mon Sep 17 00:00:00 2001 From: Lenny Komow Date: Thu, 29 Mar 2018 13:25:38 -0600 Subject: loader: Fix GetDeviceProcAddr with terminators Fix a bug where vkGetDeviceProcAddr would return a valid pointer for any device command that used a custom terminator, even if it was part of an extension which wasn't enabled Change-Id: I3b088fe0c850fbaa5f7285ced81552273bc38e7e --- loader/loader.c | 15 ++++++++++++++- loader/loader.h | 8 ++++++++ scripts/loader_extension_generator.py | 23 ++++++++++++++++++----- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index 1e7a8049..266222f3 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -4005,7 +4005,7 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_internal(VkDevice dev // object before passing the appropriate info along to the ICD. // This is why we also have to override the direct ICD call to // vkGetDeviceProcAddr to intercept those calls. - PFN_vkVoidFunction addr = get_extension_device_proc_terminator(pName); + PFN_vkVoidFunction addr = get_extension_device_proc_terminator(dev, pName); if (NULL != addr) { return addr; } @@ -5542,6 +5542,19 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physical } } + // Every extension that has a loader-defined terminator needs to be marked as enabled or disabled so that we know whether or + // not to return that terminator when vkGetDeviceProcAddr is called + for (uint32_t i = 0; i < localCreateInfo.enabledExtensionCount; ++i) { + if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { + dev->extensions.khr_swapchain_enabled = true; + } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME)) { + dev->extensions.khr_display_swapchain_enabled = true; + } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { + dev->extensions.ext_debug_marker_enabled = true; + } + dev->extensions.ext_debug_utils_enabled = icd_term->this_instance->enabled_known_extensions.ext_debug_utils; + } + res = fpCreateDevice(phys_dev_term->phys_dev, &localCreateInfo, pAllocator, &dev->icd_device); if (res != VK_SUCCESS) { loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, diff --git a/loader/loader.h b/loader/loader.h index 8abc034a..9ffa3bb9 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -192,6 +192,14 @@ struct loader_device { VkAllocationCallbacks alloc_callbacks; + // List of activated device extensions that have terminators implemented in the loader + struct { + bool khr_swapchain_enabled; + bool khr_display_swapchain_enabled; + bool ext_debug_marker_enabled; + bool ext_debug_utils_enabled; + } extensions; + struct loader_device *next; }; diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index 7f38de91..d9f5564c 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -383,6 +383,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): protos = '' protos += '// Structures defined externally, but used here\n' protos += 'struct loader_instance;\n' + protos += 'struct loader_device;\n' protos += 'struct loader_icd_term;\n' protos += 'struct loader_dev_dispatch_table;\n' protos += '\n' @@ -401,7 +402,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): protos += '// Extension interception for vkGetDeviceProcAddr function, so we can return\n' protos += '// an appropriate terminator if this is one of those few device commands requiring\n' protos += '// a terminator.\n' - protos += 'PFN_vkVoidFunction get_extension_device_proc_terminator(const char *pName);\n' + protos += 'PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName);\n' protos += '\n' protos += '// Dispatch table properly filled in with appropriate terminators for the\n' protos += '// supported extensions.\n' @@ -1365,28 +1366,38 @@ class LoaderExtensionOutputGenerator(OutputGenerator): term_func += '// Some device commands still need a terminator because the loader needs to unwrap something about them.\n' term_func += '// In many cases, the item needing unwrapping is a VkPhysicalDevice or VkSurfaceKHR object. But there may be other items\n' term_func += '// in the future.\n' - term_func += 'PFN_vkVoidFunction get_extension_device_proc_terminator(const char *pName) {\n' + term_func += 'PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName) {\n' term_func += ' PFN_vkVoidFunction addr = NULL;\n' count = 0 + is_extension = False for ext_cmd in self.ext_commands: if ext_cmd.name in DEVICE_CMDS_NEED_TERM: if ext_cmd.ext_name != cur_extension_name: + if count > 0: + count = 0; + term_func += ' }\n' + if is_extension: + term_func += ' }\n' + is_extension = False + if 'VK_VERSION_' in ext_cmd.ext_name: term_func += '\n // ---- Core %s commands\n' % ext_cmd.ext_name[11:] else: term_func += '\n // ---- %s extension commands\n' % ext_cmd.ext_name + term_func += ' if (dev->extensions.%s_enabled) {\n' % ext_cmd.ext_name[3:].lower() + is_extension = True cur_extension_name = ext_cmd.ext_name if ext_cmd.protect is not None: term_func += '#ifdef %s\n' % ext_cmd.protect if count == 0: - term_func += ' if' + term_func += ' if' else: - term_func += ' } else if' + term_func += ' } else if' term_func += '(!strcmp(pName, "%s")) {\n' % (ext_cmd.name) - term_func += ' addr = (PFN_vkVoidFunction)terminator_%s;\n' % (ext_cmd.name[2:]) + term_func += ' addr = (PFN_vkVoidFunction)terminator_%s;\n' % (ext_cmd.name[2:]) if ext_cmd.protect is not None: term_func += '#endif // %s\n' % ext_cmd.protect @@ -1394,6 +1405,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator): count += 1 if count > 0: + term_func += ' }\n' + if is_extension: term_func += ' }\n' term_func += ' return addr;\n' -- cgit v1.2.3