aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--loader/CMakeLists.txt10
-rw-r--r--loader/loader.c42
-rwxr-xr-xvk-generate.py84
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: