Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions source_common/framework/manual_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,38 @@ VkLayerDeviceCreateInfo* getChainInfo(const VkDeviceCreateInfo* pCreateInfo)
}

/* See header for documentation. */
PFN_vkVoidFunction getInstanceLayerFunction(const char* name)
std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name)
{
const std::array<const char*, 5> globalFunctions {
// Supported since Vulkan 1.0
"vkCreateInstance",
"vkEnumerateInstanceExtensionProperties",
"vkEnumerateInstanceLayerProperties",
// Supported since Vulkan 1.1
"vkEnumerateInstanceVersion",
// Supported since Vulkan 1.2
"vkGetInstanceProcAddr",
};

bool isGlobal {false};
for (const auto* globalName : globalFunctions)
{
if (!strcmp(globalName, name))
{
isGlobal = true;
break;
}
}

for (auto& function : instanceIntercepts)
{
if (!strcmp(function.name, name))
{
return function.function;
return {isGlobal, function.function};
}
}

return nullptr;
return {isGlobal, nullptr};
}

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

// Try to get vkEnumerateInstanceVersion, and assume this is a Vulkan 1.0
// feature level if we don't get it ...
auto fpFunctionRaw = fpGetProcAddr(nullptr, "vkEnumerateInstanceVersion");
auto fpFunction = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(fpFunctionRaw);
if (!fpFunction)
{
LAYER_ERR("Failed to get vkEnumerateInstanceVersion()");
return {0, 0};
LAYER_ERR("Failed to get vkEnumerateInstanceVersion(), assuming Vulkan 1.0");
return {1, 0};
}

uint32_t apiVersion = 0;
Expand Down Expand Up @@ -474,9 +497,18 @@ void enableDeviceVkExtImageCompressionControl(Instance& instance,
/** See Vulkan API for documentation. */
PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default(VkInstance instance, const char* pName)
{
// Only expose functions that the driver exposes to avoid changing
// queryable interface behavior seen by the application
auto layerFunction = getInstanceLayerFunction(pName);
auto [isGlobal, layerFunction] = getInstanceLayerFunction(pName);

// Global functions must be exposed and do not require the caller to pass
// a valid instance pointer, although it is required to be nullptr in
// Vulkan 1.2.193 or later
if (isGlobal)
{
return layerFunction;
}

// For other functions, only expose functions that the driver exposes to
// avoid changing queryable interface behavior seen by the application
if (instance)
{
std::unique_lock<std::mutex> lock {g_vulkanLock};
Expand Down
6 changes: 4 additions & 2 deletions source_common/framework/manual_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <mutex>
#include <string>
#include <thread>
#include <utility>
#include <vector>

/**
Expand Down Expand Up @@ -85,10 +86,11 @@ PFN_vkVoidFunction getFixedInstanceLayerFunction(const char* name);
*
* @param name The Vulkan function name.
*
* @return The layer function pointer, or \c nullptr if the layer doesn't
* @return Boolean indicating if this is a globally accessible function, and
* the layer function pointer, or \c nullptr if the layer doesn't
* intercept the function.
*/
PFN_vkVoidFunction getInstanceLayerFunction(const char* name);
std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name);

/**
* @brief Fetch the function for a given dynamic instance entrypoint name.
Expand Down