Reland "Vulkan: Fallback to XCB for Xlib surfaces"
This is a reland of fb0bf70459
Reland after making libx11-xcb dynamically loaded since it isn't present
on all Linux deployment targets of Chromium. Also includes a couple of
additional cosmetic changes to d3d12/PlatformFunctions noticed while
looking at it for inspiration.
Original change's description:
> Vulkan: Fallback to XCB for Xlib surfaces
>
> Chromium builds the Vulkan loader without support Xlib (because it
> prefers XCB) which caused Xlib wgpu::SwapChain creation to fail on the
> Vulkan backend.
>
> This CL adds a fallback to use VK_KHR_xcb_surface if VK_KHR_xlib_surface
> isn't present.
>
> Bug: dawn:662
> Change-Id: I0e0128ee6b5c75da03998dbae231d17e48bacc81
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/41180
> Reviewed-by: Austin Eng <enga@chromium.org>
> Commit-Queue: Austin Eng <enga@chromium.org>
> Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Bug: dawn:662
Change-Id: I617fcd1059dddfa05c29ac20d77f891ca6962342
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/41380
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
7e80cce1a9
commit
aa0e1be0e8
|
@ -162,6 +162,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
#if defined(DAWN_USE_X11)
|
#if defined(DAWN_USE_X11)
|
||||||
# define VK_USE_PLATFORM_XLIB_KHR
|
# define VK_USE_PLATFORM_XLIB_KHR
|
||||||
|
# define VK_USE_PLATFORM_XCB_KHR
|
||||||
# include "common/xlib_with_undefs.h"
|
# include "common/xlib_with_undefs.h"
|
||||||
#endif // defined(DAWN_USE_X11)
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
// interface.
|
// interface.
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
// Xlib-xcb.h technically includes Xlib.h but we separate the includes to make it more clear what
|
||||||
|
// the problem is if one of these two includes fail.
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
|
|
||||||
#undef Success
|
#undef Success
|
||||||
#undef None
|
#undef None
|
||||||
#undef Always
|
#undef Always
|
||||||
|
|
|
@ -296,6 +296,10 @@ source_set("dawn_native_sources") {
|
||||||
|
|
||||||
if (dawn_use_x11) {
|
if (dawn_use_x11) {
|
||||||
libs += [ "X11" ]
|
libs += [ "X11" ]
|
||||||
|
sources += [
|
||||||
|
"XlibXcbFunctions.cpp",
|
||||||
|
"XlibXcbFunctions.h",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_win) {
|
if (is_win) {
|
||||||
|
|
|
@ -181,6 +181,7 @@ target_link_libraries(dawn_native
|
||||||
if (DAWN_USE_X11)
|
if (DAWN_USE_X11)
|
||||||
find_package(X11 REQUIRED)
|
find_package(X11 REQUIRED)
|
||||||
target_link_libraries(dawn_native PRIVATE ${X11_LIBRARIES})
|
target_link_libraries(dawn_native PRIVATE ${X11_LIBRARIES})
|
||||||
|
target_include_directories(dawn_native PRIVATE ${X11_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
#include "dawn_native/ErrorData.h"
|
#include "dawn_native/ErrorData.h"
|
||||||
#include "dawn_native/Surface.h"
|
#include "dawn_native/Surface.h"
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
# include "dawn_native/XlibXcbFunctions.h"
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
// Forward definitions of each backend's "Connect" function that creates new BackendConnection.
|
// Forward definitions of each backend's "Connect" function that creates new BackendConnection.
|
||||||
|
@ -223,6 +227,17 @@ namespace dawn_native {
|
||||||
return mPlatform;
|
return mPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const XlibXcbFunctions* InstanceBase::GetOrCreateXlibXcbFunctions() {
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
if (mXlibXcbFunctions == nullptr) {
|
||||||
|
mXlibXcbFunctions = std::make_unique<XlibXcbFunctions>();
|
||||||
|
}
|
||||||
|
return mXlibXcbFunctions.get();
|
||||||
|
#else
|
||||||
|
UNREACHABLE();
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
}
|
||||||
|
|
||||||
Surface* InstanceBase::CreateSurface(const SurfaceDescriptor* descriptor) {
|
Surface* InstanceBase::CreateSurface(const SurfaceDescriptor* descriptor) {
|
||||||
if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) {
|
if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
class Surface;
|
class Surface;
|
||||||
|
class XlibXcbFunctions;
|
||||||
|
|
||||||
// This is called InstanceBase for consistency across the frontend, even if the backends don't
|
// This is called InstanceBase for consistency across the frontend, even if the backends don't
|
||||||
// specialize this class.
|
// specialize this class.
|
||||||
|
@ -67,6 +68,9 @@ namespace dawn_native {
|
||||||
void SetPlatform(dawn_platform::Platform* platform);
|
void SetPlatform(dawn_platform::Platform* platform);
|
||||||
dawn_platform::Platform* GetPlatform() const;
|
dawn_platform::Platform* GetPlatform() const;
|
||||||
|
|
||||||
|
// Get backend-independent libraries that need to be loaded dynamically.
|
||||||
|
const XlibXcbFunctions* GetOrCreateXlibXcbFunctions();
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
Surface* CreateSurface(const SurfaceDescriptor* descriptor);
|
Surface* CreateSurface(const SurfaceDescriptor* descriptor);
|
||||||
|
|
||||||
|
@ -97,6 +101,10 @@ namespace dawn_native {
|
||||||
|
|
||||||
ExtensionsInfo mExtensionsInfo;
|
ExtensionsInfo mExtensionsInfo;
|
||||||
TogglesInfo mTogglesInfo;
|
TogglesInfo mTogglesInfo;
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
std::unique_ptr<XlibXcbFunctions> mXlibXcbFunctions;
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2021 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "dawn_native/XlibXcbFunctions.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
XlibXcbFunctions::XlibXcbFunctions() {
|
||||||
|
if (!mLib.Open("libX11-xcb.so.1") ||
|
||||||
|
!mLib.GetProc(&xGetXCBConnection, "XGetXCBConnection")) {
|
||||||
|
mLib.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XlibXcbFunctions::~XlibXcbFunctions() = default;
|
||||||
|
|
||||||
|
bool XlibXcbFunctions::IsLoaded() const {
|
||||||
|
return xGetXCBConnection != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright 2021 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef DAWNNATIVE_XLIBXCBFUNCTIONS_H_
|
||||||
|
#define DAWNNATIVE_XLIBXCBFUNCTIONS_H_
|
||||||
|
|
||||||
|
#include "common/DynamicLib.h"
|
||||||
|
#include "dawn_native/Error.h"
|
||||||
|
|
||||||
|
#include "common/xlib_with_undefs.h"
|
||||||
|
|
||||||
|
class DynamicLib;
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
// A helper class that dynamically loads the x11-xcb library that contains XGetXCBConnection
|
||||||
|
// (and nothing else). This has to be dynamic because this libraries isn't present on all Linux
|
||||||
|
// deployment platforms that Chromium targets.
|
||||||
|
class XlibXcbFunctions {
|
||||||
|
public:
|
||||||
|
XlibXcbFunctions();
|
||||||
|
~XlibXcbFunctions();
|
||||||
|
|
||||||
|
bool IsLoaded() const;
|
||||||
|
|
||||||
|
// Functions from x11-xcb
|
||||||
|
decltype(&::XGetXCBConnection) xGetXCBConnection = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DynamicLib mLib;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // DAWNNATIVE_XLIBXCBFUNCTIONS_H_
|
|
@ -100,10 +100,8 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
PlatformFunctions::PlatformFunctions() {
|
PlatformFunctions::PlatformFunctions() = default;
|
||||||
}
|
PlatformFunctions::~PlatformFunctions() = default;
|
||||||
PlatformFunctions::~PlatformFunctions() {
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError PlatformFunctions::LoadFunctions() {
|
MaybeError PlatformFunctions::LoadFunctions() {
|
||||||
DAWN_TRY(LoadD3D12());
|
DAWN_TRY(LoadD3D12());
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
|
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
|
|
||||||
class DynamicLib;
|
|
||||||
|
|
||||||
namespace dawn_native { namespace d3d12 {
|
namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
// Loads the functions required from the platform dynamically so that we don't need to rely on
|
// Loads the functions required from the platform dynamically so that we don't need to rely on
|
||||||
|
@ -108,4 +106,4 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
}} // namespace dawn_native::d3d12
|
}} // namespace dawn_native::d3d12
|
||||||
|
|
||||||
#endif // DAWNNATIVE_VULKAN_VULKANFUNCTIONS_H_
|
#endif // DAWNNATIVE_D3D12_PLATFORMFUNCTIONS_H_
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "dawn_native/vulkan/SwapChainVk.h"
|
#include "dawn_native/vulkan/SwapChainVk.h"
|
||||||
|
|
||||||
#include "common/Compiler.h"
|
#include "common/Compiler.h"
|
||||||
|
#include "dawn_native/Instance.h"
|
||||||
#include "dawn_native/Surface.h"
|
#include "dawn_native/Surface.h"
|
||||||
#include "dawn_native/vulkan/AdapterVk.h"
|
#include "dawn_native/vulkan/AdapterVk.h"
|
||||||
#include "dawn_native/vulkan/BackendVk.h"
|
#include "dawn_native/vulkan/BackendVk.h"
|
||||||
|
@ -25,6 +26,10 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
# include "dawn_native/XlibXcbFunctions.h"
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// OldSwapChain
|
// OldSwapChain
|
||||||
|
@ -130,7 +135,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
#if defined(DAWN_USE_X11)
|
#if defined(DAWN_USE_X11)
|
||||||
case Surface::Type::Xlib:
|
case Surface::Type::Xlib: {
|
||||||
if (info.HasExt(InstanceExt::XlibSurface)) {
|
if (info.HasExt(InstanceExt::XlibSurface)) {
|
||||||
VkXlibSurfaceCreateInfoKHR createInfo;
|
VkXlibSurfaceCreateInfoKHR createInfo;
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||||
|
@ -145,7 +150,32 @@ namespace dawn_native { namespace vulkan {
|
||||||
"CreateXlibSurface"));
|
"CreateXlibSurface"));
|
||||||
return vkSurface;
|
return vkSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fall back to using XCB surfaces if the Xlib extension isn't available.
|
||||||
|
// See https://xcb.freedesktop.org/MixingCalls/ for more information about
|
||||||
|
// interoperability between Xlib and XCB
|
||||||
|
const XlibXcbFunctions* xlibXcb =
|
||||||
|
backend->GetInstance()->GetOrCreateXlibXcbFunctions();
|
||||||
|
ASSERT(xlibXcb != nullptr);
|
||||||
|
|
||||||
|
if (info.HasExt(InstanceExt::XcbSurface) && xlibXcb->IsLoaded()) {
|
||||||
|
VkXcbSurfaceCreateInfoKHR createInfo;
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||||
|
createInfo.pNext = nullptr;
|
||||||
|
createInfo.flags = 0;
|
||||||
|
// The XCB connection lives as long as the X11 display.
|
||||||
|
createInfo.connection = xlibXcb->xGetXCBConnection(
|
||||||
|
static_cast<Display*>(surface->GetXDisplay()));
|
||||||
|
createInfo.window = surface->GetXWindow();
|
||||||
|
|
||||||
|
VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
|
||||||
|
DAWN_TRY(CheckVkSuccess(
|
||||||
|
fn.CreateXcbSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
|
||||||
|
"CreateXcbSurfaceKHR"));
|
||||||
|
return vkSurface;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif // defined(DAWN_USE_X11)
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -152,6 +152,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
GET_INSTANCE_PROC(CreateXlibSurfaceKHR);
|
GET_INSTANCE_PROC(CreateXlibSurfaceKHR);
|
||||||
GET_INSTANCE_PROC(GetPhysicalDeviceXlibPresentationSupportKHR);
|
GET_INSTANCE_PROC(GetPhysicalDeviceXlibPresentationSupportKHR);
|
||||||
}
|
}
|
||||||
|
if (globalInfo.HasExt(InstanceExt::XcbSurface)) {
|
||||||
|
GET_INSTANCE_PROC(CreateXcbSurfaceKHR);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceXcbPresentationSupportKHR);
|
||||||
|
}
|
||||||
#endif // defined(DAWN_USE_X11)
|
#endif // defined(DAWN_USE_X11)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,11 @@ namespace dawn_native { namespace vulkan {
|
||||||
PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR = nullptr;
|
PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR = nullptr;
|
||||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
|
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
|
||||||
GetPhysicalDeviceXlibPresentationSupportKHR = nullptr;
|
GetPhysicalDeviceXlibPresentationSupportKHR = nullptr;
|
||||||
|
|
||||||
|
// KHR_xcb_surface
|
||||||
|
PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
|
||||||
|
GetPhysicalDeviceXcbPresentationSupportKHR = nullptr;
|
||||||
#endif // defined(DAWN_USE_X11)
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
// ---------- Device procs
|
// ---------- Device procs
|
||||||
|
|
Loading…
Reference in New Issue