diff --git a/CMakeLists.txt b/CMakeLists.txt index e48263063f..a9ff2e9458 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,65 +139,50 @@ endif() # Set bundled sdl2/qt as dependent options. # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion -CMAKE_DEPENDENT_OPTION(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) - -set(EXT_DEFAULT OFF) - -if (MSVC OR ANDROID) - set(EXT_DEFAULT ON) -endif() +cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) if (ENABLE_SDL2) # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system - CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) + cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") endif() +option(ENABLE_QT "Enable the Qt frontend" ON) +option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) +option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF) +cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) +option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) +option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) +set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") + +option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) + +set(EXT_DEFAULT OFF) +if (MSVC OR ANDROID) + set(EXT_DEFAULT ON) +endif() +option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched." ${EXT_DEFAULT}) + +option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) +cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" OFF "NOT WIN32 AND NOT ANDROID" OFF) + cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT WIN32 OR NOT ARCHITECTURE_arm64" OFF) mark_as_advanced(FORCE ENABLE_OPENGL) -option(ENABLE_QT "Enable the Qt frontend" ON) -option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) -option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF) - -CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) - -option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched." ${EXT_DEFAULT}) - option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF) -option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) -cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" OFF "NOT WIN32 AND NOT ANDROID" OFF) - -option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) - -option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) - -set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") - -option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) - -CMAKE_DEPENDENT_OPTION(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF "ENABLE_QT" OFF) +cmake_dependent_option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF "ENABLE_QT" OFF) option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") -option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ${EXT_DEFAULT}) - -# TODO(crueter): CI this? -option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) - - -CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) - -CMAKE_DEPENDENT_OPTION(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) - -CMAKE_DEPENDENT_OPTION(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) - -CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) - +option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) +if (YUZU_USE_PRECOMPILED_HEADERS) + message(STATUS "Using Precompiled Headers.") + set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) +endif() option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) if(YUZU_ENABLE_LTO) include(CheckIPOSupported) @@ -205,17 +190,42 @@ if(YUZU_ENABLE_LTO) if(NOT COMPILER_SUPPORTS_LTO) message(FATAL_ERROR "Your compiler does not support interprocedural optimization (IPO). Re-run CMake with -DYUZU_ENABLE_LTO=OFF.") endif() + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) endif() +option(USE_CCACHE "Use ccache for compilation" OFF) +set(CCACHE_PATH "ccache" CACHE STRING "Path to ccache binary") +if(USE_CCACHE) + find_program(CCACHE_BINARY ${CCACHE_PATH}) + if(CCACHE_BINARY) + message(STATUS "Found ccache at: ${CCACHE_BINARY}") + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_BINARY}) + if (YUZU_USE_PRECOMPILED_HEADERS) + message(FATAL_ERROR "Precompiled headers are incompatible with ccache. Re-run CMake with -DYUZU_USE_PRECOMPILED_HEADERS=OFF.") + endif() + else() + message(WARNING "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}") + endif() +endif() + +# TODO(crueter): CI this? +option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) + +cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) +cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) + +cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) + +cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) - -CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "LINUX" OFF) - -CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF) - set(YUZU_TZDB_PATH "" CACHE STRING "Path to a pre-downloaded timezone database") +cmake_dependent_option(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "LINUX" OFF) + +cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib" ON "APPLE" OFF) + option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF) set(DEFAULT_ENABLE_OPENSSL ON) @@ -228,15 +238,12 @@ if (ANDROID OR WIN32 OR APPLE OR PLATFORM_SUN) # your own copy of it. set(DEFAULT_ENABLE_OPENSSL OFF) endif() - if (ENABLE_WEB_SERVICE) set(DEFAULT_ENABLE_OPENSSL ON) endif() - option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) - if (ENABLE_OPENSSL) - CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) + cmake_dependent_option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) endif() if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) @@ -263,21 +270,6 @@ if (ANDROID) set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe endif() -if (YUZU_USE_PRECOMPILED_HEADERS) - if (MSVC AND CCACHE) - # buildcache does not properly cache PCH files, leading to compilation errors. - # See https://github.com/mbitsnbites/buildcache/discussions/230 - message(WARNING "buildcache does not properly support Precompiled Headers. Disabling PCH") - set(DYNARMIC_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE) - set(YUZU_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE) - endif() -endif() - -if (YUZU_USE_PRECOMPILED_HEADERS) - message(STATUS "Using Precompiled Headers.") - set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) -endif() - # Default to a Release build get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) @@ -327,6 +319,18 @@ if (YUZU_ROOM) add_compile_definitions(YUZU_ROOM) endif() +if (ANDROID OR PLATFORM_FREEBSD OR PLATFORM_OPENBSD OR PLATFORM_SUN OR APPLE) + if(CXX_APPLE OR CXX_CLANG) + # libc++ has stop_token and jthread as experimental + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-library") + else() + # Uses glibc, mostly? + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1") + endif() +endif() + # Build/optimization presets if (PLATFORM_LINUX OR CXX_CLANG) if (ARCHITECTURE_x86_64) diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 6c4afc03be..f6e3aaa4ad 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -10,6 +10,7 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi set(package_base_url "https://github.com/eden-emulator/") set(package_repo "no_platform") set(package_extension "no_platform") + set(CACHE_KEY "") # TODO(crueter): Need to convert ffmpeg to a CI. if (WIN32 OR FORCE_WIN_ARCHIVES) @@ -33,8 +34,9 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi else() message(FATAL_ERROR "No package available for this platform") endif() - set(package_url "${package_base_url}${package_repo}") - set(full_url ${package_url}${remote_path}${lib_name}${package_extension}) + string(CONCAT package_url "${package_base_url}" "${package_repo}") + string(CONCAT full_url "${package_url}" "${remote_path}" "${lib_name}" "${package_extension}") + message(STATUS "Resolved bundled URL: ${full_url}") # TODO(crueter): DELETE THIS ENTIRELY, GLORY BE TO THE CI! AddPackage( @@ -47,26 +49,12 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi # TODO(crueter): hash ) - set(${prefix_var} "${${cpm_key}_SOURCE_DIR}" PARENT_SCOPE) - message(STATUS "Using bundled binaries at ${${cpm_key}_SOURCE_DIR}") -endfunction() - -function(download_moltenvk_external platform version) - set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") - set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") - if (NOT EXISTS ${MOLTENVK_DIR}) - if (NOT EXISTS ${MOLTENVK_TAR}) - file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar - ${MOLTENVK_TAR} SHOW_PROGRESS) - endif() - - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") + if (DEFINED ${cpm_key}_SOURCE_DIR) + set(${prefix_var} "${${cpm_key}_SOURCE_DIR}" PARENT_SCOPE) + message(STATUS "Using bundled binaries at ${${cpm_key}_SOURCE_DIR}") + else() + message(FATAL_ERROR "AddPackage did not set ${cpm_key}_SOURCE_DIR") endif() - - # Add the MoltenVK library path to the prefix so find_library can locate it. - list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() # Determine installation parameters for OS, architecture, and compiler @@ -108,7 +96,7 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out set(host "linux") set(type "desktop") set(arch "linux_gcc_64") - set(arch_path "linux") + set(arch_path "gcc_64") endif() set(${host_out} "${host}" PARENT_SCOPE) @@ -143,56 +131,79 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini") if (tool) set(prefix "${base_path}/Tools") - set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target}) + list(APPEND install_args install-tool --outputdir "${base_path}" "${host}" desktop "${target}") else() set(prefix "${base_path}/${target}/${arch_path}") - set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt_base) + list(APPEND install_args install-qt --outputdir "${base_path}" "${host}" "${type}" "${target}" "${arch}" -m qt_base) if (YUZU_USE_QT_MULTIMEDIA) - set(install_args ${install_args} qtmultimedia) + list(APPEND install_args qtmultimedia) endif() if (YUZU_USE_QT_WEB_ENGINE) - set(install_args ${install_args} qtpositioning qtwebchannel qtwebengine) + list(APPEND install_args qtpositioning qtwebchannel qtwebengine) endif() - if (NOT ${YUZU_QT_MIRROR} STREQUAL "") + if (NOT "${YUZU_QT_MIRROR}" STREQUAL "") message(STATUS "Using Qt mirror ${YUZU_QT_MIRROR}") - set(install_args ${install_args} -b ${YUZU_QT_MIRROR}) + list(APPEND install_args -b "${YUZU_QT_MIRROR}") endif() endif() - message(STATUS "Install Args ${install_args}") + message(STATUS "Install Args: ${install_args}") + if (NOT EXISTS "${prefix}") message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}") set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0") if (WIN32) set(aqt_path "${base_path}/aqt.exe") if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD - ${AQT_PREBUILD_BASE_URL}/aqt.exe - ${aqt_path} SHOW_PROGRESS) + file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt.exe" "${aqt_path}" SHOW_PROGRESS) + endif() + execute_process(COMMAND "${aqt_path}" ${install_args} + WORKING_DIRECTORY "${base_path}" + RESULT_VARIABLE aqt_res + OUTPUT_VARIABLE aqt_out + ERROR_VARIABLE aqt_err) + if (NOT aqt_res EQUAL 0) + message(FATAL_ERROR "aqt.exe failed: ${aqt_err}") endif() - execute_process(COMMAND ${aqt_path} ${install_args} - WORKING_DIRECTORY ${base_path}) elseif (APPLE) set(aqt_path "${base_path}/aqt-macos") if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD - ${AQT_PREBUILD_BASE_URL}/aqt-macos - ${aqt_path} SHOW_PROGRESS) + file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt-macos" "${aqt_path}" SHOW_PROGRESS) + endif() + execute_process(COMMAND chmod +x "${aqt_path}") + execute_process(COMMAND "${aqt_path}" ${install_args} + WORKING_DIRECTORY "${base_path}" + RESULT_VARIABLE aqt_res + ERROR_VARIABLE aqt_err) + if (NOT aqt_res EQUAL 0) + message(FATAL_ERROR "aqt-macos failed: ${aqt_err}") endif() - execute_process(COMMAND chmod +x ${aqt_path}) - execute_process(COMMAND ${aqt_path} ${install_args} - WORKING_DIRECTORY ${base_path}) else() + find_program(PYTHON3_EXECUTABLE python3) + if (NOT PYTHON3_EXECUTABLE) + message(FATAL_ERROR "python3 is required to install Qt using aqt (pip mode).") + endif() set(aqt_install_path "${base_path}/aqt") file(MAKE_DIRECTORY "${aqt_install_path}") - execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall - WORKING_DIRECTORY ${base_path}) - execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args} - WORKING_DIRECTORY ${base_path}) + execute_process(COMMAND "${PYTHON3_EXECUTABLE}" -m pip install --target="${aqt_install_path}" aqtinstall + WORKING_DIRECTORY "${base_path}" + RESULT_VARIABLE pip_res + ERROR_VARIABLE pip_err) + if (NOT pip_res EQUAL 0) + message(FATAL_ERROR "pip install aqtinstall failed: ${pip_err}") + endif() + + execute_process(COMMAND "${CMAKE_COMMAND}" -E env PYTHONPATH="${aqt_install_path}" "${PYTHON3_EXECUTABLE}" -m aqt ${install_args} + WORKING_DIRECTORY "${base_path}" + RESULT_VARIABLE aqt_res + ERROR_VARIABLE aqt_err) + if (NOT aqt_res EQUAL 0) + message(FATAL_ERROR "aqt (python) failed: ${aqt_err}") + endif() endif() message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}") @@ -210,7 +221,7 @@ endfunction() function(download_qt target) determine_qt_parameters("${target}" host type arch arch_path host_type host_arch host_arch_path) - get_external_prefix(qt base_path) + set(base_path "${CMAKE_BINARY_DIR}/externals/qt") file(MAKE_DIRECTORY "${base_path}") download_qt_configuration(prefix "${target}" "${host}" "${type}" "${arch}" "${arch_path}" "${base_path}") @@ -227,26 +238,34 @@ function(download_qt target) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() -function(download_moltenvk) -set(MOLTENVK_PLATFORM "macOS") +function(download_moltenvk version platform) + if(NOT version) + message(FATAL_ERROR "download_moltenvk: version argument is required") + endif() + if(NOT platform) + message(FATAL_ERROR "download_moltenvk: platform argument is required") + endif() -set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") -set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") -if (NOT EXISTS ${MOLTENVK_DIR}) -if (NOT EXISTS ${MOLTENVK_TAR}) - file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.10-rc2/MoltenVK-all.tar - ${MOLTENVK_TAR} SHOW_PROGRESS) -endif() + set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") + set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") -execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") -endif() + if(NOT EXISTS "${MOLTENVK_DIR}") + if(NOT EXISTS "${MOLTENVK_TAR}") + file(DOWNLOAD "https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar" + "${MOLTENVK_TAR}" SHOW_PROGRESS) + endif() -# Add the MoltenVK library path to the prefix so find_library can locate it. -list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${MOLTENVK_PLATFORM}") -set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals" + RESULT_VARIABLE tar_res + ERROR_VARIABLE tar_err + ) + if(NOT tar_res EQUAL 0) + message(FATAL_ERROR "Extracting MoltenVK failed: ${tar_err}") + endif() + endif() + list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() -function(get_external_prefix lib_name prefix_var) - set(${prefix_var} "${CMAKE_BINARY_DIR}/externals/${lib_name}" PARENT_SCOPE) -endfunction() diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake index 2d7081b7db..1ae608c085 100644 --- a/CMakeModules/GenerateSCMRev.cmake +++ b/CMakeModules/GenerateSCMRev.cmake @@ -31,7 +31,11 @@ set(GIT_DESC ${BUILD_VERSION}) set(REPO_NAME "Eden") set(BUILD_ID ${GIT_REFSPEC}) set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") - set(CXX_COMPILER "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") +# Auto-updater metadata! Must somewhat mirror GitHub API endpoint +set(BUILD_AUTO_UPDATE_WEBSITE "https://github.com") +set(BUILD_AUTO_UPDATE_API "http://api.github.com") +set(BUILD_AUTO_UPDATE_REPO "eden-emulator/Releases") + configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY) diff --git a/docs/Deps.md b/docs/Deps.md index 0e7b7cff62..573d1fe14a 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -101,7 +101,7 @@ sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glsl Ubuntu, Debian, Mint Linux ```sh -sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev +sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2t64 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev vulkan-utility-libraries-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev ``` * Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required. diff --git a/docs/Options.md b/docs/Options.md index d19aab63f6..3dd84ea645 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -31,7 +31,7 @@ Notes: * Currently, build fails without this - `YUZU_USE_FASTER_LD` (ON) Check if a faster linker is available * Only available on UNIX -- `USE_SYSTEM_MOLTENVK` (OFF, macOS only) Use the system MoltenVK lib (instead of the bundled one) +- `YUZU_USE_BUNDLED_MOLTENVK` (ON, macOS only) Download bundled MoltenVK lib) - `YUZU_TZDB_PATH` (string) Path to a pre-downloaded timezone database (useful for nixOS) - `ENABLE_OPENSSL` (ON for Linux and *BSD) Enable OpenSSL backend for the ssl service * Always enabled if the web service is enabled diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index d3a05cf3e2..e8d8141711 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -59,7 +59,7 @@ android { defaultConfig { // TODO If this is ever modified, change application_id in strings.xml applicationId = "dev.eden.eden_emulator" - minSdk = 30 + minSdk = 28 targetSdk = 36 versionName = getGitVersion() diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt index 8a66ebf11f..2c35e7349a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt @@ -19,6 +19,7 @@ import org.yuzu.yuzu_emu.adapters.GameAdapter import androidx.core.view.doOnNextLayout import org.yuzu.yuzu_emu.YuzuApplication import androidx.preference.PreferenceManager +import androidx.core.view.WindowInsetsCompat /** * CarouselRecyclerView encapsulates all carousel logic for the games UI. @@ -205,8 +206,8 @@ class CarouselRecyclerView @JvmOverloads constructor( if (enabled) { useCustomDrawingOrder = true - val insets = rootWindowInsets - val bottomInset = insets?.getInsets(android.view.WindowInsets.Type.systemBars())?.bottom ?: 0 + val insets = rootWindowInsets?.let { WindowInsetsCompat.toWindowInsetsCompat(it, this) } + val bottomInset = insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: 0 val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1) val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn( 0f, diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp index 3dae6069f7..48fe1f8975 100644 --- a/src/audio_core/renderer/behavior/info_updater.cpp +++ b/src/audio_core/renderer/behavior/info_updater.cpp @@ -1,3 +1,6 @@ +// 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-2.0-or-later @@ -162,6 +165,12 @@ Result InfoUpdater::UpdateEffectsVersion1(EffectContext& effect_context, const b reinterpret_cast(output), effect_count}; for (u32 i = 0; i < effect_count; i++) { +#ifdef _WIN32 + // There's a bug in Windows where using this effect causes extreme noise. So let's skip it. + if (in_params[i].type == EffectInfoBase::Type::Reverb) { + continue; + } +#endif auto effect_info{&effect_context.GetInfo(i)}; if (effect_info->GetType() != in_params[i].type) { effect_info->ForceUnmapBuffers(pool_mapper); @@ -209,6 +218,12 @@ Result InfoUpdater::UpdateEffectsVersion2(EffectContext& effect_context, const b reinterpret_cast(output), effect_count}; for (u32 i = 0; i < effect_count; i++) { +#ifdef _WIN32 + // There's a bug in Windows where using this effect causes extreme noise. So let's skip it. + if (in_params[i].type == EffectInfoBase::Type::Reverb) { + continue; + } +#endif auto effect_info{&effect_context.GetInfo(i)}; if (effect_info->GetType() != in_params[i].type) { effect_info->ForceUnmapBuffers(pool_mapper); diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 4d7f0c1d5d..b75d743494 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -293,8 +293,7 @@ void SinkStream::WaitFreeSpace(std::stop_token stop_token) { release_cv.wait_for(lk, std::chrono::milliseconds(5), [this]() { return paused || queued_buffers < max_queue_size; }); if (queued_buffers > max_queue_size + 3) { - Common::CondvarWait(release_cv, lk, stop_token, - [this] { return paused || queued_buffers < max_queue_size; }); + release_cv.wait(lk, stop_token, [this] { return paused || queued_buffers < max_queue_size; }); } } diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h index b36fc1de96..80f32e2553 100644 --- a/src/common/bounded_threadsafe_queue.h +++ b/src/common/bounded_threadsafe_queue.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 @@ -123,7 +126,7 @@ private: } else if constexpr (Mode == PopMode::WaitWithStopToken) { // Wait until the queue is not empty. std::unique_lock lock{consumer_cv_mutex}; - Common::CondvarWait(consumer_cv, lock, stop_token, [this, read_index] { + consumer_cv.wait(lock, stop_token, [this, read_index] { return read_index != m_write_index.load(std::memory_order::acquire); }); if (stop_token.stop_requested()) { diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index b0b25eb432..722ba41949 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp @@ -3,6 +3,7 @@ #include +#include "common/assert.h" #include "common/fs/file.h" #include "common/fs/fs.h" #ifdef ANDROID diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 318f311891..a095e0c239 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -9,6 +9,7 @@ #include #include +#include "common/assert.h" #include "common/fs/fs.h" #ifdef ANDROID #include "common/fs/fs_android.h" diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 2e36d59569..3838c12903 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -56,6 +56,16 @@ #include "common/host_memory.h" #include "common/logging/log.h" +#if defined(__ANDROID__) && __ANDROID_API__ < 30 +#include +#ifndef MFD_CLOEXEC +#define MFD_CLOEXEC 0x0001U +#endif +static int memfd_create(const char* name, unsigned int flags) { + return syscall(__NR_memfd_create, name, flags); +} +#endif + namespace Common { constexpr size_t PageAlignment = 0x1000; diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index 12e59a8939..0d3c963d25 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,23 +10,13 @@ #pragma once -#include - -#ifdef __cpp_lib_jthread - #include #include -#include #include #include namespace Common { -template -void CondvarWait(Condvar& cv, std::unique_lock& lk, std::stop_token token, Pred&& pred) { - cv.wait(lk, token, std::forward(pred)); -} - template bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { std::condition_variable_any cv; @@ -35,341 +28,3 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace std { -namespace polyfill { - -using stop_state_callback = size_t; - -class stop_state { -public: - stop_state() = default; - ~stop_state() = default; - - bool request_stop() { - unique_lock lk{m_lock}; - - if (m_stop_requested) { - // Already set, nothing to do. - return false; - } - - // Mark stop requested. - m_stop_requested = true; - - while (!m_callbacks.empty()) { - // Get an iterator to the first element. - const auto it = m_callbacks.begin(); - - // Move the callback function out of the map. - function f; - swap(it->second, f); - - // Erase the now-empty map element. - m_callbacks.erase(it); - - // Run the callback. - if (f) { - f(); - } - } - - return true; - } - - bool stop_requested() const { - unique_lock lk{m_lock}; - return m_stop_requested; - } - - stop_state_callback insert_callback(function f) { - unique_lock lk{m_lock}; - - if (m_stop_requested) { - // Stop already requested. Don't insert anything, - // just run the callback synchronously. - if (f) { - f(); - } - return 0; - } - - // Insert the callback. - stop_state_callback ret = ++m_next_callback; - m_callbacks.emplace(ret, std::move(f)); - return ret; - } - - void remove_callback(stop_state_callback cb) { - unique_lock lk{m_lock}; - m_callbacks.erase(cb); - } - -private: - mutable recursive_mutex m_lock; - map> m_callbacks; - stop_state_callback m_next_callback{0}; - bool m_stop_requested{false}; -}; - -} // namespace polyfill - -class stop_token; -class stop_source; -struct nostopstate_t { - explicit nostopstate_t() = default; -}; -inline constexpr nostopstate_t nostopstate{}; - -template -class stop_callback; - -class stop_token { -public: - stop_token() noexcept = default; - - stop_token(const stop_token&) noexcept = default; - stop_token(stop_token&&) noexcept = default; - stop_token& operator=(const stop_token&) noexcept = default; - stop_token& operator=(stop_token&&) noexcept = default; - ~stop_token() = default; - - void swap(stop_token& other) noexcept { - m_stop_state.swap(other.m_stop_state); - } - - [[nodiscard]] bool stop_requested() const noexcept { - return m_stop_state && m_stop_state->stop_requested(); - } - [[nodiscard]] bool stop_possible() const noexcept { - return m_stop_state != nullptr; - } - -private: - friend class stop_source; - template - friend class stop_callback; - stop_token(shared_ptr stop_state) : m_stop_state(std::move(stop_state)) {} - -private: - shared_ptr m_stop_state; -}; - -class stop_source { -public: - stop_source() : m_stop_state(make_shared()) {} - explicit stop_source(nostopstate_t) noexcept {} - - stop_source(const stop_source&) noexcept = default; - stop_source(stop_source&&) noexcept = default; - stop_source& operator=(const stop_source&) noexcept = default; - stop_source& operator=(stop_source&&) noexcept = default; - ~stop_source() = default; - void swap(stop_source& other) noexcept { - m_stop_state.swap(other.m_stop_state); - } - - [[nodiscard]] stop_token get_token() const noexcept { - return stop_token(m_stop_state); - } - [[nodiscard]] bool stop_possible() const noexcept { - return m_stop_state != nullptr; - } - [[nodiscard]] bool stop_requested() const noexcept { - return m_stop_state && m_stop_state->stop_requested(); - } - bool request_stop() noexcept { - return m_stop_state && m_stop_state->request_stop(); - } - -private: - friend class jthread; - explicit stop_source(shared_ptr stop_state) - : m_stop_state(std::move(stop_state)) {} - -private: - shared_ptr m_stop_state; -}; - -template -class stop_callback { - static_assert(is_nothrow_destructible_v); - static_assert(is_invocable_v); - -public: - using callback_type = Callback; - - template - requires constructible_from - explicit stop_callback(const stop_token& st, - C&& cb) noexcept(is_nothrow_constructible_v) - : m_stop_state(st.m_stop_state) { - if (m_stop_state) { - m_callback = m_stop_state->insert_callback(std::move(cb)); - } - } - template - requires constructible_from - explicit stop_callback(stop_token&& st, - C&& cb) noexcept(is_nothrow_constructible_v) - : m_stop_state(std::move(st.m_stop_state)) { - if (m_stop_state) { - m_callback = m_stop_state->insert_callback(std::move(cb)); - } - } - ~stop_callback() { - if (m_stop_state && m_callback) { - m_stop_state->remove_callback(m_callback); - } - } - - stop_callback(const stop_callback&) = delete; - stop_callback(stop_callback&&) = delete; - stop_callback& operator=(const stop_callback&) = delete; - stop_callback& operator=(stop_callback&&) = delete; - -private: - shared_ptr m_stop_state; - polyfill::stop_state_callback m_callback; -}; - -template -stop_callback(stop_token, Callback) -> stop_callback; - -class jthread { -public: - using id = thread::id; - using native_handle_type = thread::native_handle_type; - - jthread() noexcept = default; - - template , jthread>>> - explicit jthread(F&& f, Args&&... args) - : m_stop_state(make_shared()), - m_thread(make_thread(std::forward(f), std::forward(args)...)) {} - - ~jthread() { - if (joinable()) { - request_stop(); - join(); - } - } - - jthread(const jthread&) = delete; - jthread(jthread&&) noexcept = default; - jthread& operator=(const jthread&) = delete; - - jthread& operator=(jthread&& other) noexcept { - m_thread.swap(other.m_thread); - m_stop_state.swap(other.m_stop_state); - return *this; - } - - void swap(jthread& other) noexcept { - m_thread.swap(other.m_thread); - m_stop_state.swap(other.m_stop_state); - } - [[nodiscard]] bool joinable() const noexcept { - return m_thread.joinable(); - } - void join() { - m_thread.join(); - } - void detach() { - m_thread.detach(); - m_stop_state.reset(); - } - - [[nodiscard]] id get_id() const noexcept { - return m_thread.get_id(); - } - [[nodiscard]] native_handle_type native_handle() { - return m_thread.native_handle(); - } - [[nodiscard]] stop_source get_stop_source() noexcept { - return stop_source(m_stop_state); - } - [[nodiscard]] stop_token get_stop_token() const noexcept { - return stop_source(m_stop_state).get_token(); - } - bool request_stop() noexcept { - return get_stop_source().request_stop(); - } - [[nodiscard]] static unsigned int hardware_concurrency() noexcept { - return thread::hardware_concurrency(); - } - -private: - template - thread make_thread(F&& f, Args&&... args) { - if constexpr (is_invocable_v, stop_token, decay_t...>) { - return thread(std::forward(f), get_stop_token(), std::forward(args)...); - } else { - return thread(std::forward(f), std::forward(args)...); - } - } - - shared_ptr m_stop_state; - thread m_thread; -}; - -} // namespace std - -namespace Common { - -template -void CondvarWait(Condvar& cv, std::unique_lock& lk, std::stop_token token, Pred pred) { - if (token.stop_requested()) { - return; - } - - std::stop_callback callback(token, [&] { - { std::scoped_lock lk2{*lk.mutex()}; } - cv.notify_all(); - }); - - cv.wait(lk, [&] { return pred() || token.stop_requested(); }); -} - -template -bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { - if (token.stop_requested()) { - return false; - } - - bool stop_requested = false; - std::condition_variable cv; - std::mutex m; - - std::stop_callback cb(token, [&] { - // Wake up the waiting thread. - { - std::scoped_lock lk{m}; - stop_requested = true; - } - cv.notify_one(); - }); - - // Perform the timed wait. - std::unique_lock lk{m}; - return !cv.wait_for(lk, rel_time, [&] { return stop_requested; }); -} - -} // namespace Common - -#endif diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 1630ceae83..60c9c119f9 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -18,6 +18,9 @@ #define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@" #define IS_DEV_BUILD @IS_DEV_BUILD@ #define COMPILER_ID "@CXX_COMPILER@" +#define BUILD_AUTO_UPDATE_WEBSITE "@BUILD_AUTO_UPDATE_WEBSITE@" +#define BUILD_AUTO_UPDATE_API "@BUILD_AUTO_UPDATE_API@" +#define BUILD_AUTO_UPDATE_REPO "@BUILD_AUTO_UPDATE_REPO@" namespace Common { @@ -34,4 +37,8 @@ constexpr const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; constexpr const char g_compiler_id[] = COMPILER_ID; constexpr const bool g_is_dev_build = IS_DEV_BUILD; +constexpr const char g_build_auto_update_website[] = BUILD_AUTO_UPDATE_WEBSITE; +constexpr const char g_build_auto_update_api[] = BUILD_AUTO_UPDATE_API; +constexpr const char g_build_auto_update_repo[] = BUILD_AUTO_UPDATE_REPO; + } // namespace Common diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index 8f48241557..b89de95a3d 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -21,5 +21,8 @@ extern const char g_title_bar_format_running[]; extern const char g_shader_cache_version[]; extern const char g_compiler_id[]; extern const bool g_is_dev_build; +extern const char g_build_auto_update_website[]; +extern const char g_build_auto_update_api[]; +extern const char g_build_auto_update_repo[]; } // namespace Common diff --git a/src/common/thread.h b/src/common/thread.h index c6976fb6cd..5ab495baaa 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -80,7 +83,7 @@ public: condvar.notify_all(); return true; } else { - CondvarWait(condvar, lk, token, + condvar.wait(lk, token, [this, current_generation] { return current_generation != generation; }); return !token.stop_requested(); } diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h index 260ad44e45..6ec9d6a2bd 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.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 @@ -47,8 +50,8 @@ public: if (requests.empty()) { wait_condition.notify_all(); } - Common::CondvarWait(condition, lock, stop_token, - [this] { return !requests.empty(); }); + condition.wait(lock, stop_token, + [this] { return !requests.empty(); }); if (stop_token.stop_requested()) { break; } diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 2ef1da0644..f9fc0ca171 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2010 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -99,7 +102,11 @@ public: T PopWait(std::stop_token stop_token) { if (Empty()) { std::unique_lock lock{cv_mutex}; - Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); }); + if constexpr (with_stop_token) { + cv.wait(lock, stop_token, [this] { return !Empty(); }); + } else { + cv.wait(lock, [this] { return !Empty(); }); + } } if (stop_token.stop_requested()) { return T{}; diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index b5e1e70b4c..6d325b4aad 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -991,6 +991,7 @@ IR::AbstractSyntaxList BuildASL(ObjectPool& inst_pool, ObjectPool 0; }); + command_cv.wait(l, stop_token, + [this]() { return command_lists.size() > 0; }); if (stop_token.stop_requested()) { return; } diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 9392534e7d..8739905d99 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -116,7 +116,7 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { state.queue.EmplaceWait(std::move(command_data), fence, block); if (block) { - Common::CondvarWait(state.cv, lk, thread.get_stop_token(), [this, fence] { + state.cv.wait(lk, thread.get_stop_token(), [this, fence] { return fence <= state.signaled_fence.load(std::memory_order_relaxed); }); } diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 6761127582..e65755de64 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp @@ -208,7 +208,7 @@ void MasterSemaphore::WaitThread(std::stop_token token) { vk::Fence fence; { std::unique_lock lock{wait_mutex}; - Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); }); + wait_cv.wait(lock, token, [this] { return !wait_queue.empty(); }); if (token.stop_requested()) { return; } diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 23279e49b9..0b29ad1389 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -279,7 +279,7 @@ void PresentManager::PresentThread(std::stop_token token) { std::unique_lock lock{queue_mutex}; // Wait for presentation frames - Common::CondvarWait(frame_cv, lock, token, [this] { return !present_queue.empty(); }); + frame_cv.wait(lock, token, [this] { return !present_queue.empty(); }); if (token.stop_requested()) { return; } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 530d161dfe..d109d22cab 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -166,7 +166,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) { std::unique_lock lk{queue_mutex}; // Wait for work. - Common::CondvarWait(event_cv, lk, stop_token, [&] { return TryPopQueue(work); }); + event_cv.wait(lk, stop_token, [&] { return TryPopQueue(work); }); // If we've been asked to stop, we're done. if (stop_token.stop_requested()) { diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index 04a51f2d1e..54183be12c 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp @@ -1,3 +1,6 @@ +// 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-2.0-or-later @@ -224,7 +227,7 @@ void TurboMode::Run(std::stop_token stop_token) { #endif // Wait for the next graphics queue submission if necessary. std::unique_lock lk{m_submission_lock}; - Common::CondvarWait(m_submission_cv, lk, stop_token, [this] { + m_submission_cv.wait(lk, stop_token, [this] { return (std::chrono::steady_clock::now() - m_submission_time) <= std::chrono::milliseconds{100}; }); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index b16c1d99ce..00e03bd935 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -366,10 +366,10 @@ if (APPLE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE TRUE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) - if (NOT USE_SYSTEM_MOLTENVK) + if (YUZU_USE_BUNDLED_MOLTENVK) set(MOLTENVK_PLATFORM "macOS") set(MOLTENVK_VERSION "v1.3.0") - download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) + download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) endif() find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index b7c0cd58d5..9f7597f471 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp @@ -14,11 +14,12 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) , ui{std::make_unique()} { - static const std::string description = std::string{Common::g_build_version}; static const std::string build_id = std::string{Common::g_build_id}; - static const std::string compiler = std::string{Common::g_compiler_id}; - - static const std::string yuzu_build = fmt::format("Eden | {} | {}", description, compiler); + static const std::string yuzu_build = fmt::format("{} | {} | {}", + std::string{Common::g_build_name}, + std::string{Common::g_build_version}, + std::string{Common::g_compiler_id} + ); const auto override_build = fmt::format(fmt::runtime( std::string(Common::g_title_bar_format_idle)), diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 7b5f2a314f..cdc4e4024a 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -108,13 +108,13 @@ void EmuThread::run() { m_system.Run(); m_stopped.Reset(); - Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; }); + m_should_run_cv.wait(lk, stop_token, [&] { return !m_should_run; }); } else { m_system.Pause(); m_stopped.Set(); EmulationPaused(lk); - Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; }); + m_should_run_cv.wait(lk, stop_token, [&] { return m_should_run; }); EmulationResumed(lk); } } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d2c12c9d40..fc7a953d77 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4192,23 +4192,25 @@ void GMainWindow::OnEmulatorUpdateAvailable() { update_prompt.addButton(QMessageBox::Yes); update_prompt.addButton(QMessageBox::Ignore); update_prompt.setText( - tr("Update %1 for Eden is available.\nWould you like to download it?").arg(version_string)); + tr("Download the %1 update?").arg(version_string)); update_prompt.exec(); if (update_prompt.button(QMessageBox::Yes) == update_prompt.clickedButton()) { - QDesktopServices::openUrl( - QUrl(QString::fromStdString("https://github.com/eden-emulator/Releases/releases/tag/") + - version_string)); + auto const full_url = fmt::format("{}/{}/releases/tag/", + std::string{Common::g_build_auto_update_website}, + std::string{Common::g_build_auto_update_repo} + ); + QDesktopServices::openUrl(QUrl(QString::fromStdString(full_url) + version_string)); } } #endif -void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, - std::string_view gpu_vendor) { - static const std::string description = std::string{Common::g_build_version}; +void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, std::string_view gpu_vendor) { static const std::string build_id = std::string{Common::g_build_id}; - static const std::string compiler = std::string{Common::g_compiler_id}; - - static const std::string yuzu_title = fmt::format("Eden | {} | {}", description, compiler); + static const std::string yuzu_title = fmt::format("{} | {} | {}", + std::string{Common::g_build_name}, + std::string{Common::g_build_version}, + std::string{Common::g_compiler_id} + ); const auto override_title = fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id); diff --git a/src/yuzu/update_checker.cpp b/src/yuzu/update_checker.cpp index 8291987d73..e54eb8d7f8 100644 --- a/src/yuzu/update_checker.cpp +++ b/src/yuzu/update_checker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -12,6 +15,7 @@ #include #include #include +#include "common/scm_rev.h" std::optional UpdateChecker::GetResponse(std::string url, std::string path) { @@ -54,8 +58,8 @@ std::optional UpdateChecker::GetResponse(std::string url, std::stri std::optional UpdateChecker::GetLatestRelease(bool include_prereleases) { - constexpr auto update_check_url = "http://api.github.com"; - std::string update_check_path = "/repos/eden-emulator/Releases"; + const auto update_check_url = std::string{Common::g_build_auto_update_api}; + std::string update_check_path = fmt::format("/repos/{}", std::string{Common::g_build_auto_update_repo}); try { if (include_prereleases) { // This can return either a prerelease or a stable release, // whichever is more recent. diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 9ec6b1d594..4b56f3794b 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -229,7 +229,7 @@ void EmuWindow_SDL2::WaitEvent() { const u32 current_time = SDL_GetTicks(); if (current_time > last_time + 2000) { const auto results = system.GetAndResetPerfStats(); - const auto title = fmt::format("Eden {} | {}-{} | FPS: {:.0f} ({:.0f}%)", + const auto title = fmt::format("{} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc, diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 4b012fe134..32f365e0d0 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -90,7 +93,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste } SDL_GL_SetSwapInterval(0); - std::string window_title = fmt::format("Eden {} | {}-{}", Common::g_build_fullname, + std::string window_title = fmt::format("{} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); render_window = SDL_CreateWindow(window_title.c_str(), @@ -138,7 +141,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste OnResize(); OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); SDL_PumpEvents(); - LOG_INFO(Frontend, "Eden Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, + LOG_INFO(Frontend, "Build string: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); Settings::LogSettings(); }