Vulkan: Handle queries for unknown functions more gracefully

This commit is contained in:
Tony Wasserka 2022-07-07 12:34:00 +02:00
parent 6a43db8c8f
commit 83c2e52ba5

View File

@ -36,18 +36,40 @@ const std::unordered_map<std::string_view, uintptr_t /* guest function address *
#undef PAIR
});
// This variable controls the behavior of vkGetDevice/InstanceProcAddr for functions we don't know the signature of:
// - if false (default), we return a nullptr (since the application might have a fallback code path)
// - if true, we return a stub function that fatally errors upon being called
constexpr bool stub_unknown_functions = false;
// Fatally erroring function with a thunk-like interface. This is used as a placeholder for unknown Vulkan functions
[[noreturn]] static void FatalError(void* raw_args) {
auto called_function = reinterpret_cast<PackedArguments<void, uintptr_t>*>(raw_args)->a0;
fprintf(stderr, "FATAL: Called unknown Vulkan function at address %p\n", reinterpret_cast<void*>(called_function));
__builtin_trap();
}
static PFN_vkVoidFunction MakeGuestCallable(const char* origin, PFN_vkVoidFunction func, const char* name) {
auto It = HostPtrInvokers.find(name);
if (It == HostPtrInvokers.end()) {
fprintf(stderr, "%s: Unknown Vulkan function at address %p: %s\n", origin, func, name);
if (stub_unknown_functions) {
const auto StubHostPtrInvoker = CallHostThunkFromRuntimePointer<FatalError, void>;
LinkAddressToFunction((uintptr_t)func, reinterpret_cast<uintptr_t>(StubHostPtrInvoker));
return func;
}
return nullptr;
}
fprintf(stderr, "Linking address %p to host invoker %#lx\n", func, It->second);
LinkAddressToFunction((uintptr_t)func, It->second);
return func;
}
PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice a_0,const char* a_1){
auto Ret = fexfn_pack_vkGetDeviceProcAddr(a_0, a_1);
if (!Ret) {
return nullptr;
}
auto It = HostPtrInvokers.find(a_1);
if (It == HostPtrInvokers.end() || !It->second) {
fprintf(stderr, "\tvkGetDeviceProcAddr: Couldn't find Guest symbol: '%s'\n", a_1);
__builtin_trap();
}
LinkAddressToFunction((uintptr_t)Ret, It->second);
return Ret;
return MakeGuestCallable(__FUNCTION__, Ret, a_1);
}
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance a_0,const char* a_1){
@ -58,13 +80,7 @@ PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance a_0,const char* a_1){
if (!Ret) {
return nullptr;
}
auto It = HostPtrInvokers.find(a_1);
if (It == HostPtrInvokers.end() || !It->second) {
fprintf(stderr, "\tvkGetInstanceProcAddr: Couldn't find Guest symbol: '%s'\n", a_1);
__builtin_trap();
}
LinkAddressToFunction((uintptr_t)Ret, It->second);
return Ret;
return MakeGuestCallable(__FUNCTION__, Ret, a_1);
}
}