aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2025-10-22 04:53:40 +0200
committercrueter <crueter@eden-emu.dev>2025-10-22 04:53:40 +0200
commit87cacbeed49facf18355c55cc93d0a2a0142be09 (patch)
tree320ab5933dd97b5f54f5fcc2cb4ed775587c9cbf /src
parent992bae4e2a14ca2547c09637b7dc6fc5f73b353a (diff)
[compat] HaikuOS port (#2805)
Still had the issues with libusb, but that should get solved with the other PRs anyways Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2805 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/common/host_memory.cpp31
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/settings.h2
-rw-r--r--src/common/thread.cpp62
-rw-r--r--src/common/virtual_buffer.cpp16
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp2
-rw-r--r--src/core/frontend/emu_window.h6
-rw-r--r--src/core/internal_network/network.cpp6
-rw-r--r--src/core/internal_network/network.h5
-rw-r--r--src/core/internal_network/sockets.h14
-rw-r--r--src/core/tools/renderdoc.cpp2
-rw-r--r--src/dynarmic/src/dynarmic/CMakeLists.txt3
-rw-r--r--src/qt_common/qt_common.cpp5
-rw-r--r--src/qt_common/util/game.cpp2
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt10
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp33
-rw-r--r--src/video_core/vulkan_common/vulkan.h5
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp4
-rw-r--r--src/video_core/vulkan_common/vulkan_surface.cpp20
20 files changed, 126 insertions, 106 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 3838c12903..6e47fa286d 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -12,7 +12,7 @@
#include <windows.h>
#include "common/dynamic_library.h"
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
+#else // ^^^ Windows ^^^ vvv POSIX vvv
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -394,7 +394,7 @@ private:
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
};
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
+#else // ^^^ Windows ^^^ vvv POSIX vvv
#ifdef ARCHITECTURE_arm64
@@ -679,32 +679,7 @@ private:
FreeRegionManager free_manager{};
};
-#else // ^^^ POSIX ^^^ vvv Generic vvv
-
-class HostMemory::Impl {
-public:
- explicit Impl([[maybe_unused]] size_t backing_size, [[maybe_unused]] size_t virtual_size) {
- // This is just a place holder.
- ASSERT_MSG(false, "Please implement fastmem in a proper way on your platform.");
- }
-
- void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm) {}
-
- void Unmap(size_t virtual_offset, size_t length) {}
-
- void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
-
- bool ClearBackingRegion(size_t physical_offset, size_t length) {
- return false;
- }
-
- void EnableDirectMappedAddress() {}
-
- u8* backing_base{nullptr};
- u8* virtual_base{nullptr};
-};
-
-#endif // ^^^ Generic ^^^
+#endif // ^^^ POSIX ^^^
HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_)
: backing_size(backing_size_), virtual_size(virtual_size_) {
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index e817acc36e..0022d242c3 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -169,7 +169,7 @@ bool IsFastmemEnabled() {
if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe) {
return bool(values.cpuopt_unsafe_host_mmu);
}
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
return false;
#else
return true;
diff --git a/src/common/settings.h b/src/common/settings.h
index 4eea9cf265..1dc3bdca20 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -296,7 +296,7 @@ struct Values {
Category::CpuDebug};
SwitchableSetting<bool> cpuopt_unsafe_host_mmu{linkage,
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
false,
#else
true,
diff --git a/src/common/thread.cpp b/src/common/thread.cpp
index 2de7465a22..3f0fb48c25 100644
--- a/src/common/thread.cpp
+++ b/src/common/thread.cpp
@@ -11,6 +11,8 @@
#include "common/thread.h"
#ifdef __APPLE__
#include <mach/mach.h>
+#elif defined(__HAIKU__)
+#include <kernel/OS.h>
#elif defined(_WIN32)
#include <windows.h>
#include "common/string_util.h"
@@ -31,43 +33,38 @@
namespace Common {
-#ifdef _WIN32
-
void SetCurrentThreadPriority(ThreadPriority new_priority) {
- auto handle = GetCurrentThread();
- int windows_priority = 0;
- switch (new_priority) {
- case ThreadPriority::Low:
- windows_priority = THREAD_PRIORITY_BELOW_NORMAL;
- break;
- case ThreadPriority::Normal:
- windows_priority = THREAD_PRIORITY_NORMAL;
- break;
- case ThreadPriority::High:
- windows_priority = THREAD_PRIORITY_ABOVE_NORMAL;
- break;
- case ThreadPriority::VeryHigh:
- windows_priority = THREAD_PRIORITY_HIGHEST;
- break;
- case ThreadPriority::Critical:
- windows_priority = THREAD_PRIORITY_TIME_CRITICAL;
- break;
- default:
- windows_priority = THREAD_PRIORITY_NORMAL;
- break;
- }
- SetThreadPriority(handle, windows_priority);
-}
-
+#ifdef _WIN32
+ int windows_priority = [&]() {
+ switch (new_priority) {
+ case ThreadPriority::Low: return THREAD_PRIORITY_BELOW_NORMAL;
+ case ThreadPriority::Normal: return THREAD_PRIORITY_NORMAL;
+ case ThreadPriority::High: return THREAD_PRIORITY_ABOVE_NORMAL;
+ case ThreadPriority::VeryHigh: return THREAD_PRIORITY_HIGHEST;
+ case ThreadPriority::Critical: return THREAD_PRIORITY_TIME_CRITICAL;
+ default: return THREAD_PRIORITY_NORMAL;
+ }
+ }();
+ SetThreadPriority(GetCurrentThread(), windows_priority);
+#elif defined(__HAIKU__)
+ // TODO: We have priorities for 3D rendering applications - may help lavapipe?
+ int priority = [&]() {
+ switch (new_priority) {
+ case ThreadPriority::Low: return B_LOW_PRIORITY;
+ case ThreadPriority::Normal: return B_NORMAL_PRIORITY;
+ case ThreadPriority::High: return B_DISPLAY_PRIORITY;
+ case ThreadPriority::VeryHigh: return B_URGENT_DISPLAY_PRIORITY;
+ case ThreadPriority::Critical: return B_URGENT_PRIORITY;
+ default: return B_NORMAL_PRIORITY;
+ }
+ }();
+ set_thread_priority(find_thread(NULL), priority);
#else
-
-void SetCurrentThreadPriority(ThreadPriority new_priority) {
pthread_t this_thread = pthread_self();
-
const auto scheduling_type = SCHED_OTHER;
s32 max_prio = sched_get_priority_max(scheduling_type);
s32 min_prio = sched_get_priority_min(scheduling_type);
- u32 level = (std::max)(static_cast<u32>(new_priority) + 1, 4U);
+ u32 level = (std::max)(u32(new_priority) + 1, 4U);
struct sched_param params;
if (max_prio > min_prio) {
@@ -77,9 +74,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
}
pthread_setschedparam(this_thread, scheduling_type, &params);
-}
-
#endif
+}
#ifdef _MSC_VER
diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp
index dea6de99f0..55ddfc243a 100644
--- a/src/common/virtual_buffer.cpp
+++ b/src/common/virtual_buffer.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,24 +17,19 @@ namespace Common {
void* AllocateMemoryPages(std::size_t size) noexcept {
#ifdef _WIN32
- void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)};
+ void* base = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE);
#else
- void* base{mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0)};
-
- if (base == MAP_FAILED) {
+ void* base = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (base == MAP_FAILED)
base = nullptr;
- }
#endif
-
ASSERT(base);
-
return base;
}
void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) noexcept {
- if (!base) {
+ if (!base)
return;
- }
#ifdef _WIN32
ASSERT(VirtualFree(base, 0, MEM_RELEASE));
#else
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 3c72ab2396..1618f2131b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -295,7 +295,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
// Curated optimizations
case Settings::CpuAccuracy::Auto:
config.unsafe_optimizations = true;
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
config.fastmem_pointer = std::nullopt;
config.fastmem_exclusive_access = false;
#endif
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 707d51d2a2..62f7de1414 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -354,7 +354,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
// Safe optimisations
case Settings::CpuAccuracy::Auto:
config.unsafe_optimizations = true;
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
config.fastmem_pointer = std::nullopt;
config.fastmem_exclusive_access = false;
#endif
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index c7b48a58d7..ee7a7693b2 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,7 +16,7 @@ namespace Core::Frontend {
class GraphicsContext;
-/// Information for the Graphics Backends signifying what type of screen pointer is in
+/// @brief Information for the Graphics Backends signifying what type of screen pointer is in
/// WindowInformation
enum class WindowSystemType {
Headless,
@@ -22,6 +25,7 @@ enum class WindowSystemType {
Wayland,
Cocoa,
Android,
+ Xcb,
};
/**
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp
index b21d8a7a16..35f2157761 100644
--- a/src/core/internal_network/network.cpp
+++ b/src/core/internal_network/network.cpp
@@ -15,7 +15,7 @@
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
-#elif defined(__unix__) || defined(__APPLE__)
+#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -24,8 +24,6 @@
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
-#else
-#error "Unimplemented platform"
#endif
#include "common/assert.h"
@@ -165,7 +163,7 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
}
}
-#elif defined(__unix__) || defined(__APPLE__) // ^ _WIN32 v __unix__
+#else // ^^^ Windows vvv POSIX
using SOCKET = int;
using WSAPOLLFD = pollfd;
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h
index 5a3343efd9..5df28911f8 100644
--- a/src/core/internal_network/network.h
+++ b/src/core/internal_network/network.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -104,7 +107,7 @@ constexpr IPv4Address TranslateIPv4(in_addr addr) {
auto& bytes = addr.S_un.S_un_b;
return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4};
}
-#elif defined(__unix__) || defined(__APPLE__)
+#else
constexpr IPv4Address TranslateIPv4(in_addr addr) {
const u32 bytes = addr.s_addr;
return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8),
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h
index 27468709fd..0b751b6622 100644
--- a/src/core/internal_network/sockets.h
+++ b/src/core/internal_network/sockets.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,15 +11,6 @@
#include <span>
#include <utility>
-#if defined(_WIN32)
-// windows
-#elif defined(__unix__) || defined(__APPLE__)
-// unix
-#else
-// haiku
-#error "Platform not implemented"
-#endif
-
#include "common/common_types.h"
#include "core/internal_network/network.h"
@@ -28,7 +22,7 @@ struct ProxyPacket;
class SocketBase {
public:
-#if defined(__unix__) || defined(__APPLE__)
+#ifndef _WIN32
using SOCKET = int;
static constexpr SOCKET INVALID_SOCKET = -1;
static constexpr SOCKET SOCKET_ERROR = -1;
diff --git a/src/core/tools/renderdoc.cpp b/src/core/tools/renderdoc.cpp
index d3a47e1d96..5fab291fe5 100644
--- a/src/core/tools/renderdoc.cpp
+++ b/src/core/tools/renderdoc.cpp
@@ -28,6 +28,8 @@ RenderdocAPI::RenderdocAPI() {
ASSERT(ret == 1);
}
}
+#elif defined(__HAIKU__)
+ // no rtld on haiku
#else
#ifdef ANDROID
static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so";
diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt
index 763ff4b34b..f21000044e 100644
--- a/src/dynarmic/src/dynarmic/CMakeLists.txt
+++ b/src/dynarmic/src/dynarmic/CMakeLists.txt
@@ -345,7 +345,8 @@ elseif (APPLE)
backend/exception_handler_macos_mig.c
)
endif()
-elseif (UNIX)
+elseif (UNIX AND NOT PLATFORM_HAIKU)
+ # Haiku lacks <ucontext.h>
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(dynarmic PRIVATE rt)
endif()
diff --git a/src/qt_common/qt_common.cpp b/src/qt_common/qt_common.cpp
index 6be241c740..1fa3df98cf 100644
--- a/src/qt_common/qt_common.cpp
+++ b/src/qt_common/qt_common.cpp
@@ -33,8 +33,7 @@ std::unique_ptr<Core::System> system = nullptr;
std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr;
std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr;
-Core::Frontend::WindowSystemType GetWindowSystemType()
-{
+Core::Frontend::WindowSystemType GetWindowSystemType() {
// Determine WSI type based on Qt platform.
QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("windows"))
@@ -49,6 +48,8 @@ Core::Frontend::WindowSystemType GetWindowSystemType()
return Core::Frontend::WindowSystemType::Cocoa;
else if (platform_name == QStringLiteral("android"))
return Core::Frontend::WindowSystemType::Android;
+ else if (platform_name == QStringLiteral("haiku"))
+ return Core::Frontend::WindowSystemType::Xcb;
LOG_CRITICAL(Frontend, "Unknown Qt platform {}!", platform_name.toStdString());
return Core::Frontend::WindowSystemType::Windows;
diff --git a/src/qt_common/util/game.cpp b/src/qt_common/util/game.cpp
index 04434c714f..e5018d24cb 100644
--- a/src/qt_common/util/game.cpp
+++ b/src/qt_common/util/game.cpp
@@ -149,7 +149,7 @@ bool MakeShortcutIcoPath(const u64 program_id,
#if defined(_WIN32)
out_icon_path = Common::FS::GetEdenPath(Common::FS::EdenPath::IconsDir);
ico_extension = "ico";
-#elif defined(__linux__) || defined(__FreeBSD__)
+#elif !defined(__ANDROID__) // Any *nix but android
out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
#endif
// Create icons directory if it doesn't exist
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index 9f7b9edd5a..fef9a5b16e 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -86,7 +86,15 @@ set(SHADER_FILES
dynamic_resolution_scale.comp
)
-find_program(GLSLANGVALIDATOR "glslangValidator")
+if (PLATFORM_HAIKU)
+ # glslangValidator WILL crash, glslang will not - why? Who the fuck knows
+ #/boot/home/glslang/build/StandAlone/glslangValidator
+ set(GLSLANGVALIDATOR "glslang")
+else()
+ # Normal sane platform who doesn't have a CRASHING glslangValidator
+ find_program(GLSLANGVALIDATOR "glslangValidator")
+endif()
+
if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND")
message(FATAL_ERROR "Required program `glslangValidator` not found.")
endif()
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index f3d884f0eb..8b10747b9a 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -50,20 +50,24 @@ bool TestProgram(const GLchar* glsl) {
return link_status == GL_TRUE;
}
-std::vector<std::string_view> GetExtensions() {
+/// @brief Query OpenGL extensions
+/// DO NOT use string_view, the driver can immediately free up the extension name and such
+/// do NOT under ANY circumstances use string_view, make a copy, it's required
+std::vector<std::string> GetExtensions() {
GLint num_extensions;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
- std::vector<std::string_view> extensions;
- extensions.reserve(num_extensions);
+ std::vector<std::string> extensions;
for (GLint index = 0; index < num_extensions; ++index) {
- extensions.push_back(
- reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, static_cast<GLuint>(index))));
+ auto const* p = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, GLuint(index)));
+ if (p != nullptr) // Fuck you? - sincerely, buggy mesa drivers
+ extensions.push_back(std::string{p});
}
return extensions;
}
-bool HasExtension(std::span<const std::string_view> extensions, std::string_view extension) {
- return std::ranges::find(extensions, extension) != extensions.end();
+/// @brief Find extension in set of extensions (string)
+bool HasExtension(std::span<const std::string> extensions, std::string_view extension) {
+ return std::ranges::find(extensions, std::string{extension}) != extensions.end();
}
std::array<u32, Shader::MaxStageTypes> BuildMaxUniformBuffers() noexcept {
@@ -148,7 +152,7 @@ static bool HasSlowSoftwareAstc(std::string_view vendor_name, std::string_view r
return false;
}
-[[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) {
+[[nodiscard]] bool IsDebugToolAttached(std::span<const std::string> extensions) {
const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
return nsight || HasExtension(extensions, "GL_EXT_debug_tool") ||
Settings::values.renderer_debug.GetValue();
@@ -160,10 +164,17 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available");
throw std::runtime_error{"Insufficient version"};
}
+#ifdef __HAIKU__
+ if (glad_glCreateProgramPipelines == nullptr) {
+ LOG_ERROR(Render_OpenGL, "You must compile Mesa +22 manually or use a different libGL.so (GLES is not supported)");
+ throw std::runtime_error{"Outdated mesa"};
+ }
+#endif
+
vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
- const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
- const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
- const std::vector extensions = GetExtensions();
+ const std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+ const std::string renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
+ const std::vector<std::string> extensions = GetExtensions();
const bool is_nvidia = vendor_name == "NVIDIA Corporation";
const bool is_amd = vendor_name == "ATI Technologies Inc.";
diff --git a/src/video_core/vulkan_common/vulkan.h b/src/video_core/vulkan_common/vulkan.h
index 62aa132915..13f679ff54 100644
--- a/src/video_core/vulkan_common/vulkan.h
+++ b/src/video_core/vulkan_common/vulkan.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,6 +13,8 @@
#define VK_USE_PLATFORM_METAL_EXT
#elif defined(__ANDROID__)
#define VK_USE_PLATFORM_ANDROID_KHR
+#elif defined(__HAIKU__)
+#define VK_USE_PLATFORM_XCB_KHR
#else
#define VK_USE_PLATFORM_XLIB_KHR
#define VK_USE_PLATFORM_WAYLAND_KHR
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp
index 1948e0030a..d9404933cd 100644
--- a/src/video_core/vulkan_common/vulkan_instance.cpp
+++ b/src/video_core/vulkan_common/vulkan_instance.cpp
@@ -59,6 +59,10 @@ namespace {
case Core::Frontend::WindowSystemType::Android:
extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
break;
+#elif defined(__HAIKU__)
+ case Core::Frontend::WindowSystemType::Xcb:
+ extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+ break;
#else
case Core::Frontend::WindowSystemType::X11:
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
diff --git a/src/video_core/vulkan_common/vulkan_surface.cpp b/src/video_core/vulkan_common/vulkan_surface.cpp
index e45f8e43fb..f1b56cc0a8 100644
--- a/src/video_core/vulkan_common/vulkan_surface.cpp
+++ b/src/video_core/vulkan_common/vulkan_surface.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -54,6 +57,23 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
+#elif defined(__HAIKU__)
+ if (window_info.type == Core::Frontend::WindowSystemType::Xcb) {
+ const VkXcbSurfaceCreateInfoKHR xcb_ci{
+ .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
+ .pNext = nullptr,
+ .flags = 0,
+ .connection = static_cast<xcb_connection_t*>(window_info.display_connection),
+ .window = xcb_window_t(uintptr_t(window_info.render_surface))
+ };
+ const auto vkCreateXcbSurfaceKHR = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(
+ dld.vkGetInstanceProcAddr(*instance, "vkCreateXcbSurfaceKHR"));
+ if (!vkCreateXcbSurfaceKHR ||
+ vkCreateXcbSurfaceKHR(*instance, &xcb_ci, nullptr, &unsafe_surface) != VK_SUCCESS) {
+ LOG_ERROR(Render_Vulkan, "Failed to initialize Xcb surface");
+ throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
+ }
+ }
#else
if (window_info.type == Core::Frontend::WindowSystemType::X11) {
const VkXlibSurfaceCreateInfoKHR xlib_ci{