From 2e10fe6680ccd384b78d41d95b757741dacfd7cb Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Thu, 22 Oct 2020 13:18:33 -0700 Subject: [PATCH] PlatformVkLinux now supports all combos of XLIB and XCB. You can now build Filament with support for both X11 APIs, or neither. If both are supported, run-time selection is achieved using a SwapChain flag. Supporting only one API at build time (or neither) is useful because our list of "required" VkInstance extensions can vary according to which API's are supported. During VkInstance creation, we do not have a priori knowledge about what kinds of swap chains will be created. (headless vs non-headless, XCB vs XLIB, etc) Note that some Vulkan implementation (e.g. some builds of SwiftShader) only support XCB. --- CMakeLists.txt | 13 ++++ .../google/android/filament/SwapChain.java | 6 ++ .../backend/include/backend/DriverEnums.h | 1 + .../backend/src/vulkan/PlatformVkAndroid.cpp | 2 +- .../backend/src/vulkan/PlatformVkAndroid.h | 2 +- filament/backend/src/vulkan/PlatformVkCocoa.h | 2 +- .../backend/src/vulkan/PlatformVkCocoa.mm | 2 +- .../backend/src/vulkan/PlatformVkCocoaTouch.h | 2 +- .../src/vulkan/PlatformVkCocoaTouch.mm | 2 +- .../backend/src/vulkan/PlatformVkLinux.cpp | 64 ++++++++++++------- filament/backend/src/vulkan/PlatformVkLinux.h | 9 ++- .../backend/src/vulkan/PlatformVkWindows.cpp | 2 +- .../backend/src/vulkan/PlatformVkWindows.h | 2 +- filament/backend/src/vulkan/VulkanDriver.cpp | 3 +- filament/backend/src/vulkan/VulkanPlatform.h | 2 +- filament/include/filament/SwapChain.h | 6 ++ libs/bluevk/include/vulkan/vk_platform.h | 3 +- 17 files changed, 87 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11345d35e5..7dd3c71ba8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,10 @@ option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the c option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF) +option(FILAMENT_SUPPORTS_XCB "Include XCB support in Linux builds" ON) + +option(FILAMENT_SUPPORTS_XLIB "Include XLIB support in Linux builds" ON) + set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "2" CACHE STRING "Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 2." ) @@ -84,6 +88,15 @@ if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL) endif() if (LINUX) + + if (FILAMENT_SUPPORTS_XCB) + add_definitions(-DFILAMENT_SUPPORTS_XCB) + endif() + + if (FILAMENT_SUPPORTS_XLIB) + add_definitions(-DFILAMENT_SUPPORTS_XLIB) + endif() + execute_process(COMMAND uname -p OUTPUT_VARIABLE PROCESSOR_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java index 3f16a81172..96821515fc 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java +++ b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java @@ -85,6 +85,12 @@ public class SwapChain { */ public static final long CONFIG_READABLE = 0x2; + /** + * Indicates that the native X11 window is an XCB window rather than an XLIB window. + * This is ignored on non-Linux platforms and in builds that support only one X11 API. + */ + public static final long CONFIG_ENABLE_XCB = 0x4; + SwapChain(long nativeSwapChain, Object surface) { mNativeObject = nativeSwapChain; mSurface = surface; diff --git a/filament/backend/include/backend/DriverEnums.h b/filament/backend/include/backend/DriverEnums.h index cb17bdf010..b951756650 100644 --- a/filament/backend/include/backend/DriverEnums.h +++ b/filament/backend/include/backend/DriverEnums.h @@ -41,6 +41,7 @@ namespace backend { static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1; static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2; +static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4; static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES. static constexpr size_t MAX_SAMPLER_COUNT = 16; // Matches the Adreno Vulkan driver. diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.cpp b/filament/backend/src/vulkan/PlatformVkAndroid.cpp index 273e32dc31..409199232a 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.cpp +++ b/filament/backend/src/vulkan/PlatformVkAndroid.cpp @@ -47,7 +47,7 @@ Driver* PlatformVkAndroid::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance) noexcept { +void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance, uint64_t flags) noexcept { const VkInstance instance = (VkInstance) vkinstance; ANativeWindow* aNativeWindow = (ANativeWindow*) nativeWindow; VkAndroidSurfaceCreateInfoKHR createInfo { diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.h b/filament/backend/src/vulkan/PlatformVkAndroid.h index c8fa312740..a7ee6de47c 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.h +++ b/filament/backend/src/vulkan/PlatformVkAndroid.h @@ -29,7 +29,7 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoa.h b/filament/backend/src/vulkan/PlatformVkCocoa.h index 3309e2121e..ea5956e050 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.h +++ b/filament/backend/src/vulkan/PlatformVkCocoa.h @@ -27,7 +27,7 @@ namespace filament { class PlatformVkCocoa final : public backend::VulkanPlatform { public: backend::Driver* createDriver(void* sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoa.mm b/filament/backend/src/vulkan/PlatformVkCocoa.mm index 91a3ff9118..b488df2117 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoa.mm @@ -51,7 +51,7 @@ Driver* PlatformVkCocoa::createDriver(void* sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { // Obtain the CAMetalLayer-backed view. NSView* nsview = (__bridge NSView*) nativeWindow; ASSERT_POSTCONDITION(nsview, "Unable to obtain Metal-backed NSView."); diff --git a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h index d2242b6276..b4be989420 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h @@ -27,7 +27,7 @@ namespace filament { class PlatformVkCocoaTouch final : public backend::VulkanPlatform { public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm b/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm index f73ac70ece..d32c2a6872 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm @@ -46,7 +46,7 @@ Driver* PlatformVkCocoaTouch::createDriver(void* const sharedContext) noexcept { sizeof(requestedExtensions) / sizeof(requestedExtensions[0])); } -void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { #if METAL_AVAILABLE CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow; diff --git a/filament/backend/src/vulkan/PlatformVkLinux.cpp b/filament/backend/src/vulkan/PlatformVkLinux.cpp index 94e89b3e5a..f1d61f7ea8 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinux.cpp @@ -36,14 +36,18 @@ static constexpr const char* LIBRARY_X11 = "libX11.so.6"; #ifdef FILAMENT_SUPPORTS_XCB typedef xcb_connection_t* (*XCB_CONNECT)(const char *displayname, int *screenp); -#else +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB typedef Display* (*X11_OPEN_DISPLAY)(const char*); #endif struct X11Functions { #ifdef FILAMENT_SUPPORTS_XCB XCB_CONNECT xcbConnect; -#else +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB X11_OPEN_DISPLAY openDisplay; #endif void* library = nullptr; @@ -55,7 +59,8 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { "VK_KHR_surface", #ifdef FILAMENT_SUPPORTS_XCB "VK_KHR_xcb_surface", -#else +#endif +#ifdef FILAMENT_SUPPORTS_XLIB "VK_KHR_xlib_surface", #endif "VK_KHR_get_physical_device_properties2", @@ -67,42 +72,57 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkLinux::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { -#ifdef FILAMENT_SUPPORTS_XCB +void* PlatformVkLinux::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { if (g_x11.library == nullptr) { g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW); ASSERT_PRECONDITION(g_x11.library, "Unable to open X11 library."); + +#ifdef FILAMENT_SUPPORTS_XCB g_x11.xcbConnect = (XCB_CONNECT) dlsym(g_x11.library, "xcb_connect"); int screen; mConnection = g_x11.xcbConnect(nullptr, &screen); - } - ASSERT_POSTCONDITION(vkCreateXcbSurfaceKHR, "Unable to load vkCreateXcbSurfaceKHR function."); - VkSurfaceKHR surface = nullptr; - const uint64_t ptrval = reinterpret_cast(nativeWindow); - VkXcbSurfaceCreateInfoKHR createInfo = { - .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, - .connection = mConnection, - .window = (xcb_window_t) ptrval, - }; - VkResult result = vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); -#else - if (g_x11.library == nullptr) { - g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW); - ASSERT_PRECONDITION(g_x11.library, "Unable to open X11 library."); + ASSERT_POSTCONDITION(vkCreateXcbSurfaceKHR, "Unable to load vkCreateXcbSurfaceKHR function."); +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB g_x11.openDisplay = (X11_OPEN_DISPLAY) dlsym(g_x11.library, "XOpenDisplay"); mDisplay = g_x11.openDisplay(NULL); ASSERT_PRECONDITION(mDisplay, "Unable to open X11 display."); + ASSERT_POSTCONDITION(vkCreateXlibSurfaceKHR, "Unable to load vkCreateXlibSurfaceKHR function."); +#endif + } - ASSERT_POSTCONDITION(vkCreateXlibSurfaceKHR, "Unable to load vkCreateXlibSurfaceKHR function."); + VkSurfaceKHR surface = nullptr; + +#ifdef FILAMENT_SUPPORTS_XCB +#ifdef FILAMENT_SUPPORTS_XLIB +const bool windowIsXCB = flags & SWAP_CHAIN_CONFIG_ENABLE_XCB; +#else +const bool windowIsXCB = true; +#endif + + if (windowIsXCB) { + const uint64_t ptrval = reinterpret_cast(nativeWindow); + VkXcbSurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, + .connection = mConnection, + .window = (xcb_window_t) ptrval, + }; + vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + return surface; + } +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB VkXlibSurfaceCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, .dpy = mDisplay, .window = (Window) nativeWindow, }; - VkResult result = vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); #endif - ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateXlibSurfaceKHR error."); + return surface; } diff --git a/filament/backend/src/vulkan/PlatformVkLinux.h b/filament/backend/src/vulkan/PlatformVkLinux.h index c112ecd628..8dde97bc73 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.h +++ b/filament/backend/src/vulkan/PlatformVkLinux.h @@ -24,7 +24,9 @@ #ifdef FILAMENT_SUPPORTS_XCB #include -#else +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB #include #endif @@ -35,14 +37,15 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } private: #ifdef FILAMENT_SUPPORTS_XCB xcb_connection_t* mConnection; -#else +#endif +#ifdef FILAMENT_SUPPORTS_XLIB Display* mDisplay; #endif }; diff --git a/filament/backend/src/vulkan/PlatformVkWindows.cpp b/filament/backend/src/vulkan/PlatformVkWindows.cpp index e5a168304f..a38b05075d 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.cpp +++ b/filament/backend/src/vulkan/PlatformVkWindows.cpp @@ -40,7 +40,7 @@ Driver* PlatformVkWindows::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { VkSurfaceKHR surface = nullptr; HWND window = (HWND) nativeWindow; diff --git a/filament/backend/src/vulkan/PlatformVkWindows.h b/filament/backend/src/vulkan/PlatformVkWindows.h index dfc7f84493..335bda8327 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.h +++ b/filament/backend/src/vulkan/PlatformVkWindows.h @@ -29,7 +29,7 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 8c032195cf..419246b81c 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -559,7 +559,8 @@ void VulkanDriver::createSyncR(Handle sh, int) { void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags) { const VkInstance instance = mContext.instance; - auto vksurface = (VkSurfaceKHR) mContextManager.createVkSurfaceKHR(nativeWindow, instance); + auto vksurface = (VkSurfaceKHR) mContextManager.createVkSurfaceKHR(nativeWindow, instance, + flags); auto* swapChain = construct_handle(mHandleMap, sch, mContext, vksurface); // TODO: move the following line into makeCurrent. diff --git a/filament/backend/src/vulkan/VulkanPlatform.h b/filament/backend/src/vulkan/VulkanPlatform.h index daa32da03f..0d560dcffa 100644 --- a/filament/backend/src/vulkan/VulkanPlatform.h +++ b/filament/backend/src/vulkan/VulkanPlatform.h @@ -43,7 +43,7 @@ namespace backend { class VulkanPlatform : public DefaultPlatform { public: // Given a Vulkan instance and native window handle, creates the platform-specific surface. - virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept = 0; + virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept = 0; ~VulkanPlatform() override; }; diff --git a/filament/include/filament/SwapChain.h b/filament/include/filament/SwapChain.h index 61470c0c5d..6ebd331134 100644 --- a/filament/include/filament/SwapChain.h +++ b/filament/include/filament/SwapChain.h @@ -153,6 +153,12 @@ public: */ static const uint64_t CONFIG_READABLE = backend::SWAP_CHAIN_CONFIG_READABLE; + /** + * Indicates that the native X11 window is an XCB window rather than an XLIB window. + * This is ignored on non-Linux platforms and in builds that support only one X11 API. + */ + static const uint64_t CONFIG_ENABLE_XCB = backend::SWAP_CHAIN_CONFIG_ENABLE_XCB; + void* getNativeWindow() const noexcept; }; diff --git a/libs/bluevk/include/vulkan/vk_platform.h b/libs/bluevk/include/vulkan/vk_platform.h index 4bfd1f0c1a..e8dc718721 100644 --- a/libs/bluevk/include/vulkan/vk_platform.h +++ b/libs/bluevk/include/vulkan/vk_platform.h @@ -28,7 +28,8 @@ #elif defined(__linux__) #if defined(FILAMENT_SUPPORTS_XCB) #define VK_USE_PLATFORM_XCB_KHR 1 -#else +#endif +#if defined(FILAMENT_SUPPORTS_XLIB) #define VK_USE_PLATFORM_XLIB_KHR 1 #endif #elif defined(__APPLE__)