diff --git a/filament/backend/include/backend/platforms/VulkanPlatform.h b/filament/backend/include/backend/platforms/VulkanPlatform.h index c0b83c684b..b141e736f9 100644 --- a/filament/backend/include/backend/platforms/VulkanPlatform.h +++ b/filament/backend/include/backend/platforms/VulkanPlatform.h @@ -27,8 +27,19 @@ namespace filament::backend { class VulkanPlatform : public Platform { public: + struct SurfaceBundle { + void* surface; + // On certain platforms, the extent of the surface cannot be queried from Vulkan. In those + // situations, we allow the frontend to pass in the extent to use in creating the swap + // chains. Platform implementation should set extent to 0 if they do not expect to set the + // swap chain extent. + uint32_t width; + uint32_t height; + }; + // Given a Vulkan instance and native window handle, creates the platform-specific surface. - virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept = 0; + virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept = 0; ~VulkanPlatform() override; }; diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.cpp b/filament/backend/src/vulkan/PlatformVkAndroid.cpp index cbeb4b921b..570bc5014d 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.cpp +++ b/filament/backend/src/vulkan/PlatformVkAndroid.cpp @@ -29,23 +29,32 @@ using namespace bluevk; namespace filament::backend { -Driver* PlatformVkAndroid::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + +Driver* PlatformVkAndroid::createDriver(void* const sharedContext, + const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); static const char* requiredInstanceExtensions[] = { "VK_KHR_android_surface" }; return VulkanDriverFactory::create(this, requiredInstanceExtensions, 1, driverConfig); } -void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance, uint64_t flags) noexcept { +SurfaceBundle PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance, + uint64_t flags) noexcept { const VkInstance instance = (VkInstance) vkinstance; ANativeWindow* aNativeWindow = (ANativeWindow*) nativeWindow; VkAndroidSurfaceCreateInfoKHR createInfo { .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, .window = aNativeWindow }; - VkSurfaceKHR surface = VK_NULL_HANDLE; - VkResult result = vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC, &surface); + SurfaceBundle bundle { + .surface = VK_NULL_HANDLE, + .width = 0, + .height = 0 + }; + VkResult result = vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateAndroidSurfaceKHR error."); - return (void*) surface; + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.h b/filament/backend/src/vulkan/PlatformVkAndroid.h index 6d90df311b..9df82ec43e 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.h +++ b/filament/backend/src/vulkan/PlatformVkAndroid.h @@ -29,7 +29,8 @@ public: Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle 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 9d41152049..6fddee2fa1 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.h +++ b/filament/backend/src/vulkan/PlatformVkCocoa.h @@ -27,7 +27,8 @@ namespace filament::backend { class PlatformVkCocoa final : public VulkanPlatform { public: Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle 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 247b703901..d5b8040b7e 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoa.mm @@ -34,6 +34,8 @@ using namespace bluevk; namespace filament::backend { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + Driver* PlatformVkCocoa::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); static const char* requiredInstanceExtensions[] = { @@ -42,21 +44,28 @@ Driver* PlatformVkCocoa::createDriver(void* sharedContext, const Platform::Drive return VulkanDriverFactory::create(this, requiredInstanceExtensions, 1, driverConfig); } -void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { +SurfaceBundle 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."); // Create the VkSurface. ASSERT_POSTCONDITION(vkCreateMacOSSurfaceMVK, "Unable to load vkCreateMacOSSurfaceMVK."); - VkSurfaceKHR surface = nullptr; VkMacOSSurfaceCreateInfoMVK createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; createInfo.pView = (__bridge void*) nsview; - VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, &surface); + + SurfaceBundle bundle { + .surface = nullptr, + .width = 0, + .height = 0 + }; + VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateMacOSSurfaceMVK error."); - return surface; + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h index 98710af9a0..479277a8cf 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h @@ -27,7 +27,8 @@ namespace filament::backend { class PlatformVkCocoaTouch final : public VulkanPlatform { public: Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle 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 5c7a2e375d..64f6b2abdb 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm @@ -39,31 +39,37 @@ using namespace bluevk; namespace filament::backend { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + Driver* PlatformVkCocoaTouch::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); static const char* requestedExtensions[] = {"VK_MVK_ios_surface"}; return VulkanDriverFactory::create(this, requestedExtensions, 1, driverConfig); } -void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { +SurfaceBundle PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept { + SurfaceBundle bundle { + .surface = nullptr, + .width = 0, + .height = 0 + }; #if METAL_AVAILABLE CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow; // Create the VkSurface. ASSERT_POSTCONDITION(vkCreateIOSSurfaceMVK, "Unable to load vkCreateIOSSurfaceMVK function."); - VkSurfaceKHR surface = nullptr; VkIOSSurfaceCreateInfoMVK createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; createInfo.pNext = NULL; createInfo.flags = 0; createInfo.pView = metalLayer; - VkResult result = vkCreateIOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, &surface); - ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateIOSSurfaceMVK error."); - return surface; -#else - return nullptr; + VkResult result = vkCreateIOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); + ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateIOSSurfaceMVK error."); #endif + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkLinuxGGP.cpp b/filament/backend/src/vulkan/PlatformVkLinuxGGP.cpp index 07739e43aa..65cf2f73e3 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxGGP.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinuxGGP.cpp @@ -28,6 +28,8 @@ using namespace bluevk; namespace filament::backend { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + Driver* PlatformVkLinuxGGP::createDriver( void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { @@ -46,8 +48,13 @@ Driver* PlatformVkLinuxGGP::createDriver( #endif } -void* PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance, - uint64_t flags) noexcept { +SurfaceBundle PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept { + SurfaceBundle bundle { + .surface = nullptr, + .width = 0, + .height = 0 + }; #if defined(FILAMENT_SUPPORTS_GGP) VkStreamDescriptorSurfaceCreateInfoGGP surface_create_info = { VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP}; @@ -59,16 +66,14 @@ void* PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance, ASSERT_PRECONDITION(fpCreateStreamDescriptorSurfaceGGP != nullptr, "Error getting VkInstance " "function vkCreateStreamDescriptorSurfaceGGP"); - VkSurfaceKHR surface = nullptr; VkResult res = fpCreateStreamDescriptorSurfaceGGP( static_cast(instance), &surface_create_info, nullptr, - &surface); + (VkSurfaceKHR*) &bundle.surface); ASSERT_PRECONDITION(res == VK_SUCCESS, "Error in vulkan: %d", res); - return surface; #else PANIC_PRECONDITION("Filament does not support GGP."); - return nullptr; #endif + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkLinuxGGP.h b/filament/backend/src/vulkan/PlatformVkLinuxGGP.h index fad6175075..142386a6aa 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxGGP.h +++ b/filament/backend/src/vulkan/PlatformVkLinuxGGP.h @@ -30,8 +30,8 @@ class PlatformVkLinuxGGP final : public VulkanPlatform { void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, - uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkLinuxWayland.cpp b/filament/backend/src/vulkan/PlatformVkLinuxWayland.cpp index 858b0847e0..1e3fe085ce 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxWayland.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinuxWayland.cpp @@ -27,8 +27,19 @@ using namespace bluevk; +namespace { +typedef struct _wl { + struct wl_display *display; + struct wl_surface *surface; + uint32_t width; + uint32_t height; +} wl; +} // anonymous namespace + namespace filament::backend { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + Driver* PlatformVkLinuxWayland::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); const char* requiredInstanceExtensions[] = { @@ -38,15 +49,8 @@ Driver* PlatformVkLinuxWayland::createDriver(void* const sharedContext, const Pl sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0]), driverConfig); } -void* PlatformVkLinuxWayland::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { - - typedef struct _wl { - struct wl_display *display; - struct wl_surface *surface; - } wl; - - VkSurfaceKHR surface = nullptr; - +SurfaceBundle PlatformVkLinuxWayland::createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept { wl* ptrval = reinterpret_cast(nativeWindow); VkWaylandSurfaceCreateInfoKHR createInfo = { @@ -56,11 +60,15 @@ void* PlatformVkLinuxWayland::createVkSurfaceKHR(void* nativeWindow, void* insta .display = ptrval->display, .surface = ptrval->surface }; - - VkResult result = vkCreateWaylandSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + SurfaceBundle bundle { + .surface = VK_NULL_HANDLE, + .width = ptrval->width, + .height = ptrval->height + }; + VkResult result = vkCreateWaylandSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateWaylandSurfaceKHR error."); - - return surface; + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkLinuxWayland.h b/filament/backend/src/vulkan/PlatformVkLinuxWayland.h index 8d87617d77..544bc06219 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxWayland.h +++ b/filament/backend/src/vulkan/PlatformVkLinuxWayland.h @@ -30,7 +30,8 @@ public: Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkLinuxX11.cpp b/filament/backend/src/vulkan/PlatformVkLinuxX11.cpp index 12be10fb1d..e62bdb3f3f 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxX11.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinuxX11.cpp @@ -29,6 +29,8 @@ using namespace bluevk; namespace filament::backend { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + static constexpr const char* LIBRARY_X11 = "libX11.so.6"; #ifdef FILAMENT_SUPPORTS_XCB @@ -50,7 +52,8 @@ struct X11Functions { void* library = nullptr; } g_x11; -Driver* PlatformVkLinuxX11::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { +Driver* PlatformVkLinuxX11::createDriver(void* const sharedContext, + const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); const char* requiredInstanceExtensions[] = { #ifdef FILAMENT_SUPPORTS_XCB @@ -64,7 +67,8 @@ Driver* PlatformVkLinuxX11::createDriver(void* const sharedContext, const Platfo sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0]), driverConfig); } -void* PlatformVkLinuxX11::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { +SurfaceBundle PlatformVkLinuxX11::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."); @@ -85,7 +89,11 @@ void* PlatformVkLinuxX11::createVkSurfaceKHR(void* nativeWindow, void* instance, } - VkSurfaceKHR surface = nullptr; + SurfaceBundle bundle { + .surface = nullptr, + .width = 0, + .height = 0 + }; #ifdef FILAMENT_SUPPORTS_XCB #ifdef FILAMENT_SUPPORTS_XLIB @@ -101,8 +109,9 @@ const bool windowIsXCB = true; .connection = mConnection, .window = (xcb_window_t) ptrval, }; - vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); - return surface; + vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); + return bundle; } #endif @@ -112,10 +121,11 @@ const bool windowIsXCB = true; .dpy = mDisplay, .window = (Window) nativeWindow, }; - vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, + (VkSurfaceKHR*) &bundle.surface); #endif - return surface; + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkLinuxX11.h b/filament/backend/src/vulkan/PlatformVkLinuxX11.h index 7b65ebec22..e07dc71ab9 100644 --- a/filament/backend/src/vulkan/PlatformVkLinuxX11.h +++ b/filament/backend/src/vulkan/PlatformVkLinuxX11.h @@ -37,7 +37,8 @@ public: Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } diff --git a/filament/backend/src/vulkan/PlatformVkWindows.cpp b/filament/backend/src/vulkan/PlatformVkWindows.cpp index 07e5daf063..29b320e88e 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.cpp +++ b/filament/backend/src/vulkan/PlatformVkWindows.cpp @@ -27,15 +27,22 @@ using namespace bluevk; namespace filament::backend { -Driver* PlatformVkWindows::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept { +using SurfaceBundle = VulkanPlatform::SurfaceBundle; + +Driver* PlatformVkWindows::createDriver(void* const sharedContext, + const Platform::DriverConfig& driverConfig) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); const char* requiredInstanceExtensions[] = { "VK_KHR_win32_surface" }; return VulkanDriverFactory::create(this, requiredInstanceExtensions, 1, driverConfig); } -void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { - VkSurfaceKHR surface = nullptr; - +SurfaceBundle PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance, + uint64_t flags) noexcept { + SurfaceBundle bundle { + .surface = nullptr, + .width = 0, + .height = 0 + }; HWND window = (HWND) nativeWindow; VkWin32SurfaceCreateInfoKHR createInfo = {}; @@ -43,10 +50,11 @@ void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance, createInfo.hwnd = window; createInfo.hinstance = GetModuleHandle(nullptr); - VkResult result = vkCreateWin32SurfaceKHR((VkInstance) instance, &createInfo, nullptr, &surface); + VkResult result = vkCreateWin32SurfaceKHR((VkInstance) instance, &createInfo, nullptr, + (VkSurfaceKHR*) &bundle.surface); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateWin32SurfaceKHR error."); - return surface; + return bundle; } } // namespace filament::backend diff --git a/filament/backend/src/vulkan/PlatformVkWindows.h b/filament/backend/src/vulkan/PlatformVkWindows.h index d34663f6cb..2598af9ffe 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.h +++ b/filament/backend/src/vulkan/PlatformVkWindows.h @@ -29,7 +29,8 @@ public: Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; + VulkanPlatform::SurfaceBundle 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 a50abb0017..0cfc675754 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -395,9 +395,14 @@ 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, - flags); - construct(sch, mContext, mStagePool, vksurface); + auto bundle = mContextManager.createVkSurfaceKHR(nativeWindow, instance, flags); + VkSurfaceKHR surface = (VkSurfaceKHR) bundle.surface; + VkExtent2D fallback{bundle.width, bundle.height}; + if (fallback.width > 0 && fallback.height > 0) { + construct(sch, mContext, mStagePool, surface, fallback); + } else { + construct(sch, mContext, mStagePool, surface); + } } void VulkanDriver::createSwapChainHeadlessR(Handle sch, diff --git a/filament/backend/src/vulkan/VulkanSwapChain.cpp b/filament/backend/src/vulkan/VulkanSwapChain.cpp index aa8ff76f30..40a757f639 100644 --- a/filament/backend/src/vulkan/VulkanSwapChain.cpp +++ b/filament/backend/src/vulkan/VulkanSwapChain.cpp @@ -23,6 +23,10 @@ using namespace bluevk; using namespace utils; +namespace { +constexpr uint32_t VULKAN_UNDEFINED_EXTENT = 0xFFFFFFFF; +} // anonymous namespace + namespace filament::backend { bool VulkanSwapChain::acquire() { @@ -127,8 +131,12 @@ void VulkanSwapChain::create(VulkanStagePool& stagePool) { ASSERT_POSTCONDITION(foundSuitablePresentMode, "Desired present mode is not supported by this device."); // Create the low-level swap chain. - - clientSize = caps.currentExtent; + if (caps.currentExtent.width == VULKAN_UNDEFINED_EXTENT || + caps.currentExtent.height == VULKAN_UNDEFINED_EXTENT) { + clientSize = mFallbackExtent; + } else { + clientSize = caps.currentExtent; + } const VkCompositeAlphaFlagBitsKHR compositeAlpha = (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; @@ -297,8 +305,10 @@ static void getPresentationQueue(VulkanContext& mContext, VulkanSwapChain& sc) { } // Primary SwapChain constructor. (not headless) -VulkanSwapChain::VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, VkSurfaceKHR vksurface) : - mContext(context) { +VulkanSwapChain::VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, VkSurfaceKHR vksurface, + VkExtent2D fallbackExtent) : + mContext(context), + mFallbackExtent(fallbackExtent) { suboptimal = false; surface = vksurface; firstRenderPass = true; @@ -341,9 +351,15 @@ bool VulkanSwapChain::hasResized() const { if (surface == VK_NULL_HANDLE) { return false; } - VkSurfaceCapabilitiesKHR surfaceCapabilities; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(mContext.physicalDevice, surface, &surfaceCapabilities); - return !equivalent(clientSize, surfaceCapabilities.currentExtent); + VkSurfaceCapabilitiesKHR caps; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(mContext.physicalDevice, surface, &caps); + VkExtent2D perceivedExtent = caps.currentExtent; + // Create the low-level swap chain. + if (caps.currentExtent.width == VULKAN_UNDEFINED_EXTENT || + caps.currentExtent.height == VULKAN_UNDEFINED_EXTENT) { + perceivedExtent = mFallbackExtent; + } + return !equivalent(clientSize, perceivedExtent); } VulkanTexture& VulkanSwapChain::getColorTexture() { diff --git a/filament/backend/src/vulkan/VulkanSwapChain.h b/filament/backend/src/vulkan/VulkanSwapChain.h index c1b880adcc..d0dbb0ed0a 100644 --- a/filament/backend/src/vulkan/VulkanSwapChain.h +++ b/filament/backend/src/vulkan/VulkanSwapChain.h @@ -28,10 +28,14 @@ namespace filament::backend { struct VulkanSwapChain : public HwSwapChain { - VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, VkSurfaceKHR vksurface); + // The *fallbackExtent* parameter is for the case where the extent returned by the physical + // surface is 0xFFFFFFFF. + VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, VkSurfaceKHR vksurface, + VkExtent2D fallbackExtent={.width=640, .height=320}); // Headless constructor. - VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, uint32_t width, uint32_t height); + VulkanSwapChain(VulkanContext& context, VulkanStagePool& stagePool, uint32_t width, + uint32_t height); bool acquire(); void create(VulkanStagePool& stagePool); @@ -63,6 +67,7 @@ struct VulkanSwapChain : public HwSwapChain { private: VulkanContext& mContext; uint32_t mCurrentSwapIndex = 0u; + const VkExtent2D mFallbackExtent = {}; // Color attachments are swapped, but depth is not. Typically there are 2 or 3 color attachments // in a swap chain. diff --git a/libs/filamentapp/src/NativeWindowHelperLinux.cpp b/libs/filamentapp/src/NativeWindowHelperLinux.cpp index 0edec8340d..979c495ce7 100644 --- a/libs/filamentapp/src/NativeWindowHelperLinux.cpp +++ b/libs/filamentapp/src/NativeWindowHelperLinux.cpp @@ -32,15 +32,23 @@ void* getNativeWindow(SDL_Window* sdlWindow) { } else if (wmi.subsystem == SDL_SYSWM_WAYLAND) { #if defined(FILAMENT_SUPPORTS_WAYLAND) + int width = 0; + int height = 0; + SDL_GetWindowSize(sdlWindow, &width, &height); + // Static is used here to allocate the struct pointer for the lifetime of the program. // Without static the valid struct quickyly goes out of scope, and ends with seemingly // random segfaults. static struct { struct wl_display *display; struct wl_surface *surface; + uint32_t width; + uint32_t height; } wayland { wmi.info.wl.display, wmi.info.wl.surface, + static_cast(width), + static_cast(height) }; return (void *) &wayland; #endif