diff options
| -rw-r--r-- | loader/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | loader/loader.c | 42 | ||||
| -rwxr-xr-x | vk-generate.py | 84 |
3 files changed, 121 insertions, 15 deletions
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index d8039304..002e4052 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -11,6 +11,10 @@ add_custom_command(OUTPUT vulkan.def COMMAND ${PYTHON_CMD} ${PROJECT_SOURCE_DIR}/vk-generate.py win-def-file vulkan all > vulkan.def DEPENDS ${PROJECT_SOURCE_DIR}/vk-generate.py ${PROJECT_SOURCE_DIR}/vulkan.py) +add_custom_command(OUTPUT gpa_helper.h + COMMAND ${PYTHON_CMD} ${PROJECT_SOURCE_DIR}/vk-generate.py loader-get-proc-addr loader > gpa_helper.h + DEPENDS ${PROJECT_SOURCE_DIR}/vk-generate.py ${PROJECT_SOURCE_DIR}/vulkan.py) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} @@ -23,16 +27,16 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") if (WIN32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS -DXCB_NVIDIA") - add_library(vulkan SHARED loader.c loader.h dirent_on_windows.c dispatch.c table_ops.h vulkan.def) + add_library(vulkan SHARED loader.c loader.h dirent_on_windows.c dispatch.c table_ops.h gpa_helper.h vulkan.def) set_target_properties(vulkan PROPERTIES LINK_FLAGS "/DEF:${PROJECT_SOURCE_DIR}/loader/vulkan.def") - add_library(VKstatic STATIC loader.c loader.h dirent_on_windows.c dispatch.c table_ops.h) + add_library(VKstatic STATIC loader.c loader.h dirent_on_windows.c dispatch.c table_ops.h gpa_helper.h) set_target_properties(VKstatic PROPERTIES OUTPUT_NAME VKstatic) target_link_libraries(vulkan) endif() if (NOT WIN32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES -Wpointer-arith") - add_library(vulkan SHARED loader.c dispatch.c table_ops.h) + add_library(vulkan SHARED loader.c dispatch.c table_ops.h gpa_helper.h) set_target_properties(vulkan PROPERTIES SOVERSION 0) target_link_libraries(vulkan -ldl -lpthread) endif() diff --git a/loader/loader.c b/loader/loader.c index 3ce99f01..712118ac 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -42,6 +42,7 @@ #endif // WIN32 #include "loader_platform.h" #include "table_ops.h" +#include "gpa_helper.h" #include "loader.h" #include "vkIcd.h" // The following is #included again to catch certain OS-specific functions @@ -711,6 +712,28 @@ static void loader_init_dispatch_table(VkLayerDispatchTable *tab, PFN_vkGetProcA tab->EnumerateLayers = vkEnumerateLayers; } +static void *loader_gpa_internal(VkPhysicalGpu gpu, const char * pName) +{ + if (gpu == NULL) { + return NULL;; + } + VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu; + VkLayerDispatchTable * disp_table = * (VkLayerDispatchTable **) gpuw->baseObject; + void *addr; + + if (disp_table == NULL) + return NULL; + + addr = loader_lookup_dispatch_table(disp_table, pName); + if (addr) + return addr; + else { + if (disp_table->GetProcAddr == NULL) + return NULL; + return disp_table->GetProcAddr(gpuw->nextObject, pName); + } +} + extern struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu, uint32_t *gpu_index) { /* @@ -971,7 +994,7 @@ extern uint32_t loader_activate_layers(struct loader_icd *icd, uint32_t gpu_inde if (!loader_layers_activated(icd, gpu_index)) { VkBaseLayerObject *gpuObj = gpu; VkBaseLayerObject *nextGpuObj, *baseObj = gpuObj->baseObject; - PFN_vkGetProcAddr nextGPA = vkGetProcAddr; + PFN_vkGetProcAddr nextGPA = loader_gpa_internal; count = loader_get_layer_libs(icd, gpu_index, ext_count, ext_names, &pLayerNames); if (!count) @@ -1211,12 +1234,21 @@ LOADER_EXPORT VkResult VKAPI vkEnumerateGpus( LOADER_EXPORT void * VKAPI vkGetProcAddr(VkPhysicalGpu gpu, const char * pName) { if (gpu == NULL) { - return NULL; + + /* return entrypoint addresses that are global (in the loader)*/ + return globalGetProcAddr(pName); } - VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu; - VkLayerDispatchTable * disp_table = * (VkLayerDispatchTable **) gpuw->baseObject; + void *addr; + /* for entrypoints that loader must handle (ie non-dispatchable or create object) + make sure the loader entrypoint is returned */ + addr = loader_non_passthrough_gpa(pName); + if (addr) + return addr; + + /* return the dispatch table entrypoint for the fastest case */ + const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) gpu; if (disp_table == NULL) return NULL; @@ -1226,7 +1258,7 @@ LOADER_EXPORT void * VKAPI vkGetProcAddr(VkPhysicalGpu gpu, const char * pName) else { if (disp_table->GetProcAddr == NULL) return NULL; - return disp_table->GetProcAddr(gpuw->nextObject, pName); + return disp_table->GetProcAddr(gpu, pName); } } diff --git a/vk-generate.py b/vk-generate.py index 29b9d17b..dec71753 100755 --- a/vk-generate.py +++ b/vk-generate.py @@ -33,7 +33,6 @@ def generate_get_proc_addr_check(name): return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \ " return NULL;" % ((name,) * 3) - class Subcommand(object): def __init__(self, argv): self.argv = argv @@ -43,6 +42,18 @@ class Subcommand(object): def run(self): print(self.generate()) + def _does_function_create_object(self, proto): + out_objs = proto.object_out_params() + if proto.name == "ResetFences": + return False + return out_objs and out_objs[-1] == proto.params[-1] + + def _is_loader_special_case(self, proto): + if proto.name in ["GetProcAddr", "EnumerateGpus", "EnumerateLayers"]: + return True + return not self.is_dispatchable_object_first_param(proto) + + def is_dispatchable_object_first_param(self, proto): in_objs = proto.object_in_params() non_dispatch_objs = ["VkInstance"] @@ -107,12 +118,6 @@ class LoaderEntrypointsSubcommand(Subcommand): def generate_header(self): return "#include \"loader.h\"" - def _is_loader_special_case(self, proto): - if proto.name in ["GetProcAddr", "EnumerateGpus", "EnumerateLayers"]: - return True - - return not self.is_dispatchable_object_first_param(proto) - def _generate_object_setup(self, proto): method = "loader_init_data" cond = "res == VK_SUCCESS" @@ -454,6 +459,70 @@ class WinDefFileSubcommand(Subcommand): return "\n".join(body) +class LoaderGetProcAddrSubcommand(Subcommand): + def run(self): + self.prefix = "vk" + + # we could get the list from argv if wanted + self.intercepted = [proto.name for proto in self.protos] + + for proto in self.protos: + if proto.name == "GetProcAddr": + self.gpa = proto + + super().run() + + def generate_header(self): + return "\n".join(["#include <string.h>"]) + + def generate_body(self): + lookups = [] + for proto in self.protos: + if proto.name not in self.intercepted: + lookups.append("/* no %s%s */" % (self.prefix, proto.name)) + continue + + if 'WsiX11AssociateConnection' == proto.name: + lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)") + lookups.append("if (!strcmp(name, \"%s\"))" % proto.name) + lookups.append(" return (%s) %s%s;" % + (self.gpa.ret, self.prefix, proto.name)) + lookups.append("#endif") + + special_lookups = [] + # these functions require special trampoline code beyond just the normal create object trampoline code + special_names = ["AllocDescriptorSets", "GetMultiGpuCompatibility"] + for proto in self.protos: + if self._is_loader_special_case(proto) or self._does_function_create_object(proto) or proto.name in special_names: + special_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name) + special_lookups.append(" return (%s) %s%s;" % + (self.gpa.ret, self.prefix, proto.name)) + else: + continue + body = [] + body.append("static inline %s globalGetProcAddr(const char *name)" % + self.gpa.ret) + body.append("{") + body.append(generate_get_proc_addr_check("name")) + body.append("") + body.append(" name += 2;") + body.append(" %s" % "\n ".join(lookups)) + body.append("") + body.append(" return NULL;") + body.append("}") + body.append("") + body.append("static inline void *loader_non_passthrough_gpa(const char *name)") + body.append("{") + body.append(generate_get_proc_addr_check("name")) + body.append("") + body.append(" name += 2;") + body.append(" %s" % "\n ".join(special_lookups)) + body.append("") + body.append(" return NULL;") + body.append("}") + + return "\n".join(body) + def main(): subcommands = { "loader-entrypoints": LoaderEntrypointsSubcommand, @@ -462,6 +531,7 @@ def main(): "icd-get-proc-addr": IcdGetProcAddrSubcommand, "layer-intercept-proc": LayerInterceptProcSubcommand, "win-def-file": WinDefFileSubcommand, + "loader-get-proc-addr": LoaderGetProcAddrSubcommand, } if len(sys.argv) < 2 or sys.argv[1] not in subcommands: |
