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}
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()
#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
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)
{
/*
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)
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;
else {
if (disp_table->GetProcAddr == NULL)
return NULL;
- return disp_table->GetProcAddr(gpuw->nextObject, pName);
+ return disp_table->GetProcAddr(gpu, pName);
}
}
return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
" return NULL;" % ((name,) * 3)
-
class Subcommand(object):
def __init__(self, argv):
self.argv = argv
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"]
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"
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,
"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: