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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<uint64_t>(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<uint64_t>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
#ifdef FILAMENT_SUPPORTS_XCB
|
||||
#include <xcb/xcb.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef FILAMENT_SUPPORTS_XLIB
|
||||
#include <X11/Xlib.h>
|
||||
#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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -559,7 +559,8 @@ void VulkanDriver::createSyncR(Handle<HwSync> sh, int) {
|
||||
|
||||
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> 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<VulkanSwapChain>(mHandleMap, sch, mContext, vksurface);
|
||||
|
||||
// TODO: move the following line into makeCurrent.
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
Reference in New Issue
Block a user