build(windows): add arm64 support (#3905)

Signed-off-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
Signed-off-by: Coia Prant <coiaprant@gmail.com>
Co-authored-by: Ricky8955555 <rkmiao@duck.com>
Co-authored-by: Mike Fara <mjfara@gmail.com>
Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
This commit is contained in:
Coia Prant 2026-02-08 10:03:05 +08:00 committed by GitHub
commit d591643706
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 242 additions and 56 deletions

View file

@ -23,6 +23,10 @@ jobs:
- name: Install npm dependencies - name: Install npm dependencies
run: npm install --ignore-scripts run: npm install --ignore-scripts
- name: Debug install
if: always()
run: cat "${HOME}/.npm/_logs/*-debug-0.log" || true
- name: Build - name: Build
env: env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View file

@ -29,6 +29,11 @@ jobs:
arch: x86_64 arch: x86_64
msystem: ucrt64 msystem: ucrt64
toolchain: ucrt-x86_64 toolchain: ucrt-x86_64
- name: Windows-ARM64
os: windows-11-arm
arch: aarch64
msystem: clangarm64
toolchain: clang-aarch64
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@ -46,7 +51,9 @@ jobs:
- name: Update Windows dependencies - name: Update Windows dependencies
env: env:
MSYSTEM: ${{ matrix.msystem }} # MSYSTEM is a built-in environment variable of MSYS2.
# Do not use this environment variable name.
MATRIX_MSYSTEM: ${{ matrix.msystem }}
TOOLCHAIN: ${{ matrix.toolchain }} TOOLCHAIN: ${{ matrix.toolchain }}
shell: msys2 {0} shell: msys2 {0}
run: | run: |
@ -62,17 +69,22 @@ jobs:
"mingw-w64-${TOOLCHAIN}-curl-winssl" "mingw-w64-${TOOLCHAIN}-curl-winssl"
"mingw-w64-${TOOLCHAIN}-gcc" "mingw-w64-${TOOLCHAIN}-gcc"
"mingw-w64-${TOOLCHAIN}-graphviz" "mingw-w64-${TOOLCHAIN}-graphviz"
"mingw-w64-${TOOLCHAIN}-MinHook"
"mingw-w64-${TOOLCHAIN}-miniupnpc" "mingw-w64-${TOOLCHAIN}-miniupnpc"
"mingw-w64-${TOOLCHAIN}-nlohmann-json" "mingw-w64-${TOOLCHAIN}-nlohmann-json"
"mingw-w64-${TOOLCHAIN}-nodejs" "mingw-w64-${TOOLCHAIN}-nodejs"
"mingw-w64-${TOOLCHAIN}-nsis"
"mingw-w64-${TOOLCHAIN}-onevpl" "mingw-w64-${TOOLCHAIN}-onevpl"
"mingw-w64-${TOOLCHAIN}-openssl" "mingw-w64-${TOOLCHAIN}-openssl"
"mingw-w64-${TOOLCHAIN}-opus" "mingw-w64-${TOOLCHAIN}-opus"
"mingw-w64-${TOOLCHAIN}-toolchain" "mingw-w64-${TOOLCHAIN}-toolchain"
) )
if [[ "${MATRIX_MSYSTEM}" == "ucrt64" ]]; then
dependencies+=(
"mingw-w64-${TOOLCHAIN}-MinHook"
"mingw-w64-${TOOLCHAIN}-nsis"
)
fi
# do not modify below this line # do not modify below this line
ignore_packages=() ignore_packages=()
@ -83,7 +95,7 @@ jobs:
tarball="${pkg}-${version}-any.pkg.tar.zst" tarball="${pkg}-${version}-any.pkg.tar.zst"
# download working version # download working version
wget "https://repo.msys2.org/mingw/${MSYSTEM}/${tarball}" wget "https://repo.msys2.org/mingw/${MATRIX_MSYSTEM}/${tarball}"
tarballs="${tarballs} ${tarball}" tarballs="${tarballs} ${tarball}"
done done
@ -189,6 +201,11 @@ jobs:
mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi
mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip
- name: Debug nsis
if: always()
shell: msys2 {0}
run: cat ./build/cpack_artifacts/_CPack_Packages/win64/NSIS/NSISOutput.log || true
- name: Debug wix - name: Debug wix
if: always() if: always()
shell: msys2 {0} shell: msys2 {0}

View file

@ -9,6 +9,13 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
# gcc complains about misleading indentation in some mingw includes # gcc complains about misleading indentation in some mingw includes
list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-misleading-indentation) list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-misleading-indentation)
# Disable warnings for Windows ARM64
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-dll-attribute-on-redeclaration) # Boost
list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-unknown-warning-option) # ViGEmClient
list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-unused-variable) # Boost
endif()
# see gcc bug 98723 # see gcc bug 98723
add_definitions(-DUSE_BOOST_REGEX) add_definitions(-DUSE_BOOST_REGEX)

View file

@ -1,9 +1,35 @@
# windows specific dependencies # windows specific dependencies
# Make sure MinHook is installed # MinHook setup - use installed minhook for AMD64, otherwise download minhook-detours for ARM64
find_library(MINHOOK_LIBRARY libMinHook.a REQUIRED) if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
find_path(MINHOOK_INCLUDE_DIR MinHook.h PATH_SUFFIXES include REQUIRED) # Make sure MinHook is installed for x86/x64
find_library(MINHOOK_LIBRARY libMinHook.a REQUIRED)
find_path(MINHOOK_INCLUDE_DIR MinHook.h PATH_SUFFIXES include REQUIRED)
add_library(minhook::minhook STATIC IMPORTED) add_library(minhook::minhook STATIC IMPORTED)
set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION ${MINHOOK_LIBRARY}) set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION ${MINHOOK_LIBRARY})
target_include_directories(minhook::minhook INTERFACE ${MINHOOK_INCLUDE_DIR}) target_include_directories(minhook::minhook INTERFACE ${MINHOOK_INCLUDE_DIR})
else()
# Download pre-built minhook-detours for ARM64
message(STATUS "Downloading minhook-detours pre-built binaries for ARM64")
include(FetchContent)
FetchContent_Declare(
minhook-detours
URL https://github.com/m417z/minhook-detours/releases/download/v1.0.6/minhook-detours-1.0.6.zip
URL_HASH SHA256=E719959D824511E27395A82AEDA994CAAD53A67EE5894BA5FC2F4BF1FA41E38E
)
FetchContent_MakeAvailable(minhook-detours)
# Create imported library for the pre-built DLL
set(_MINHOOK_DLL
"${minhook-detours_SOURCE_DIR}/Release/minhook-detours.ARM64.Release.dll"
CACHE INTERNAL "Path to minhook-detours DLL")
add_library(minhook::minhook SHARED IMPORTED GLOBAL)
set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION "${_MINHOOK_DLL}")
set_property(TARGET minhook::minhook PROPERTY IMPORTED_IMPLIB
"${minhook-detours_SOURCE_DIR}/Release/minhook-detours.ARM64.Release.lib")
set_target_properties(minhook::minhook PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${minhook-detours_SOURCE_DIR}/src"
)
endif()

View file

@ -4,6 +4,11 @@ install(TARGETS sunshine RUNTIME DESTINATION "." COMPONENT application)
# Hardening: include zlib1.dll (loaded via LoadLibrary() in openssl's libcrypto.a) # Hardening: include zlib1.dll (loaded via LoadLibrary() in openssl's libcrypto.a)
install(FILES "${ZLIB}" DESTINATION "." COMPONENT application) install(FILES "${ZLIB}" DESTINATION "." COMPONENT application)
# ARM64: include minhook-detours DLL (shared library for ARM64)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" AND DEFINED _MINHOOK_DLL)
install(FILES "${_MINHOOK_DLL}" DESTINATION "." COMPONENT application)
endif()
# ViGEmBus installer # ViGEmBus installer
set(VIGEMBUS_INSTALLER "${CMAKE_BINARY_DIR}/scripts/vigembus_installer.exe") set(VIGEMBUS_INSTALLER "${CMAKE_BINARY_DIR}/scripts/vigembus_installer.exe")
set(VIGEMBUS_DOWNLOAD_URL_1 "https://github.com/nefarius/ViGEmBus/releases/download") set(VIGEMBUS_DOWNLOAD_URL_1 "https://github.com/nefarius/ViGEmBus/releases/download")

View file

@ -3,12 +3,18 @@
set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}") set(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\\\${PROJECT_EXE}")
# Enable detailed logging only on AMD64
if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
set(NSIS_LOGSET_COMMAND "LogSet on")
else()
set(NSIS_LOGSET_COMMAND "")
endif()
# Extra install commands # Extra install commands
# Runs the main setup script which handles all installation tasks # Runs the main setup script which handles all installation tasks
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
; Enable detailed logging ${NSIS_LOGSET_COMMAND}
LogSet on
IfSilent +3 0 IfSilent +3 0
nsExec::ExecToLog \ nsExec::ExecToLog \
'powershell -ExecutionPolicy Bypass \ 'powershell -ExecutionPolicy Bypass \
@ -24,8 +30,7 @@ SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
# Runs the main setup script which handles all uninstallation tasks # Runs the main setup script which handles all uninstallation tasks
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
"${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
; Enable detailed logging ${NSIS_LOGSET_COMMAND}
LogSet on
nsExec::ExecToLog \ nsExec::ExecToLog \
'powershell -ExecutionPolicy Bypass \ 'powershell -ExecutionPolicy Bypass \
-File \\\"$INSTDIR\\\\scripts\\\\sunshine-setup.ps1\\\" -Action uninstall' -File \\\"$INSTDIR\\\\scripts\\\\sunshine-setup.ps1\\\" -Action uninstall'

View file

@ -126,33 +126,53 @@ sudo port install "${dependencies[@]}"
``` ```
#### Windows #### Windows
First you need to install [MSYS2](https://www.msys2.org), then startup "MSYS2 UCRT64" and execute the following
commands. > [!WARNING]
> Cross-compilation is not supported on Windows. You must build on the target architecture.
First, you need to install [MSYS2](https://www.msys2.org).
For AMD64 startup "MSYS2 UCRT64" (or for ARM64 startup "MSYS2 CLANGARM64") then execute the following commands.
##### Update all packages ##### Update all packages
```bash ```bash
pacman -Syu pacman -Syu
``` ```
##### Set toolchain variable
For UCRT64:
```bash
export TOOLCHAIN="ucrt-x86_64"
```
For CLANGARM64:
```bash
export TOOLCHAIN="clang-aarch64"
```
##### Install dependencies ##### Install dependencies
```bash ```bash
dependencies=( dependencies=(
"git" "git"
"mingw-w64-ucrt-x86_64-boost" # Optional "mingw-w64-${TOOLCHAIN}-boost" # Optional
"mingw-w64-ucrt-x86_64-cmake" "mingw-w64-${TOOLCHAIN}-cmake"
"mingw-w64-ucrt-x86_64-cppwinrt" "mingw-w64-${TOOLCHAIN}-cppwinrt"
"mingw-w64-ucrt-x86_64-curl-winssl" "mingw-w64-${TOOLCHAIN}-curl-winssl"
"mingw-w64-ucrt-x86_64-doxygen" # Optional, for docs... better to install official Doxygen "mingw-w64-${TOOLCHAIN}-doxygen" # Optional, for docs... better to install official Doxygen
"mingw-w64-ucrt-x86_64-graphviz" # Optional, for docs "mingw-w64-${TOOLCHAIN}-graphviz" # Optional, for docs
"mingw-w64-ucrt-x86_64-MinHook" "mingw-w64-${TOOLCHAIN}-miniupnpc"
"mingw-w64-ucrt-x86_64-miniupnpc" "mingw-w64-${TOOLCHAIN}-nodejs"
"mingw-w64-ucrt-x86_64-nodejs" "mingw-w64-${TOOLCHAIN}-onevpl"
"mingw-w64-ucrt-x86_64-nsis" "mingw-w64-${TOOLCHAIN}-openssl"
"mingw-w64-ucrt-x86_64-onevpl" "mingw-w64-${TOOLCHAIN}-opus"
"mingw-w64-ucrt-x86_64-openssl" "mingw-w64-${TOOLCHAIN}-toolchain"
"mingw-w64-ucrt-x86_64-opus"
"mingw-w64-ucrt-x86_64-toolchain"
) )
if [[ "${MSYSTEM}" == "UCRT64" ]]; then
dependencies+=(
"mingw-w64-${TOOLCHAIN}-MinHook"
"mingw-w64-${TOOLCHAIN}-nsis"
)
fi
pacman -S "${dependencies[@]}" pacman -S "${dependencies[@]}"
``` ```

View file

@ -329,21 +329,30 @@ brew uninstall sunshine
### Windows ### Windows
> [!NOTE]
> Sunshine supports ARM64 on Windows; however, this should be considered experimental. This version does not properly
> support GPU scheduling and any hardware acceleration.
#### Installer (recommended) #### Installer (recommended)
> [!CAUTION] > [!CAUTION]
> The msi installer is preferred moving forward. Before using a different type of installer, you should manually > The msi installer is preferred moving forward. Before using a different type of installer, you should manually
> uninstall the previous installation. > uninstall the previous installation.
1. Download and install 1. Download and install based on your architecture:
[Sunshine-Windows-AMD64-installer.msi](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.msi)
[Sunshine-Windows-AMD64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.exe) | Architecture | Installer |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| AMD64/x64 (Intel/AMD) | [Sunshine-Windows-AMD64-installer.msi](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.msi) |
| AMD64/x64 (Intel/AMD) | [Sunshine-Windows-AMD64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.exe) |
| ARM64 | [Sunshine-Windows-ARM64-installer.msi](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-ARM64-installer.msi) |
| ARM64 | [Sunshine-Windows-ARM64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-ARM64-installer.exe) |
> [!TIP] > [!TIP]
> Installer logs can be found in the following locations.<br> > Installer logs can be found in the following locations.<br>
> | File | log paths | > | File | log paths |
> | ---- | --------- | > | ---- | --------- |
> | .exe | `%%PROGRAMFILES%/Sunshine/install.log`<br>`%%TEMP%/Sunshine/logs/install/` | > | .exe | `%%PROGRAMFILES%/Sunshine/install.log` (AMD64 only)<br>`%%TEMP%/Sunshine/logs/install/` |
> | .msi | `%%TEMP%/Sunshine/logs/install/` | > | .msi | `%%TEMP%/Sunshine/logs/install/` |
> [!CAUTION] > [!CAUTION]
@ -359,8 +368,13 @@ overflow menu. Different versions of Windows may provide slightly different step
> By using this package instead of the installer, performance will be reduced. This package is not > By using this package instead of the installer, performance will be reduced. This package is not
> recommended for most users. No support will be provided! > recommended for most users. No support will be provided!
1. Download and extract 1. Download and extract based on your architecture:
[Sunshine-Windows-AMD64-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-portable.zip)
| Architecture | Installer |
|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| AMD64/x64 (Intel/AMD) | [Sunshine-Windows-AMD64-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-portable.zip) |
| ARM64 | [Sunshine-Windows-ARM64-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-ARM64-portable.zip) |
2. Open command prompt as administrator 2. Open command prompt as administrator
3. Firewall rules 3. Firewall rules

View file

@ -22,6 +22,10 @@
"@vitejs/plugin-vue": "6.0.1", "@vitejs/plugin-vue": "6.0.1",
"serve": "14.2.5", "serve": "14.2.5",
"vite": "6.3.6", "vite": "6.3.6",
"vite-plugin-ejs": "1.7.0" "vite-plugin-ejs": "1.7.0",
"@rollup/wasm-node": "4.57.1"
},
"overrides": {
"rollup": "npm:@rollup/wasm-node@4.57.1"
} }
} }

View file

@ -695,7 +695,7 @@ elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
cuda_version="12.9.1" cuda_version="12.9.1"
cuda_build="575.57.08" cuda_build="575.57.08"
gcc_version="13" gcc_version="13"
nvm_node=0 nvm_node=1
elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
distro="debian" distro="debian"
version="13" version="13"
@ -704,7 +704,7 @@ elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
cuda_version="12.9.1" cuda_version="12.9.1"
cuda_build="575.57.08" cuda_build="575.57.08"
gcc_version="14" gcc_version="14"
nvm_node=0 nvm_node=1
elif grep -q "PLATFORM_ID=\"platform:f41\"" /etc/os-release; then elif grep -q "PLATFORM_ID=\"platform:f41\"" /etc/os-release; then
distro="fedora" distro="fedora"
version="41" version="41"

View file

@ -187,7 +187,7 @@ namespace config {
}; };
template<class T> template<class T>
std::optional<int> quality_from_view(const std::string_view &quality_type, const std::optional<int>(&original)) { ::std::optional<int> quality_from_view(const ::std::string_view &quality_type, const ::std::optional<int>(&original)) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (quality_type == #x##sv) \ if (quality_type == #x##sv) \
return (int) T::x return (int) T::x
@ -199,7 +199,7 @@ namespace config {
} }
template<class T> template<class T>
std::optional<int> rc_from_view(const std::string_view &rc, const std::optional<int>(&original)) { ::std::optional<int> rc_from_view(const ::std::string_view &rc, const ::std::optional<int>(&original)) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (rc == #x##sv) \ if (rc == #x##sv) \
return (int) T::x return (int) T::x
@ -212,7 +212,7 @@ namespace config {
} }
template<class T> template<class T>
std::optional<int> usage_from_view(const std::string_view &usage, const std::optional<int>(&original)) { ::std::optional<int> usage_from_view(const ::std::string_view &usage, const ::std::optional<int>(&original)) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (usage == #x##sv) \ if (usage == #x##sv) \
return (int) T::x return (int) T::x
@ -225,7 +225,7 @@ namespace config {
return original; return original;
} }
int coder_from_view(const std::string_view &coder) { int coder_from_view(const ::std::string_view &coder) {
if (coder == "auto"sv) { if (coder == "auto"sv) {
return _auto; return _auto;
} }

View file

@ -56,7 +56,6 @@ namespace nvenc {
autopop_context push_context(); autopop_context push_context();
HMODULE dll = nullptr;
const ID3D11DevicePtr d3d_device; const ID3D11DevicePtr d3d_device;
ID3D11Texture2DPtr d3d_input_texture; ID3D11Texture2DPtr d3d_input_texture;

View file

@ -32,14 +32,14 @@ DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64)
#define STEAM_DRIVER_SUBDIR L"x64" #define STEAM_DRIVER_SUBDIR L"x64"
#else
#warning No known Steam audio driver for this architecture
#endif #endif
namespace { namespace {
constexpr auto SAMPLE_RATE = 48000; constexpr auto SAMPLE_RATE = 48000;
#ifdef STEAM_DRIVER_SUBDIR
constexpr auto STEAM_AUDIO_DRIVER_PATH = L"%CommonProgramFiles(x86)%\\Steam\\drivers\\Windows10\\" STEAM_DRIVER_SUBDIR L"\\SteamStreamingSpeakers.inf"; constexpr auto STEAM_AUDIO_DRIVER_PATH = L"%CommonProgramFiles(x86)%\\Steam\\drivers\\Windows10\\" STEAM_DRIVER_SUBDIR L"\\SteamStreamingSpeakers.inf";
#endif
constexpr auto waveformat_mask_stereo = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; constexpr auto waveformat_mask_stereo = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;

View file

@ -1907,6 +1907,12 @@ namespace platf::dxgi {
if (!boost::algorithm::ends_with(name, "_nvenc")) { if (!boost::algorithm::ends_with(name, "_nvenc")) {
return false; return false;
} }
} else if (adapter_desc.VendorId == 0x4D4F4351 || // Qualcomm (QCOM as MOQC reversed)
adapter_desc.VendorId == 0x5143) { // Qualcomm alternate ID
// If it's not a MediaFoundation encoder, it's not compatible with a Qualcomm GPU
if (!boost::algorithm::ends_with(name, "_mf")) {
return false;
}
} else { } else {
BOOST_LOG(warning) << "Unknown GPU vendor ID: " << util::hex(adapter_desc.VendorId).to_string_view(); BOOST_LOG(warning) << "Unknown GPU vendor ID: " << util::hex(adapter_desc.VendorId).to_string_view();
} }

View file

@ -10,6 +10,7 @@
// standard includes // standard includes
#include <cmath> #include <cmath>
#include <thread> #include <thread>
#include <vector>
// lib includes // lib includes
#include <ViGEm/Client.h> #include <ViGEm/Client.h>
@ -1134,9 +1135,9 @@ namespace platf {
void unicode(input_t &input, char *utf8, int size) { void unicode(input_t &input, char *utf8, int size) {
// We can do no worse than one UTF-16 character per byte of UTF-8 // We can do no worse than one UTF-16 character per byte of UTF-8
WCHAR wide[size]; std::vector<WCHAR> wide(size);
int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide, size); int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide.data(), size);
if (chars <= 0) { if (chars <= 0) {
return; return;
} }

View file

@ -9,6 +9,7 @@
#include <iterator> #include <iterator>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <vector>
// lib includes // lib includes
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -1383,7 +1384,7 @@ namespace platf {
auto const max_bufs_per_msg = send_info.payload_buffers.size() + (send_info.headers ? 1 : 0); auto const max_bufs_per_msg = send_info.payload_buffers.size() + (send_info.headers ? 1 : 0);
WSABUF bufs[(send_info.headers ? send_info.block_count : 1) * max_bufs_per_msg]; std::vector<WSABUF> bufs((send_info.headers ? send_info.block_count : 1) * max_bufs_per_msg);
DWORD bufcount = 0; DWORD bufcount = 0;
if (send_info.headers) { if (send_info.headers) {
// Interleave buffers for headers and payloads // Interleave buffers for headers and payloads
@ -1409,7 +1410,7 @@ namespace platf {
} }
} }
msg.lpBuffers = bufs; msg.lpBuffers = bufs.data();
msg.dwBufferCount = bufcount; msg.dwBufferCount = bufcount;
msg.dwFlags = 0; msg.dwFlags = 0;

View file

@ -41,4 +41,4 @@ BEGIN
END END
END END
SuperDuperAmazing ICON DISCARDABLE PROJECT_ICON_PATH SuperDuperAmazing ICON DISCARDABLE TOSTRING(PROJECT_ICON_PATH)

View file

@ -300,6 +300,7 @@ namespace video {
ALWAYS_REPROBE = 1 << 9, ///< This is an encoder of last resort and we want to aggressively probe for a better one ALWAYS_REPROBE = 1 << 9, ///< This is an encoder of last resort and we want to aggressively probe for a better one
YUV444_SUPPORT = 1 << 10, ///< Encoder may support 4:4:4 chroma sampling depending on hardware YUV444_SUPPORT = 1 << 10, ///< Encoder may support 4:4:4 chroma sampling depending on hardware
ASYNC_TEARDOWN = 1 << 11, ///< Encoder supports async teardown on a different thread ASYNC_TEARDOWN = 1 << 11, ///< Encoder supports async teardown on a different thread
FIXED_GOP_SIZE = 1 << 12, ///< Use fixed small GOP size (encoder doesn't support on-demand IDR frames)
}; };
class avcodec_encode_session_t: public encode_session_t { class avcodec_encode_session_t: public encode_session_t {
@ -825,6 +826,63 @@ namespace video {
}, },
PARALLEL_ENCODING PARALLEL_ENCODING
}; };
encoder_t mediafoundation {
"mediafoundation"sv,
std::make_unique<encoder_platform_formats_avcodec>(
AV_HWDEVICE_TYPE_D3D11VA,
AV_HWDEVICE_TYPE_NONE,
AV_PIX_FMT_D3D11,
AV_PIX_FMT_NV12, // SDR 4:2:0 8-bit (only format Qualcomm supports)
AV_PIX_FMT_NONE, // No HDR - Qualcomm MF only supports 8-bit
AV_PIX_FMT_NONE, // No YUV444 SDR
AV_PIX_FMT_NONE, // No YUV444 HDR
dxgi_init_avcodec_hardware_input_buffer
),
{
// Common options for AV1 - Qualcomm MF encoder
{
{"hw_encoding"s, 1},
{"rate_control"s, "cbr"s},
{"scenario"s, "display_remoting"s},
},
{}, // SDR-specific options
{}, // HDR-specific options
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
"av1_mf"s,
},
{
// Common options for HEVC - Qualcomm MF encoder
{
{"hw_encoding"s, 1},
{"rate_control"s, "cbr"s},
{"scenario"s, "display_remoting"s},
},
{}, // SDR-specific options
{}, // HDR-specific options
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
"hevc_mf"s,
},
{
// Common options for H.264 - Qualcomm MF encoder
{
{"hw_encoding"s, 1},
{"rate_control"s, "cbr"s},
{"scenario"s, "display_remoting"s},
},
{}, // SDR-specific options
{}, // HDR-specific options
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
"h264_mf"s,
},
PARALLEL_ENCODING | FIXED_GOP_SIZE // MF encoder doesn't support on-demand IDR frames
};
#endif #endif
encoder_t software { encoder_t software {
@ -1031,6 +1089,7 @@ namespace video {
#ifdef _WIN32 #ifdef _WIN32
&quicksync, &quicksync,
&amdvce, &amdvce,
&mediafoundation,
#endif #endif
#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) #if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__)
&vaapi, &vaapi,
@ -1566,11 +1625,17 @@ namespace video {
ctx->max_b_frames = 0; ctx->max_b_frames = 0;
// Use an infinite GOP length since I-frames are generated on demand // Use an infinite GOP length since I-frames are generated on demand
ctx->gop_size = encoder.flags & LIMITED_GOP_SIZE ? // Exception: encoders with FIXED_GOP_SIZE flag don't support on-demand IDR
std::numeric_limits<std::int16_t>::max() : if (encoder.flags & FIXED_GOP_SIZE) {
std::numeric_limits<int>::max(); // Fixed GOP for encoders that don't support on-demand IDR (e.g. Media Foundation)
ctx->gop_size = 120; // ~2 seconds at 60 FPS - larger to reduce oversized IDR frame frequency
ctx->keyint_min = std::numeric_limits<int>::max(); ctx->keyint_min = 120;
} else {
ctx->gop_size = encoder.flags & LIMITED_GOP_SIZE ?
std::numeric_limits<std::int16_t>::max() :
std::numeric_limits<int>::max();
ctx->keyint_min = std::numeric_limits<int>::max();
}
// Some client decoders have limits on the number of reference frames // Some client decoders have limits on the number of reference frames
if (config.numRefFrames) { if (config.numRefFrames) {

View file

@ -220,6 +220,7 @@ namespace video {
#ifdef _WIN32 #ifdef _WIN32
extern encoder_t amdvce; extern encoder_t amdvce;
extern encoder_t quicksync; extern encoder_t quicksync;
extern encoder_t mediafoundation;
#endif #endif
#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__) #if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__)

View file

@ -163,4 +163,15 @@ if (WIN32)
# prefer static libraries since we're linking statically # prefer static libraries since we're linking statically
# this fixes libcurl linking errors when using non MSYS2 version of CMake # this fixes libcurl linking errors when using non MSYS2 version of CMake
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) set_target_properties(${PROJECT_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1)
# Copy minhook-detours DLL to test binary directory for ARM64
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" AND DEFINED _MINHOOK_DLL)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${_MINHOOK_DLL}"
"${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Copying minhook-detours DLL to test binary directory"
VERBATIM
)
endif()
endif () endif ()