mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-11-28 09:10:48 +00:00
Thunks/vulkan: Thunk libvulkan directly instead of libvulkan_device
This commit is contained in:
parent
fe2f54fc3d
commit
b93b713179
@ -31,75 +31,19 @@
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libX11.so.6.4.0"
|
||||
]
|
||||
},
|
||||
"Vulkan-radeon": {
|
||||
"Library": "libvulkan_radeon-guest.so",
|
||||
"Vulkan": {
|
||||
"Library": "libvulkan-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_radeon.so"
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan.so",
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan.so.1",
|
||||
],
|
||||
"Comment": [
|
||||
"Vulkan library relies on xcb, otherwise it crashes with jemalloc"
|
||||
]
|
||||
},
|
||||
"Vulkan-lavapipe": {
|
||||
"Library": "libvulkan_lvp-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_lvp.so"
|
||||
]
|
||||
},
|
||||
"Vulkan-freedreno": {
|
||||
"Library": "libvulkan_freedreno-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_freedreno.so"
|
||||
]
|
||||
},
|
||||
"Vulkan-intel": {
|
||||
"Library": "libvulkan_intel-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_intel.so"
|
||||
]
|
||||
},
|
||||
"Vulkan-panfrost": {
|
||||
"Library": "libvulkan_panfrost-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_panfrost.so"
|
||||
]
|
||||
},
|
||||
"Vulkan-nvidia": {
|
||||
"Library": "libvulkan_nvidia-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libGLX_nvidia.so.0"
|
||||
],
|
||||
"Comment": [
|
||||
"Not currently wired up"
|
||||
]
|
||||
},
|
||||
"Vulkan-virtio": {
|
||||
"Library": "libvulkan_virtio-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/x86_64-linux-gnu/libvulkan_virtio.so"
|
||||
]
|
||||
},
|
||||
"xcb": {
|
||||
"Library": "libxcb-guest.so",
|
||||
"Overlay": [
|
||||
|
@ -135,19 +135,8 @@ add_guest_lib(Xrender)
|
||||
generate(libXfixes ${CMAKE_CURRENT_SOURCE_DIR}/../libXfixes/libXfixes_interface.cpp thunks function_packs function_packs_public)
|
||||
add_guest_lib(Xfixes)
|
||||
|
||||
set (VULKAN_LIBS
|
||||
vulkan_radeon
|
||||
vulkan_lvp
|
||||
vulkan_freedreno
|
||||
vulkan_intel
|
||||
vulkan_panfrost
|
||||
vulkan_virtio
|
||||
)
|
||||
|
||||
foreach (LIB IN LISTS VULKAN_LIBS)
|
||||
generate(libvulkan_device LIBNAME lib${LIB} ${CMAKE_CURRENT_SOURCE_DIR}/../libvulkan_device/libvulkan_device_interface.cpp thunks function_packs function_packs_public symbol_list)
|
||||
add_guest_lib_with_name(vulkan_device ${LIB})
|
||||
endforeach()
|
||||
generate(libvulkan ${CMAKE_CURRENT_SOURCE_DIR}/../libvulkan/libvulkan_interface.cpp thunks function_packs function_packs_public symbol_list)
|
||||
add_guest_lib(vulkan)
|
||||
|
||||
generate(libxcb ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb/libxcb_interface.cpp thunks function_packs function_packs_public callback_structs callback_unpacks_header callback_unpacks_header_init callback_unpacks callback_typedefs)
|
||||
add_guest_lib(xcb)
|
||||
|
@ -118,19 +118,8 @@ add_host_lib(Xrender)
|
||||
generate(libXfixes ${CMAKE_CURRENT_SOURCE_DIR}/../libXfixes/libXfixes_interface.cpp function_unpacks tab_function_unpacks ldr ldr_ptrs)
|
||||
add_host_lib(Xfixes)
|
||||
|
||||
set (VULKAN_LIBS
|
||||
vulkan_radeon
|
||||
vulkan_lvp
|
||||
vulkan_freedreno
|
||||
vulkan_intel
|
||||
vulkan_panfrost
|
||||
vulkan_virtio
|
||||
)
|
||||
|
||||
foreach (LIB IN LISTS VULKAN_LIBS)
|
||||
generate(libvulkan_device LIBNAME lib${LIB} ${CMAKE_CURRENT_SOURCE_DIR}/../libvulkan_device/libvulkan_device_interface.cpp function_unpacks tab_function_unpacks ldr ldr_ptrs symbol_list)
|
||||
add_host_lib_with_name(vulkan_device ${LIB})
|
||||
endforeach()
|
||||
generate(libvulkan ${CMAKE_CURRENT_SOURCE_DIR}/../libvulkan/libvulkan_interface.cpp function_unpacks tab_function_unpacks ldr ldr_ptrs symbol_list)
|
||||
add_host_lib(vulkan)
|
||||
|
||||
generate(libxcb ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb/libxcb_interface.cpp function_unpacks tab_function_unpacks ldr ldr_ptrs callback_structs callback_unpacks_header callback_typedefs)
|
||||
add_host_lib(xcb)
|
||||
|
73
ThunkLibs/libvulkan/Guest.cpp
Normal file
73
ThunkLibs/libvulkan/Guest.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
$info$
|
||||
tags: thunklibs|Vulkan
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#define VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "common/Guest.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <dlfcn.h>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "thunks.inl"
|
||||
#include "function_packs.inl"
|
||||
#include "function_packs_public.inl"
|
||||
#include "symbol_list.inl"
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Maps Vulkan API function names to the address of a guest function which is
|
||||
// linked to the corresponding host function pointer
|
||||
const std::unordered_map<std::string_view, uintptr_t /* guest function address */> HostPtrInvokers =
|
||||
std::invoke([]() {
|
||||
#define PAIR(name, unused) Ret[#name] = reinterpret_cast<uintptr_t>(GetCallerForHostThunkFromRuntimePointer<fexthunks_libvulkan_hostcall_##name>(name));
|
||||
std::unordered_map<std::string_view, uintptr_t> Ret;
|
||||
FOREACH_internal_SYMBOL(PAIR)
|
||||
return Ret;
|
||||
#undef PAIR
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance a_0,const char* a_1){
|
||||
if (a_1 == std::string_view { "vkGetDeviceProcAddr" }) {
|
||||
return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
|
||||
} else {
|
||||
auto Ret = fexfn_pack_vkGetInstanceProcAddr(a_0, 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOAD_LIB(libvulkan)
|
118
ThunkLibs/libvulkan/Host.cpp
Normal file
118
ThunkLibs/libvulkan/Host.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
$info$
|
||||
tags: thunklibs|Vulkan
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#define VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "common/Host.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "ldr_ptrs.inl"
|
||||
|
||||
static bool SetupInstance{};
|
||||
static std::mutex SetupMutex{};
|
||||
|
||||
#define LDR_PTR(fn) fexldr_ptr_libvulkan_##fn
|
||||
|
||||
static void DoSetupWithInstance(VkInstance instance) {
|
||||
std::unique_lock lk {SetupMutex};
|
||||
|
||||
// Needed since the Guest-endpoint calls without a function pointer
|
||||
// TODO: Support use of multiple instances
|
||||
(void*&)LDR_PTR(vkGetDeviceProcAddr) = (void*)LDR_PTR(vkGetInstanceProcAddr)(instance, "vkGetDeviceProcAddr");
|
||||
if (LDR_PTR(vkGetDeviceProcAddr) == nullptr) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// Query pointers for functions customized below
|
||||
(void*&)LDR_PTR(vkCreateInstance) = (void*)LDR_PTR(vkGetInstanceProcAddr)(instance, "vkCreateInstance");
|
||||
(void*&)LDR_PTR(vkCreateDevice) = (void*)LDR_PTR(vkGetInstanceProcAddr)(instance, "vkCreateDevice");
|
||||
|
||||
// Only do this lookup once.
|
||||
// NOTE: If vkGetInstanceProcAddr was called with a null instance, only a few function pointers will be filled with non-null values, so we do repeat the lookup in that case
|
||||
if (instance) {
|
||||
SetupInstance = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define FEXFN_IMPL(fn) fexfn_impl_libvulkan_##fn
|
||||
|
||||
// Functions with callbacks are overridden to ignore the guest-side callbacks
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateShaderModule)(VkDevice a_0, const VkShaderModuleCreateInfo* a_1, const VkAllocationCallbacks* a_2, VkShaderModule* a_3) {
|
||||
(void*&)LDR_PTR(vkCreateShaderModule) = (void*)LDR_PTR(vkGetDeviceProcAddr)(a_0, "vkCreateShaderModule");
|
||||
return LDR_PTR(vkCreateShaderModule)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateInstance)(const VkInstanceCreateInfo* a_0, const VkAllocationCallbacks* a_1, VkInstance* a_2) {
|
||||
return LDR_PTR(vkCreateInstance)(a_0, nullptr, a_2);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateDevice)(VkPhysicalDevice a_0, const VkDeviceCreateInfo* a_1, const VkAllocationCallbacks* a_2, VkDevice* a_3){
|
||||
return LDR_PTR(vkCreateDevice)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkAllocateMemory)(VkDevice a_0, const VkMemoryAllocateInfo* a_1, const VkAllocationCallbacks* a_2, VkDeviceMemory* a_3){
|
||||
(void*&)LDR_PTR(vkAllocateMemory) = (void*)LDR_PTR(vkGetDeviceProcAddr)(a_0, "vkAllocateMemory");
|
||||
return LDR_PTR(vkAllocateMemory)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static void FEXFN_IMPL(vkFreeMemory)(VkDevice a_0, VkDeviceMemory a_1, const VkAllocationCallbacks* a_2) {
|
||||
(void*&)LDR_PTR(vkFreeMemory) = (void*)LDR_PTR(vkGetDeviceProcAddr)(a_0, "vkFreeMemory");
|
||||
LDR_PTR(vkFreeMemory)(a_0, a_1, nullptr);
|
||||
}
|
||||
|
||||
static PFN_vkVoidFunction FEXFN_IMPL(vkGetDeviceProcAddr)(VkDevice a_0, const char* a_1) {
|
||||
// Just return the host facing function pointer
|
||||
// The guest will handle mapping if this exists
|
||||
|
||||
// Check for functions with stubbed callbacks first
|
||||
if (std::strcmp(a_1, "vkCreateShaderModule") == 0) {
|
||||
return (PFN_vkVoidFunction)fexfn_impl_libvulkan_vkCreateShaderModule;
|
||||
} else if (std::strcmp(a_1, "vkCreateInstance") == 0) {
|
||||
return (PFN_vkVoidFunction)fexfn_impl_libvulkan_vkCreateInstance;
|
||||
} else if (std::strcmp(a_1, "vkCreateDevice") == 0) {
|
||||
return (PFN_vkVoidFunction)fexfn_impl_libvulkan_vkCreateDevice;
|
||||
} else if (std::strcmp(a_1, "vkAllocateMemory") == 0) {
|
||||
return (PFN_vkVoidFunction)fexfn_impl_libvulkan_vkAllocateMemory;
|
||||
} else if (std::strcmp(a_1, "vkFreeMemory") == 0) {
|
||||
return (PFN_vkVoidFunction)fexfn_impl_libvulkan_vkFreeMemory;
|
||||
}
|
||||
|
||||
auto ret = LDR_PTR(vkGetDeviceProcAddr)(a_0, a_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PFN_vkVoidFunction FEXFN_IMPL(vkGetInstanceProcAddr)(VkInstance a_0, const char* a_1) {
|
||||
if (!SetupInstance && a_0) {
|
||||
DoSetupWithInstance(a_0);
|
||||
}
|
||||
|
||||
// Just return the host facing function pointer
|
||||
// The guest will handle mapping if it exists
|
||||
auto ret = LDR_PTR(vkGetInstanceProcAddr)(a_0, a_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#include "function_unpacks.inl"
|
||||
|
||||
static ExportEntry exports[] = {
|
||||
#include "tab_function_unpacks.inl"
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
#include "ldr.inl"
|
||||
|
||||
EXPORTS(libvulkan)
|
@ -9,6 +9,15 @@ struct fex_gen_config;
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
template<> struct fex_gen_config<vkGetDeviceProcAddr> : fexgen::custom_host_impl, fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
template<> struct fex_gen_config<vkGetInstanceProcAddr> : fexgen::custom_host_impl, fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<auto>
|
||||
struct fex_gen_config : fexgen::generate_guest_symtable, fexgen::indirect_guest_calls {
|
||||
};
|
||||
|
||||
template<> struct fex_gen_config<vkAcquireNextImage2KHR> {};
|
||||
template<> struct fex_gen_config<vkAcquireNextImageKHR> {};
|
||||
template<> struct fex_gen_config<vkAcquirePerformanceConfigurationINTEL> {};
|
||||
@ -282,7 +291,6 @@ template<> struct fex_gen_config<vkGetDeviceGroupSurfacePresentModesKHR> {};
|
||||
template<> struct fex_gen_config<vkGetDeviceMemoryCommitment> {};
|
||||
template<> struct fex_gen_config<vkGetDeviceMemoryOpaqueCaptureAddress> {};
|
||||
template<> struct fex_gen_config<vkGetDeviceMemoryOpaqueCaptureAddressKHR> {};
|
||||
template<> struct fex_gen_config<vkGetDeviceProcAddr> : fexgen::custom_host_impl, fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
template<> struct fex_gen_config<vkGetDeviceQueue> {};
|
||||
template<> struct fex_gen_config<vkGetDeviceQueue2> {};
|
||||
template<> struct fex_gen_config<vkGetDisplayModeProperties2KHR> {};
|
||||
@ -304,7 +312,6 @@ template<> struct fex_gen_config<vkGetImageSparseMemoryRequirements2KHR> {};
|
||||
template<> struct fex_gen_config<vkGetImageSubresourceLayout> {};
|
||||
template<> struct fex_gen_config<vkGetImageViewAddressNVX> {};
|
||||
template<> struct fex_gen_config<vkGetImageViewHandleNVX> {};
|
||||
template<> struct fex_gen_config<vkGetInstanceProcAddr> : fexgen::custom_host_impl, fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
template<> struct fex_gen_config<vkGetMemoryFdKHR> {};
|
||||
template<> struct fex_gen_config<vkGetMemoryFdPropertiesKHR> {};
|
||||
template<> struct fex_gen_config<vkGetMemoryHostPointerPropertiesEXT> {};
|
||||
@ -429,3 +436,5 @@ template<> struct fex_gen_config<vkWaitForFences> {};
|
||||
template<> struct fex_gen_config<vkWaitSemaphores> {};
|
||||
template<> struct fex_gen_config<vkWaitSemaphoresKHR> {};
|
||||
template<> struct fex_gen_config<vkWriteAccelerationStructuresPropertiesKHR> {};
|
||||
|
||||
} // namespace internal
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
$info$
|
||||
tags: thunklibs|Vulkan
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#define VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "common/Guest.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <dlfcn.h>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "thunks.inl"
|
||||
#include "function_packs.inl"
|
||||
#include "function_packs_public.inl"
|
||||
#include "symbol_list.inl"
|
||||
|
||||
extern "C" {
|
||||
static bool Setup{};
|
||||
static std::unordered_map<std::string_view,PFN_vkVoidFunction*> PtrsToLookUp{};
|
||||
|
||||
// Setup can't be done on shared library constructor
|
||||
// Needs to be deferred until post-constructor phase to remove the chance of crashing
|
||||
static void DoSetup() {
|
||||
// Initialize unordered_map from generated initializer-list
|
||||
PtrsToLookUp = {
|
||||
#define PAIR(name, unused) { #name, (PFN_vkVoidFunction*)name },
|
||||
FOREACH_SYMBOL(PAIR)
|
||||
#undef PAIR
|
||||
};
|
||||
|
||||
Setup = true;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice a_0,const char* a_1){
|
||||
if (!Setup) {
|
||||
DoSetup();
|
||||
}
|
||||
|
||||
auto ret = fexfn_pack_vkGetDeviceProcAddr(a_0, a_1);
|
||||
|
||||
if (ret == nullptr) {
|
||||
// Early out if our instance doesn't have the pointer
|
||||
// Definitely means we don't support it
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Okay, we found a host side function for this
|
||||
// Now return our local instance of this function
|
||||
auto It = PtrsToLookUp.find(a_1);
|
||||
if (It == PtrsToLookUp.end() || !It->second) {
|
||||
fprintf(stderr, "\tvkGetDeviceProcAddr: Couldn't find Guest symbol: '%s'\n", a_1);
|
||||
__builtin_trap();
|
||||
}
|
||||
return (PFN_vkVoidFunction)It->second;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance a_0,const char* a_1){
|
||||
if (!Setup) {
|
||||
DoSetup();
|
||||
}
|
||||
|
||||
// Search our host install first to see if the pointer exists
|
||||
// This also populates a map on the host facing side
|
||||
auto ret = fexfn_pack_vkGetInstanceProcAddr(a_0, a_1);
|
||||
if (ret == nullptr) {
|
||||
// Early out if our instance doesn't have the pointer
|
||||
// Definitely means we don't support it
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto It = PtrsToLookUp.find(a_1);
|
||||
if (It == PtrsToLookUp.end() || !It->second) {
|
||||
fprintf(stderr, "\tvkGetInstanceProcAddr: Couldn't find Guest symbol: '%s'\n", a_1);
|
||||
__builtin_trap();
|
||||
}
|
||||
return (PFN_vkVoidFunction)It->second;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define DOLOAD(name) LOAD_LIB(name)
|
||||
DOLOAD(LIBLIB_NAME)
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
$info$
|
||||
tags: thunklibs|Vulkan
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#define VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "common/Host.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "ldr_ptrs.inl"
|
||||
|
||||
#include "symbol_list.inl"
|
||||
|
||||
static bool SetupDev{};
|
||||
static bool SetupInstance{};
|
||||
std::mutex SetupMutex{};
|
||||
|
||||
static std::unordered_map<std::string_view,PFN_vkVoidFunction*> PtrsToLookUp{};
|
||||
|
||||
|
||||
#define CONCAT(a, b, c) a##_##b##_##c
|
||||
#define EVAL(a, b) CONCAT(fexldr_ptr, a, b)
|
||||
#define LDR_PTR(fn) EVAL(LIBLIB_NAME, fn)
|
||||
|
||||
static void DoSetupWithDevice(VkDevice dev) {
|
||||
std::unique_lock lk {SetupMutex};
|
||||
|
||||
auto add_ptr = [&](const char* name) {
|
||||
auto Lookup = PtrsToLookUp.find(name);
|
||||
if (Lookup != PtrsToLookUp.end() && *Lookup->second == nullptr) {
|
||||
auto Res = LDR_PTR(vkGetDeviceProcAddr)(dev, name);
|
||||
if (Res) {
|
||||
*Lookup->second = Res;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define PAIR(name, unused) add_ptr(#name);
|
||||
FOREACH_SYMBOL(PAIR)
|
||||
#undef PAIR
|
||||
|
||||
SetupDev = true;
|
||||
}
|
||||
|
||||
static void DoSetupWithInstance(VkInstance instance) {
|
||||
std::unique_lock lk {SetupMutex};
|
||||
|
||||
auto add_ptr = [&](const char* name) {
|
||||
auto Lookup = PtrsToLookUp.find(name);
|
||||
auto Res = LDR_PTR(vkGetInstanceProcAddr)(instance, name);
|
||||
if (Res) {
|
||||
*Lookup->second = Res;
|
||||
}
|
||||
};
|
||||
|
||||
#define PAIR(name, unused) add_ptr(#name);
|
||||
FOREACH_SYMBOL(PAIR);
|
||||
#undef PAIR
|
||||
|
||||
// Only do this lookup once.
|
||||
// NOTE: If vkGetInstanceProcAddr was called with a null instance, only a few function pointers will be filled with non-null values, so we do repeat the lookup in that case
|
||||
if (instance) {
|
||||
SetupInstance = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define FEXFN_IMPL3(a, b, c) a##_##b##_##c
|
||||
#define FEXFN_IMPL2(a, b) FEXFN_IMPL3(fexfn_impl, a, b)
|
||||
#define FEXFN_IMPL(fn) FEXFN_IMPL2(LIBLIB_NAME, fn)
|
||||
|
||||
static PFN_vkVoidFunction FEXFN_IMPL(vkGetDeviceProcAddr)(VkDevice a_0, const char* a_1) {
|
||||
if (!SetupDev) {
|
||||
DoSetupWithDevice(a_0);
|
||||
}
|
||||
|
||||
// Just return the host facing function pointer
|
||||
// The guest will handle mapping if this exists
|
||||
auto ret = LDR_PTR(vkGetDeviceProcAddr)(a_0, a_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PFN_vkVoidFunction FEXFN_IMPL(vkGetInstanceProcAddr)(VkInstance a_0, const char* a_1) {
|
||||
if (!SetupInstance) {
|
||||
DoSetupWithInstance(a_0);
|
||||
}
|
||||
|
||||
// Just return the host facing function pointer
|
||||
// The guest will handle mapping if it exists
|
||||
auto ret = LDR_PTR(vkGetInstanceProcAddr)(a_0, a_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateShaderModule)(VkDevice a_0, const VkShaderModuleCreateInfo* a_1, const VkAllocationCallbacks* a_2, VkShaderModule* a_3) {
|
||||
return LDR_PTR(vkCreateShaderModule)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateInstance)(const VkInstanceCreateInfo* a_0, const VkAllocationCallbacks* a_1, VkInstance* a_2) {
|
||||
return LDR_PTR(vkCreateInstance)(a_0, nullptr, a_2);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkCreateDevice)(VkPhysicalDevice a_0, const VkDeviceCreateInfo* a_1, const VkAllocationCallbacks* a_2, VkDevice* a_3){
|
||||
return LDR_PTR(vkCreateDevice)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static VkResult FEXFN_IMPL(vkAllocateMemory)(VkDevice a_0, const VkMemoryAllocateInfo* a_1, const VkAllocationCallbacks* a_2, VkDeviceMemory* a_3){
|
||||
return LDR_PTR(vkAllocateMemory)(a_0, a_1, nullptr, a_3);
|
||||
}
|
||||
|
||||
static void FEXFN_IMPL(vkFreeMemory)(VkDevice a_0, VkDeviceMemory a_1, const VkAllocationCallbacks* a_2) {
|
||||
LDR_PTR(vkFreeMemory)(a_0, a_1, nullptr);
|
||||
}
|
||||
|
||||
|
||||
#include "function_unpacks.inl"
|
||||
|
||||
static ExportEntry exports[] = {
|
||||
#include "tab_function_unpacks.inl"
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
static void DoSetup() {
|
||||
// Initialize unordered_map from generated initializer-list
|
||||
#define PAIR(name, unused) { #name, (PFN_vkVoidFunction*)&LDR_PTR(name) },
|
||||
PtrsToLookUp = {
|
||||
FOREACH_SYMBOL(PAIR)
|
||||
};
|
||||
#undef PAIR
|
||||
}
|
||||
|
||||
#include "ldr.inl"
|
||||
|
||||
#define LDR_HANDLE3(a) fexldr_ptr##_##a##_##so
|
||||
#define LDR_HANDLE2(a) LDR_HANDLE3(a)
|
||||
#define LDR_HANDLE LDR_HANDLE2(LIBLIB_NAME)
|
||||
|
||||
static void init_func() {
|
||||
// Initialize some initial pointers that we can get while loading
|
||||
(void*&)LDR_PTR(vkGetInstanceProcAddr) = dlsym(LDR_HANDLE, "vkGetInstanceProcAddr");
|
||||
if (LDR_PTR(vkGetInstanceProcAddr) == nullptr) {
|
||||
(void*&)LDR_PTR(vkGetInstanceProcAddr) = dlsym(LDR_HANDLE, "vk_icdGetInstanceProcAddr");
|
||||
}
|
||||
|
||||
(void*&)LDR_PTR(vkEnumerateInstanceVersion) = (void *) LDR_PTR(vkGetInstanceProcAddr)(nullptr, "vkEnumerateInstanceVersion");
|
||||
(void*&)LDR_PTR(vkEnumerateInstanceExtensionProperties) = (void *) LDR_PTR(vkGetInstanceProcAddr)(nullptr, "vkEnumerateInstanceExtensionProperties");
|
||||
(void*&)LDR_PTR(vkEnumerateInstanceLayerProperties) = (void*) LDR_PTR(vkGetInstanceProcAddr)(nullptr, "vkEnumerateInstanceLayerProperties");
|
||||
(void*&)LDR_PTR(vkCreateInstance) = (void*) LDR_PTR(vkGetInstanceProcAddr)(nullptr, "vkCreateInstance");
|
||||
|
||||
DoSetup();
|
||||
}
|
||||
|
||||
#define DOEXPORT_INIT(name, init) EXPORTS_INIT(name, init)
|
||||
DOEXPORT_INIT(LIBLIB_NAME, init_func)
|
Loading…
Reference in New Issue
Block a user