Skip to content

Commit f33c4da

Browse files
authored
Framework: Support vkGetInstanceProcAddr for global functions (#130)
Add support for global function queries for vkGetInstanceProcAddr, allows function queries with a nullptr instance handle. This is not required for the Android loader, but is needed for the Khronos standard loader on Linux and Windows.
1 parent ba6b2aa commit f33c4da

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

source_common/framework/manual_functions.cpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,38 @@ VkLayerDeviceCreateInfo* getChainInfo(const VkDeviceCreateInfo* pCreateInfo)
111111
}
112112

113113
/* See header for documentation. */
114-
PFN_vkVoidFunction getInstanceLayerFunction(const char* name)
114+
std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name)
115115
{
116+
const std::array<const char*, 5> globalFunctions {
117+
// Supported since Vulkan 1.0
118+
"vkCreateInstance",
119+
"vkEnumerateInstanceExtensionProperties",
120+
"vkEnumerateInstanceLayerProperties",
121+
// Supported since Vulkan 1.1
122+
"vkEnumerateInstanceVersion",
123+
// Supported since Vulkan 1.2
124+
"vkGetInstanceProcAddr",
125+
};
126+
127+
bool isGlobal {false};
128+
for (const auto* globalName : globalFunctions)
129+
{
130+
if (!strcmp(globalName, name))
131+
{
132+
isGlobal = true;
133+
break;
134+
}
135+
}
136+
116137
for (auto& function : instanceIntercepts)
117138
{
118139
if (!strcmp(function.name, name))
119140
{
120-
return function.function;
141+
return {isGlobal, function.function};
121142
}
122143
}
123144

124-
return nullptr;
145+
return {isGlobal, nullptr};
125146
}
126147

127148
/* See header for documentation. */
@@ -147,12 +168,14 @@ APIVersion getInstanceAPIVersion(PFN_vkGetInstanceProcAddr fpGetProcAddr)
147168
return { 1, 3 };
148169
#endif
149170

171+
// Try to get vkEnumerateInstanceVersion, and assume this is a Vulkan 1.0
172+
// feature level if we don't get it ...
150173
auto fpFunctionRaw = fpGetProcAddr(nullptr, "vkEnumerateInstanceVersion");
151174
auto fpFunction = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(fpFunctionRaw);
152175
if (!fpFunction)
153176
{
154-
LAYER_ERR("Failed to get vkEnumerateInstanceVersion()");
155-
return {0, 0};
177+
LAYER_ERR("Failed to get vkEnumerateInstanceVersion(), assuming Vulkan 1.0");
178+
return {1, 0};
156179
}
157180

158181
uint32_t apiVersion = 0;
@@ -474,9 +497,18 @@ void enableDeviceVkExtImageCompressionControl(Instance& instance,
474497
/** See Vulkan API for documentation. */
475498
PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default(VkInstance instance, const char* pName)
476499
{
477-
// Only expose functions that the driver exposes to avoid changing
478-
// queryable interface behavior seen by the application
479-
auto layerFunction = getInstanceLayerFunction(pName);
500+
auto [isGlobal, layerFunction] = getInstanceLayerFunction(pName);
501+
502+
// Global functions must be exposed and do not require the caller to pass
503+
// a valid instance pointer, although it is required to be nullptr in
504+
// Vulkan 1.2.193 or later
505+
if (isGlobal)
506+
{
507+
return layerFunction;
508+
}
509+
510+
// For other functions, only expose functions that the driver exposes to
511+
// avoid changing queryable interface behavior seen by the application
480512
if (instance)
481513
{
482514
std::unique_lock<std::mutex> lock {g_vulkanLock};

source_common/framework/manual_functions.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <mutex>
4545
#include <string>
4646
#include <thread>
47+
#include <utility>
4748
#include <vector>
4849

4950
/**
@@ -85,10 +86,11 @@ PFN_vkVoidFunction getFixedInstanceLayerFunction(const char* name);
8586
*
8687
* @param name The Vulkan function name.
8788
*
88-
* @return The layer function pointer, or \c nullptr if the layer doesn't
89+
* @return Boolean indicating if this is a globally accessible function, and
90+
* the layer function pointer, or \c nullptr if the layer doesn't
8991
* intercept the function.
9092
*/
91-
PFN_vkVoidFunction getInstanceLayerFunction(const char* name);
93+
std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name);
9294

9395
/**
9496
* @brief Fetch the function for a given dynamic instance entrypoint name.

0 commit comments

Comments
 (0)