Skip to content

Commit

Permalink
Workaround pre-instance functions on Android (#53)
Browse files Browse the repository at this point in the history
Pre-instance functions are not supposed to be intercepted, but Android
doesn't implement the better interface for chainable pre-instance
functions. Trying to use vkGetInstanceProcAddr to get the "next layer 
down" vkEnumerateInstanceExtensionProperties so a layer can query
what extensions are available will not work for any layer other than the
bottom layer in the stack.

If you have multiple layers in installed, the higher layers will use
vkGetInstanceProcAddr to get the function in the next layer down and
get the stub implementation for the extensions the layer itself 
implements without the request reaching the driver.
  • Loading branch information
solidpixel authored Jan 13, 2025
1 parent 4982028 commit 2ced999
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
33 changes: 29 additions & 4 deletions source_common/framework/manual_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,30 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default(
) {
LAYER_TRACE(__func__);

auto* chainInfo = getChainInfo(pCreateInfo);
auto supportedExtensions = getInstanceExtensionList(pCreateInfo);
// We cannot reliably query the available instance extensions on Android if multiple layers are
// installed, so we disable this by default. This occurs because Android only implements the v0
// specification between the loader and the interceptor, and does not implement chainable
// intercepts for vkEnumerateInstanceExtensionProperties().
//
// On Android if you call chainInfo getInstanceProcAddr() to get the function in the next layer
// you will get the layer implementation of the function, and layer implementations of this
// function will return the additional extensions that the layer itself provides. It does not
// forward to the driver, and any query for anything other than the layer will just return
// VK_ERROR_LAYER_NOT_PRESENT.
//
// If you are running with a single layer you can set this to true, and use proper queries.
constexpr bool queryExtensions = false;

std::vector<std::string> supportedExtensions;
if (queryExtensions)
{
supportedExtensions = getInstanceExtensionList(pCreateInfo);
}

auto* chainInfo = getChainInfo(pCreateInfo);
auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
auto fpCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(fpGetInstanceProcAddr(nullptr, "vkCreateInstance"));
auto fpCreateInstanceRaw = fpGetInstanceProcAddr(nullptr, "vkCreateInstance");
auto fpCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(fpCreateInstanceRaw);
if (!fpCreateInstance)
{
return VK_ERROR_INITIALIZATION_FAILED;
Expand All @@ -471,7 +490,13 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default(

// Query extension state
std::string targetExt("VK_EXT_debug_utils");
bool targetSupported = isIn(targetExt, supportedExtensions);
// Assume common extensions are available (see comment at start of function)
bool targetSupported = true;
if (queryExtensions)
{
targetSupported = isIn(targetExt, supportedExtensions);
}

bool targetEnabled = isInExtensionList(
targetExt,
pCreateInfo->enabledExtensionCount,
Expand Down
5 changes: 5 additions & 0 deletions source_common/framework/manual_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ PFN_vkVoidFunction getDeviceLayerFunction(
/**
* @brief Fetch the list of supported extensions from the instance.
*
* WARNING: This function only works on Android and only works for the bottom
* layer in a stack. Layers higher up the stack are likely to crash, and there
* is no workaround because the the Android loader doesn't implement chainable
* queries for pre-instance functions.
*
* @param pCreateInfo The instance creation data from the loader.
*
* @return The list of supported extensions; empty list on failure.
Expand Down

0 comments on commit 2ced999

Please sign in to comment.