diff options
-rwxr-xr-x | .ci/scripts/linux/docker.sh | 6 | ||||
-rw-r--r-- | src/audio_core/audio_core.cpp | 2 | ||||
-rw-r--r-- | src/audio_core/audio_manager.cpp | 17 | ||||
-rw-r--r-- | src/audio_core/audio_manager.h | 19 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/audio_renderer.cpp | 2 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/audio_renderer.h | 2 | ||||
-rw-r--r-- | src/common/settings.h | 1 | ||||
-rw-r--r-- | src/core/internal_network/network.cpp | 12 | ||||
-rw-r--r-- | src/core/internal_network/sockets.h | 11 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_debug.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/input_profiles.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 3 | ||||
-rw-r--r-- | src/yuzu/startup_checks.cpp | 91 | ||||
-rw-r--r-- | src/yuzu/startup_checks.h | 2 |
16 files changed, 102 insertions, 82 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index b9862d1c2..e85dba029 100755 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh @@ -35,11 +35,11 @@ rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester # Download tools needed to build an AppImage wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage -wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64 +wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so # Set executable bit chmod 755 \ - AppRun-patched-x86_64 \ + AppRun.sh \ exec-x86_64.so \ linuxdeploy-x86_64.AppImage \ linuxdeploy-plugin-qt-x86_64.AppImage @@ -60,6 +60,6 @@ find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print # Workaround for building yuzu with GCC 10 but also trying to distribute it to Ubuntu 18.04 et al. # See https://github.com/darealshinji/AppImageKit-checkrt cp exec-x86_64.so AppDir/usr/optional/exec.so -cp AppRun-patched-x86_64 AppDir/AppRun +cp AppRun.sh AppDir/AppRun cp --dereference /usr/lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6 cp --dereference /lib/x86_64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1 diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index c845330cd..07a679c32 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -8,7 +8,7 @@ namespace AudioCore { -AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>(system)} { +AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>()} { CreateSinks(); // Must be created after the sinks adsp = std::make_unique<AudioRenderer::ADSP::ADSP>(system, *output_sink); diff --git a/src/audio_core/audio_manager.cpp b/src/audio_core/audio_manager.cpp index 2f1bba9c3..2acde668e 100644 --- a/src/audio_core/audio_manager.cpp +++ b/src/audio_core/audio_manager.cpp @@ -1,14 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "audio_core/audio_in_manager.h" #include "audio_core/audio_manager.h" -#include "audio_core/audio_out_manager.h" #include "core/core.h" +#include "core/hle/service/audio/errors.h" namespace AudioCore { -AudioManager::AudioManager(Core::System& system_) : system{system_} { +AudioManager::AudioManager() { thread = std::jthread([this]() { ThreadFunc(); }); } @@ -27,7 +26,7 @@ Result AudioManager::SetOutManager(BufferEventFunc buffer_func) { const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; if (buffer_events[index] == nullptr) { - buffer_events[index] = buffer_func; + buffer_events[index] = std::move(buffer_func); needs_update = true; events.SetAudioEvent(Event::Type::AudioOutManager, true); } @@ -43,7 +42,7 @@ Result AudioManager::SetInManager(BufferEventFunc buffer_func) { const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; if (buffer_events[index] == nullptr) { - buffer_events[index] = buffer_func; + buffer_events[index] = std::move(buffer_func); needs_update = true; events.SetAudioEvent(Event::Type::AudioInManager, true); } @@ -60,19 +59,21 @@ void AudioManager::ThreadFunc() { running = true; while (running) { - auto timed_out{events.Wait(l, std::chrono::seconds(2))}; + const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; if (events.CheckAudioEventSet(Event::Type::Max)) { break; } for (size_t i = 0; i < buffer_events.size(); i++) { - if (events.CheckAudioEventSet(Event::Type(i)) || timed_out) { + const auto event_type = static_cast<Event::Type>(i); + + if (events.CheckAudioEventSet(event_type) || timed_out) { if (buffer_events[i]) { buffer_events[i](); } } - events.SetAudioEvent(Event::Type(i), false); + events.SetAudioEvent(event_type, false); } } } diff --git a/src/audio_core/audio_manager.h b/src/audio_core/audio_manager.h index 8cbd95e22..abf077de4 100644 --- a/src/audio_core/audio_manager.h +++ b/src/audio_core/audio_manager.h @@ -10,22 +10,11 @@ #include <thread> #include "audio_core/audio_event.h" -#include "core/hle/service/audio/errors.h" -namespace Core { -class System; -} +union Result; namespace AudioCore { -namespace AudioOut { -class Manager; -} - -namespace AudioIn { -class Manager; -} - /** * The AudioManager's main purpose is to wait for buffer events for the audio in and out managers, * and call an associated callback to release buffers. @@ -43,7 +32,7 @@ class AudioManager { using BufferEventFunc = std::function<void()>; public: - explicit AudioManager(Core::System& system); + explicit AudioManager(); /** * Shutdown the audio manager. @@ -80,10 +69,6 @@ private: */ void ThreadFunc(); - /// Core system - Core::System& system; - /// Have sessions started palying? - bool sessions_started{}; /// Is the main thread running? std::atomic<bool> running{}; /// Unused diff --git a/src/audio_core/renderer/adsp/audio_renderer.cpp b/src/audio_core/renderer/adsp/audio_renderer.cpp index bafe4822a..ab2257bd8 100644 --- a/src/audio_core/renderer/adsp/audio_renderer.cpp +++ b/src/audio_core/renderer/adsp/audio_renderer.cpp @@ -47,7 +47,7 @@ RenderMessage AudioRenderer_Mailbox::ADSPWaitMessage() { return msg; } -CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const s32 session_id) { +CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const u32 session_id) { return command_buffers[session_id]; } diff --git a/src/audio_core/renderer/adsp/audio_renderer.h b/src/audio_core/renderer/adsp/audio_renderer.h index 02e923c84..151f38c1b 100644 --- a/src/audio_core/renderer/adsp/audio_renderer.h +++ b/src/audio_core/renderer/adsp/audio_renderer.h @@ -83,7 +83,7 @@ public: * @param session_id - The session id to get (0 or 1). * @return The command buffer. */ - CommandBuffer& GetCommandBuffer(s32 session_id); + CommandBuffer& GetCommandBuffer(u32 session_id); /** * Set the command buffer with the given session id (0 or 1). diff --git a/src/common/settings.h b/src/common/settings.h index 851812f28..d2452c93b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -531,6 +531,7 @@ struct Values { Setting<bool> use_auto_stub{false, "use_auto_stub"}; Setting<bool> enable_all_controllers{false, "enable_all_controllers"}; Setting<bool> create_crash_dumps{false, "create_crash_dumps"}; + Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"}; // Miscellaneous Setting<std::string> log_filter{"*:Info", "log_filter"}; diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index cdf38a2a4..447fbffaa 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -364,7 +364,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { std::vector<WSAPOLLFD> host_pollfds(pollfds.size()); std::transform(pollfds.begin(), pollfds.end(), host_pollfds.begin(), [](PollFD fd) { WSAPOLLFD result; - result.fd = fd.socket->fd; + result.fd = fd.socket->GetFD(); result.events = TranslatePollEvents(fd.events); result.revents = 0; return result; @@ -430,12 +430,12 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { return {AcceptResult{}, GetAndLogLastError()}; } - AcceptResult result; - result.socket = std::make_unique<Socket>(); - result.socket->fd = new_socket; - ASSERT(addrlen == sizeof(sockaddr_in)); - result.sockaddr_in = TranslateToSockAddrIn(addr); + + AcceptResult result{ + .socket = std::make_unique<Socket>(new_socket), + .sockaddr_in = TranslateToSockAddrIn(addr), + }; return {std::move(result), Errno::SUCCESS}; } diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index a70429b19..2e328c645 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -32,6 +32,10 @@ public: std::unique_ptr<SocketBase> socket; SockAddrIn sockaddr_in; }; + + SocketBase() = default; + explicit SocketBase(SOCKET fd_) : fd{fd_} {} + virtual ~SocketBase() = default; virtual SocketBase& operator=(const SocketBase&) = delete; @@ -89,12 +93,19 @@ public: virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; + [[nodiscard]] SOCKET GetFD() const { + return fd; + } + +protected: SOCKET fd = INVALID_SOCKET; }; class Socket : public SocketBase { public: Socket() = default; + explicit Socket(SOCKET fd_) : SocketBase{fd_} {} + ~Socket() override; Socket(const Socket&) = delete; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index a4ed68422..195074bf2 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -546,6 +546,7 @@ void Config::ReadDebuggingValues() { ReadBasicSetting(Settings::values.use_auto_stub); ReadBasicSetting(Settings::values.enable_all_controllers); ReadBasicSetting(Settings::values.create_crash_dumps); + ReadBasicSetting(Settings::values.perform_vulkan_check); qt_config->endGroup(); } @@ -1162,6 +1163,7 @@ void Config::SaveDebuggingValues() { WriteBasicSetting(Settings::values.disable_macro_jit); WriteBasicSetting(Settings::values.enable_all_controllers); WriteBasicSetting(Settings::values.create_crash_dumps); + WriteBasicSetting(Settings::values.perform_vulkan_check); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 622808e94..dacc75a20 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -77,6 +77,7 @@ void ConfigureDebug::SetConfiguration() { ui->disable_loop_safety_checks->setChecked( Settings::values.disable_shader_loop_safety_checks.GetValue()); ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); + ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue()); #ifdef YUZU_USE_QT_WEB_ENGINE ui->disable_web_applet->setChecked(UISettings::values.disable_web_applet.GetValue()); @@ -117,6 +118,7 @@ void ConfigureDebug::ApplyConfiguration() { ui->disable_loop_safety_checks->isChecked(); Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); Settings::values.extended_logging = ui->extended_logging->isChecked(); + Settings::values.perform_vulkan_check = ui->perform_vulkan_check->isChecked(); UISettings::values.disable_web_applet = ui->disable_web_applet->isChecked(); Debugger::ToggleConsole(); Common::Log::Filter filter; diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 314d47af5..102c8c66c 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -313,6 +313,16 @@ </property> </widget> </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="perform_vulkan_check"> + <property name="toolTip"> + <string>Enables yuzu to check for a working Vulkan environment when the program starts up. Disable this if this is causing issues with external programs seeing yuzu.</string> + </property> + <property name="text"> + <string>Perform Startup Vulkan Check</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp index 807afbeb2..9bb69cab1 100644 --- a/src/yuzu/configuration/input_profiles.cpp +++ b/src/yuzu/configuration/input_profiles.cpp @@ -67,6 +67,8 @@ std::vector<std::string> InputProfiles::GetInputProfileNames() { profile_names.push_back(profile_name); } + std::stable_sort(profile_names.begin(), profile_names.end()); + return profile_names; } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3c1bd19db..23245a976 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4086,7 +4086,8 @@ int main(int argc, char* argv[]) { } #endif - if (StartupChecks(argv[0], &has_broken_vulkan)) { + if (StartupChecks(argv[0], &has_broken_vulkan, + Settings::values.perform_vulkan_check.GetValue())) { return 0; } diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index 29b87da05..fc2693f9d 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp @@ -57,7 +57,7 @@ bool CheckEnvVars(bool* is_child) { return false; } -bool StartupChecks(const char* arg0, bool* has_broken_vulkan) { +bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulkan_check) { #ifdef _WIN32 // Set the startup variable for child processes const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT); @@ -67,29 +67,32 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan) { return false; } - PROCESS_INFORMATION process_info; - std::memset(&process_info, '\0', sizeof(process_info)); - - if (!SpawnChild(arg0, &process_info, 0)) { - return false; - } - - // Wait until the processs exits and get exit code from it - WaitForSingleObject(process_info.hProcess, INFINITE); - DWORD exit_code = STILL_ACTIVE; - const int err = GetExitCodeProcess(process_info.hProcess, &exit_code); - if (err == 0) { - std::fprintf(stderr, "GetExitCodeProcess failed with error %d\n", GetLastError()); - } - - // Vulkan is broken if the child crashed (return value is not zero) - *has_broken_vulkan = (exit_code != 0); - - if (CloseHandle(process_info.hProcess) == 0) { - std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); - } - if (CloseHandle(process_info.hThread) == 0) { - std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); + if (perform_vulkan_check) { + // Spawn child process that performs Vulkan check + PROCESS_INFORMATION process_info; + std::memset(&process_info, '\0', sizeof(process_info)); + + if (!SpawnChild(arg0, &process_info, 0)) { + return false; + } + + // Wait until the processs exits and get exit code from it + WaitForSingleObject(process_info.hProcess, INFINITE); + DWORD exit_code = STILL_ACTIVE; + const int err = GetExitCodeProcess(process_info.hProcess, &exit_code); + if (err == 0) { + std::fprintf(stderr, "GetExitCodeProcess failed with error %d\n", GetLastError()); + } + + // Vulkan is broken if the child crashed (return value is not zero) + *has_broken_vulkan = (exit_code != 0); + + if (CloseHandle(process_info.hProcess) == 0) { + std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); + } + if (CloseHandle(process_info.hThread) == 0) { + std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); + } } if (!SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, nullptr)) { @@ -98,26 +101,28 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan) { } #elif defined(YUZU_UNIX) - const pid_t pid = fork(); - if (pid == 0) { - CheckVulkan(); - return true; - } else if (pid == -1) { - const int err = errno; - std::fprintf(stderr, "fork failed with error %d\n", err); - return false; - } - - // Get exit code from child process - int status; - const int r_val = wait(&status); - if (r_val == -1) { - const int err = errno; - std::fprintf(stderr, "wait failed with error %d\n", err); - return false; + if (perform_vulkan_check) { + const pid_t pid = fork(); + if (pid == 0) { + CheckVulkan(); + return true; + } else if (pid == -1) { + const int err = errno; + std::fprintf(stderr, "fork failed with error %d\n", err); + return false; + } + + // Get exit code from child process + int status; + const int r_val = wait(&status); + if (r_val == -1) { + const int err = errno; + std::fprintf(stderr, "wait failed with error %d\n", err); + return false; + } + // Vulkan is broken if the child crashed (return value is not zero) + *has_broken_vulkan = (status != 0); } - // Vulkan is broken if the child crashed (return value is not zero) - *has_broken_vulkan = (status != 0); #endif return false; } diff --git a/src/yuzu/startup_checks.h b/src/yuzu/startup_checks.h index f2fc2d9d4..d8e563be6 100644 --- a/src/yuzu/startup_checks.h +++ b/src/yuzu/startup_checks.h @@ -13,7 +13,7 @@ constexpr char ENV_VAR_ENABLED_TEXT[] = "ON"; void CheckVulkan(); bool CheckEnvVars(bool* is_child); -bool StartupChecks(const char* arg0, bool* has_broken_vulkan); +bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulkan_check); #ifdef _WIN32 bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags); |