diff --git a/Common/MVKCommonEnvironment.h b/Common/MVKCommonEnvironment.h index d9139793..ae4c6e34 100644 --- a/Common/MVKCommonEnvironment.h +++ b/Common/MVKCommonEnvironment.h @@ -102,8 +102,7 @@ extern "C" { #endif /** Directive to identify public symbols. */ -#define MVK_PUBLIC_SYMBOL __attribute__((visibility("default"))) - +#define MVK_PUBLIC_SYMBOL __attribute__((visibility("default"))) __attribute__((used)) /** Directive to make a public alias of another symbol. */ #define MVK_PUBLIC_ALIAS(ALIAS, TARGET) asm(".globl _" #ALIAS "\n\t_" #ALIAS " = _" #TARGET) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 95be3e72..4c1a7130 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -22,6 +22,10 @@ Released TBD `MTLCommandBuffer` is finished using it. - Fix memory leak of `MVKFences` and `MVKSemaphores` when a swapchain image is acquired more than it is presented. +- Ensure Vulkan public symbols are not stripped from the library when + statically linked to an app that calls all Vulkan functions dynamically. +- Per Vulkan 1.2 spec, support calling `vkGetInstanceProcAddr()` with a + null instance, when `vkGetInstanceProcAddr` itself is the function name. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index 2bb5e407..05fb750a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -449,7 +449,6 @@ void MVKInstance::initProcAddrs() { ADD_INST_ENTRY_POINT(vkGetPhysicalDeviceProperties); ADD_INST_ENTRY_POINT(vkGetPhysicalDeviceQueueFamilyProperties); ADD_INST_ENTRY_POINT(vkGetPhysicalDeviceMemoryProperties); - ADD_INST_ENTRY_POINT(vkGetInstanceProcAddr); ADD_INST_ENTRY_POINT(vkCreateDevice); ADD_INST_ENTRY_POINT(vkEnumerateDeviceExtensionProperties); ADD_INST_ENTRY_POINT(vkEnumerateDeviceLayerProperties); diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm index c1126227..7a4aa18f 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm @@ -141,7 +141,7 @@ bool MVKExtensionList::isEnabled(const char* extnName) const { const MVKExtension* extnAry = &extensionArray; for (uint32_t extnIdx = 0; extnIdx < extnCnt; extnIdx++) { const MVKExtension& extn = extnAry[extnIdx]; - if ( strcmp(extn.pProperties->extensionName, extnName) == 0 ) { + if (mvkStringsAreEqual(extn.pProperties->extensionName, extnName)) { return extn.enabled; } } @@ -153,7 +153,7 @@ void MVKExtensionList::enable(const char* extnName) { MVKExtension* extnAry = &extensionArray; for (uint32_t extnIdx = 0; extnIdx < extnCnt; extnIdx++) { MVKExtension& extn = extnAry[extnIdx]; - if ( strcmp(extn.pProperties->extensionName, extnName) == 0 ) { + if (mvkStringsAreEqual(extn.pProperties->extensionName, extnName)) { extn.enabled = true; return; } diff --git a/MoltenVK/MoltenVK/Layers/MVKLayers.mm b/MoltenVK/MoltenVK/Layers/MVKLayers.mm index 2613cee2..94f73f0e 100644 --- a/MoltenVK/MoltenVK/Layers/MVKLayers.mm +++ b/MoltenVK/MoltenVK/Layers/MVKLayers.mm @@ -65,7 +65,7 @@ MVKLayer* MVKLayerManager::getLayerNamed(const char* pLayerName) { uint32_t layCnt = (uint32_t)_layers.size(); for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) { MVKLayer* pLayer = &_layers[layIdx]; - if ( strcmp(pLayer->getName(), pLayerName) == 0 ) { return pLayer; } + if (mvkStringsAreEqual(pLayer->getName(), pLayerName)) { return pLayer; } } return VK_NULL_HANDLE; } diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h index 30d0a4bf..a0ad5ed8 100644 --- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h +++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h @@ -549,6 +549,15 @@ bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) { return (pV1 && pV2) ? (memcmp(pV1, pV2, sizeof(T) * count) == 0) : false; } +/** + * If both pV1 and pV2 are not null, returns whether the contents of the two strings are equal, + * otherwise returns false. This functionality is different than the char version of mvkAreEqual(), + * which works on individual chars or char arrays, not strings. + */ +static inline bool mvkStringsAreEqual(const char* pV1, const char* pV2, size_t count = 1) { + return (pV1 && pV2) ? (strcmp(pV1, pV2) == 0) : false; +} + /** * Sets the value referenced by the destination pointer with the value referenced by * the source pointer, and returns whether the value was set. diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index 24c75a1e..01473c20 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -284,17 +284,18 @@ MVK_PUBLIC_VULKAN_SYMBOL PFN_vkVoidFunction vkGetInstanceProcAddr( VkInstance instance, const char* pName) { - MVKTraceVulkanCallStart(); - // Handle the special platform functions where the instance parameter may be NULL. PFN_vkVoidFunction func = nullptr; - if (strcmp(pName, "vkCreateInstance") == 0) { + MVKTraceVulkanCallStart(); + if (mvkStringsAreEqual(pName, "vkGetInstanceProcAddr")) { + func = (PFN_vkVoidFunction)vkGetInstanceProcAddr; + } else if (mvkStringsAreEqual(pName, "vkCreateInstance")) { func = (PFN_vkVoidFunction)vkCreateInstance; - } else if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) { + } else if (mvkStringsAreEqual(pName, "vkEnumerateInstanceExtensionProperties")) { func = (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties; - } else if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) { + } else if (mvkStringsAreEqual(pName, "vkEnumerateInstanceLayerProperties")) { func = (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties; - } else if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) { + } else if (mvkStringsAreEqual(pName, "vkEnumerateInstanceVersion")) { func = (PFN_vkVoidFunction)vkEnumerateInstanceVersion; } else if (instance) { MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance); @@ -3419,9 +3420,9 @@ MVK_PUBLIC_SYMBOL PFN_vkVoidFunction vk_icdGetInstanceProcAddr( MVKTraceVulkanCallStart(); PFN_vkVoidFunction func = nullptr; - if (strcmp(pName, "vk_icdNegotiateLoaderICDInterfaceVersion") == 0) { + if (mvkStringsAreEqual(pName, "vk_icdNegotiateLoaderICDInterfaceVersion")) { func = (PFN_vkVoidFunction)vk_icdNegotiateLoaderICDInterfaceVersion; - } else if (strcmp(pName, "vk_icdGetPhysicalDeviceProcAddr") == 0) { + } else if (mvkStringsAreEqual(pName, "vk_icdGetPhysicalDeviceProcAddr")) { func = (PFN_vkVoidFunction)vk_icdGetPhysicalDeviceProcAddr; } else { func = vkGetInstanceProcAddr(instance, pName);