From e81f59d1e1bda849f7a716ab70eb3472293cd12b Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:41:28 -0700 Subject: [PATCH] Create XCB Connection mechanism for WSISurface implementation for Linux (#2400) - Add new Linux Trait to determine which display driver client API to use (only xcb supported for now) - Add support for xcb connections (initial) for Linux/Vulkan - Fix minor assertion caused by wrong use of sizeof - Fix casing issue in a couple of material files (Linux is case sensitive) --- .../AzFramework/API/ApplicationAPI_Linux.h | 32 +++++++++++++ .../Application/Application_Linux.cpp | 47 +++++++++++++++++++ .../Platform/Linux/platform_linux.cmake | 27 +++++++++++ .../Platform/Linux/glad_vulkan_linux.cmake | 18 +++++-- .../Platform/Linux/RHI/WSISurface_Linux.cpp | 22 +++++++++ .../001_lucy_regression_test.material | 2 +- .../002_wrinkle_regression_test.material | 2 +- cmake/Platform/Linux/PAL_linux.cmake | 4 ++ 8 files changed, 149 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h index 2c7d6e100c..03c65ce0c3 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h @@ -9,8 +9,13 @@ #pragma once +#include #include +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif // LY_COMPILE_DEFINITIONS + namespace AzFramework { class LinuxLifecycleEvents @@ -25,4 +30,31 @@ namespace AzFramework using Bus = AZ::EBus; }; + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + class LinuxXcbConnectionManager + { + public: + AZ_RTTI(LinuxXcbConnectionManager, "{649951316-3626-4C9D-9DCA-2E7ABF84C0A9}"); + + virtual ~LinuxXcbConnectionManager() = default; + + virtual xcb_connection_t* GetXcbConnection() const = 0; + }; + + class LinuxXcbConnectionManagerBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using LinuxXcbConnectionManagerBus = AZ::EBus; + using LinuxXcbConnectionManagerInterface = AZ::Interface; + +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp index 71779444b1..eb4165453e 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp @@ -12,6 +12,32 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + class LinuxXcbConnectionManagerImpl + : public LinuxXcbConnectionManagerBus::Handler + { + public: + LinuxXcbConnectionManagerImpl() + { + m_xcbConnection = xcb_connect(nullptr, nullptr); + AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); + LinuxXcbConnectionManagerBus::Handler::BusConnect(); + } + + ~LinuxXcbConnectionManagerImpl() + { + LinuxXcbConnectionManagerBus::Handler::BusDisconnect(); + xcb_disconnect(m_xcbConnection); + } + xcb_connection_t* GetXcbConnection() const override + { + return m_xcbConnection; + } + private: + xcb_connection_t* m_xcbConnection = nullptr; + }; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + //////////////////////////////////////////////////////////////////////////////////////////////// class ApplicationLinux : public Application::Implementation @@ -27,6 +53,12 @@ namespace AzFramework // Application::Implementation void PumpSystemEventLoopOnce() override; void PumpSystemEventLoopUntilEmpty() override; + private: + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + AZStd::unique_ptr m_xcbConnectionManager; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,11 +71,26 @@ namespace AzFramework ApplicationLinux::ApplicationLinux() { LinuxLifecycleEvents::Bus::Handler::BusConnect(); + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + m_xcbConnectionManager = AZStd::make_unique(); + if (LinuxXcbConnectionManagerInterface::Get() == nullptr) + { + LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); + } +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } //////////////////////////////////////////////////////////////////////////////////////////////// ApplicationLinux::~ApplicationLinux() { +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) + { + LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); + } + m_xcbConnectionManager.reset(); +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB LinuxLifecycleEvents::Bus::Handler::BusDisconnect(); } diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake index 7a325ca97e..c79c5f1dff 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake @@ -5,3 +5,30 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # + +# Based on the linux window manager trait, perform the appropriate additional build configurations +# Only 'xcb', 'wayland', and 'xlib' are recognized +if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") + + find_library(XCB_LIBRARY xcb) + + set(LY_BUILD_DEPENDENCIES + PRIVATE + ${XCB_LIBRARY} + ) + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland") + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND) + +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib") + + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB) + +else() + + message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized") + +endif() diff --git a/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake b/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake index 41de383023..1936c5b911 100644 --- a/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake +++ b/Gems/Atom/RHI/Vulkan/3rdParty/Platform/Linux/glad_vulkan_linux.cmake @@ -6,6 +6,18 @@ # # -set(GLAD_VULKAN_COMPILE_DEFINITIONS - VK_USE_PLATFORM_XCB_KHR -) +if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_XCB_KHR + ) +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_WAYLAND_KHR + ) +elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib") + set(GLAD_VULKAN_COMPILE_DEFINITIONS + VK_USE_PLATFORM_XLIB_KHR + ) +else() + message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized") +endif() diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp index 87b75d8609..98e91519ea 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#include #include #include #include @@ -17,15 +18,36 @@ namespace AZ { Instance& instance = Instance::GetInstance(); +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + + xcb_connection_t* xcb_connection = nullptr; + if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get(); + xcbConnectionManager != nullptr) + { + xcb_connection = xcbConnectionManager->GetXcbConnection(); + } + AZ_Error("AtomVulkan_RHI", xcb_connection!=nullptr, "Unable to get XCB Connection"); + VkXcbSurfaceCreateInfoKHR createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; createInfo.pNext = nullptr; createInfo.flags = 0; + createInfo.connection = xcb_connection; createInfo.window = static_cast(m_descriptor.m_windowHandle.GetIndex()); const VkResult result = vkCreateXcbSurfaceKHR(instance.GetNativeInstance(), &createInfo, nullptr, &m_nativeSurface); AssertSuccess(result); return ConvertResult(result); +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND + #error "Linux Window Manager Wayland not supported." + return RHI::ResultCode::Unimplemented; +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB + #error "Linux Window Manager XLIB not supported." + return RHI::ResultCode::Unimplemented; +#else + #error "Linux Window Manager not recognized." + return RHI::ResultCode::Unimplemented; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } } } diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material index c359fea3b5..bafb047be9 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_lucy_regression_test.material @@ -30,7 +30,7 @@ }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png" + "textureMap": "Objects/Lucy/Lucy_Normal.png" }, "subsurfaceScattering": { "enableSubsurfaceScattering": true, diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material index ce42f32b67..400044d29f 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material @@ -29,7 +29,7 @@ }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png" + "textureMap": "Objects/Lucy/Lucy_Normal.png" }, "subsurfaceScattering": { "enableSubsurfaceScattering": true, diff --git a/cmake/Platform/Linux/PAL_linux.cmake b/cmake/Platform/Linux/PAL_linux.cmake index 2f60b7e2c8..c137538ac0 100644 --- a/cmake/Platform/Linux/PAL_linux.cmake +++ b/cmake/Platform/Linux/PAL_linux.cmake @@ -37,3 +37,7 @@ set(LY_ASSET_DEPLOY_ASSET_TYPE "pc" CACHE STRING "Set the asset type for deploym # Set the python cmd tool ly_set(LY_PYTHON_CMD ${CMAKE_CURRENT_SOURCE_DIR}/python/python.sh) + +# Set the default window manager that applications should be using on Linux +# Note: Only ("xcb", "wayland", or "xlib" should be considered) +set(PAL_TRAIT_LINUX_WINDOW_MANAGER "xcb" CACHE STRING "Sets the Window Manager type to use when configuring Linux (xcb, wayland, or xlib)")