diff --git a/generator/generate_vulkan_common.py b/generator/generate_vulkan_common.py index dcbbba7..fc18509 100644 --- a/generator/generate_vulkan_common.py +++ b/generator/generate_vulkan_common.py @@ -32,30 +32,48 @@ import sys import xml.etree.ElementTree as ET -# These functions are manually created as fully exported entry points in the -# layer library, and are not part of the dynamic dispatch behavior -MANUAL_FUNCTIONS = { - # Exposed by loader so not handled by the layer +# These functions are not part of the layer implementation +EXCLUDED_FUNCTIONS = { + # Functions exposed by loader not the implementation 'vkEnumerateInstanceVersion', - # Exposed as symbols managed by the loader so not handled by the layer - 'vkGetInstanceProcAddr', +} + +# These functions are excluded from generated intercept and dispatch tables +NO_INTERCEPT_OR_DISPATCH_FUNCTIONS = { + # Functions resolved by the loaded not the implementation 'vkGetDeviceProcAddr', - # Exposed by layer as explicit entry points + 'vkGetInstanceProcAddr', +} + +# These functions are excluded from generated intercept tables +NO_INTERCEPT_FUNCTIONS = { + # Functions exported as shared object exports and resolved by loader + 'vkEnumerateDeviceExtensionProperties', 'vkEnumerateDeviceLayerProperties', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties', } -# These functions are manually exported, but we can use driver forwarding -FORWARD_WITHOUT_INTERCEPT = { - 'vkEnumerateDeviceExtensionProperties', - 'vkEnumerateInstanceExtensionProperties', +# These functions are excluded from generated dispatch tables +NO_DISPATCH_FUNCTIONS = { + # Functions resolved by the loaded not the implementation + 'vkCreateDevice', + 'vkCreateInstance', } -# These functions are found via the loader-injected chain info -INTERCEPT_WITHOUT_FORWARD = { +# These functions are excluded from generated declarations +CUSTOM_FUNCTIONS = { 'vkCreateDevice', 'vkCreateInstance', + 'vkDestroyDevice', + 'vkDestroyInstance', + 'vkGetDeviceProcAddr', + 'vkGetInstanceProcAddr', + 'vkEnumerateDeviceExtensionProperties', + 'vkEnumerateDeviceLayerProperties', + 'vkEnumerateInstanceExtensionProperties', + 'vkEnumerateInstanceLayerProperties', + 'vkGetDeviceImageMemoryRequirementsKHR', } # Filter out extensions from these vendors by default @@ -284,7 +302,7 @@ def __init__(self, mapping, root): self.params.append((ptype, text, tail)) # Filter out functions that are not dynamically dispatched - if self.name in MANUAL_FUNCTIONS: + if self.name in EXCLUDED_FUNCTIONS: raise NotImplementedError # Filter out functions that are not in our supported mapping @@ -299,7 +317,10 @@ def __init__(self, mapping, root): elif dispatch_type in DEVICE_FUNCTION_PARAM_TYPE: self.dispatch_type = 'device' else: - assert False, f'Unknown dispatch: {dispatch_type} {self.name}' + if self.name.startswith('vkEnumerateInstance'): + self.dispatch_type = 'instance' + else: + assert False, f'Unknown dispatch: {dispatch_type} {self.name}' def load_template(path): @@ -346,11 +367,15 @@ def generate_layer_instance_dispatch_table(file, mapping, commands): if command.dispatch_type != 'instance': continue + tname = command.name + if tname in NO_INTERCEPT_OR_DISPATCH_FUNCTIONS: + continue + plat_define = mapping.get_platform_define(command.name) ttype = f'PFN_{command.name}' - tname = command.name - if tname not in FORWARD_WITHOUT_INTERCEPT: + + if tname not in NO_INTERCEPT_FUNCTIONS: if plat_define: itable_members.append(f'#if defined({plat_define})') @@ -358,7 +383,7 @@ def generate_layer_instance_dispatch_table(file, mapping, commands): if plat_define: itable_members.append('#endif') - if tname not in INTERCEPT_WITHOUT_FORWARD: + if tname not in NO_DISPATCH_FUNCTIONS: if plat_define: dispatch_table_members.append(f'#if defined({plat_define})') dispatch_table_inits.append(f'#if defined({plat_define})') @@ -457,7 +482,7 @@ def generate_layer_instance_layer_decls(file, mapping, commands): file.write('\n') -def generate_layer_instance_layer_defs(file, mapping, commands, manual_commands): +def generate_layer_instance_layer_defs(file, mapping, commands): # Write the copyright header to the file write_copyright_header(file) @@ -470,6 +495,13 @@ def generate_layer_instance_layer_defs(file, mapping, commands, manual_commands) if command.dispatch_type != 'instance': continue + tname = command.name + if tname in NO_INTERCEPT_FUNCTIONS: + continue + + if tname in CUSTOM_FUNCTIONS: + continue + plat_define = mapping.get_platform_define(command.name) if plat_define: lines.append(f'#if defined({plat_define})\n') @@ -492,16 +524,13 @@ def generate_layer_instance_layer_defs(file, mapping, commands, manual_commands) lines.append(') {') lines.append(' LAYER_TRACE(__func__);\n') - if command.name in manual_commands: - lines.append(manual_commands[command.name]) - else: - lines.append(' // Hold the lock to access layer-wide global store') - lines.append(' std::unique_lock lock { g_vulkanLock };') - lines.append(f' auto* layer = Instance::retrieve({dispatch});\n') + lines.append(' // Hold the lock to access layer-wide global store') + lines.append(' std::unique_lock lock { g_vulkanLock };') + lines.append(f' auto* layer = Instance::retrieve({dispatch});\n') - lines.append(' // Release the lock to call into the driver') - lines.append(' lock.unlock();') - lines.append(f' {retfwd}layer->driver.{command.name}({parmfwd});') + lines.append(' // Release the lock to call into the driver') + lines.append(' lock.unlock();') + lines.append(f' {retfwd}layer->driver.{command.name}({parmfwd});') lines.append('}\n') @@ -527,9 +556,12 @@ def generate_layer_device_dispatch_table(file, mapping, commands): if command.dispatch_type != 'device': continue + tname = command.name + if tname in NO_INTERCEPT_OR_DISPATCH_FUNCTIONS: + continue + plat_define = mapping.get_platform_define(command.name) ttype = f'PFN_{command.name}' - tname = command.name if plat_define: itable_members.append(f'#if defined({plat_define})') @@ -613,7 +645,7 @@ def generate_layer_device_layer_decls(file, mapping, commands): file.write('\n') -def generate_layer_device_layer_defs(file, mapping, commands, manual_commands): +def generate_layer_device_layer_defs(file, mapping, commands): # Write the copyright header to the file write_copyright_header(file) @@ -626,6 +658,10 @@ def generate_layer_device_layer_defs(file, mapping, commands, manual_commands): if command.dispatch_type != 'device': continue + tname = command.name + if tname in CUSTOM_FUNCTIONS: + continue + plat_define = mapping.get_platform_define(command.name) if plat_define: lines.append(f'#if defined({plat_define})\n') @@ -649,16 +685,13 @@ def generate_layer_device_layer_defs(file, mapping, commands, manual_commands): lines.append(') {') lines.append(' LAYER_TRACE(__func__);\n') - if command.name in manual_commands: - lines.append(manual_commands[command.name]) - else: - lines.append(' // Hold the lock to access layer-wide global store') - lines.append(' std::unique_lock lock { g_vulkanLock };') - lines.append(f' auto* layer = Device::retrieve({dispatch});\n') + lines.append(' // Hold the lock to access layer-wide global store') + lines.append(' std::unique_lock lock { g_vulkanLock };') + lines.append(f' auto* layer = Device::retrieve({dispatch});\n') - lines.append(' // Release the lock to call into the driver') - lines.append(' lock.unlock();') - lines.append(f' {retfwd}layer->driver.{command.name}({parmfwd});') + lines.append(' // Release the lock to call into the driver') + lines.append(' lock.unlock();') + lines.append(f' {retfwd}layer->driver.{command.name}({parmfwd});') lines.append('}\n') @@ -669,23 +702,6 @@ def generate_layer_device_layer_defs(file, mapping, commands, manual_commands): file.write(data) -def load_handwritten_commands(): - ''' - Load the small number of hand-written functions from template files. - ''' - script_dir = os.path.dirname(__file__) - template_dir = os.path.join(script_dir, 'vk_codegen') - pattern = re.compile(r'^function_(.*)\.txt$') - - commands = {} - for path in os.listdir(template_dir): - match = pattern.match(path) - if match: - commands[match.group(1)] = load_template(path) - - return commands - - def copy_resource(src_dir, out_dir): out_dir = os.path.abspath(out_dir) os.makedirs(out_dir, exist_ok=True) @@ -738,9 +754,6 @@ def main(): # Sort functions into alphabetical order commands.sort(key=lambda x: x.name) - # Load hand written function bodies - manual_commands = load_handwritten_commands() - # Generate dynamic resources outfile = os.path.join(outdir, 'instance_dispatch_table.hpp') with open(outfile, 'w', encoding='utf-8', newline='\n') as handle: @@ -756,7 +769,7 @@ def main(): outfile = os.path.join(outdir, 'instance_functions.cpp') with open(outfile, 'w', encoding='utf-8', newline='\n') as handle: - generate_layer_instance_layer_defs(handle, mapping, commands, manual_commands) + generate_layer_instance_layer_defs(handle, mapping, commands) outfile = os.path.join(outdir, 'device_functions.hpp') with open(outfile, 'w', encoding='utf-8', newline='\n') as handle: @@ -764,7 +777,7 @@ def main(): outfile = os.path.join(outdir, 'device_functions.cpp') with open(outfile, 'w', encoding='utf-8', newline='\n') as handle: - generate_layer_device_layer_defs(handle, mapping, commands, manual_commands) + generate_layer_device_layer_defs(handle, mapping, commands) return 0 diff --git a/generator/vk_codegen/function_vkCreateDevice.txt b/generator/vk_codegen/function_vkCreateDevice.txt deleted file mode 100644 index df1c87b..0000000 --- a/generator/vk_codegen/function_vkCreateDevice.txt +++ /dev/null @@ -1,30 +0,0 @@ - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Instance::retrieve(physicalDevice); - - // Release the lock to call into the driver - lock.unlock(); - - auto* chainInfo = getChainInfo(pCreateInfo); - auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; - auto fpGetDeviceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; - auto fpCreateDevice = reinterpret_cast(fpGetInstanceProcAddr(layer->instance, "vkCreateDevice")); - if (!fpCreateDevice) - { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Advance the link info for the next element on the chain - chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; - auto res = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); - if (res != VK_SUCCESS) - { - return res; - } - - // Retake the lock to access layer-wide global store - lock.lock(); - auto device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr); - Device::store(*pDevice, std::move(device)); - - return VK_SUCCESS; \ No newline at end of file diff --git a/generator/vk_codegen/function_vkCreateInstance.txt b/generator/vk_codegen/function_vkCreateInstance.txt deleted file mode 100644 index 54a774b..0000000 --- a/generator/vk_codegen/function_vkCreateInstance.txt +++ /dev/null @@ -1,56 +0,0 @@ - auto* chainInfo = getChainInfo(pCreateInfo); - auto supportedExtensions = getInstanceExtensionList(pCreateInfo); - - auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; - auto fpCreateInstance = reinterpret_cast(fpGetInstanceProcAddr(nullptr, "vkCreateInstance")); - if (!fpCreateInstance) - { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Create a copy we can write - VkInstanceCreateInfo newCreateInfo = *pCreateInfo; - - // Query extension state - std::string targetExt("VK_EXT_debug_utils"); - bool targetSupported = isIn(targetExt, supportedExtensions); - bool targetEnabled = isInExtensionList( - targetExt, - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - if (!targetSupported) - { - LAYER_LOG("WARNING: Cannot enable additional extension: %s", targetExt.c_str()); - } - - // Enable the extension if we need to - std::vector newExtList; - if (targetSupported && !targetEnabled) - { - LAYER_LOG("Enabling additional extension: %s", targetExt.c_str()); - newExtList = cloneExtensionList( - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - newExtList.push_back(targetExt.c_str()); - - newCreateInfo.enabledExtensionCount = newExtList.size(); - newCreateInfo.ppEnabledExtensionNames = newExtList.data(); - } - - chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; - auto res = fpCreateInstance(&newCreateInfo, pAllocator, pInstance); - if (res != VK_SUCCESS) - { - return res; - } - - // Retake the lock to access layer-wide global store - auto instance = std::make_unique(*pInstance, fpGetInstanceProcAddr); - { - std::lock_guard lock { g_vulkanLock }; - Instance::store(*pInstance, instance); - } - - return VK_SUCCESS; \ No newline at end of file diff --git a/generator/vk_codegen/function_vkDestroyDevice.txt b/generator/vk_codegen/function_vkDestroyDevice.txt deleted file mode 100644 index 37837ed..0000000 --- a/generator/vk_codegen/function_vkDestroyDevice.txt +++ /dev/null @@ -1,11 +0,0 @@ - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Device::retrieve(device); - - // Layer proxy must be destroyed before the driver version - // so we can clean up any layer-owned resources - Device::destroy(layer); - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkDestroyDevice(device, pAllocator); \ No newline at end of file diff --git a/generator/vk_codegen/function_vkDestroyInstance.txt b/generator/vk_codegen/function_vkDestroyInstance.txt deleted file mode 100644 index 53bf5d1..0000000 --- a/generator/vk_codegen/function_vkDestroyInstance.txt +++ /dev/null @@ -1,11 +0,0 @@ - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Instance::retrieve(instance); - - // Layer proxy must be destroyed before the driver version - // so we can clean up any layer-owned resources - Instance::destroy(layer); - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkDestroyInstance(instance, pAllocator); diff --git a/generator/vk_codegen/function_vkGetDeviceImageMemoryRequirementsKHR.txt b/generator/vk_codegen/function_vkGetDeviceImageMemoryRequirementsKHR.txt deleted file mode 100644 index 749389f..0000000 --- a/generator/vk_codegen/function_vkGetDeviceImageMemoryRequirementsKHR.txt +++ /dev/null @@ -1,19 +0,0 @@ - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Device::retrieve(device); - - // Workaround Unreal Engine trying to invoke this via a function pointer - // queried from a Vulkan 1.1 instance with vkGetInstanceProcAddress() using - // a device created from a later a Vulkan 1.0 context for which the - // function is unavailable because VK_KHR_maintenance4 requires Vulkan 1.1 - if (!layer->driver.vkGetDeviceImageMemoryRequirementsKHR) - { - pMemoryRequirements->memoryRequirements.size = 0; - pMemoryRequirements->memoryRequirements.alignment = 0; - pMemoryRequirements->memoryRequirements.memoryTypeBits = 0; - return; - } - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkGetDeviceImageMemoryRequirementsKHR(device, pInfo, pMemoryRequirements); \ No newline at end of file diff --git a/generator/vk_codegen/instance_defs.txt b/generator/vk_codegen/instance_defs.txt index bd28163..d4891fb 100644 --- a/generator/vk_codegen/instance_defs.txt +++ b/generator/vk_codegen/instance_defs.txt @@ -7,7 +7,7 @@ #include "instance.hpp" // Include from common code -#include "framework/instance_functions_manual.hpp" +#include "framework/manual_functions.hpp" #include "framework/instance_functions.hpp" #include "framework/utils.hpp" diff --git a/generator/vk_codegen/source_CMakeLists.txt b/generator/vk_codegen/source_CMakeLists.txt index 286a5ea..01b9e65 100644 --- a/generator/vk_codegen/source_CMakeLists.txt +++ b/generator/vk_codegen/source_CMakeLists.txt @@ -41,8 +41,8 @@ configure_file( add_library( ${VK_LAYER} SHARED + ${PROJECT_SOURCE_DIR}/../source_common/framework/entry.cpp device.cpp - entry.cpp instance.cpp) target_include_directories( diff --git a/layer_example/source/CMakeLists.txt b/layer_example/source/CMakeLists.txt index 822aaed..33dbe6e 100644 --- a/layer_example/source/CMakeLists.txt +++ b/layer_example/source/CMakeLists.txt @@ -41,8 +41,8 @@ configure_file( add_library( ${VK_LAYER} SHARED + ${PROJECT_SOURCE_DIR}/../source_common/framework/entry.cpp device.cpp - entry.cpp instance.cpp layer_device_functions.cpp) diff --git a/layer_example/source/entry.cpp b/layer_example/source/entry.cpp deleted file mode 100644 index 0038cc6..0000000 --- a/layer_example/source/entry.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * ---------------------------------------------------------------------------- - */ - -/** - * @file - * This module exposes the entrypoints used by the layer loader. - * - * Note that the Android loader requires more functions to be exposed as - * library symbols than other Vulkan loaders. - */ -#include -#include -#include -#include - -#include "framework/instance_functions_manual.hpp" -#include "framework/utils.hpp" - -std::mutex g_vulkanLock; - -extern "C" { - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( - VkDevice device, - const char* pName -) { - return vkGetDeviceProcAddr_default(device, pName); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( - VkInstance instance, - const char* pName -) { - return vkGetInstanceProcAddr_default(instance, pName); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties -) { - return vkEnumerateInstanceExtensionProperties_default(pLayerName, pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( - VkPhysicalDevice gpu, - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties -) { - return vkEnumerateDeviceExtensionProperties_default(gpu, pLayerName, pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( - uint32_t* pPropertyCount, - VkLayerProperties* pProperties -) { - return vkEnumerateInstanceLayerProperties_default(pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( - VkPhysicalDevice gpu, - uint32_t* pPropertyCount, - VkLayerProperties* pProperties -) { - return vkEnumerateDeviceLayerProperties_default(gpu, pPropertyCount, pProperties); -} - -} diff --git a/layer_gpu_timeline/source/CMakeLists.txt b/layer_gpu_timeline/source/CMakeLists.txt index 75c021c..d267712 100644 --- a/layer_gpu_timeline/source/CMakeLists.txt +++ b/layer_gpu_timeline/source/CMakeLists.txt @@ -41,8 +41,8 @@ configure_file( add_library( ${VK_LAYER} SHARED + ${PROJECT_SOURCE_DIR}/../source_common/framework/entry.cpp device.cpp - entry.cpp instance.cpp) target_include_directories( diff --git a/layer_gpu_timeline/source/entry.cpp b/layer_gpu_timeline/source/entry.cpp deleted file mode 100644 index 0038cc6..0000000 --- a/layer_gpu_timeline/source/entry.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * ---------------------------------------------------------------------------- - */ - -/** - * @file - * This module exposes the entrypoints used by the layer loader. - * - * Note that the Android loader requires more functions to be exposed as - * library symbols than other Vulkan loaders. - */ -#include -#include -#include -#include - -#include "framework/instance_functions_manual.hpp" -#include "framework/utils.hpp" - -std::mutex g_vulkanLock; - -extern "C" { - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( - VkDevice device, - const char* pName -) { - return vkGetDeviceProcAddr_default(device, pName); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( - VkInstance instance, - const char* pName -) { - return vkGetInstanceProcAddr_default(instance, pName); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties -) { - return vkEnumerateInstanceExtensionProperties_default(pLayerName, pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( - VkPhysicalDevice gpu, - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties -) { - return vkEnumerateDeviceExtensionProperties_default(gpu, pLayerName, pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( - uint32_t* pPropertyCount, - VkLayerProperties* pProperties -) { - return vkEnumerateInstanceLayerProperties_default(pPropertyCount, pProperties); -} - -/** See Vulkan API for documentation. */ -VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( - VkPhysicalDevice gpu, - uint32_t* pPropertyCount, - VkLayerProperties* pProperties -) { - return vkEnumerateDeviceLayerProperties_default(gpu, pPropertyCount, pProperties); -} - -} diff --git a/source_common/framework/CMakeLists.txt b/source_common/framework/CMakeLists.txt index 29921a1..4b38e03 100644 --- a/source_common/framework/CMakeLists.txt +++ b/source_common/framework/CMakeLists.txt @@ -27,7 +27,7 @@ add_library( ${LIB_BINARY} STATIC device_functions.cpp instance_functions.cpp - instance_functions_manual.cpp) + manual_functions.cpp) target_include_directories( ${LIB_BINARY} PRIVATE diff --git a/source_common/framework/device_functions.cpp b/source_common/framework/device_functions.cpp index c31c6f6..52c2dae 100644 --- a/source_common/framework/device_functions.cpp +++ b/source_common/framework/device_functions.cpp @@ -4923,26 +4923,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkDestroyDescriptorUpdateTemplateKHR_default( layer->driver.vkDestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR void VKAPI_CALL layer_vkDestroyDevice_default( - VkDevice device, - const VkAllocationCallbacks* pAllocator -) { - LAYER_TRACE(__func__); - - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Device::retrieve(device); - - // Layer proxy must be destroyed before the driver version - // so we can clean up any layer-owned resources - Device::destroy(layer); - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkDestroyDevice(device, pAllocator); -} - /* See Vulkan API for documentation. */ VKAPI_ATTR void VKAPI_CALL layer_vkDestroyEvent_default( VkDevice device, @@ -5947,35 +5927,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceImageMemoryRequirements_default( layer->driver.vkGetDeviceImageMemoryRequirements(device, pInfo, pMemoryRequirements); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceImageMemoryRequirementsKHR_default( - VkDevice device, - const VkDeviceImageMemoryRequirements* pInfo, - VkMemoryRequirements2* pMemoryRequirements -) { - LAYER_TRACE(__func__); - - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Device::retrieve(device); - - // Workaround Unreal Engine trying to invoke this via a function pointer - // queried from a Vulkan 1.1 instance with vkGetInstanceProcAddress() using - // a device created from a later a Vulkan 1.0 context for which the - // function is unavailable because VK_KHR_maintenance4 requires Vulkan 1.1 - if (!layer->driver.vkGetDeviceImageMemoryRequirementsKHR) - { - pMemoryRequirements->memoryRequirements.size = 0; - pMemoryRequirements->memoryRequirements.alignment = 0; - pMemoryRequirements->memoryRequirements.memoryTypeBits = 0; - return; - } - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkGetDeviceImageMemoryRequirementsKHR(device, pInfo, pMemoryRequirements); -} - /* See Vulkan API for documentation. */ VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceImageSparseMemoryRequirements_default( VkDevice device, diff --git a/source_common/framework/device_functions.hpp b/source_common/framework/device_functions.hpp index 2321307..131daf3 100644 --- a/source_common/framework/device_functions.hpp +++ b/source_common/framework/device_functions.hpp @@ -6197,6 +6197,21 @@ VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceMicromapCompatibilityEXT( layer_vkGetDeviceMicromapCompatibilityEXT_default(device, pVersionInfo, pCompatibility); } +/* See Vulkan API for documentation. */ +/* Default common code pass-through implementation. */ +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL layer_vkGetDeviceProcAddr_default( + VkDevice device, + const char* pName); + +/* Match-all template to use default implementation. */ +template +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL layer_vkGetDeviceProcAddr( + VkDevice device, + const char* pName +) { + return layer_vkGetDeviceProcAddr_default(device, pName); +} + /* See Vulkan API for documentation. */ /* Default common code pass-through implementation. */ VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceQueue_default( diff --git a/source_common/framework/instance_functions_manual.cpp b/source_common/framework/device_functions_manual.cpp similarity index 70% rename from source_common/framework/instance_functions_manual.cpp rename to source_common/framework/device_functions_manual.cpp index 3e31d6e..576021e 100644 --- a/source_common/framework/instance_functions_manual.cpp +++ b/source_common/framework/device_functions_manual.cpp @@ -30,7 +30,7 @@ * implementations on a per-layer basis if needed. */ -#include "framework/instance_functions_manual.hpp" +#include "framework/manual_functions.hpp" /** * @brief Shared globals. @@ -247,32 +247,7 @@ std::vector cloneExtensionList( } /** See Vulkan API for documentation. */ -PFN_vkVoidFunction vkGetDeviceProcAddr_default( - VkDevice device, - const char* pName -) { - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Device::retrieve(device); - lock.unlock(); - - // Only expose functions that the driver exposes to avoid changing - // queryable interface behavior seen by the application - auto driverFunction = layer->driver.vkGetDeviceProcAddr(device, pName); - auto layerFunction = getDeviceLayerFunction(pName); - - // If driver exposes it and the layer has one, use the layer function - if (driverFunction && layerFunction) - { - return layerFunction; - } - - // Otherwise just use the driver function, which may be nullptr - return driverFunction; -} - -/** See Vulkan API for documentation. */ -PFN_vkVoidFunction vkGetInstanceProcAddr_default( +PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default( VkInstance instance, const char* pName ) { @@ -308,7 +283,32 @@ PFN_vkVoidFunction vkGetInstanceProcAddr_default( } /** See Vulkan API for documentation. */ -VkResult vkEnumerateInstanceExtensionProperties_default( +PFN_vkVoidFunction layer_vkGetDeviceProcAddr_default( + VkDevice device, + const char* pName +) { + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Device::retrieve(device); + lock.unlock(); + + // Only expose functions that the driver exposes to avoid changing + // queryable interface behavior seen by the application + auto driverFunction = layer->driver.vkGetDeviceProcAddr(device, pName); + auto layerFunction = getDeviceLayerFunction(pName); + + // If driver exposes it and the layer has one, use the layer function + if (driverFunction && layerFunction) + { + return layerFunction; + } + + // Otherwise just use the driver function, which may be nullptr + return driverFunction; +} + +/** See Vulkan API for documentation. */ +VkResult layer_vkEnumerateInstanceExtensionProperties_default( const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties @@ -327,7 +327,7 @@ VkResult vkEnumerateInstanceExtensionProperties_default( } /** See Vulkan API for documentation. */ -VkResult vkEnumerateDeviceExtensionProperties_default( +VkResult layer_vkEnumerateDeviceExtensionProperties_default( VkPhysicalDevice gpu, const char* pLayerName, uint32_t* pPropertyCount, @@ -362,7 +362,7 @@ VkResult vkEnumerateDeviceExtensionProperties_default( } /** See Vulkan API for documentation. */ -VkResult vkEnumerateInstanceLayerProperties_default( +VkResult layer_vkEnumerateInstanceLayerProperties_default( uint32_t* pPropertyCount, VkLayerProperties* pProperties ) { @@ -386,7 +386,7 @@ VkResult vkEnumerateInstanceLayerProperties_default( } /** See Vulkan API for documentation. */ -VkResult vkEnumerateDeviceLayerProperties_default( +VkResult layer_vkEnumerateDeviceLayerProperties_default( VkPhysicalDevice gpu, uint32_t* pPropertyCount, VkLayerProperties* pProperties @@ -411,3 +411,131 @@ VkResult vkEnumerateDeviceLayerProperties_default( *pPropertyCount = layerProps.size(); return VK_SUCCESS; } + +/* See Vulkan API for documentation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance +) { + LAYER_TRACE(__func__); + + auto* chainInfo = getChainInfo(pCreateInfo); + auto supportedExtensions = getInstanceExtensionList(pCreateInfo); + + auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + auto fpCreateInstance = reinterpret_cast(fpGetInstanceProcAddr(nullptr, "vkCreateInstance")); + if (!fpCreateInstance) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Create a copy we can write + VkInstanceCreateInfo newCreateInfo = *pCreateInfo; + + // Query extension state + std::string targetExt("VK_EXT_debug_utils"); + bool targetSupported = isIn(targetExt, supportedExtensions); + bool targetEnabled = isInExtensionList( + targetExt, + pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); + + if (!targetSupported) + { + LAYER_LOG("WARNING: Cannot enable additional extension: %s", targetExt.c_str()); + } + + // Enable the extension if we need to + std::vector newExtList; + if (targetSupported && !targetEnabled) + { + LAYER_LOG("Enabling additional extension: %s", targetExt.c_str()); + newExtList = cloneExtensionList( + pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); + + newExtList.push_back(targetExt.c_str()); + + newCreateInfo.enabledExtensionCount = newExtList.size(); + newCreateInfo.ppEnabledExtensionNames = newExtList.data(); + } + + chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; + auto res = fpCreateInstance(&newCreateInfo, pAllocator, pInstance); + if (res != VK_SUCCESS) + { + return res; + } + + // Retake the lock to access layer-wide global store + auto instance = std::make_unique(*pInstance, fpGetInstanceProcAddr); + { + std::lock_guard lock { g_vulkanLock }; + Instance::store(*pInstance, instance); + } + + return VK_SUCCESS; +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR void VKAPI_CALL layer_vkDestroyInstance_default( + VkInstance instance, + const VkAllocationCallbacks* pAllocator +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(instance); + + // Layer proxy must be destroyed before the driver version + // so we can clean up any layer-owned resources + Instance::destroy(layer); + + // Release the lock to call into the driver + lock.unlock(); + layer->driver.vkDestroyInstance(instance, pAllocator); + +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDevice_default( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(physicalDevice); + + // Release the lock to call into the driver + lock.unlock(); + + auto* chainInfo = getChainInfo(pCreateInfo); + auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + auto fpGetDeviceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; + auto fpCreateDevice = reinterpret_cast(fpGetInstanceProcAddr(layer->instance, "vkCreateDevice")); + if (!fpCreateDevice) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Advance the link info for the next element on the chain + chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; + auto res = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); + if (res != VK_SUCCESS) + { + return res; + } + + // Retake the lock to access layer-wide global store + lock.lock(); + auto device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr); + Device::store(*pDevice, std::move(device)); + + return VK_SUCCESS; +} \ No newline at end of file diff --git a/generator/vk_layer/source/entry.cpp b/source_common/framework/entry.cpp similarity index 77% rename from generator/vk_layer/source/entry.cpp rename to source_common/framework/entry.cpp index 0038cc6..d1090e6 100644 --- a/generator/vk_layer/source/entry.cpp +++ b/source_common/framework/entry.cpp @@ -30,14 +30,20 @@ * Note that the Android loader requires more functions to be exposed as * library symbols than other Vulkan loaders. */ -#include -#include #include -#include -#include "framework/instance_functions_manual.hpp" +#include "framework/device_functions.hpp" +#include "framework/instance_functions.hpp" #include "framework/utils.hpp" +#if __has_include ("layer_device_functions.hpp") + #include "layer_device_functions.hpp" +#endif + +#if __has_include ("layer_instance_functions.hpp") + #include "layer_instance_functions.hpp" +#endif + std::mutex g_vulkanLock; extern "C" { @@ -47,7 +53,7 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( VkDevice device, const char* pName ) { - return vkGetDeviceProcAddr_default(device, pName); + return layer_vkGetDeviceProcAddr(device, pName); } /** See Vulkan API for documentation. */ @@ -55,7 +61,7 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( VkInstance instance, const char* pName ) { - return vkGetInstanceProcAddr_default(instance, pName); + return layer_vkGetInstanceProcAddr(instance, pName); } /** See Vulkan API for documentation. */ @@ -64,7 +70,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionPrope uint32_t* pPropertyCount, VkExtensionProperties* pProperties ) { - return vkEnumerateInstanceExtensionProperties_default(pLayerName, pPropertyCount, pProperties); + return layer_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties); } /** See Vulkan API for documentation. */ @@ -74,7 +80,7 @@ VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensio uint32_t* pPropertyCount, VkExtensionProperties* pProperties ) { - return vkEnumerateDeviceExtensionProperties_default(gpu, pLayerName, pPropertyCount, pProperties); + return layer_vkEnumerateDeviceExtensionProperties(gpu, pLayerName, pPropertyCount, pProperties); } /** See Vulkan API for documentation. */ @@ -82,7 +88,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerPropertie uint32_t* pPropertyCount, VkLayerProperties* pProperties ) { - return vkEnumerateInstanceLayerProperties_default(pPropertyCount, pProperties); + return layer_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties); } /** See Vulkan API for documentation. */ @@ -91,7 +97,7 @@ VK_LAYER_EXPORT_ANDROID VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerPro uint32_t* pPropertyCount, VkLayerProperties* pProperties ) { - return vkEnumerateDeviceLayerProperties_default(gpu, pPropertyCount, pProperties); + return layer_vkEnumerateDeviceLayerProperties(gpu, pPropertyCount, pProperties); } } diff --git a/source_common/framework/instance_dispatch_table.hpp b/source_common/framework/instance_dispatch_table.hpp index 73ea229..8f7488d 100644 --- a/source_common/framework/instance_dispatch_table.hpp +++ b/source_common/framework/instance_dispatch_table.hpp @@ -481,6 +481,7 @@ static const struct InstanceInterceptTableEntry instanceIntercepts[] = { ENTRY(vkGetDeviceMemoryOpaqueCaptureAddress), ENTRY(vkGetDeviceMemoryOpaqueCaptureAddressKHR), ENTRY(vkGetDeviceMicromapCompatibilityEXT), + ENTRY(vkGetDeviceProcAddr), ENTRY(vkGetDeviceQueue), ENTRY(vkGetDeviceQueue2), ENTRY(vkGetEventStatus), @@ -603,6 +604,9 @@ struct InstanceDispatchTable { PFN_vkDestroyInstance vkDestroyInstance; PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; + PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; @@ -692,6 +696,9 @@ static inline void initDriverInstanceDispatchTable( ENTRY(vkDestroyInstance); ENTRY(vkDestroySurfaceKHR); ENTRY(vkEnumerateDeviceExtensionProperties); + ENTRY(vkEnumerateDeviceLayerProperties); + ENTRY(vkEnumerateInstanceExtensionProperties); + ENTRY(vkEnumerateInstanceLayerProperties); ENTRY(vkEnumeratePhysicalDeviceGroups); ENTRY(vkEnumeratePhysicalDeviceGroupsKHR); ENTRY(vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR); diff --git a/source_common/framework/instance_functions.cpp b/source_common/framework/instance_functions.cpp index a430ddc..3c613f3 100644 --- a/source_common/framework/instance_functions.cpp +++ b/source_common/framework/instance_functions.cpp @@ -32,7 +32,7 @@ #include "instance.hpp" // Include from common code -#include "framework/instance_functions_manual.hpp" +#include "framework/manual_functions.hpp" #include "framework/instance_functions.hpp" #include "framework/utils.hpp" @@ -96,47 +96,6 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDebugUtilsMessengerEXT_default( return layer->driver.vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDevice_default( - VkPhysicalDevice physicalDevice, - const VkDeviceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDevice* pDevice -) { - LAYER_TRACE(__func__); - - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Instance::retrieve(physicalDevice); - - // Release the lock to call into the driver - lock.unlock(); - - auto* chainInfo = getChainInfo(pCreateInfo); - auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; - auto fpGetDeviceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; - auto fpCreateDevice = reinterpret_cast(fpGetInstanceProcAddr(layer->instance, "vkCreateDevice")); - if (!fpCreateDevice) - { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Advance the link info for the next element on the chain - chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; - auto res = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); - if (res != VK_SUCCESS) - { - return res; - } - - // Retake the lock to access layer-wide global store - lock.lock(); - auto device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr); - Device::store(*pDevice, std::move(device)); - - return VK_SUCCESS; -} - /* See Vulkan API for documentation. */ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDisplayModeKHR_default( VkPhysicalDevice physicalDevice, @@ -174,72 +133,6 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDisplayPlaneSurfaceKHR_default( return layer->driver.vkCreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default( - const VkInstanceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkInstance* pInstance -) { - LAYER_TRACE(__func__); - - auto* chainInfo = getChainInfo(pCreateInfo); - auto supportedExtensions = getInstanceExtensionList(pCreateInfo); - - auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; - auto fpCreateInstance = reinterpret_cast(fpGetInstanceProcAddr(nullptr, "vkCreateInstance")); - if (!fpCreateInstance) - { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Create a copy we can write - VkInstanceCreateInfo newCreateInfo = *pCreateInfo; - - // Query extension state - std::string targetExt("VK_EXT_debug_utils"); - bool targetSupported = isIn(targetExt, supportedExtensions); - bool targetEnabled = isInExtensionList( - targetExt, - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - if (!targetSupported) - { - LAYER_LOG("WARNING: Cannot enable additional extension: %s", targetExt.c_str()); - } - - // Enable the extension if we need to - std::vector newExtList; - if (targetSupported && !targetEnabled) - { - LAYER_LOG("Enabling additional extension: %s", targetExt.c_str()); - newExtList = cloneExtensionList( - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - newExtList.push_back(targetExt.c_str()); - - newCreateInfo.enabledExtensionCount = newExtList.size(); - newCreateInfo.ppEnabledExtensionNames = newExtList.data(); - } - - chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; - auto res = fpCreateInstance(&newCreateInfo, pAllocator, pInstance); - if (res != VK_SUCCESS) - { - return res; - } - - // Retake the lock to access layer-wide global store - auto instance = std::make_unique(*pInstance, fpGetInstanceProcAddr); - { - std::lock_guard lock { g_vulkanLock }; - Instance::store(*pInstance, instance); - } - - return VK_SUCCESS; -} - /* See Vulkan API for documentation. */ VKAPI_ATTR void VKAPI_CALL layer_vkDebugReportMessageEXT_default( VkInstance instance, @@ -296,27 +189,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkDestroyDebugUtilsMessengerEXT_default( layer->driver.vkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR void VKAPI_CALL layer_vkDestroyInstance_default( - VkInstance instance, - const VkAllocationCallbacks* pAllocator -) { - LAYER_TRACE(__func__); - - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Instance::retrieve(instance); - - // Layer proxy must be destroyed before the driver version - // so we can clean up any layer-owned resources - Instance::destroy(layer); - - // Release the lock to call into the driver - lock.unlock(); - layer->driver.vkDestroyInstance(instance, pAllocator); - -} - /* See Vulkan API for documentation. */ VKAPI_ATTR void VKAPI_CALL layer_vkDestroySurfaceKHR_default( VkInstance instance, @@ -334,24 +206,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkDestroySurfaceKHR_default( layer->driver.vkDestroySurfaceKHR(instance, surface, pAllocator); } -/* See Vulkan API for documentation. */ -VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateDeviceExtensionProperties_default( - VkPhysicalDevice physicalDevice, - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties -) { - LAYER_TRACE(__func__); - - // Hold the lock to access layer-wide global store - std::unique_lock lock { g_vulkanLock }; - auto* layer = Instance::retrieve(physicalDevice); - - // Release the lock to call into the driver - lock.unlock(); - return layer->driver.vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties); -} - /* See Vulkan API for documentation. */ VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumeratePhysicalDeviceGroups_default( VkInstance instance, diff --git a/source_common/framework/instance_functions.hpp b/source_common/framework/instance_functions.hpp index 481a930..3314ed6 100644 --- a/source_common/framework/instance_functions.hpp +++ b/source_common/framework/instance_functions.hpp @@ -276,6 +276,55 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateDeviceExtensionProperties( return layer_vkEnumerateDeviceExtensionProperties_default(physicalDevice, pLayerName, pPropertyCount, pProperties); } +/* See Vulkan API for documentation. */ +/* Default common code pass-through implementation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateDeviceLayerProperties_default( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +/* Match-all template to use default implementation. */ +template +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateDeviceLayerProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties +) { + return layer_vkEnumerateDeviceLayerProperties_default(physicalDevice, pPropertyCount, pProperties); +} + +/* See Vulkan API for documentation. */ +/* Default common code pass-through implementation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateInstanceExtensionProperties_default( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +/* Match-all template to use default implementation. */ +template +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties +) { + return layer_vkEnumerateInstanceExtensionProperties_default(pLayerName, pPropertyCount, pProperties); +} + +/* See Vulkan API for documentation. */ +/* Default common code pass-through implementation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateInstanceLayerProperties_default( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +/* Match-all template to use default implementation. */ +template +VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumerateInstanceLayerProperties( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties +) { + return layer_vkEnumerateInstanceLayerProperties_default(pPropertyCount, pProperties); +} + /* See Vulkan API for documentation. */ /* Default common code pass-through implementation. */ VKAPI_ATTR VkResult VKAPI_CALL layer_vkEnumeratePhysicalDeviceGroups_default( @@ -441,6 +490,21 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkGetDisplayPlaneSupportedDisplaysKHR( return layer_vkGetDisplayPlaneSupportedDisplaysKHR_default(physicalDevice, planeIndex, pDisplayCount, pDisplays); } +/* See Vulkan API for documentation. */ +/* Default common code pass-through implementation. */ +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL layer_vkGetInstanceProcAddr_default( + VkInstance instance, + const char* pName); + +/* Match-all template to use default implementation. */ +template +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL layer_vkGetInstanceProcAddr( + VkInstance instance, + const char* pName +) { + return layer_vkGetInstanceProcAddr_default(instance, pName); +} + /* See Vulkan API for documentation. */ /* Default common code pass-through implementation. */ VKAPI_ATTR VkResult VKAPI_CALL layer_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT_default( diff --git a/source_common/framework/manual_functions.cpp b/source_common/framework/manual_functions.cpp new file mode 100644 index 0000000..46d68c4 --- /dev/null +++ b/source_common/framework/manual_functions.cpp @@ -0,0 +1,590 @@ +/* + * SPDX-License-Identifier: MIT + * ---------------------------------------------------------------------------- + * Copyright (c) 2024 Arm Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * ---------------------------------------------------------------------------- + */ + +/** + * @file + * This module exposes common functionality used by layer entrypoints, + * implemented as library code which can be swapped for alternative + * implementations on a per-layer basis if needed. + */ + +#include "framework/manual_functions.hpp" + +/** + * @brief Shared globals. + */ +extern std::mutex g_vulkanLock; + +/** + * @brief The layer configuration. + */ +#define LGL_VERSION VK_MAKE_VERSION(LGL_VER_MAJOR, LGL_VER_MINOR, LGL_VER_PATCH) + +static const std::array layerProps = { + {{ LGL_LAYER_NAME, LGL_VERSION, 1, LGL_LAYER_DESC }}, +}; + +/** + * @brief Dispatch table lookup entry. + */ +struct DispatchTableEntry +{ + /** + * @brief The function entrypoint name. + */ + const char* name; + + /** + * @brief The function pointer. + */ + PFN_vkVoidFunction function; +}; + +/** + * @brief Utility macro to define a lookup for a core function. + */ +#define VK_TABLE_ENTRY(func) \ + { STR(func), reinterpret_cast(func) } + +/** + * @brief Utility macro to define a lookup for a layer-dispatch-only function. + */ +#define VK_TABLE_ENTRYL(func) \ + { STR(func), reinterpret_cast(layer_##func) } + +/* See header for documentation. */ +VkLayerInstanceCreateInfo* getChainInfo( + const VkInstanceCreateInfo* pCreateInfo +) { + auto* info = static_cast(pCreateInfo->pNext); + while (info) + { + bool isType = info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; + bool isFunction = info->function == VK_LAYER_LINK_INFO; + if (isType && isFunction) + { + break; + } + + info = static_cast(info->pNext); + } + + return const_cast(info); +} + +/* See header for documentation. */ +VkLayerDeviceCreateInfo* getChainInfo( + const VkDeviceCreateInfo* pCreateInfo +) { + auto* info = static_cast(pCreateInfo->pNext); + while (info) + { + bool isType = info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; + bool isFunction = info->function == VK_LAYER_LINK_INFO; + if (isType && isFunction) + { + break; + } + + info = static_cast(info->pNext); + } + + return const_cast(info); +} + +/* See header for documentation. */ +PFN_vkVoidFunction getFixedInstanceLayerFunction( + const char* name +) { + static const DispatchTableEntry layerFunctions[] = { + VK_TABLE_ENTRY(vkGetInstanceProcAddr), + VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties), + VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties), + VK_TABLE_ENTRY(vkEnumerateInstanceLayerProperties), + VK_TABLE_ENTRY(vkEnumerateInstanceExtensionProperties), + }; + + for (auto &function : layerFunctions) + { + if (!strcmp(function.name, name)) + { + return function.function; + } + } + + return nullptr; +} + +/* See header for documentation. */ +PFN_vkVoidFunction getInstanceLayerFunction( + const char* name +) { + for (auto &function : instanceIntercepts) + { + if (!strcmp(function.name, name)) + { + return function.function; + } + } + + return nullptr; +} + +/* See header for documentation. */ +PFN_vkVoidFunction getDeviceLayerFunction( + const char* name +) { + static const DispatchTableEntry layerFunctions[] = { + VK_TABLE_ENTRY(vkGetDeviceProcAddr), + VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties), + VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties), + }; + + for (auto &function : layerFunctions) + { + if (!strcmp(function.name, name)) + { + return function.function; + } + } + + for (auto &function : deviceIntercepts) + { + if (!strcmp(function.name, name)) + { + return function.function; + } + } + + return nullptr; +} + +/* See header for documentation. */ +std::vector getInstanceExtensionList( + const VkInstanceCreateInfo* pCreateInfo +) { + std::vector foundExtensions; + + // Fetch the functions needed to query extensions availability + auto* chainInfo = getChainInfo(pCreateInfo); + auto fpGetProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + auto fpGetExtensionsRaw = fpGetProcAddr(nullptr, "vkEnumerateInstanceExtensionProperties"); + auto fpGetExtensions = reinterpret_cast(fpGetExtensionsRaw); + if (!fpGetExtensions) + { + return foundExtensions; + } + + // Query number of extensions + uint32_t count; + fpGetExtensions(nullptr, &count, nullptr); + + // Reserve memory for, and then query, the extensions + std::vector extensions; + extensions.resize(count); + fpGetExtensions(nullptr, &count, extensions.data()); + + // Build the function return list + for (uint32_t i = 0; i < count; i++) + { + foundExtensions.emplace_back(extensions[i].extensionName); + } + + return foundExtensions; +} + +/* See header for documentation. */ +bool isInExtensionList( + const std::string& target, + uint32_t extensionCount, + const char* const* extensionList +) { + for(uint32_t i = 0; i < extensionCount; i++) + { + if (target == extensionList[i]) + { + return true; + } + } + + return false; +} + +/* See header for documentation. */ +std::vector cloneExtensionList( + uint32_t extensionCount, + const char* const* extensionList +) { + std::vector data; + for(uint32_t i = 0; i < extensionCount; i++) + { + data.emplace_back(extensionList[i]); + } + + return data; +} + +/** See Vulkan API for documentation. */ +PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default( + VkInstance instance, + const char* pName +) { + // Always expose these functions ... + PFN_vkVoidFunction layerFunction = getFixedInstanceLayerFunction(pName); + if (layerFunction) + { + return layerFunction; + } + + // Otherwise, only expose functions that the driver exposes to avoid + // changing queryable interface behavior seen by the application + layerFunction = getInstanceLayerFunction(pName); + if (instance) { + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(instance); + + // Don't hold the lock while calling the driver + lock.unlock(); + PFN_vkVoidFunction driverFunction = layer->nlayerGetProcAddress(instance, pName); + + // If driver exposes it and the layer has one, use the layer function + if (driverFunction && layerFunction) + { + return layerFunction; + } + + // Otherwise just use the driver function, which may be nullptr + return driverFunction; + } + + return layerFunction; +} + +/** See Vulkan API for documentation. */ +PFN_vkVoidFunction layer_vkGetDeviceProcAddr_default( + VkDevice device, + const char* pName +) { + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Device::retrieve(device); + lock.unlock(); + + // Only expose functions that the driver exposes to avoid changing + // queryable interface behavior seen by the application + auto driverFunction = layer->driver.vkGetDeviceProcAddr(device, pName); + auto layerFunction = getDeviceLayerFunction(pName); + + // If driver exposes it and the layer has one, use the layer function + if (driverFunction && layerFunction) + { + return layerFunction; + } + + // Otherwise just use the driver function, which may be nullptr + return driverFunction; +} + +/** See Vulkan API for documentation. */ +VkResult layer_vkEnumerateInstanceExtensionProperties_default( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties +) { + LAYER_TRACE(__func__); + + UNUSED(pProperties); + + if (!pLayerName || strcmp(pLayerName, layerProps[0].layerName)) + { + return VK_ERROR_LAYER_NOT_PRESENT; + } + + *pPropertyCount = 0; + return VK_SUCCESS; +} + +/** See Vulkan API for documentation. */ +VkResult layer_vkEnumerateDeviceExtensionProperties_default( + VkPhysicalDevice gpu, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties +) { + LAYER_TRACE(__func__); + + UNUSED(pProperties); + + // Android layer enumeration will always pass a nullptr for the device + if (!gpu) + { + if (!pLayerName || strcmp(pLayerName, layerProps[0].layerName)) + { + return VK_ERROR_LAYER_NOT_PRESENT; + } + + *pPropertyCount = 0; + return VK_SUCCESS; + } + + // For other cases forward to the driver to handle it + assert(!pLayerName); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(gpu); + + // Release the lock to call into the driver + lock.unlock(); + return layer->driver.vkEnumerateDeviceExtensionProperties(gpu, pLayerName, pPropertyCount, pProperties); +} + +/** See Vulkan API for documentation. */ +VkResult layer_vkEnumerateInstanceLayerProperties_default( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties +) { + LAYER_TRACE(__func__); + + if (pProperties) + { + size_t count = std::min(layerProps.size(), static_cast(*pPropertyCount)); + if (count < layerProps.size()) + { + return VK_INCOMPLETE; + } + + memcpy(pProperties, layerProps.data(), count * sizeof(VkLayerProperties)); + *pPropertyCount = count; + return VK_SUCCESS; + } + + *pPropertyCount = layerProps.size(); + return VK_SUCCESS; +} + +/** See Vulkan API for documentation. */ +VkResult layer_vkEnumerateDeviceLayerProperties_default( + VkPhysicalDevice gpu, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties +) { + LAYER_TRACE(__func__); + + UNUSED(gpu); + + if (pProperties) + { + size_t count = std::min(layerProps.size(), static_cast(*pPropertyCount)); + if (count < layerProps.size()) + { + return VK_INCOMPLETE; + } + + memcpy(pProperties, layerProps.data(), count * sizeof(VkLayerProperties)); + *pPropertyCount = count; + return VK_SUCCESS; + } + + *pPropertyCount = layerProps.size(); + return VK_SUCCESS; +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance +) { + LAYER_TRACE(__func__); + + auto* chainInfo = getChainInfo(pCreateInfo); + auto supportedExtensions = getInstanceExtensionList(pCreateInfo); + + auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + auto fpCreateInstance = reinterpret_cast(fpGetInstanceProcAddr(nullptr, "vkCreateInstance")); + if (!fpCreateInstance) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Create a copy we can write + VkInstanceCreateInfo newCreateInfo = *pCreateInfo; + + // Query extension state + std::string targetExt("VK_EXT_debug_utils"); + bool targetSupported = isIn(targetExt, supportedExtensions); + bool targetEnabled = isInExtensionList( + targetExt, + pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); + + if (!targetSupported) + { + LAYER_LOG("WARNING: Cannot enable additional extension: %s", targetExt.c_str()); + } + + // Enable the extension if we need to + std::vector newExtList; + if (targetSupported && !targetEnabled) + { + LAYER_LOG("Enabling additional extension: %s", targetExt.c_str()); + newExtList = cloneExtensionList( + pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); + + newExtList.push_back(targetExt.c_str()); + + newCreateInfo.enabledExtensionCount = newExtList.size(); + newCreateInfo.ppEnabledExtensionNames = newExtList.data(); + } + + chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; + auto res = fpCreateInstance(&newCreateInfo, pAllocator, pInstance); + if (res != VK_SUCCESS) + { + return res; + } + + // Retake the lock to access layer-wide global store + auto instance = std::make_unique(*pInstance, fpGetInstanceProcAddr); + { + std::lock_guard lock { g_vulkanLock }; + Instance::store(*pInstance, instance); + } + + return VK_SUCCESS; +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR void VKAPI_CALL layer_vkDestroyInstance_default( + VkInstance instance, + const VkAllocationCallbacks* pAllocator +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(instance); + + // Layer proxy must be destroyed before the driver version + // so we can clean up any layer-owned resources + Instance::destroy(layer); + + // Release the lock to call into the driver + lock.unlock(); + layer->driver.vkDestroyInstance(instance, pAllocator); + +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDevice_default( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Instance::retrieve(physicalDevice); + + // Release the lock to call into the driver + lock.unlock(); + + auto* chainInfo = getChainInfo(pCreateInfo); + auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + auto fpGetDeviceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; + auto fpCreateDevice = reinterpret_cast(fpGetInstanceProcAddr(layer->instance, "vkCreateDevice")); + if (!fpCreateDevice) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Advance the link info for the next element on the chain + chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; + auto res = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); + if (res != VK_SUCCESS) + { + return res; + } + + // Retake the lock to access layer-wide global store + lock.lock(); + auto device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr); + Device::store(*pDevice, std::move(device)); + + return VK_SUCCESS; +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR void VKAPI_CALL layer_vkDestroyDevice_default( + VkDevice device, + const VkAllocationCallbacks* pAllocator +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Device::retrieve(device); + + // Layer proxy must be destroyed before the driver version + // so we can clean up any layer-owned resources + Device::destroy(layer); + + // Release the lock to call into the driver + lock.unlock(); + layer->driver.vkDestroyDevice(device, pAllocator); +} + +/* See Vulkan API for documentation. */ +VKAPI_ATTR void VKAPI_CALL layer_vkGetDeviceImageMemoryRequirementsKHR_default( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements +) { + LAYER_TRACE(__func__); + + // Hold the lock to access layer-wide global store + std::unique_lock lock { g_vulkanLock }; + auto* layer = Device::retrieve(device); + + // Workaround Unreal Engine trying to invoke this via a function pointer + // queried from a Vulkan 1.1 instance with vkGetInstanceProcAddress() using + // a device created from a later a Vulkan 1.0 context for which the + // function is unavailable because VK_KHR_maintenance4 requires Vulkan 1.1 + if (!layer->driver.vkGetDeviceImageMemoryRequirementsKHR) + { + pMemoryRequirements->memoryRequirements.size = 0; + pMemoryRequirements->memoryRequirements.alignment = 0; + pMemoryRequirements->memoryRequirements.memoryTypeBits = 0; + return; + } + + // Release the lock to call into the driver + lock.unlock(); + layer->driver.vkGetDeviceImageMemoryRequirementsKHR(device, pInfo, pMemoryRequirements); +} diff --git a/source_common/framework/instance_functions_manual.hpp b/source_common/framework/manual_functions.hpp similarity index 82% rename from source_common/framework/instance_functions_manual.hpp rename to source_common/framework/manual_functions.hpp index e9bd118..de50267 100644 --- a/source_common/framework/instance_functions_manual.hpp +++ b/source_common/framework/manual_functions.hpp @@ -144,37 +144,3 @@ bool isInExtensionList( std::vector cloneExtensionList( uint32_t extensionCount, const char* const* extensionList); - -/** See Vulkan API for documentation. */ -PFN_vkVoidFunction vkGetDeviceProcAddr_default( - VkDevice device, - const char* pName); - -/** See Vulkan API for documentation. */ -PFN_vkVoidFunction vkGetInstanceProcAddr_default( - VkInstance instance, - const char* pName); - -/** See Vulkan API for documentation. */ -VkResult vkEnumerateInstanceExtensionProperties_default( - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties); - -/** See Vulkan API for documentation. */ -VkResult vkEnumerateDeviceExtensionProperties_default( - VkPhysicalDevice gpu, - const char* pLayerName, - uint32_t* pPropertyCount, - VkExtensionProperties* pProperties); - -/** See Vulkan API for documentation. */ -VkResult vkEnumerateInstanceLayerProperties_default( - uint32_t* pPropertyCount, - VkLayerProperties* pProperties); - -/** See Vulkan API for documentation. */ -VkResult vkEnumerateDeviceLayerProperties_default( - VkPhysicalDevice gpu, - uint32_t* pPropertyCount, - VkLayerProperties* pProperties);