From c39e3bece60fb0af6fa1652bee87c2cb8f75dd80 Mon Sep 17 00:00:00 2001 From: crueter Date: Thu, 14 Aug 2025 22:02:59 -0400 Subject: [PATCH 1/5] [cmake] do not allow system xbyak Signed-off-by: crueter --- externals/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 91659ee595..232cc866da 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -46,6 +46,7 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) REPO "Lizzie841/xbyak" SHA ${XBYAK_HASH} HASH ${XBYAK_SHA512SUM} + BUNDLED_PACKAGE ON ) endif() From e807e32b1aee1daff61b8ebf61f7b38bd895a8c9 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 15 Aug 2025 04:12:45 +0200 Subject: [PATCH 2/5] [compat] fix solaris Qt build (#194) Co-authored-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/194 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- CMakeLists.txt | 9 ++++- docs/Development.md | 1 + docs/build/Solaris.md | 13 +++++++ .../android/multiplayer/multiplayer.cpp | 18 +++++----- src/common/host_memory.cpp | 35 +++++++++---------- src/core/CMakeLists.txt | 4 +-- src/core/internal_network/network.cpp | 8 ++--- src/core/internal_network/network.h | 4 +-- src/core/internal_network/socket_proxy.cpp | 2 +- src/core/internal_network/sockets.h | 8 +++-- src/network/announce_multiplayer_session.cpp | 9 ++--- src/video_core/renderer_opengl/gl_device.cpp | 6 ++-- .../gl_staging_buffer_pool.cpp | 1 + src/yuzu/CMakeLists.txt | 5 +++ src/yuzu/configuration/configure_graphics.cpp | 10 +++--- .../configure_input_player_widget.cpp | 2 +- src/yuzu/configuration/shared_widget.cpp | 28 +++++++-------- src/yuzu/discord_impl.cpp | 2 +- src/yuzu/main.cpp | 4 +-- src/yuzu/startup_checks.cpp | 8 ++--- src/yuzu/startup_checks.h | 4 +-- 21 files changed, 105 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fb69b9a3b..4199f0a904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,11 @@ project(yuzu) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") +if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") + # Terrific Solaris pkg shenanigans + list(APPEND CMAKE_PREFIX_PATH "/usr/lib/qt/6.6/lib/amd64/cmake") + list(APPEND CMAKE_MODULE_PATH "/usr/lib/qt/6.6/lib/amd64/cmake") +endif() set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) @@ -649,8 +654,10 @@ if (ENABLE_QT) find_package(Qt6 REQUIRED COMPONENTS Multimedia) endif() - if (UNIX AND NOT APPLE) + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") find_package(Qt6 REQUIRED COMPONENTS DBus GuiPrivate) + elseif (UNIX AND NOT APPLE) + find_package(Qt6 REQUIRED COMPONENTS DBus Gui) endif() if (ENABLE_QT_TRANSLATION) diff --git a/docs/Development.md b/docs/Development.md index 3e1ff62ae6..26a10fd062 100644 --- a/docs/Development.md +++ b/docs/Development.md @@ -104,6 +104,7 @@ Then type `target remote localhost:1234` and type `c` (for continue) - and then - `br `: Set breakpoint at ``. - `delete`: Deletes all breakpoints. - `catch throw`: Breakpoint at throw. Can also use `br __cxa_throw` +- `br _mesa_error`: Break on mesa errors (set environment variable `MESA_DEBUG=1` beforehand), see [MESA_DEBUG](https://mesa-docs.readthedocs.io/en/latest/debugging.html). Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference of a pointer) or `*(1 + var)` (computed expression). diff --git a/docs/build/Solaris.md b/docs/build/Solaris.md index c7daa2279b..be681d5308 100644 --- a/docs/build/Solaris.md +++ b/docs/build/Solaris.md @@ -87,6 +87,19 @@ export PATH="$PATH:$PWD" - **Build**: `cmake --build build`. - **Installing**: `sudo cmake --install build`. +### Running + +Default Mesa is a bit outdated, the following environment variables should be set for a smoother experience: +```sh +export MESA_GL_VERSION_OVERRIDE=4.6 +export MESA_GLSL_VERSION_OVERRIDE=460 +export MESA_EXTENSION_MAX_YEAR=2025 +export MESA_DEBUG=1 +export MESA_VK_VERSION_OVERRIDE=1.3 +# Only if nvidia/intel drm drivers cause crashes, will severely hinder performance +export LIBGL_ALWAYS_SOFTWARE=1 +``` + ### Notes - Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`). diff --git a/src/common/android/multiplayer/multiplayer.cpp b/src/common/android/multiplayer/multiplayer.cpp index 26bb800ce2..ff57eedec3 100644 --- a/src/common/android/multiplayer/multiplayer.cpp +++ b/src/common/android/multiplayer/multiplayer.cpp @@ -205,8 +205,8 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress std::string token; // TODO(alekpop): properly handle the compile definition, it's not working right -//#ifdef ENABLE_WEB_SERVICE -// LOG_INFO(WebService, "Web Service enabled"); +#ifdef ENABLE_WEB_SERVICE + LOG_INFO(WebService, "Web Service enabled"); if (isPublic) { WebService::Client client(Settings::values.web_api_url.GetValue(), Settings::values.eden_username.GetValue(), @@ -220,9 +220,9 @@ NetPlayStatus AndroidMultiplayer::NetPlayCreateRoom(const std::string &ipaddress LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size()); } } -//#else -// LOG_INFO(WebService, "Web Service disabled"); -//#endif +#else + LOG_ERROR(WebService, "Web Service disabled"); +#endif member->Join(username, ipaddress.c_str(), static_cast(port), 0, Network::NoPreferredIP, password, token); @@ -432,12 +432,12 @@ std::vector AndroidMultiplayer::NetPlayGetBanList() { std::unique_ptr AndroidMultiplayer::CreateVerifyBackend(bool use_validation) { std::unique_ptr verify_backend; if (use_validation) { -//#ifdef ENABLE_WEB_SERVICE +#ifdef ENABLE_WEB_SERVICE verify_backend = std::make_unique(Settings::values.web_api_url.GetValue()); -//#else -// verify_backend = std::make_unique(); -//#endif +#else + verify_backend = std::make_unique(); +#endif } else { verify_backend = std::make_unique(); } diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 9e34cd3ac6..949cd188f3 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -442,16 +442,15 @@ static int shm_open_anon(int flags, mode_t mode) { for (char *fill = start; fill < limit; r /= 8) *fill++ = '0' + (r % 8); int fd = shm_open(name, flags, mode); - if (fd != -1) - return ([](const char *name, int fd) { - if (shm_unlink(name) == -1) { - int tmp = errno; - close(fd); - errno = tmp; - return -1; - } - return fd; - })(name, fd); + if (fd != -1) { + if (shm_unlink(name) == -1) { + int tmp = errno; + close(fd); + errno = tmp; + return -1; + } + return fd; + } if (errno != EEXIST) break; } @@ -464,15 +463,13 @@ static int shm_open_anon(int flags, mode_t mode) { int fd; if ((fd = shm_mkstemp(name)) == -1) return -1; - return ([](const char *name, int fd) { - if (shm_unlink(name) == -1) { - int tmp = errno; - close(fd); - errno = tmp; - return -1; - } - return fd; - })(name, fd); + if (shm_unlink(name) == -1) { + int tmp = errno; + close(fd); + errno = tmp; + return -1; + } + return fd; } #endif diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8159bea87e..03e86b0d99 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1199,8 +1199,8 @@ if (MINGW) endif() if (ENABLE_WEB_SERVICE) - target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE) - target_link_libraries(core PRIVATE web_service) + target_compile_definitions(core PUBLIC -DENABLE_WEB_SERVICE) + target_link_libraries(core PUBLIC web_service) endif() if (HAS_NCE) diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 7785c1d163..49179617a7 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -12,7 +12,7 @@ #ifdef _WIN32 #include #include -#elif YUZU_UNIX +#elif defined(__unix__) #include #include #include @@ -77,7 +77,7 @@ SOCKET GetInterruptSocket() { sockaddr TranslateFromSockAddrIn(SockAddrIn input) { sockaddr_in result; -#if YUZU_UNIX +#ifdef __unix__ result.sin_len = sizeof(result); #endif @@ -162,7 +162,7 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) { } } -#elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX +#elif defined(__unix__) // ^ _WIN32 v __unix__ using SOCKET = int; using WSAPOLLFD = pollfd; @@ -835,7 +835,7 @@ std::pair Socket::Send(std::span message, int flags) { ASSERT(flags == 0); int native_flags = 0; -#if YUZU_UNIX +#ifdef __unix__ native_flags |= MSG_NOSIGNAL; // do not send us SIGPIPE #endif const auto result = send(fd, reinterpret_cast(message.data()), diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h index b7b7d773a4..64f3f121df 100644 --- a/src/core/internal_network/network.h +++ b/src/core/internal_network/network.h @@ -13,7 +13,7 @@ #ifdef _WIN32 #include -#elif YUZU_UNIX +#else #include #endif @@ -104,7 +104,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 YUZU_UNIX +#elif defined(__unix__) constexpr IPv4Address TranslateIPv4(in_addr addr) { const u32 bytes = addr.s_addr; return IPv4Address{static_cast(bytes), static_cast(bytes >> 8), diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index eba1e28c5e..c263fb4ca8 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -15,7 +15,7 @@ #include "core/internal_network/socket_proxy.h" #include "network/network.h" -#if YUZU_UNIX +#ifdef __unix__ #include #endif diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 3a32dff75d..65ebb893ad 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -9,7 +9,11 @@ #include #if defined(_WIN32) -#elif !YUZU_UNIX +// windows +#elif defined(__unix__) +// unix +#else +// haiku #error "Platform not implemented" #endif @@ -24,7 +28,7 @@ struct ProxyPacket; class SocketBase { public: -#ifdef YUZU_UNIX +#ifdef __unix__ using SOCKET = int; static constexpr SOCKET INVALID_SOCKET = -1; static constexpr SOCKET SOCKET_ERROR = -1; diff --git a/src/network/announce_multiplayer_session.cpp b/src/network/announce_multiplayer_session.cpp index 9d86ea378c..d2a47de73d 100644 --- a/src/network/announce_multiplayer_session.cpp +++ b/src/network/announce_multiplayer_session.cpp @@ -13,9 +13,9 @@ #include "common/settings.h" #include "network/network.h" -//#ifdef ENABLE_WEB_SERVICE +#ifdef ENABLE_WEB_SERVICE #include "web_service/announce_room_json.h" -//#endif +#endif namespace Core { @@ -28,7 +28,7 @@ AnnounceMultiplayerSession::AnnounceMultiplayerSession() { Settings::values.eden_username.GetValue(), Settings::values.eden_token.GetValue()); #else - backend = std::make_unique(); + backend = std::make_unique(); #endif } @@ -155,11 +155,12 @@ bool AnnounceMultiplayerSession::IsRunning() const { void AnnounceMultiplayerSession::UpdateCredentials() { ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running"); - #ifdef ENABLE_WEB_SERVICE backend = std::make_unique(Settings::values.web_api_url.GetValue(), Settings::values.eden_username.GetValue(), Settings::values.eden_token.GetValue()); +#else + backend = std::make_unique(); #endif } diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 9be1b08055..3cb7529a64 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -24,6 +24,8 @@ using namespace Common::Literals; namespace OpenGL { namespace { + +// TODO: Needs to explicitly enable ARB_TESSELLATION_SHADER for GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS constexpr std::array LIMIT_UBOS = { GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, GL_MAX_GEOMETRY_UNIFORM_BLOCKS, @@ -62,7 +64,7 @@ bool HasExtension(std::span extensions, std::string_view } std::array BuildMaxUniformBuffers() noexcept { - std::array max; + std::array max{}; std::ranges::transform(LIMIT_UBOS, max.begin(), &GetInteger); return max; } @@ -108,7 +110,7 @@ bool IsASTCSupported() { static bool HasSlowSoftwareAstc(std::string_view vendor_name, std::string_view renderer) { // ifdef for Unix reduces string comparisons for non-Windows drivers, and Intel -#ifdef YUZU_UNIX +#ifdef __unix__ // Sorted vaguely by how likely a vendor is to appear if (vendor_name == "AMD") { // RadeonSI diff --git a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp index bdd8e47f61..5767d6b7de 100644 --- a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp +++ b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp @@ -60,6 +60,7 @@ size_t StagingBuffers::RequestBuffer(size_t requested_size) { storage_flags | GL_MAP_PERSISTENT_BIT); alloc.map = static_cast(glMapNamedBufferRange(alloc.buffer.handle, 0, next_pow2_size, map_flags | GL_MAP_PERSISTENT_BIT)); + DEBUG_ASSERT(alloc.map != nullptr); alloc.size = next_pow2_size; allocs.emplace_back(std::move(alloc)); return allocs.size() - 1; diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 473355e805..2e31f47cd5 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -497,6 +497,11 @@ if (YUZU_ROOM) target_link_libraries(yuzu PRIVATE yuzu-room) endif() +# Explicit linking required +if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") + target_link_libraries(yuzu PRIVATE X11) +endif() + # Extra deps add_subdirectory(externals) target_link_libraries(yuzu PRIVATE QuaZip::QuaZip) diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 54c931e56c..16846878f9 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -295,7 +295,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { api_restore_global_button = widget->restore_button; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(api_restore_global_button, &QAbstractButton::clicked, + api_restore_global_button->connect(api_restore_global_button, &QAbstractButton::clicked, [this](bool) { UpdateAPILayout(); }); // Detach API's restore button and place it where we want @@ -327,7 +327,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { restore_button->setEnabled(true); widget->layout()->addWidget(restore_button); - QObject::connect(restore_button, &QAbstractButton::clicked, + restore_button->connect(restore_button, &QAbstractButton::clicked, [restore_button, this](bool) { Settings::values.vsync_mode.SetGlobal(true); PopulateVSyncModeSelection(true); @@ -340,7 +340,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { UpdateVsyncSetting(); restore_button->setVisible(true); }; - QObject::connect(widget->combobox, QOverload::of(&QComboBox::activated), + widget->combobox->connect(widget->combobox, QOverload::of(&QComboBox::activated), [set_non_global]() { set_non_global(); }); vsync_restore_global_button = restore_button; } @@ -379,7 +379,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { Settings::values.bg_red.UsingGlobal(), ui->bg_widget); ui->bg_widget->layout()->addWidget(bg_restore_button); - QObject::connect(bg_restore_button, &QAbstractButton::clicked, + bg_restore_button->connect(bg_restore_button, &QAbstractButton::clicked, [bg_restore_button, this](bool) { const int r = Settings::values.bg_red.GetValue(true); const int g = Settings::values.bg_green.GetValue(true); @@ -390,7 +390,7 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) { bg_restore_button->setEnabled(false); }); - QObject::connect(ui->bg_button, &QAbstractButton::clicked, [bg_restore_button](bool) { + ui->bg_button->connect(ui->bg_button, &QAbstractButton::clicked, [bg_restore_button](bool) { bg_restore_button->setVisible(true); bg_restore_button->setEnabled(true); }); diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index b3d9d8006b..5c7eb59d7c 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -2429,7 +2429,7 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co 1.0 - std::sqrt((offset.x() * offset.x()) + (offset.y() * offset.y())) * 0.1f); const float rotation = - ((offset.x() == 0) ? atan(1) * 2 : atan(offset.y() / offset.x())) * (180 / (atan(1) * 4)); + ((offset.x() == 0.f) ? std::atan(1.f) * 2.f : std::atan(offset.y() / offset.x())) * (180.f / (std::atan(1.f) * 4.f)); p.save(); p.translate(offset_center); diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp index c27a4644e9..e23d86dc69 100644 --- a/src/yuzu/configuration/shared_widget.cpp +++ b/src/yuzu/configuration/shared_widget.cpp @@ -118,7 +118,7 @@ QWidget* Widget::CreateCheckBox(Settings::BasicSetting* bool_setting, const QStr }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(checkbox, &QCheckBox::clicked, [touch]() { touch(); }); + checkbox->connect(checkbox, &QCheckBox::clicked, [touch]() { touch(); }); } return checkbox; @@ -165,7 +165,7 @@ QWidget* Widget::CreateCombobox(std::function& serializer, }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(combobox, QOverload::of(&QComboBox::activated), + combobox->connect(combobox, QOverload::of(&QComboBox::activated), [touch]() { touch(); }); } @@ -223,9 +223,8 @@ QWidget* Widget::CreateRadioGroup(std::function& serializer, }; if (!Settings::IsConfiguringGlobal()) { - for (const auto& [id, button] : radio_buttons) { - QObject::connect(button, &QAbstractButton::clicked, [touch]() { touch(); }); - } + for (const auto& [id, button] : radio_buttons) + button->connect(button, &QAbstractButton::clicked, [touch]() { touch(); }); } return group; @@ -249,7 +248,7 @@ QWidget* Widget::CreateLineEdit(std::function& serializer, }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); + line_edit->connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); } return line_edit; @@ -266,7 +265,7 @@ static void CreateIntSlider(Settings::BasicSetting& setting, bool reversed, floa feedback->setText(use_format.arg(QVariant::fromValue(present).value())); }; - QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback); + slider->connect(slider, &QAbstractSlider::valueChanged, update_feedback); update_feedback(std::strtol(setting.ToString().c_str(), nullptr, 0)); slider->setMinimum(std::strtol(setting.MinVal().c_str(), nullptr, 0)); @@ -293,7 +292,7 @@ static void CreateFloatSlider(Settings::BasicSetting& setting, bool reversed, fl feedback->setText(use_format.arg(QVariant::fromValue(present).value())); }; - QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback); + slider->connect(slider, &QAbstractSlider::valueChanged, update_feedback); update_feedback(std::strtof(setting.ToString().c_str(), nullptr)); slider->setMinimum(min_val * use_multiplier); @@ -346,7 +345,7 @@ QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& gi slider->setInvertedAppearance(reversed); if (!Settings::IsConfiguringGlobal()) { - QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); }); + slider->connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); }); } return container; @@ -376,7 +375,7 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix, }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(spinbox, QOverload::of(&QSpinBox::valueChanged), [this, touch]() { + spinbox->connect(spinbox, QOverload::of(&QSpinBox::valueChanged), [this, touch]() { if (spinbox->value() != std::strtol(setting.ToStringGlobal().c_str(), nullptr, 0)) { touch(); } @@ -410,7 +409,7 @@ QWidget* Widget::CreateDoubleSpinBox(const QString& given_suffix, }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(double_spinbox, QOverload::of(&QDoubleSpinBox::valueChanged), + double_spinbox->connect(double_spinbox, QOverload::of(&QDoubleSpinBox::valueChanged), [this, touch]() { if (double_spinbox->value() != std::strtod(setting.ToStringGlobal().c_str(), nullptr)) { @@ -453,8 +452,7 @@ QWidget* Widget::CreateHexEdit(std::function& serializer, restore_func = [this, to_hex]() { line_edit->setText(to_hex(RelevantDefault(setting))); }; if (!Settings::IsConfiguringGlobal()) { - - QObject::connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); + line_edit->connect(line_edit, &QLineEdit::textChanged, [touch]() { touch(); }); } return line_edit; @@ -488,7 +486,7 @@ QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict, restore_func = [this, get_clear_val]() { date_time_edit->setDateTime(get_clear_val()); }; if (!Settings::IsConfiguringGlobal()) { - QObject::connect(date_time_edit, &QDateTimeEdit::editingFinished, + date_time_edit->connect(date_time_edit, &QDateTimeEdit::editingFinished, [this, get_clear_val, touch]() { if (date_time_edit->dateTime() != get_clear_val()) { touch(); @@ -665,7 +663,7 @@ void Widget::SetupComponent(const QString& label, std::function& load_fu } else { layout->addWidget(restore_button); - QObject::connect(restore_button, &QAbstractButton::clicked, + restore_button->connect(restore_button, &QAbstractButton::clicked, [this, restore_func, checkbox_restore_func](bool) { LOG_DEBUG(Frontend, "Restore global state for \"{}\"", setting.GetLabel()); diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp index 04f4ddb3a1..497fa0f115 100644 --- a/src/yuzu/discord_impl.cpp +++ b/src/yuzu/discord_impl.cpp @@ -100,7 +100,7 @@ void DiscordImpl::Update() { request.setTransferTimeout(3000); QNetworkReply* reply = manager.head(request); QEventLoop request_event_loop; - QObject::connect(reply, &QNetworkReply::finished, &request_event_loop, &QEventLoop::quit); + reply->connect(reply, &QNetworkReply::finished, &request_event_loop, &QEventLoop::quit); request_event_loop.exec(); UpdateGameStatus(reply->error()); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2ad8ed9720..4e0ff685bf 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -536,7 +536,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) } return QString{}; }); - QObject::connect(&update_watcher, &QFutureWatcher::finished, this, + update_watcher.connect(&update_watcher, &QFutureWatcher::finished, this, &GMainWindow::OnEmulatorUpdateAvailable); update_watcher.setFuture(update_future); } @@ -5786,7 +5786,7 @@ int main(int argc, char* argv[]) { // After settings have been loaded by GMainWindow, apply the filter main_window.show(); - QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window, + app.connect(&app, &QGuiApplication::applicationStateChanged, &main_window, &GMainWindow::OnAppFocusStateChanged); int result = app.exec(); diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index 6eefc94ed0..2e77c7cd06 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp @@ -7,7 +7,7 @@ #include #include #include -#elif defined(YUZU_UNIX) +#else #include #include #include @@ -56,7 +56,7 @@ bool CheckEnvVars(bool* is_child) { IS_CHILD_ENV_VAR, GetLastError()); return true; } -#elif defined(YUZU_UNIX) +#else const char* startup_check_var = getenv(STARTUP_CHECK_ENV_VAR); if (startup_check_var != nullptr && std::strncmp(startup_check_var, ENV_VAR_ENABLED_TEXT, 8) == 0) { @@ -110,7 +110,7 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka STARTUP_CHECK_ENV_VAR, GetLastError()); } -#elif defined(YUZU_UNIX) +#else const int env_var_set = setenv(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT, 1); if (env_var_set == -1) { const int err = errno; @@ -175,7 +175,7 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags) { return true; } -#elif defined(YUZU_UNIX) +#else pid_t SpawnChild(const char* arg0) { const pid_t pid = fork(); diff --git a/src/yuzu/startup_checks.h b/src/yuzu/startup_checks.h index 2f86fb843d..79bf8beba1 100644 --- a/src/yuzu/startup_checks.h +++ b/src/yuzu/startup_checks.h @@ -5,7 +5,7 @@ #ifdef _WIN32 #include -#elif defined(YUZU_UNIX) +#else #include #endif @@ -19,6 +19,6 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka #ifdef _WIN32 bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags); -#elif defined(YUZU_UNIX) +#else pid_t SpawnChild(const char* arg0); #endif From b906abf9fcfd87113b07d6cd2726808ff95eb6eb Mon Sep 17 00:00:00 2001 From: MaranBr Date: Fri, 15 Aug 2025 14:01:11 +0200 Subject: [PATCH 3/5] [kernel] Ensure all kernel objects exist before destroying them and avoid infinite loop between Open() and Close() functions (#261) This ensures that all kernel objects exist before destroying them and prevents an infinite loop between the Open() and Close() functions. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/261 Reviewed-by: Shinmegumi Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/core/hle/kernel/k_auto_object.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 8d4e0df44f..c61b10625a 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -1,5 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -153,12 +156,15 @@ public: // Atomically decrement the reference count, not allowing it to become negative. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { + if (cur_ref_count == 0) { + return; + } ASSERT(cur_ref_count > 0); } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, std::memory_order_acq_rel)); - // If ref count hits zero, destroy the object. - if (cur_ref_count - 1 == 0) { + // If ref count hits 1, destroy the object. + if (cur_ref_count == 1) { KernelCore& kernel = m_kernel; this->Destroy(); KAutoObject::UnregisterWithKernel(kernel, this); From 72fb15cacc3fe3c399bd21b002922625b8f286e5 Mon Sep 17 00:00:00 2001 From: SDK Chan Date: Fri, 15 Aug 2025 20:11:08 +0200 Subject: [PATCH 4/5] [shader_recompiler] ISBERD minor cleanups (#211) Clean up some ISBERD related implementations. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/211 Reviewed-by: Shinmegumi Co-authored-by: SDK Chan Co-committed-by: SDK Chan --- src/shader_recompiler/CMakeLists.txt | 4 + .../frontend/maxwell/translate/impl/impl.cpp | 39 +++++++ .../frontend/maxwell/translate/impl/impl.h | 33 ++++++ .../impl/internal_stage_buffer_entry_read.cpp | 104 ++++++------------ src/video_core/CMakeLists.txt | 3 + 5 files changed, 113 insertions(+), 70 deletions(-) diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 4954beda8c..5d896db93d 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -240,6 +243,7 @@ add_library(shader_recompiler STATIC runtime_info.h shader_info.h varying_state.h + ) target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools-opt SPIRV-Tools SPIRV-Tools-link) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index b0ebc75f7d..157e5dfaaf 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -268,4 +271,40 @@ void TranslatorVisitor::ResetOFlag() { SetOFlag(ir.Imm1(false)); } +IR::U32 TranslatorVisitor::apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value) { + if (shift_value != Isberd::Shift::Default) { + return ir.ShiftLeftLogical(result, ir.Imm32(1)); + } + return result; +} + +IR::U32 TranslatorVisitor::apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz) { + switch (sz) { + case Isberd::SZ::U8: + return ir.LoadGlobalU8(ir.UConvert(64, address)); + case Isberd::SZ::U16: + return ir.LoadGlobalU16(ir.UConvert(64, address)); + case Isberd::SZ::U32: + case Isberd::SZ::F32: + return ir.LoadGlobal32(ir.UConvert(64, address)); + default: + UNREACHABLE(); + } +} + +IR::U32 TranslatorVisitor::compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value) { + IR::U32 address{}; + if (src_reg_num == 0xFF) { + address = ir.Imm32(imm); + } else { + auto offset = ir.Imm32(imm); + address = ir.IAdd(X(src_reg), offset); + if (skew_value != 0) { + address = ir.IAdd(address, ir.LaneId()); + } + } + + return address; +}; + } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index adf7cad068..1b2547a1bd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -53,6 +56,30 @@ enum class FPCompareOp : u64 { T, }; +namespace Isberd { +enum class Mode : u64 { + Default, + Patch, + Prim, + Attr, +}; + +enum class Shift : u64 { + Default, + U16, + B32, +}; + +enum class SZ : u64 { + U8, + U16, + U32, + F32, +}; + +} // namespace Isberd + + class TranslatorVisitor { public: explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {} @@ -381,6 +408,12 @@ public: void ResetSFlag(); void ResetCFlag(); void ResetOFlag(); + +private: + // Helper functions for various translator visitors + IR::U32 apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value); + IR::U32 apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz_value); + IR::U32 compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value); }; } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index d71c65069b..2aaf85772d 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -9,21 +9,6 @@ #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" namespace Shader::Maxwell { -namespace { -enum class Mode : u64 { - Default, - Patch, - Prim, - Attr, -}; - -enum class Shift : u64 { - Default, - U16, - B32, -}; - -} // Anonymous namespace // Valid only for GS, TI, VS and trap void TranslatorVisitor::ISBERD(u64 insn) { @@ -35,70 +20,49 @@ void TranslatorVisitor::ISBERD(u64 insn) { BitField<24, 8, u32> imm; BitField<31, 1, u64> skew; BitField<32, 1, u64> o; - BitField<33, 2, Mode> mode; - BitField<47, 2, Shift> shift; + BitField<33, 2, Isberd::Mode> mode; + BitField<36, 4, Isberd::SZ> sz; + BitField<47, 2, Isberd::Shift> shift; } const isberd{insn}; - if (isberd.skew != 0) { - IR::U32 current_lane_id{ir.LaneId()}; - IR::U32 result{ir.IAdd(X(isberd.src_reg), current_lane_id)}; - X(isberd.dest_reg, result); - } + auto address = compute_ISBERD_address(isberd.src_reg, isberd.src_reg_num, isberd.imm, isberd.skew); if (isberd.o != 0) { - IR::U32 address{}; - IR::F32 result{}; - if (isberd.src_reg_num == 0xFF) { - address = ir.Imm32(isberd.imm); - result = ir.GetAttributeIndexed(address); - } else { - IR::U32 offset = ir.Imm32(isberd.imm); - address = ir.IAdd(X(isberd.src_reg), offset); - result = ir.GetAttributeIndexed(address); - } - X(isberd.dest_reg, ir.BitCast(result)); + auto result = apply_ISBERD_size_read(address, isberd.sz.Value()); + X(isberd.dest_reg, apply_ISBERD_shift(result, isberd.shift.Value())); + + return; } - if (isberd.mode != Mode::Default) { - IR::F32 result{}; - IR::U32 index{}; - if (isberd.src_reg_num == 0xFF) { - index = ir.Imm32(isberd.imm); - } else { - index = ir.IAdd(X(isberd.src_reg), ir.Imm32(isberd.imm)); + + if (isberd.mode != Isberd::Mode::Default) { + IR::F32 result_f32{}; + switch (isberd.mode.Value()) { + case Isberd::Mode::Patch: + result_f32 = ir.GetPatch(address.Patch()); + break; + case Isberd::Mode::Prim: + result_f32 = ir.GetAttribute(address.Attribute()); + break; + case Isberd::Mode::Attr: + result_f32 = ir.GetAttributeIndexed(address); + break; + default: + UNREACHABLE(); } - switch (static_cast(isberd.mode.Value())) { - case static_cast(Mode::Patch): - result = ir.GetPatch(index.Patch()); - break; - case static_cast(Mode::Prim): - result = ir.GetAttribute(index.Attribute()); - break; - case static_cast(Mode::Attr): - result = ir.GetAttributeIndexed(index); - break; - } - X(isberd.dest_reg, ir.BitCast(result)); + auto result_u32 = ir.BitCast(result_f32); + X(isberd.dest_reg, apply_ISBERD_shift(result_u32, isberd.shift.Value())); + return; } - if (isberd.shift != Shift::Default) { - IR::U32 result{}; - switch (static_cast(isberd.shift.Value())) { - case static_cast(Shift::U16): - result = ir.ShiftLeftLogical(result, static_cast(ir.Imm16(1))); - break; - case static_cast(Shift::B32): - result = ir.ShiftLeftLogical(result, ir.Imm32(1)); - break; - } + + if (isberd.skew != 0) { + auto result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); X(isberd.dest_reg, result); + + return; } - //LOG_DEBUG(Shader, "(STUBBED) called {}", insn); - if (isberd.src_reg_num == 0xFF) { - IR::U32 src_imm{ir.Imm32(static_cast(isberd.imm))}; - IR::U32 result{ir.IAdd(X(isberd.src_reg), src_imm)}; - X(isberd.dest_reg, result); - } else { - X(isberd.dest_reg, X(isberd.src_reg)); - } + + // Fallback if nothing else applies + X(isberd.dest_reg, X(isberd.src_reg)); } } // namespace Shader::Maxwell diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 83111c31b0..89fe7a35f9 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later From f35018782d3ac74b6c5601678aa66e6e2b8f08aa Mon Sep 17 00:00:00 2001 From: wildcard Date: Sat, 9 Aug 2025 22:33:08 +0200 Subject: [PATCH 5/5] [Vk] Improve Stencil Handling and Fix Read-After-Write Hazard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Improves stencil handling: - Adds surface type detection to distinguish between color, depth, stencil, and depth-stencil formats - Only enables stencil load/store operations for surfaces that actually contain stencil data - Avoids unnecessary stencil operations for non-stencil formats (DONT_CARE) 2. Fixes read-after-write (RAW) synchronization hazards: - Adds a subpass self-dependency (subpass 0 → subpass 0) - Synchronizes color/depth writes with subsequent shader reads - Uses VK_DEPENDENCY_BY_REGION_BIT for efficient synchronization - Covers all relevant stages: • src: Color output + Early/Late fragment tests • dst: Fragment shader • Access: Write → Read transitions here is what hazard looks like [1147.550616] Render.Vulkan video_core/vulkan_common/vulkan_debug_callback.cpp:DebugUtilCallback:55: Validation Error: [ SYNC-HAZARD-READ-AFTER-WRITE ] Object 0: handle = 0x7409630000000192, type = VK_OBJECT_TYPE_IMAGE_VIEW; | MessageID = 0xe4d96472 | vkCmdDrawIndexed: Hazard READ_AFTER_WRITE for VkImageView 0x7409630000000192[], in VkCommandBuffer 0xb400007cb003ea70[], and VkPipeline 0x44d3470000000213[], VkDescriptorSet 0x0[], type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: VK_IMAGE_LAYOUT_GENERAL, binding #2, index 0. Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_SAMPLED_READ, prior_usage: SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: SYNC_FRAGMENT_SHADER_COLOR_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_READ|SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ|SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE|SYNC_SUBPASS_SHADER_HUAWEI_INPUT_ATTACHMENT_READ, command: vkCmdPipelineBarrier, seq_no: 45, reset_no: 129). Signed-off-by: crueter --- .../renderer_vulkan/vk_render_pass_cache.cpp | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index 7746a88d34..80ff75e3b9 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,23 +17,55 @@ namespace Vulkan { namespace { using VideoCore::Surface::PixelFormat; +using VideoCore::Surface::SurfaceType; -VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, - VkSampleCountFlagBits samples) { - using MaxwellToVK::SurfaceFormat; - return { - .flags = {}, - .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, - .samples = samples, - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }; -} -} // Anonymous namespace + constexpr SurfaceType GetSurfaceType(PixelFormat format) { + switch (format) { + // Depth formats + case PixelFormat::D16_UNORM: + case PixelFormat::D32_FLOAT: + case PixelFormat::X8_D24_UNORM: + return SurfaceType::Depth; + + // Stencil formats + case PixelFormat::S8_UINT: + return SurfaceType::Stencil; + + // Depth+Stencil formats + case PixelFormat::D24_UNORM_S8_UINT: + case PixelFormat::S8_UINT_D24_UNORM: + case PixelFormat::D32_FLOAT_S8_UINT: + return SurfaceType::DepthStencil; + + // Everything else is a color texture + default: + return SurfaceType::ColorTexture; + } + } + + VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, + VkSampleCountFlagBits samples) { + using MaxwellToVK::SurfaceFormat; + + const SurfaceType surface_type = GetSurfaceType(format); + const bool has_stencil = surface_type == SurfaceType::DepthStencil || + surface_type == SurfaceType::Stencil; + + return { + .flags = {}, + .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, + .samples = samples, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = has_stencil ? VK_ATTACHMENT_LOAD_OP_LOAD + : VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE + : VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_GENERAL, + .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + }; + } + } // Anonymous namespace RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} @@ -78,6 +113,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .preserveAttachmentCount = 0, .pPreserveAttachments = nullptr, }; + const VkSubpassDependency dependency{ + .srcSubpass = 0, // Current subpass + .dstSubpass = 0, // Same subpass (self-dependency) + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT + }; pair->second = device->GetLogical().CreateRenderPass({ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .pNext = nullptr, @@ -86,8 +133,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .pAttachments = descriptions.empty() ? nullptr : descriptions.data(), .subpassCount = 1, .pSubpasses = &subpass, - .dependencyCount = 0, - .pDependencies = nullptr, + .dependencyCount = 1, + .pDependencies = &dependency, }); return *pair->second; }