Files
FEX-Emu--FEX/ThunkLibs/libvulkan_device/Host.cpp
T
Tony Wasserka 85651ad090 Thunks/vulkan: Simplify API entrypoint lookup
This avoids the need for the heap-allocated string->symbol map that had
to be kept around previously.
2021-11-18 19:27:09 +01:00

185 lines
5.6 KiB
C++

/*
$info$
tags: thunklibs|vulkan
$end_info$
*/
#include "Header.inl"
#include <mutex>
#include <stdio.h>
#include <string>
#include <unordered_map>
#include <vector>
#include "common/Host.h"
#include <dlfcn.h>
#include "ldr_ptrs.inl"
#include "function_unpacks.inl"
static bool SetupDev{};
static bool SetupInstance{};
std::mutex SetupMutex{};
static std::unordered_map<std::string_view,PFN_vkVoidFunction*> PtrsToLookUp{};
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, ptr_unused) add_ptr(#name);
#include "ldr_ptrs_pair.inl"
#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, ptr) add_ptr(#name);
#include "ldr_ptrs_pair.inl"
#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;
}
}
static void UNPACKFUNC(vkGetDeviceProcAddr)(void *argsv){
struct arg_t {VkDevice a_0;const char* a_1;PFN_vkVoidFunction rv;};
auto args = (arg_t*)argsv;
if (!SetupDev) {
DoSetupWithDevice(args->a_0);
}
// Just return the host facing function pointer
// The guest will handle mapping if this exists
args->rv =
LDR_PTR(vkGetDeviceProcAddr)
(args->a_0,args->a_1);
}
static void UNPACKFUNC(vkGetInstanceProcAddr)(void *argsv){
struct arg_t {VkInstance a_0;const char* a_1;PFN_vkVoidFunction rv;};
auto args = (arg_t*)argsv;
if (!SetupInstance) {
DoSetupWithInstance(args->a_0);
}
// Just return the host facing function pointer
// The guest will handle mapping if it exists
args->rv =
LDR_PTR(vkGetInstanceProcAddr)
(args->a_0,args->a_1);
}
static void UNPACKFUNC(vkCreateShaderModule)(void *argsv){
struct arg_t {VkDevice a_0;const VkShaderModuleCreateInfo* a_1;const VkAllocationCallbacks* a_2;VkShaderModule* a_3;VkResult rv;};
auto args = (arg_t*)argsv;
args->rv =
LDR_PTR(vkCreateShaderModule)
(args->a_0,args->a_1, nullptr,args->a_3);
}
static void UNPACKFUNC(vkCmdSetBlendConstants)(void *argsv){
struct arg_t {VkCommandBuffer a_0;const float a_1[4];};
auto args = (arg_t*)argsv;
LDR_PTR(vkCmdSetBlendConstants)
(args->a_0,args->a_1);
}
static void UNPACKFUNC(vkCreateInstance)(void *argsv){
struct arg_t {const VkInstanceCreateInfo* a_0;const VkAllocationCallbacks* a_1;VkInstance* a_2;VkResult rv;};
auto args = (arg_t*)argsv;
args->rv =
LDR_PTR(vkCreateInstance)
(args->a_0, nullptr,args->a_2);
}
static void UNPACKFUNC(vkCreateDevice)(void *argsv){
struct arg_t {VkPhysicalDevice a_0;const VkDeviceCreateInfo* a_1;const VkAllocationCallbacks* a_2;VkDevice* a_3;VkResult rv;};
auto args = (arg_t*)argsv;
args->rv =
LDR_PTR(vkCreateDevice)
(args->a_0,args->a_1, nullptr,args->a_3);
}
static void UNPACKFUNC(vkAllocateMemory)(void *argsv){
struct arg_t {VkDevice a_0;const VkMemoryAllocateInfo* a_1;const VkAllocationCallbacks* a_2;VkDeviceMemory* a_3;VkResult rv;};
auto args = (arg_t*)argsv;
args->rv =
LDR_PTR(vkAllocateMemory)
(args->a_0,args->a_1,nullptr,args->a_3);
}
static void UNPACKFUNC(vkFreeMemory)(void *argsv){
struct arg_t {VkDevice a_0;VkDeviceMemory a_1;const VkAllocationCallbacks* a_2;};
auto args = (arg_t*)argsv;
LDR_PTR(vkFreeMemory)
(args->a_0,args->a_1,nullptr);
}
static void UNPACKFUNC(vkGetPhysicalDeviceSurfaceSupportKHR)(void *argsv){
struct arg_t {VkPhysicalDevice a_0;uint32_t a_1;VkSurfaceKHR a_2;VkBool32* a_3;VkResult rv;};
auto args = (arg_t*)argsv;
args->rv = LDR_PTR(vkGetPhysicalDeviceSurfaceSupportKHR)
(args->a_0,args->a_1,args->a_2,args->a_3);
}
static ExportEntry exports[] = {
#include "tab_function_unpacks.inl"
{ nullptr, nullptr }
};
#include "ldr.inl"
static void DoSetup() {
// Initialize unordered_map from generated initializer-list
PtrsToLookUp = {
#define PAIR(name, ptr) { #name, (PFN_vkVoidFunction*)ptr },
#include "ldr_ptrs_pair.inl"
#undef PAIR
};
}
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)