diff --git a/.github/semantic.yml b/.github/semantic.yml new file mode 100644 index 00000000..b5eb70d0 --- /dev/null +++ b/.github/semantic.yml @@ -0,0 +1,14 @@ +--- +# This file is centrally managed in https://github.com//.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in +# the above-mentioned repo. + +# This is the configuration file for https://github.com/Ezard/semantic-prs + +enabled: true +titleOnly: true # We only use the PR title as we squash and merge +commitsOnly: false +titleAndCommits: false +anyCommit: false +allowMergeCommits: false +allowRevertCommits: false diff --git a/DOCKER_README.md b/DOCKER_README.md index be27e2fa..2ff7bbf8 100644 --- a/DOCKER_README.md +++ b/DOCKER_README.md @@ -54,6 +54,7 @@ docker run -d \ --device /dev/dri/ \ --name= \ --restart=unless-stopped \ + --ipc=host \ -e PUID= \ -e PGID= \ -e TZ= \ @@ -80,6 +81,7 @@ services: - PUID= - PGID= - TZ= + ipc: host ports: - "47984-47990:47984-47990/tcp" - "48010:48010" @@ -125,6 +127,9 @@ port `47990` (e.g. `http://:47990`). The internal port must be `47990`, | `-e PGID=` | Group ID | `1001` | False | | `-e TZ=` | Lookup [TZ value][1] | `America/New_York` | False | +For additional configuration, it is recommended to reference the *Games on Whales* +[sunshine config](https://github.com/games-on-whales/gow/blob/2e442292d79b9d996f886b8a03d22b6eb6bddf7b/compose/streamers/sunshine.yml). + [1]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones #### User / Group Identifiers: diff --git a/cmake/compile_definitions/linux.cmake b/cmake/compile_definitions/linux.cmake index e07c2a55..d90f5dc6 100644 --- a/cmake/compile_definitions/linux.cmake +++ b/cmake/compile_definitions/linux.cmake @@ -24,57 +24,42 @@ if(${SUNSHINE_ENABLE_CUDA}) # https://tech.amikelive.com/node-930/cuda-compatibility-of-nvidia-display-gpu-drivers/ if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 6.5) list(APPEND CMAKE_CUDA_ARCHITECTURES 10) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_10,code=sm_10") elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 6.5) list(APPEND CMAKE_CUDA_ARCHITECTURES 50 52) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_50,code=sm_50") - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_52,code=sm_52") endif() if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 7.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 11) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_11,code=sm_11") elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER 7.6) list(APPEND CMAKE_CUDA_ARCHITECTURES 60 61 62) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_60,code=sm_60") - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_61,code=sm_61") - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_62,code=sm_62") endif() + # https://docs.nvidia.com/cuda/archive/9.2/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 20) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_20,code=sm_20") elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 70) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_70,code=sm_70") endif() + # https://docs.nvidia.com/cuda/archive/10.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) - list(APPEND CMAKE_CUDA_ARCHITECTURES 75) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_75,code=sm_75") + list(APPEND CMAKE_CUDA_ARCHITECTURES 72 75) endif() + # https://docs.nvidia.com/cuda/archive/11.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 30) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_30,code=sm_30") elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 80) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_80,code=sm_80") - endif() - - if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) - list(APPEND CMAKE_CUDA_ARCHITECTURES 86) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_86,code=sm_86") endif() + # https://docs.nvidia.com/cuda/archive/11.8.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.8) - list(APPEND CMAKE_CUDA_ARCHITECTURES 90) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_90,code=sm_90") + list(APPEND CMAKE_CUDA_ARCHITECTURES 86 87 89 90) endif() if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 35) - # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -gencode arch=compute_35,code=sm_35") endif() # sort the architectures diff --git a/crowdin.yml b/crowdin.yml index 3dd19366..3a5e4281 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -2,6 +2,7 @@ "base_path": "." "base_url": "https://api.crowdin.com" # optional (for Crowdin Enterprise only) "preserve_hierarchy": true # false will flatten tree on crowdin, but doesn't work with dest option +"pull_request_title": "chore(l10n): update translations" "pull_request_labels": [ "crowdin", "l10n" diff --git a/docs/getting_started.md b/docs/getting_started.md index c738992b..a9bd5561 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -43,7 +43,7 @@ CUDA is used for NVFBC capture. 11.8.0 450.80.02 - 35;50;52;60;61;62;70;75;80;86;90 + 35;50;52;60;61;62;70;72;75;80;86;87;89;90 sunshine.AppImage @@ -55,7 +55,7 @@ CUDA is used for NVFBC capture. 12.0.0 525.60.13 - 50;52;60;61;62;70;75;80;86;90 + 50;52;60;61;62;70;72;75;80;86;87;89;90 sunshine_{arch}.flatpak diff --git a/packaging/linux/AppImage/AppRun b/packaging/linux/AppImage/AppRun index 404704c3..e90ee3a4 100644 --- a/packaging/linux/AppImage/AppRun +++ b/packaging/linux/AppImage/AppRun @@ -49,6 +49,7 @@ function install() { cat "$SUNSHINE_SHARE_HERE/udev/rules.d/60-sunshine.rules" | sudo tee /etc/udev/rules.d/60-sunshine.rules sudo udevadm control --reload-rules sudo udevadm trigger --property-match=DEVNAME=/dev/uinput + sudo udevadm trigger --property-match=DEVNAME=/dev/uhid # sunshine service mkdir -p ~/.config/systemd/user diff --git a/packaging/linux/Arch/sunshine.install b/packaging/linux/Arch/sunshine.install index a8a700f1..6b274cdf 100644 --- a/packaging/linux/Arch/sunshine.install +++ b/packaging/linux/Arch/sunshine.install @@ -5,7 +5,9 @@ do_setcap() { do_udev_reload() { udevadm control --reload-rules udevadm trigger --property-match=DEVNAME=/dev/uinput + udevadm trigger --property-match=DEVNAME=/dev/uhid modprobe uinput || true + modprobe uhid || true } post_install() { diff --git a/scripts/requirements.txt b/scripts/requirements.txt index 9cfd158f..cd2ef869 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,2 +1,2 @@ -Babel==2.15.0 +Babel==2.16.0 clang-format diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp index ed88e8d5..96ddff84 100644 --- a/src/platform/windows/display_vram.cpp +++ b/src/platform/windows/display_vram.cpp @@ -1871,6 +1871,13 @@ namespace platf::dxgi { if (!boost::algorithm::ends_with(name, "_qsv")) { return false; } + if (config.chromaSamplingType == 1) { + if (config.videoFormat == 0 || config.videoFormat == 2) { + // QSV doesn't support 4:4:4 in H.264 or AV1 + return false; + } + // TODO: Blacklist HEVC 4:4:4 based on adapter model + } } else if (adapter_desc.VendorId == 0x10de) { // Nvidia // If it's not an NVENC encoder, it's not compatible with an Nvidia GPU diff --git a/src/video.cpp b/src/video.cpp index d8438e21..86c7eced 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1455,9 +1455,7 @@ namespace video { bool hardware = platform_formats->avcodec_base_dev_type != AV_HWDEVICE_TYPE_NONE; - auto &video_format = config.videoFormat == 0 ? encoder.h264 : - config.videoFormat == 1 ? encoder.hevc : - encoder.av1; + auto &video_format = encoder.codec_from_config(config); if (!video_format[encoder_t::PASSED] || !disp->is_codec_supported(video_format.name, config)) { BOOST_LOG(error) << encoder.name << ": "sv << video_format.name << " mode not supported"sv; return nullptr; @@ -1971,10 +1969,7 @@ namespace video { } { - auto encoder_name = config.videoFormat == 0 ? encoder.h264.name : - config.videoFormat == 1 ? encoder.hevc.name : - config.videoFormat == 2 ? encoder.av1.name : - "unknown"; + auto encoder_name = encoder.codec_from_config(config).name; BOOST_LOG(info) << "Creating encoder " << logging::bracket(encoder_name); @@ -2537,7 +2532,8 @@ namespace video { // H.264 is special because encoders may support YUV 4:4:4 without supporting 10-bit color depth if (encoder.flags & YUV444_SUPPORT) { config_t config_h264_yuv444 { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0, 1 }; - encoder.h264[encoder_t::YUV444] = validate_config(disp, encoder, config_h264_yuv444); + encoder.h264[encoder_t::YUV444] = disp->is_codec_supported(encoder.h264.name, config_h264_yuv444) && + validate_config(disp, encoder, config_h264_yuv444) >= 0; } else { encoder.h264[encoder_t::YUV444] = false; @@ -2557,17 +2553,30 @@ namespace video { if (!flag_map[encoder_t::PASSED]) return; + auto encoder_codec_name = encoder.codec_from_config(config).name; + // Test 4:4:4 HDR first. If 4:4:4 is supported, 4:2:0 should also be supported. config.chromaSamplingType = 1; - if ((encoder.flags & YUV444_SUPPORT) && validate_config(disp, encoder, config) >= 0) { + if ((encoder.flags & YUV444_SUPPORT) && + disp->is_codec_supported(encoder_codec_name, config) && + validate_config(disp, encoder, config) >= 0) { flag_map[encoder_t::DYNAMIC_RANGE] = true; flag_map[encoder_t::YUV444] = true; return; } + else { + flag_map[encoder_t::YUV444] = false; + } // Test 4:2:0 HDR config.chromaSamplingType = 0; - flag_map[encoder_t::DYNAMIC_RANGE] = validate_config(disp, encoder, config) >= 0; + if (disp->is_codec_supported(encoder_codec_name, config) && + validate_config(disp, encoder, config) >= 0) { + flag_map[encoder_t::DYNAMIC_RANGE] = true; + } + else { + flag_map[encoder_t::DYNAMIC_RANGE] = false; + } }; // HDR is not supported with H.264. Don't bother even trying it. diff --git a/src/video.h b/src/video.h index 0b1baac8..6a50b2e3 100644 --- a/src/video.h +++ b/src/video.h @@ -17,6 +17,29 @@ extern "C" { struct AVPacket; namespace video { + /* Encoding configuration requested by remote client */ + struct config_t { + int width; // Video width in pixels + int height; // Video height in pixels + int framerate; // Requested framerate, used in individual frame bitrate budget calculation + int bitrate; // Video bitrate in kilobits (1000 bits) for requested framerate + int slicesPerFrame; // Number of slices per frame + int numRefFrames; // Max number of reference frames + + /* Requested color range and SDR encoding colorspace, HDR encoding colorspace is always BT.2020+ST2084 + Color range (encoderCscMode & 0x1) : 0 - limited, 1 - full + SDR encoding colorspace (encoderCscMode >> 1) : 0 - BT.601, 1 - BT.709, 2 - BT.2020 */ + int encoderCscMode; + + int videoFormat; // 0 - H.264, 1 - HEVC, 2 - AV1 + + /* Encoding color depth (bit depth): 0 - 8-bit, 1 - 10-bit + HDR encoding activates when color depth is higher than 8-bit and the display which is being captured is operating in HDR mode */ + int dynamicRange; + + int chromaSamplingType; // 0 - 4:2:0, 1 - 4:4:4 + }; + platf::mem_type_e map_base_dev_type(AVHWDeviceType type); platf::pix_fmt_e @@ -163,6 +186,21 @@ namespace video { } } av1, hevc, h264; + const codec_t & + codec_from_config(const config_t &config) const { + switch (config.videoFormat) { + default: + BOOST_LOG(error) << "Unknown video format " << config.videoFormat << ", falling back to H.264"; + // fallthrough + case 0: + return h264; + case 1: + return hevc; + case 2: + return av1; + } + } + uint32_t flags; }; @@ -309,29 +347,6 @@ namespace video { using hdr_info_t = std::unique_ptr; - /* Encoding configuration requested by remote client */ - struct config_t { - int width; // Video width in pixels - int height; // Video height in pixels - int framerate; // Requested framerate, used in individual frame bitrate budget calculation - int bitrate; // Video bitrate in kilobits (1000 bits) for requested framerate - int slicesPerFrame; // Number of slices per frame - int numRefFrames; // Max number of reference frames - - /* Requested color range and SDR encoding colorspace, HDR encoding colorspace is always BT.2020+ST2084 - Color range (encoderCscMode & 0x1) : 0 - limited, 1 - full - SDR encoding colorspace (encoderCscMode >> 1) : 0 - BT.601, 1 - BT.709, 2 - BT.2020 */ - int encoderCscMode; - - int videoFormat; // 0 - H.264, 1 - HEVC, 2 - AV1 - - /* Encoding color depth (bit depth): 0 - 8-bit, 1 - 10-bit - HDR encoding activates when color depth is higher than 8-bit and the display which is being captured is operating in HDR mode */ - int dynamicRange; - - int chromaSamplingType; // 0 - 4:2:0, 1 - 4:4:4 - }; - extern int active_hevc_mode; extern int active_av1_mode; extern bool last_encoder_probe_supported_ref_frames_invalidation; diff --git a/src_assets/linux/misc/postinst b/src_assets/linux/misc/postinst index e406c762..47deb784 100644 --- a/src_assets/linux/misc/postinst +++ b/src_assets/linux/misc/postinst @@ -8,9 +8,10 @@ if [ -x "$path_to_setcap" ] ; then $path_to_setcap cap_sys_admin+p $path_to_sunshine fi -# Trigger udev rule reload for /dev/uinput +# Trigger udev rule reload for /dev/uinput and /dev/uhid path_to_udevadm=$(which udevadm) if [ -x "$path_to_udevadm" ] ; then $path_to_udevadm control --reload-rules $path_to_udevadm trigger --property-match=DEVNAME=/dev/uinput + $path_to_udevadm trigger --property-match=DEVNAME=/dev/uhid fi