mirror of
https://github.com/godotengine/godot.git
synced 2024-11-25 05:33:11 +00:00
Merge pull request #65798 from kisg/dynamic_openxr_loader
Dynamic loading of OpenXR Loader on Android
This commit is contained in:
commit
3472bdd6b6
@ -18,10 +18,26 @@ env_openxr.Prepend(
|
||||
thirdparty_dir + "/src",
|
||||
thirdparty_dir + "/src/common",
|
||||
thirdparty_dir + "/src/external/jsoncpp/include",
|
||||
thirdparty_dir + "/src/loader",
|
||||
]
|
||||
)
|
||||
|
||||
if env["platform"] == "android":
|
||||
# may need to set OPENXR_ANDROID_VERSION_SUFFIX
|
||||
env_openxr.AppendUnique(CPPDEFINES=["XR_OS_ANDROID", "XR_USE_PLATFORM_ANDROID"])
|
||||
env_openxr.AppendUnique(CPPDEFINES=["JSON_USE_EXCEPTION=0"])
|
||||
|
||||
# may need to include java parts of the openxr loader
|
||||
elif env["platform"] == "linuxbsd":
|
||||
env_openxr.AppendUnique(CPPDEFINES=["XR_OS_LINUX"])
|
||||
|
||||
if env["x11"]:
|
||||
env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"])
|
||||
|
||||
# FIXME: Review what needs to be set for Android and macOS.
|
||||
env_openxr.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])
|
||||
elif env["platform"] == "windows":
|
||||
env_openxr.AppendUnique(CPPDEFINES=["XR_OS_WINDOWS", "NOMINMAX", "XR_USE_PLATFORM_WIN32"])
|
||||
|
||||
# may need to check and set:
|
||||
# - XR_USE_TIMESPEC
|
||||
|
||||
@ -29,27 +45,9 @@ env_thirdparty = env_openxr.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["DISABLE_STD_FILESYSTEM"])
|
||||
|
||||
if env["platform"] == "android":
|
||||
# may need to set OPENXR_ANDROID_VERSION_SUFFIX
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_ANDROID", "XR_USE_PLATFORM_ANDROID"])
|
||||
|
||||
# may need to include java parts of the openxr loader
|
||||
elif env["platform"] == "linuxbsd":
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX"])
|
||||
|
||||
if env["x11"]:
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"])
|
||||
|
||||
# FIXME: Review what needs to be set for Android and macOS.
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])
|
||||
elif env["platform"] == "windows":
|
||||
env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_WINDOWS", "NOMINMAX", "XR_USE_PLATFORM_WIN32"])
|
||||
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")
|
||||
|
||||
# add in common files (hope these don't clash with us)
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/common/object_info.cpp")
|
||||
if "-fno-exceptions" in env_thirdparty["CXXFLAGS"]:
|
||||
env_thirdparty["CXXFLAGS"].remove("-fno-exceptions")
|
||||
env_thirdparty.Append(CPPPATH=[thirdparty_dir + "/src/loader"])
|
||||
|
||||
# add in external jsoncpp dependency
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_reader.cpp")
|
||||
@ -57,17 +55,24 @@ env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_writer.cpp")
|
||||
|
||||
# add in load
|
||||
if env["platform"] == "android":
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/android_utilities.cpp")
|
||||
if env["platform"] != "android":
|
||||
# On Android the openxr_loader is provided by separate plugins for each device
|
||||
# Build the engine using object files
|
||||
khrloader_obj = []
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")
|
||||
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/object_info.cpp")
|
||||
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
|
||||
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
|
||||
env.modules_sources += khrloader_obj
|
||||
|
||||
env.modules_sources += thirdparty_obj
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
def can_build(env, platform):
|
||||
if (
|
||||
platform == "linuxbsd" or platform == "windows"
|
||||
): # or platform == "android" -- temporarily disabled android support
|
||||
if platform in ("linuxbsd", "windows", "android"):
|
||||
return env["openxr"]
|
||||
else:
|
||||
# not supported on these platforms
|
||||
|
@ -29,7 +29,12 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "openxr_android_extension.h"
|
||||
#include "java_godot_wrapper.h"
|
||||
#include "os_android.h"
|
||||
#include "thread_jandroid.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <modules/openxr/openxr_api.h>
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
@ -42,19 +47,16 @@ OpenXRAndroidExtension *OpenXRAndroidExtension::get_singleton() {
|
||||
OpenXRAndroidExtension::OpenXRAndroidExtension(OpenXRAPI *p_openxr_api) :
|
||||
OpenXRExtensionWrapper(p_openxr_api) {
|
||||
singleton = this;
|
||||
|
||||
request_extensions[XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME] = nullptr; // must be available
|
||||
}
|
||||
|
||||
// Initialize the loader
|
||||
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
|
||||
result = xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", (PFN_xrVoidFunction *)(&xrInitializeLoaderKHR));
|
||||
ERR_FAIL_COND_MSG(XR_FAILED(result), "Failed to retrieve pointer to xrInitializeLoaderKHR");
|
||||
void OpenXRAndroidExtension::on_before_instance_created() {
|
||||
EXT_INIT_XR_FUNC(xrInitializeLoaderKHR);
|
||||
|
||||
// TODO fix this code, this is still code from GDNative!
|
||||
JNIEnv *env = android_api->godot_android_get_env();
|
||||
JNIEnv *env = get_jni_env();
|
||||
JavaVM *vm;
|
||||
env->GetJavaVM(&vm);
|
||||
jobject activity_object = env->NewGlobalRef(android_api->godot_android_get_activity());
|
||||
jobject activity_object = env->NewGlobalRef(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
|
||||
|
||||
XrLoaderInitInfoAndroidKHR loader_init_info_android = {
|
||||
.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR,
|
||||
@ -62,7 +64,7 @@ OpenXRAndroidExtension::OpenXRAndroidExtension(OpenXRAPI *p_openxr_api) :
|
||||
.applicationVM = vm,
|
||||
.applicationContext = activity_object
|
||||
};
|
||||
xrInitializeLoaderKHR((const XrLoaderInitInfoBaseHeaderKHR *)&loader_init_info_android);
|
||||
XrResult result = xrInitializeLoaderKHR((const XrLoaderInitInfoBaseHeaderKHR *)&loader_init_info_android);
|
||||
ERR_FAIL_COND_MSG(XR_FAILED(result), "Failed to call xrInitializeLoaderKHR");
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef OPENXR_ANDROID_EXTENSION_H
|
||||
#define OPENXR_ANDROID_EXTENSION_H
|
||||
|
||||
#include "../util.h"
|
||||
#include "openxr_extension_wrapper.h"
|
||||
|
||||
class OpenXRAndroidExtension : public OpenXRExtensionWrapper {
|
||||
@ -38,10 +39,16 @@ public:
|
||||
static OpenXRAndroidExtension *get_singleton();
|
||||
|
||||
OpenXRAndroidExtension(OpenXRAPI *p_openxr_api);
|
||||
|
||||
virtual void on_before_instance_created() override;
|
||||
|
||||
virtual ~OpenXRAndroidExtension() override;
|
||||
|
||||
private:
|
||||
static OpenXRAndroidExtension *singleton;
|
||||
|
||||
// Initialize the loader
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrInitializeLoaderKHR, (const XrLoaderInitInfoBaseHeaderKHR *), loaderInitInfo)
|
||||
};
|
||||
|
||||
#endif // OPENXR_ANDROID_EXTENSION_H
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
|
||||
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; }
|
||||
|
||||
virtual void on_before_instance_created() {}
|
||||
virtual void on_instance_created(const XrInstance p_instance) {}
|
||||
virtual void on_instance_destroyed() {}
|
||||
virtual void on_session_created(const XrSession p_instance) {}
|
||||
|
@ -31,30 +31,12 @@
|
||||
#include "core/string/print_string.h"
|
||||
|
||||
#include "../extensions/openxr_vulkan_extension.h"
|
||||
#include "../openxr_api.h"
|
||||
#include "../openxr_util.h"
|
||||
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
// need to include Vulkan so we know of type definitions
|
||||
#define XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
|
||||
// however due to the way the openxr headers are put together, we have no choice.
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// include platform dependent structs
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
PFN_xrGetVulkanGraphicsRequirements2KHR xrGetVulkanGraphicsRequirements2KHR_ptr = nullptr;
|
||||
PFN_xrCreateVulkanInstanceKHR xrCreateVulkanInstanceKHR_ptr = nullptr;
|
||||
PFN_xrGetVulkanGraphicsDevice2KHR xrGetVulkanGraphicsDevice2KHR_ptr = nullptr;
|
||||
PFN_xrCreateVulkanDeviceKHR xrCreateVulkanDeviceKHR_ptr = nullptr;
|
||||
|
||||
OpenXRVulkanExtension::OpenXRVulkanExtension(OpenXRAPI *p_openxr_api) :
|
||||
OpenXRGraphicsExtensionWrapper(p_openxr_api) {
|
||||
VulkanContext::set_vulkan_hooks(this);
|
||||
@ -69,36 +51,15 @@ OpenXRVulkanExtension::~OpenXRVulkanExtension() {
|
||||
}
|
||||
|
||||
void OpenXRVulkanExtension::on_instance_created(const XrInstance p_instance) {
|
||||
XrResult result;
|
||||
|
||||
ERR_FAIL_NULL(openxr_api);
|
||||
|
||||
// Obtain pointers to functions we're accessing here, they are (not yet) part of core.
|
||||
result = xrGetInstanceProcAddr(p_instance, "xrGetVulkanGraphicsRequirements2KHR", (PFN_xrVoidFunction *)&xrGetVulkanGraphicsRequirements2KHR_ptr);
|
||||
if (XR_FAILED(result)) {
|
||||
print_line("OpenXR: Failed to xrGetVulkanGraphicsRequirements2KHR entry point [", openxr_api->get_error_string(result), "]");
|
||||
}
|
||||
|
||||
result = xrGetInstanceProcAddr(p_instance, "xrCreateVulkanInstanceKHR", (PFN_xrVoidFunction *)&xrCreateVulkanInstanceKHR_ptr);
|
||||
if (XR_FAILED(result)) {
|
||||
print_line("OpenXR: Failed to xrCreateVulkanInstanceKHR entry point [", openxr_api->get_error_string(result), "]");
|
||||
}
|
||||
|
||||
result = xrGetInstanceProcAddr(p_instance, "xrGetVulkanGraphicsDevice2KHR", (PFN_xrVoidFunction *)&xrGetVulkanGraphicsDevice2KHR_ptr);
|
||||
if (XR_FAILED(result)) {
|
||||
print_line("OpenXR: Failed to xrGetVulkanGraphicsDevice2KHR entry point [", openxr_api->get_error_string(result), "]");
|
||||
}
|
||||
|
||||
result = xrGetInstanceProcAddr(p_instance, "xrCreateVulkanDeviceKHR", (PFN_xrVoidFunction *)&xrCreateVulkanDeviceKHR_ptr);
|
||||
if (XR_FAILED(result)) {
|
||||
print_line("OpenXR: Failed to xrCreateVulkanDeviceKHR entry point [", openxr_api->get_error_string(result), "]");
|
||||
}
|
||||
}
|
||||
|
||||
XrResult OpenXRVulkanExtension::xrGetVulkanGraphicsRequirements2KHR(XrInstance p_instance, XrSystemId p_system_id, XrGraphicsRequirementsVulkanKHR *p_graphics_requirements) {
|
||||
ERR_FAIL_NULL_V(xrGetVulkanGraphicsRequirements2KHR_ptr, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return (*xrGetVulkanGraphicsRequirements2KHR_ptr)(p_instance, p_system_id, p_graphics_requirements);
|
||||
EXT_INIT_XR_FUNC(xrGetVulkanGraphicsRequirements2KHR);
|
||||
EXT_INIT_XR_FUNC(xrCreateVulkanInstanceKHR);
|
||||
EXT_INIT_XR_FUNC(xrGetVulkanGraphicsDevice2KHR);
|
||||
EXT_INIT_XR_FUNC(xrCreateVulkanDeviceKHR);
|
||||
EXT_INIT_XR_FUNC(xrEnumerateSwapchainImages);
|
||||
}
|
||||
|
||||
bool OpenXRVulkanExtension::check_graphics_api_support(XrVersion p_desired_version) {
|
||||
@ -141,12 +102,6 @@ bool OpenXRVulkanExtension::check_graphics_api_support(XrVersion p_desired_versi
|
||||
return true;
|
||||
}
|
||||
|
||||
XrResult OpenXRVulkanExtension::xrCreateVulkanInstanceKHR(XrInstance p_instance, const XrVulkanInstanceCreateInfoKHR *p_create_info, VkInstance *r_vulkan_instance, VkResult *r_vulkan_result) {
|
||||
ERR_FAIL_NULL_V(xrCreateVulkanInstanceKHR_ptr, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return (*xrCreateVulkanInstanceKHR_ptr)(p_instance, p_create_info, r_vulkan_instance, r_vulkan_result);
|
||||
}
|
||||
|
||||
bool OpenXRVulkanExtension::create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) {
|
||||
// get the vulkan version we are creating
|
||||
uint32_t vulkan_version = p_vulkan_create_info->pApplicationInfo->apiVersion;
|
||||
@ -195,12 +150,6 @@ bool OpenXRVulkanExtension::create_vulkan_instance(const VkInstanceCreateInfo *p
|
||||
return true;
|
||||
}
|
||||
|
||||
XrResult OpenXRVulkanExtension::xrGetVulkanGraphicsDevice2KHR(XrInstance p_instance, const XrVulkanGraphicsDeviceGetInfoKHR *p_get_info, VkPhysicalDevice *r_vulkan_physical_device) {
|
||||
ERR_FAIL_NULL_V(xrGetVulkanGraphicsDevice2KHR_ptr, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return (*xrGetVulkanGraphicsDevice2KHR_ptr)(p_instance, p_get_info, r_vulkan_physical_device);
|
||||
}
|
||||
|
||||
bool OpenXRVulkanExtension::get_physical_device(VkPhysicalDevice *r_device) {
|
||||
ERR_FAIL_NULL_V(openxr_api, false);
|
||||
|
||||
@ -222,12 +171,6 @@ bool OpenXRVulkanExtension::get_physical_device(VkPhysicalDevice *r_device) {
|
||||
return true;
|
||||
}
|
||||
|
||||
XrResult OpenXRVulkanExtension::xrCreateVulkanDeviceKHR(XrInstance p_instance, const XrVulkanDeviceCreateInfoKHR *p_create_info, VkDevice *r_device, VkResult *r_result) {
|
||||
ERR_FAIL_NULL_V(xrCreateVulkanDeviceKHR_ptr, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return (*xrCreateVulkanDeviceKHR_ptr)(p_instance, p_create_info, r_device, r_result);
|
||||
}
|
||||
|
||||
bool OpenXRVulkanExtension::create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) {
|
||||
ERR_FAIL_NULL_V(openxr_api, false);
|
||||
|
||||
|
@ -36,16 +36,25 @@
|
||||
|
||||
#include "drivers/vulkan/vulkan_context.h"
|
||||
|
||||
// Forward declare these so we don't need OpenXR headers where-ever this is included
|
||||
// Including OpenXR at this point gives loads and loads of compile issues especially
|
||||
// on Windows because windows.h is EVIL and really shouldn't be included outside of platform
|
||||
// but we really don't have a choice in the matter
|
||||
#include "../openxr_api.h"
|
||||
#include "../util.h"
|
||||
|
||||
struct XrGraphicsRequirementsVulkanKHR;
|
||||
struct XrVulkanInstanceCreateInfoKHR;
|
||||
struct XrVulkanGraphicsDeviceGetInfoKHR;
|
||||
struct XrVulkanDeviceCreateInfoKHR;
|
||||
struct XrGraphicsBindingVulkanKHR;
|
||||
// need to include Vulkan so we know of type definitions
|
||||
#define XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
|
||||
// however due to the way the openxr headers are put together, we have no choice.
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
// The jobject type from jni.h is used by openxr_platform.h on Android.
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
// include platform dependent structs
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
class OpenXRVulkanExtension : public OpenXRGraphicsExtensionWrapper, VulkanHooks {
|
||||
public:
|
||||
@ -84,10 +93,11 @@ private:
|
||||
uint32_t vulkan_queue_family_index = 0;
|
||||
uint32_t vulkan_queue_index = 0;
|
||||
|
||||
XrResult xrGetVulkanGraphicsRequirements2KHR(XrInstance p_instance, XrSystemId p_system_id, XrGraphicsRequirementsVulkanKHR *p_graphics_requirements);
|
||||
XrResult xrCreateVulkanInstanceKHR(XrInstance p_instance, const XrVulkanInstanceCreateInfoKHR *p_create_info, VkInstance *r_vulkan_instance, VkResult *r_vulkan_result);
|
||||
XrResult xrGetVulkanGraphicsDevice2KHR(XrInstance p_instance, const XrVulkanGraphicsDeviceGetInfoKHR *p_get_info, VkPhysicalDevice *r_vulkan_physical_device);
|
||||
XrResult xrCreateVulkanDeviceKHR(XrInstance p_instance, const XrVulkanDeviceCreateInfoKHR *p_create_info, VkDevice *r_device, VkResult *r_result);
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetVulkanGraphicsRequirements2KHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsVulkanKHR *), p_graphics_requirements)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrCreateVulkanInstanceKHR, (XrInstance), p_instance, (const XrVulkanInstanceCreateInfoKHR *), p_create_info, (VkInstance *), r_vulkan_instance, (VkResult *), r_vulkan_result)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetVulkanGraphicsDevice2KHR, (XrInstance), p_instance, (const XrVulkanGraphicsDeviceGetInfoKHR *), p_get_info, (VkPhysicalDevice *), r_vulkan_physical_device)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrCreateVulkanDeviceKHR, (XrInstance), p_instance, (const XrVulkanDeviceCreateInfoKHR *), p_create_info, (VkDevice *), r_device, (VkResult *), r_result)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateSwapchainImages, (XrSwapchain), p_swapchain, (uint32_t), p_image_capacity_input, (uint32_t *), p_image_count_output, (XrSwapchainImageBaseHeader *), p_images)
|
||||
};
|
||||
|
||||
#endif // OPENXR_VULKAN_EXTENSION_H
|
||||
|
@ -41,6 +41,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
#define OPENXR_LOADER_NAME "libopenxr_loader.so"
|
||||
#include "extensions/openxr_android_extension.h"
|
||||
#endif
|
||||
|
||||
@ -284,6 +285,9 @@ bool OpenXRAPI::create_instance() {
|
||||
0, // runtimeVersion, from here will be set by our get call
|
||||
"" // runtimeName
|
||||
};
|
||||
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetInstanceProperties);
|
||||
|
||||
result = xrGetInstanceProperties(instance, &instanceProps);
|
||||
if (XR_FAILED(result)) {
|
||||
// not fatal probably
|
||||
@ -992,9 +996,94 @@ bool OpenXRAPI::is_running() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool OpenXRAPI::openxr_loader_init() {
|
||||
#ifdef ANDROID_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(openxr_loader_library_handle != nullptr, false, "OpenXR Loader library is already loaded.");
|
||||
|
||||
{
|
||||
Error error_code = OS::get_singleton()->open_dynamic_library(OPENXR_LOADER_NAME, openxr_loader_library_handle);
|
||||
ERR_FAIL_COND_V_MSG(error_code != OK, false, "OpenXR loader not found.");
|
||||
}
|
||||
|
||||
{
|
||||
Error error_code = OS::get_singleton()->get_dynamic_library_symbol_handle(openxr_loader_library_handle, "xrGetInstanceProcAddr", (void *&)xrGetInstanceProcAddr);
|
||||
ERR_FAIL_COND_V_MSG(error_code != OK, false, "Symbol xrGetInstanceProcAddr not found in OpenXR Loader library.");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Resolve the symbols that don't require an instance
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateInstance);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateApiLayerProperties);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateInstanceExtensionProperties);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenXRAPI::resolve_instance_openxr_symbols() {
|
||||
ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false);
|
||||
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrAcquireSwapchainImage);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrApplyHapticFeedback);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrAttachSessionActionSets);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrBeginFrame);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrBeginSession);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateAction);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateActionSet);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateActionSpace);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateReferenceSpace);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateSession);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrCreateSwapchain);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroyAction);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroyActionSet);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroyInstance);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroySession);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroySpace);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrDestroySwapchain);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEndFrame);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEndSession);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateReferenceSpaces);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateSwapchainFormats);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateViewConfigurations);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrEnumerateViewConfigurationViews);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetActionStateBoolean);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetActionStateFloat);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetActionStateVector2f);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetCurrentInteractionProfile);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetSystem);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrGetSystemProperties);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrLocateViews);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrLocateSpace);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrPathToString);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrPollEvent);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrReleaseSwapchainImage);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrResultToString);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrStringToPath);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrSuggestInteractionProfileBindings);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrSyncActions);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrWaitFrame);
|
||||
OPENXR_API_INIT_XR_FUNC_V(xrWaitSwapchainImage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XrResult OpenXRAPI::get_instance_proc_addr(const char *p_name, PFN_xrVoidFunction *p_addr) {
|
||||
XrResult result = xrGetInstanceProcAddr(instance, p_name, p_addr);
|
||||
|
||||
if (result != XR_SUCCESS) {
|
||||
String error_message = String("Symbol ") + p_name + " not found in OpenXR instance.";
|
||||
ERR_FAIL_COND_V_MSG(true, result, error_message.utf8().get_data());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool OpenXRAPI::initialize(const String &p_rendering_driver) {
|
||||
ERR_FAIL_COND_V_MSG(instance != XR_NULL_HANDLE, false, "OpenXR instance was already created");
|
||||
|
||||
if (!openxr_loader_init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_rendering_driver == "vulkan") {
|
||||
#ifdef VULKAN_ENABLED
|
||||
graphics_extension = memnew(OpenXRVulkanExtension(this));
|
||||
@ -1017,6 +1106,10 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
|
||||
}
|
||||
|
||||
// initialize
|
||||
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
|
||||
wrapper->on_before_instance_created();
|
||||
}
|
||||
|
||||
if (!load_layer_properties()) {
|
||||
destroy_instance();
|
||||
return false;
|
||||
@ -1032,6 +1125,11 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!resolve_instance_openxr_symbols()) {
|
||||
destroy_instance();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!get_system_info()) {
|
||||
destroy_instance();
|
||||
return false;
|
||||
@ -1669,6 +1767,13 @@ OpenXRAPI::~OpenXRAPI() {
|
||||
layer_properties = nullptr;
|
||||
}
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
if (openxr_loader_library_handle) {
|
||||
OS::get_singleton()->close_dynamic_library(openxr_loader_library_handle);
|
||||
openxr_loader_library_handle = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,8 @@
|
||||
#include "extensions/openxr_composition_layer_provider.h"
|
||||
#include "extensions/openxr_extension_wrapper.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
// Note, OpenXR code that we wrote for our plugin makes use of C++20 notation for initialising structs which ensures zeroing out unspecified members.
|
||||
// Godot is currently restricted to C++17 which doesn't allow this notation. Make sure critical fields are set.
|
||||
|
||||
@ -134,6 +136,61 @@ private:
|
||||
bool load_supported_extensions();
|
||||
bool is_extension_supported(const String &p_extension) const;
|
||||
|
||||
bool openxr_loader_init();
|
||||
bool resolve_instance_openxr_symbols();
|
||||
|
||||
void *openxr_loader_library_handle = nullptr;
|
||||
|
||||
// function pointers
|
||||
#ifdef ANDROID_ENABLED
|
||||
// On non-Android platforms we use the OpenXR symbol linked into the engine binary.
|
||||
PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr = nullptr;
|
||||
#endif
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrAcquireSwapchainImage, (XrSwapchain), swapchain, (const XrSwapchainImageAcquireInfo *), acquireInfo, (uint32_t *), index)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrApplyHapticFeedback, (XrSession), session, (const XrHapticActionInfo *), hapticActionInfo, (const XrHapticBaseHeader *), hapticFeedback)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrAttachSessionActionSets, (XrSession), session, (const XrSessionActionSetsAttachInfo *), attachInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrBeginFrame, (XrSession), session, (const XrFrameBeginInfo *), frameBeginInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrBeginSession, (XrSession), session, (const XrSessionBeginInfo *), beginInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateAction, (XrActionSet), actionSet, (const XrActionCreateInfo *), createInfo, (XrAction *), action)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateActionSet, (XrInstance), instance, (const XrActionSetCreateInfo *), createInfo, (XrActionSet *), actionSet)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateActionSpace, (XrSession), session, (const XrActionSpaceCreateInfo *), createInfo, (XrSpace *), space)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrCreateInstance, (const XrInstanceCreateInfo *), createInfo, (XrInstance *), instance)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateReferenceSpace, (XrSession), session, (const XrReferenceSpaceCreateInfo *), createInfo, (XrSpace *), space)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateSession, (XrInstance), instance, (const XrSessionCreateInfo *), createInfo, (XrSession *), session)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateSwapchain, (XrSession), session, (const XrSwapchainCreateInfo *), createInfo, (XrSwapchain *), swapchain)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroyAction, (XrAction), action)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroyActionSet, (XrActionSet), actionSet)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroyInstance, (XrInstance), instance)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroySession, (XrSession), session)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroySpace, (XrSpace), space)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroySwapchain, (XrSwapchain), swapchain)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrEndFrame, (XrSession), session, (const XrFrameEndInfo *), frameEndInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrEndSession, (XrSession), session)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrEnumerateApiLayerProperties, (uint32_t), propertyCapacityInput, (uint32_t *), propertyCountOutput, (XrApiLayerProperties *), properties)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateInstanceExtensionProperties, (const char *), layerName, (uint32_t), propertyCapacityInput, (uint32_t *), propertyCountOutput, (XrExtensionProperties *), properties)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateReferenceSpaces, (XrSession), session, (uint32_t), spaceCapacityInput, (uint32_t *), spaceCountOutput, (XrReferenceSpaceType *), spaces)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateSwapchainFormats, (XrSession), session, (uint32_t), formatCapacityInput, (uint32_t *), formatCountOutput, (int64_t *), formats)
|
||||
EXT_PROTO_XRRESULT_FUNC5(xrEnumerateViewConfigurations, (XrInstance), instance, (XrSystemId), systemId, (uint32_t), viewConfigurationTypeCapacityInput, (uint32_t *), viewConfigurationTypeCountOutput, (XrViewConfigurationType *), viewConfigurationTypes)
|
||||
EXT_PROTO_XRRESULT_FUNC6(xrEnumerateViewConfigurationViews, (XrInstance), instance, (XrSystemId), systemId, (XrViewConfigurationType), viewConfigurationType, (uint32_t), viewCapacityInput, (uint32_t *), viewCountOutput, (XrViewConfigurationView *), views)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetActionStateBoolean, (XrSession), session, (const XrActionStateGetInfo *), getInfo, (XrActionStateBoolean *), state)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetActionStateFloat, (XrSession), session, (const XrActionStateGetInfo *), getInfo, (XrActionStateFloat *), state)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetActionStateVector2f, (XrSession), session, (const XrActionStateGetInfo *), getInfo, (XrActionStateVector2f *), state)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetCurrentInteractionProfile, (XrSession), session, (XrPath), topLevelUserPath, (XrInteractionProfileState *), interactionProfile)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrGetInstanceProperties, (XrInstance), instance, (XrInstanceProperties *), instanceProperties)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetSystem, (XrInstance), instance, (const XrSystemGetInfo *), getInfo, (XrSystemId *), systemId)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrGetSystemProperties, (XrInstance), instance, (XrSystemId), systemId, (XrSystemProperties *), properties)
|
||||
EXT_PROTO_XRRESULT_FUNC4(xrLocateSpace, (XrSpace), space, (XrSpace), baseSpace, (XrTime), time, (XrSpaceLocation *), location)
|
||||
EXT_PROTO_XRRESULT_FUNC6(xrLocateViews, (XrSession), session, (const XrViewLocateInfo *), viewLocateInfo, (XrViewState *), viewState, (uint32_t), viewCapacityInput, (uint32_t *), viewCountOutput, (XrView *), views)
|
||||
EXT_PROTO_XRRESULT_FUNC5(xrPathToString, (XrInstance), instance, (XrPath), path, (uint32_t), bufferCapacityInput, (uint32_t *), bufferCountOutput, (char *), buffer)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrPollEvent, (XrInstance), instance, (XrEventDataBuffer *), eventData)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrReleaseSwapchainImage, (XrSwapchain), swapchain, (const XrSwapchainImageReleaseInfo *), releaseInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrResultToString, (XrInstance), instance, (XrResult), value, (char *), buffer)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrStringToPath, (XrInstance), instance, (const char *), pathString, (XrPath *), path)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrSuggestInteractionProfileBindings, (XrInstance), instance, (const XrInteractionProfileSuggestedBinding *), suggestedBindings)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrSyncActions, (XrSession), session, (const XrActionsSyncInfo *), syncInfo)
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrWaitFrame, (XrSession), session, (const XrFrameWaitInfo *), frameWaitInfo, (XrFrameState *), frameState)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrWaitSwapchainImage, (XrSwapchain), swapchain, (const XrSwapchainImageWaitInfo *), waitInfo)
|
||||
|
||||
// instance
|
||||
bool create_instance();
|
||||
bool get_system_info();
|
||||
@ -231,6 +288,7 @@ public:
|
||||
static bool openxr_is_enabled(bool p_check_run_in_editor = true);
|
||||
static OpenXRAPI *get_singleton();
|
||||
|
||||
XrResult get_instance_proc_addr(const char *p_name, PFN_xrVoidFunction *p_addr);
|
||||
String get_error_string(XrResult result);
|
||||
String get_swapchain_format_name(int64_t p_swapchain_format) const;
|
||||
|
||||
|
110
modules/openxr/util.h
Normal file
110
modules/openxr/util.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*************************************************************************/
|
||||
/* util.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#define UNPACK(...) __VA_ARGS__
|
||||
|
||||
#define INIT_XR_FUNC_V(openxr_api, name) \
|
||||
do { \
|
||||
XrResult get_instance_proc_addr_result; \
|
||||
get_instance_proc_addr_result = openxr_api->get_instance_proc_addr(#name, (PFN_xrVoidFunction *)&name##_ptr); \
|
||||
ERR_FAIL_COND_V(XR_FAILED(get_instance_proc_addr_result), false); \
|
||||
} while (0)
|
||||
|
||||
#define EXT_INIT_XR_FUNC_V(name) INIT_XR_FUNC_V(openxr_api, name)
|
||||
#define OPENXR_API_INIT_XR_FUNC_V(name) INIT_XR_FUNC_V(this, name)
|
||||
|
||||
#define INIT_XR_FUNC(openxr_api, name) \
|
||||
do { \
|
||||
XrResult get_instance_proc_addr_result; \
|
||||
get_instance_proc_addr_result = openxr_api->get_instance_proc_addr(#name, (PFN_xrVoidFunction *)&name##_ptr); \
|
||||
ERR_FAIL_COND(XR_FAILED(get_instance_proc_addr_result)); \
|
||||
} while (0)
|
||||
|
||||
#define EXT_INIT_XR_FUNC(name) INIT_XR_FUNC(openxr_api, name)
|
||||
#define OPENXR_API_INIT_XR_FUNC(name) INIT_XR_FUNC(this, name)
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC1(func_name, arg1_type, arg1) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1); \
|
||||
}
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC2(func_name, arg1_type, arg1, arg2_type, arg2) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1, UNPACK arg2_type arg2) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1, arg2); \
|
||||
}
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC3(func_name, arg1_type, arg1, arg2_type, arg2, arg3_type, arg3) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1, UNPACK arg2_type arg2, UNPACK arg3_type arg3) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1, arg2, arg3); \
|
||||
}
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC4(func_name, arg1_type, arg1, arg2_type, arg2, arg3_type, arg3, arg4_type, arg4) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1, UNPACK arg2_type arg2, UNPACK arg3_type arg3, UNPACK arg4_type arg4) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1, arg2, arg3, arg4); \
|
||||
}
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC5(func_name, arg1_type, arg1, arg2_type, arg2, arg3_type, arg3, arg4_type, arg4, arg5_type, arg5) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1, UNPACK arg2_type arg2, UNPACK arg3_type arg3, UNPACK arg4_type arg4, UNPACK arg5_type arg5) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1, arg2, arg3, arg4, arg5); \
|
||||
}
|
||||
|
||||
#define EXT_PROTO_XRRESULT_FUNC6(func_name, arg1_type, arg1, arg2_type, arg2, arg3_type, arg3, arg4_type, arg4, arg5_type, arg5, arg6_type, arg6) \
|
||||
PFN_##func_name func_name##_ptr = nullptr; \
|
||||
XRAPI_ATTR XrResult XRAPI_CALL func_name(UNPACK arg1_type arg1, UNPACK arg2_type arg2, UNPACK arg3_type arg3, UNPACK arg4_type arg4, UNPACK arg5_type arg5, UNPACK arg6_type arg6) const { \
|
||||
if (!func_name##_ptr) { \
|
||||
return XR_ERROR_HANDLE_INVALID; \
|
||||
} \
|
||||
return (*func_name##_ptr)(arg1, arg2, arg3, arg4, arg5, arg6); \
|
||||
}
|
||||
|
||||
#endif // UTIL_H
|
Loading…
Reference in New Issue
Block a user