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)
This commit is contained in:
Steve Pham
2021-07-26 13:41:28 -07:00
committed by GitHub
parent 900cc08510
commit e81f59d1e1
8 changed files with 149 additions and 5 deletions
@@ -9,8 +9,13 @@
#pragma once
#include <AzCore/Interface/Interface.h>
#include <AzCore/EBus/EBus.h>
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <xcb/xcb.h>
#endif // LY_COMPILE_DEFINITIONS
namespace AzFramework
{
class LinuxLifecycleEvents
@@ -25,4 +30,31 @@ namespace AzFramework
using Bus = AZ::EBus<LinuxLifecycleEvents>;
};
#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<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -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<LinuxXcbConnectionManager> 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<LinuxXcbConnectionManagerImpl>();
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();
}
@@ -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()
@@ -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()
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <RHI/Conversion.h>
#include <RHI/Instance.h>
#include <RHI/WSISurface.h>
@@ -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<xcb_window_t>(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
}
}
}
@@ -30,7 +30,7 @@
},
"normal": {
"flipY": true,
"textureMap": "Objects/Lucy/Lucy_normal.png"
"textureMap": "Objects/Lucy/Lucy_Normal.png"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
@@ -29,7 +29,7 @@
},
"normal": {
"flipY": true,
"textureMap": "Objects/Lucy/Lucy_normal.png"
"textureMap": "Objects/Lucy/Lucy_Normal.png"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
+4
View File
@@ -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)")