Skip to content

feat(linux): Add Vulkan video encoder for Linux#4603

Open
neatnoise wants to merge 24 commits intoLizardByte:masterfrom
neatnoise:vulkan-pr
Open

feat(linux): Add Vulkan video encoder for Linux#4603
neatnoise wants to merge 24 commits intoLizardByte:masterfrom
neatnoise:vulkan-pr

Conversation

@neatnoise
Copy link

@neatnoise neatnoise commented Jan 19, 2026

Description

This PR adds Vulkan video encoding support for Linux, providing an alternative to VAAPI encoding.

Changes:

  • Vulkan encoder: New FFmpeg-based Vulkan encoder (h264_vulkan, hevc_vulkan, av1_vulkan) with zero-copy DMA-BUF import and Vulkan compute RGB-to-YUV conversion — no EGL/GL dependency, all GPU work stays in a single Vulkan queue
  • Web UI: Added Vulkan encoder selection and settings to the configuration interface
  • Documentation: Added docs for vulkan encoder options in docs/configuration.md

Dependencies:

Requires corresponding PR in LizardByte/build-deps (ffmpeg-vulkan branch) to enable BUILD_FFMPEG_VULKAN option, which enables Vulkan encoder support in FFmpeg builds.

Testing:

  • Tested on single GPU setup: AMD Radeon 780M (integrated)
  • Tested on multi-GPU setup: AMD Radeon 9070 XT (discrete) + AMD Radeon 780M (integrated)
  • Tested on Arch Linux KDE desktop

Screenshot

image

Issues Fixed or Closed

Roadmap Issues

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

@neatnoise neatnoise changed the title Add Vulkan video encoder for Linux (KMS capture) feat(web): Add Vulkan video encoder for Linux Jan 19, 2026
@neatnoise neatnoise changed the title feat(web): Add Vulkan video encoder for Linux feat(linux): Add Vulkan video encoder for Linux Jan 19, 2026
Copy link
Member

@ReenigneArcher ReenigneArcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ReenigneArcher
Copy link
Member

I will convert this to draft for now, please change it back when you're ready for a full review. Thanks!

@ReenigneArcher ReenigneArcher marked this pull request as draft January 19, 2026 20:45
@neatnoise
Copy link
Author

Its ready

@andygrundman
Copy link
Contributor

andygrundman commented Jan 20, 2026

I know this PR is about encoding, but I saw changes to capture as well. Do you know if this could support variable framerate capture, similar to how capture works on Windows? In my limited experience Linux always captures at the stream framerate.

The ideal capture process would be capturing only when the image has changed (with duplicated frames subject to minimum_fps_target), as well as capturing using a frame interval timer requested by the client or based on the framerate. For example, an Xbox client works best if frames are captured on a timer with an interval of 59.94fps (60000/1001), a desktop client could just use a 60fps interval. One thing you do not want to do is base anything on the host's vsync interval.

@ReenigneArcher
Copy link
Member

Its ready

I left a bunch of review comments.

@neatnoise
Copy link
Author

I know this PR is about encoding, but I saw changes to capture as well. Do you know if this could support variable framerate capture, similar to how capture works on Windows? In my limited experience Linux always captures at the stream framerate.

The ideal capture process would be capturing only when the image has changed (with duplicated frames subject to minimum_fps_target), as well as capturing using a frame interval timer requested by the client or based on the framerate. For example, an Xbox client works best if frames are captured on a timer with an interval of 59.94fps (60000/1001), a desktop client could just use a 60fps interval. One thing you do not want to do is base anything on the host's vsync interval.

Yes, the kms_vblank option already behaves this way with variable frame rate similarly to Windows. It encodes that many frames that are generated by a game. It also respects fps frame rate which are set by a client (if the clients sets 60, it won't generate more than 60 fps with some minimal margin)

@neatnoise
Copy link
Author

@ReenigneArcher I made proposed changes. I also added a tiling fix for RNDA 4 when Gnome DE is used. Would be helpful if somebody with Nvidia and Intel GPUs could test the new encoder

@neatnoise
Copy link
Author

neatnoise commented Feb 17, 2026

@ReenigneArcher I've tested with vulkan ffmpeg build https://github.com/LizardByte/build-deps/actions/runs/21850415771?pr=606 successfully.

Tweaked kms_vblank for the game Cronos The New Dawn meanwhile.

Tested in many games with various resolutions with and without vsync in-game and kms_vblank enabled and disabled. Tested with vulkan and vaapi encoders. It works solid.

@XT-Martinez

This comment was marked as off-topic.

@ReenigneArcher
Copy link
Member

ReenigneArcher commented Feb 18, 2026

This PR needs to be rebased to pick up the right FFmpeg pre-build, before I can run CI.

Edit: actually the build-deps commit that added Vulkan hadn't been merged here yet: #4735

@psyke83
Copy link
Contributor

psyke83 commented Feb 18, 2026

@neatnoise

Also, don't forget to verify compatibility with portalgrab when rebasing. This is enough to get started, but you might want to refine/verify:

diff --git a/src/platform/linux/portalgrab.cpp b/src/platform/linux/portalgrab.cpp
index 1f4e9062..eeaf1c92 100644
--- a/src/platform/linux/portalgrab.cpp
+++ b/src/platform/linux/portalgrab.cpp
@@ -29,6 +29,7 @@
 #include "src/platform/common.h"
 #include "src/video.h"
 #include "vaapi.h"
+#include "vulkan_encode.h"
 #include "wayland.h"
 
 namespace {
@@ -748,6 +749,7 @@ namespace portal {
         // On hybrid GPU systems (Intel+NVIDIA), DMA-BUFs come from the Intel GPU and cannot
         // be imported into CUDA, so we fall back to memory buffers in that case.
         bool use_dmabuf = n_dmabuf_infos > 0 && (mem_type == platf::mem_type_e::vaapi ||
+                                                 mem_type == platf::mem_type_e::vulkan ||
                                                  (mem_type == platf::mem_type_e::cuda && display_is_nvidia));
         if (use_dmabuf) {
           for (int i = 0; i < n_dmabuf_infos; i++) {
@@ -1226,6 +1228,9 @@ namespace portal {
         return va::make_avcodec_encode_device(width, height, n_dmabuf_infos > 0);
       }
 #endif
+      if (mem_type == platf::mem_type_e::vulkan) {
+        return vk::make_avcodec_encode_device_vram(width, height, 0, 0);
+      }
 
 #ifdef SUNSHINE_BUILD_CUDA
       if (mem_type == platf::mem_type_e::cuda) {
@@ -1368,7 +1373,7 @@ namespace portal {
 namespace platf {
   std::shared_ptr<display_t> portal_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
     using enum platf::mem_type_e;
-    if (hwdevice_type != system && hwdevice_type != vaapi && hwdevice_type != cuda) {
+    if (hwdevice_type != system && hwdevice_type != vaapi && hwdevice_type != vulkan && hwdevice_type != cuda) {
       BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
       return nullptr;
     }

@neatnoise
Copy link
Author

@XT-Martinez It looks like ffmpeg without built-in vulkan support, you need to build it with ffmpeg vulkan supported binaries (like from link above).

@psyke83 will do. I will add vulkan support also for portal grab. Actually I have my portal/pipeware implementation here https://github.com/neatnoise/Sunshine/tree/vulkan%2Bpipewire . So It will be similar.

@neatnoise
Copy link
Author

  • Rebased to sunshine master (with portal support)
  • Added vulkan+portal support
  • Cleaned up to just add vulkan support - removed kms_vblank option (i might create a separate PR for it in the future)

The best results on my machine are portal+vulkan (vulkan settings low latency + vbr) and existing portal+vaapi. Portal seems to have a lower latency than KMS.

@gschintgen
Copy link
Contributor

FWIW I found the vblank option quite interesting. (But I don't have much time right now to actually check it out.)

@psyke83
Copy link
Contributor

psyke83 commented Feb 19, 2026

With the default settings (vbr, ll), the stream is massively violating the target bitrate (70Mbps target is saturating my wifi connection at 250Mbps+). I didn't notice this with prior testing.

@psyke83
Copy link
Contributor

psyke83 commented Feb 19, 2026

This is the issue:

conn@ryzenl:~/work/sunshine$ ffmpeg 2>&1 -h encoder=hevc_vulkan | grep -A5 rc_mode 
  -rc_mode           <int>        E..V....... Select rate control type (from 0 to UINT32_MAX) (default auto)
     auto            4294967295   E..V....... Choose mode automatically based on parameters
     driver          0            E..V....... Driver-specific rate control
     cqp             1            E..V....... Constant quantizer mode
     cbr             2            E..V....... Constant bitrate mode
     vbr             4            E..V....... Variable bitrate mode
conn@ryzenl:~/work/sunshine$ ffmpeg 2>&1 -h encoder=h264_vulkan | grep -A5 rc_mode 
  -rc_mode           <int>        E..V....... Select rate control type (from 0 to UINT32_MAX) (default auto)
     auto            4294967295   E..V....... Choose mode automatically based on parameters
     driver          0            E..V....... Driver-specific rate control
     cqp             1            E..V....... Constant quantizer mode
     cbr             2            E..V....... Constant bitrate mode
     vbr             4            E..V....... Variable bitrate mode

Your current PR is assigning VBR as 3 erroneously. When set to 4, I'm not seeing the crazy bitrate overshooting.

@neatnoise
Copy link
Author

This is the issue:

conn@ryzenl:~/work/sunshine$ ffmpeg 2>&1 -h encoder=hevc_vulkan | grep -A5 rc_mode 
  -rc_mode           <int>        E..V....... Select rate control type (from 0 to UINT32_MAX) (default auto)
     auto            4294967295   E..V....... Choose mode automatically based on parameters
     driver          0            E..V....... Driver-specific rate control
     cqp             1            E..V....... Constant quantizer mode
     cbr             2            E..V....... Constant bitrate mode
     vbr             4            E..V....... Variable bitrate mode
conn@ryzenl:~/work/sunshine$ ffmpeg 2>&1 -h encoder=h264_vulkan | grep -A5 rc_mode 
  -rc_mode           <int>        E..V....... Select rate control type (from 0 to UINT32_MAX) (default auto)
     auto            4294967295   E..V....... Choose mode automatically based on parameters
     driver          0            E..V....... Driver-specific rate control
     cqp             1            E..V....... Constant quantizer mode
     cbr             2            E..V....... Constant bitrate mode
     vbr             4            E..V....... Variable bitrate mode

Your current PR is assigning VBR as 3 erroneously. When set to 4, I'm not seeing the crazy bitrate overshooting.

Fixed

@ReenigneArcher
Copy link
Member

build-deps has been updated in Sunshine to include the version with vulkan support.

@neatnoise
Copy link
Author

@ReenigneArcher rebased with the current master. It works fine:

lut 24 11:58:17 REDACTED_HOST systemd[834]: Starting Self-hosted game stream host for Moonlight...
lut 24 11:58:23 REDACTED_HOST systemd[834]: Started Self-hosted game stream host for Moonlight.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037958] [0x00007fd88eecb600] [info]    config: 'vk_tune' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037977] [0x00007fd88eecb600] [info]    config: 'wan_encryption_mode' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037979] [0x00007fd88eecb600] [info]    config: 'vaapi_strict_rc_buffer' = enabled
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037984] [0x00007fd88eecb600] [info]    config: 'lan_encryption_mode' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037986] [0x00007fd88eecb600] [info]    config: 'vk_rc_mode' = 4
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037988] [0x00007fd88eecb600] [info]    config: 'minimum_fps_target' = 10
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037989] [0x00007fd88eecb600] [info]    config: 'gamepad' = xone
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037991] [0x00007fd88eecb600] [info]    config: 'external_ip' = REDACTED_IP
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037992] [0x00007fd88eecb600] [info]    config: 'encoder' = vulkan
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037994] [0x00007fd88eecb600] [info]    config: 'capture' = portal
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.037997] [0x00007fd88eecb600] [info]    config: 'address_family' = both
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: Sunshine version: 0.0.0-e76b2ffb commit:
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: Package Publisher: Third Party Publisher
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: Publisher Website:
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: Get support: https://app.lizardbyte.dev/support
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'address_family' = both
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'capture' = portal
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'encoder' = vulkan
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'external_ip' = REDACTED_IP
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'gamepad' = xone
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'minimum_fps_target' = 10
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'vk_rc_mode' = 4
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'lan_encryption_mode' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'vaapi_strict_rc_buffer' = enabled
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'wan_encryption_mode' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: config: 'vk_tune' = 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.038]: Info: Loaded portal restore token from disk
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.152]: Info: Trying encoder [vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.152]: Info: Screencasting with XDG portal
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.152]: Info: Requested frame rate [60/1, approx. 60 fps]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.152]: Info: Found display [wayland-0]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.163]: Info: Loaded portal restore token from disk
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.167]: Error: SelectDevices failed with response code: 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.167]: Warning: RemoteDesktop.SelectDevices failed, falling back to ScreenCast-only mode
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.181]: Info: Connected to pipewire version 1.4.10
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.182]: Info: Video format: 12
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.182]: Info: Size: 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.182]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.182]: Info: using DMA-BUF buffers
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.182]: Info: Video format: 12
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.183]: Info: Size: 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.183]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.183]: Info: using DMA-BUF buffers
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.191]: Info: Using negotiated resolution 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.191]: Info: Creating encoder [h264_vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.191]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.191]: Info: Color depth: 8-bit
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.191]: Info: Color range: JPEG
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.220]: Info: Streaming bitrate is 1000000
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.239]: Info: Creating encoder [hevc_vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.239]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.239]: Info: Color depth: 8-bit
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.239]: Info: Color range: JPEG
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.262]: Info: Streaming bitrate is 1000000
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.281]: Info: Creating encoder [av1_vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.281]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.281]: Info: Color depth: 8-bit
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.281]: Info: Color range: JPEG
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.302]: Info: Streaming bitrate is 1000000
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.321]: Info: Screencasting with XDG portal
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.321]: Info: Requested frame rate [60/1, approx. 60 fps]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.321]: Info: Found display [wayland-0]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.328]: Info: Loaded portal restore token from disk
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.331]: Error: SelectDevices failed with response code: 2
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.331]: Warning: RemoteDesktop.SelectDevices failed, falling back to ScreenCast-only mode
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.343]: Info: Connected to pipewire version 1.4.10
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Video format: 12
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Size: 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: using DMA-BUF buffers
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Video format: 12
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Size: 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.345]: Info: using DMA-BUF buffers
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.353]: Info: Using negotiated resolution 1920x1080
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.353]: Info: Creating encoder [hevc_vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.353]: Info: Color coding: SDR (Rec. 709)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.353]: Info: Color depth: 10-bit
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.353]: Info: Color range: JPEG
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.376]: Info: Streaming bitrate is 1000000
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.398]: Info: Creating encoder [av1_vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.398]: Info: Color coding: SDR (Rec. 709)
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.398]: Info: Color depth: 10-bit
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.398]: Info: Color range: JPEG
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.418]: Info: Streaming bitrate is 1000000
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info: // Testing for available encoders, this may generate errors. You can safely ignore those errors. //
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info:
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info: // Ignore any errors mentioned above, they are not relevant. //
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info:
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info: Found H.264 encoder: h264_vulkan [vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info: Found HEVC encoder: hevc_vulkan [vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.442]: Info: Found AV1 encoder: av1_vulkan [vulkan]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.443]: Info: Starting system tray
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.444]: Info: Adding avahi service REDACTED_HOST
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.444]: Info: Configuration UI available at [https://localhost:47990]
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: libayatana-appindicator is deprecated. Please use libayatana-appindicator-glib in newly written code.
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.467]: Info: System tray created
lut 24 11:58:23 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:23.467]: Info: Starting main loop
lut 24 11:58:24 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:24.379]: Info: Avahi service REDACTED_HOST successfully established.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.525]: Info: Trying encoder [vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.525]: Info: Screencasting with XDG portal
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.525]: Info: Requested frame rate [60/1, approx. 60 fps]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.525]: Info: Found display [wayland-0]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.533]: Info: Loaded portal restore token from disk
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.537]: Error: SelectDevices failed with response code: 2
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.537]: Warning: RemoteDesktop.SelectDevices failed, falling back to ScreenCast-only mode
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.551]: Info: Connected to pipewire version 1.4.10
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.552]: Info: Video format: 12
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.552]: Info: Size: 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.552]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.552]: Info: using DMA-BUF buffers
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.553]: Info: Video format: 12
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.553]: Info: Size: 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.553]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.553]: Info: using DMA-BUF buffers
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.561]: Info: Using negotiated resolution 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.561]: Info: Creating encoder [h264_vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.561]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.561]: Info: Color depth: 8-bit
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.561]: Info: Color range: JPEG
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.591]: Info: Streaming bitrate is 1000000
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.613]: Info: Creating encoder [hevc_vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.613]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.613]: Info: Color depth: 8-bit
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.613]: Info: Color range: JPEG
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.636]: Info: Streaming bitrate is 1000000
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.654]: Info: Creating encoder [av1_vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.654]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.654]: Info: Color depth: 8-bit
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.654]: Info: Color range: JPEG
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.674]: Info: Streaming bitrate is 1000000
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.695]: Info: Screencasting with XDG portal
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.696]: Info: Requested frame rate [60/1, approx. 60 fps]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.696]: Info: Found display [wayland-0]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.702]: Info: Loaded portal restore token from disk
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.705]: Error: SelectDevices failed with response code: 2
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.705]: Warning: RemoteDesktop.SelectDevices failed, falling back to ScreenCast-only mode
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.716]: Info: Connected to pipewire version 1.4.10
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Video format: 12
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Size: 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: using DMA-BUF buffers
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Video format: 12
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Size: 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.718]: Info: using DMA-BUF buffers
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.726]: Info: Using negotiated resolution 1920x1080
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.726]: Info: Creating encoder [hevc_vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.726]: Info: Color coding: SDR (Rec. 709)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.726]: Info: Color depth: 10-bit
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.726]: Info: Color range: JPEG
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.748]: Info: Streaming bitrate is 1000000
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.770]: Info: Creating encoder [av1_vulkan]
⠋ Thinking...lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.770]: Info: Color coding: SDR (Rec. 709)
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.770]: Info: Color depth: 10-bit
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.770]: Info: Color range: JPEG
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.790]: Info: Streaming bitrate is 1000000
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: // Testing for available encoders, this may generate errors. You can safely ignore those errors. //
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info:
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: // Ignore any errors mentioned above, they are not relevant. //
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info:
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: Found H.264 encoder: h264_vulkan [vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: Found HEVC encoder: hevc_vulkan [vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: Found AV1 encoder: av1_vulkan [vulkan]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.811]: Info: Executing [Desktop]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.950]: Info: Video encryption enabled
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.950]: Info: New streaming session started [active sessions: 1]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.974]: Info: CLIENT CONNECTED
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.976]: Info: Loaded portal restore token from disk
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.977]: Info: Screencasting with XDG portal
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.977]: Info: Requested frame rate [60fps]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.977]: Info: Found display [wayland-0]
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.983]: Info: Loaded portal restore token from disk
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.986]: Error: SelectDevices failed with response code: 2
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.986]: Warning: RemoteDesktop.SelectDevices failed, falling back to ScreenCast-only mode
lut 24 11:58:42 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:42.999]: Info: Connected to pipewire version 1.4.10
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.000]: Info: Video format: 12
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.000]: Info: Size: 1920x1080
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.000]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.000]: Info: using DMA-BUF buffers
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.001]: Info: Video format: 12
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.001]: Info: Size: 1920x1080
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.001]: Info: Framerate (from compositor): 0/1 (variable rate capture)
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.001]: Info: using DMA-BUF buffers
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.009]: Info: Using negotiated resolution 1920x1080
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.009]: Info: Creating encoder [h264_vulkan]
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.009]: Info: Color coding: SDR (Rec. 601)
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.009]: Info: Color depth: 8-bit
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.009]: Info: Color range: MPEG
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: WARNING: radv is not a conformant Vulkan implementation, testing use only.
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.036]: Info: Streaming bitrate is 14988000
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.041]: Info: Minimum FPS target set to ~5fps (200ms)
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.473]: Info: Found default monitor by name: alsa_output.REDACTED_PCInalog-stereo.monitor
lut 24 11:58:43 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:43.483]: Info: Opus initialized: 48 kHz, 2 channels, 512 kbps (total), LOWDELAY
lut 24 11:58:51 REDACTED_HOST sunshine[3540]: [2026-02-24 11:58:51.608]: Info: Web UI: [::1] -- not authorized

Copy link
Member

@ReenigneArcher ReenigneArcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I have a review below.

In addition to my review, I have a question. Will there be issues if there is a mismatch in the vulkan header and vulkan loader versions here versus what is used in the build-deps (FFmpeg) repo?

@ReenigneArcher ReenigneArcher marked this pull request as ready for review February 26, 2026 02:04
@neatnoise
Copy link
Author

Thank you, I have a review below.

In addition to my review, I have a question. Will there be issues if there is a mismatch in the vulkan header and vulkan loader versions here versus what is used in the build-deps (FFmpeg) repo?

The build-deps repo bundles Vulkan Headers/Loader v1.4.344 (statically linked into FFmpeg), while my Sunshine compiles against the system's v1.4.341 (CachyOS distro). The two
don't share Vulkan types directly — Sunshine talks to FFmpeg through libavutil/hwcontext_vulkan.h. Since core Vulkan types and ABI haven't changed between these versions, there's no practical risk of mismatch.

- Remove format qualifiers from compute shader to support both
  NV12 (8-bit) and P010 (10-bit) with a single SPIR-V binary
- Detect P010 from FFmpeg sw_format and use R16/RG16 target views
- Rename shader from rgb2nv12 to rgb2yuv to reflect format-agnostic nature
Remove NO_RC_BUF_LIMIT flag from the Vulkan encoder so that
rc_buffer_size is set to a single-frame VBV by the generic encoder
setup. This constrains the hardware rate controller from producing
oversized frames after periods of bitrate undershoot.
When VBR rc_mode is selected, rc_min_rate was pinned to the same value
as rc_max_rate and bit_rate. This prevented the encoder from
undershooting on simple frames, causing accumulated headroom that led
to large bitrate spikes on complex frames.

Clear rc_min_rate to 0 in VBR mode so the encoder can freely vary
bitrate downward, eliminating the budget buildup that causes overshoot.
Cap rc_max_rate to 120% of target bitrate in VBR mode so FFmpeg's
Vulkan encoder passes a meaningful maxBitrate ceiling to the driver.
Without this, maxBitrate == averageBitrate gives the driver no
explicit limit, causing hardware-dependent spikes (e.g. 26->46 Mbit).

Also add NO_RC_BUF_LIMIT flag since FFmpeg's Vulkan encoder does not
read rc_buffer_size (it uses virtualBufferSizeInMs which it never
populates from AVCodecContext).
- Replace C-style arrays with std::array across vulkan_encode.cpp,
  rgb2yuv.spv.h, and video.cpp
- Refactor vk_vram_t from 35 fields to 19 by grouping into sub-structs
  (vk_device_t, compute_pipeline_t, cmd_submission_t, target_state_t)
- Use C++17 if-init-statement for render_path and merge nested if
- Add override to ~vk_vram_t() destructor
- Add & operator to init_hw_device function pointer reference
- Rename set_frame parameter to avoid shadowing member field
- Replace redundant explicit types with auto where cast provides type
- Remove redundant VkAccessFlagBits cast
- Split multi-variable declarations into separate statements
- Replace typedef with using alias in video.cpp
- Remove empty style block from VulkanEncoder.vue
Remove the 120% rc_max_rate cap added in 5d1ee1a. Both vulkan-pr and
vulkan+control now share the same overshoot fix: only rc_min_rate=0 in
VBR mode.
@codecov
Copy link

codecov bot commented Mar 14, 2026

Bundle Report

Changes will increase total bundle size by 2.02kB (0.26%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
sunshine-esm 782.85kB 2.02kB (0.26%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: sunshine-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/_plugin-*.js 420 bytes 353.0kB 0.12%
assets/config-*.js 1.6kB 68.3kB 2.39%

Files in assets/_plugin-*.js:

  • ./src_assets/common/assets/web/public/assets/locale/en.json → Total Size: 38.31kB

Files in assets/config-*.js:

  • ./src_assets/common/assets/web/configs/tabs/ContainerEncoders.vue → Total Size: 2.07kB

  • ./src_assets/common/assets/web/configs/tabs/Advanced.vue → Total Size: 9.39kB

  • ./src_assets/common/assets/web/configs/tabs/encoders/VulkanEncoder.vue → Total Size: 2.75kB

  • ./src_assets/common/assets/web/config.html → Total Size: 0 bytes

@codecov
Copy link

codecov bot commented Mar 14, 2026

Codecov Report

❌ Patch coverage is 0.18587% with 537 lines in your changes missing coverage. Please review.
✅ Project coverage is 16.63%. Comparing base (2a5901b) to head (0b2167e).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/platform/linux/vulkan_encode.cpp 0.00% 505 Missing ⚠️
src/video.cpp 5.00% 19 Missing ⚠️
src/platform/linux/portalgrab.cpp 0.00% 4 Missing ⚠️
src/platform/linux/wlgrab.cpp 0.00% 4 Missing ⚠️
src/platform/linux/kmsgrab.cpp 0.00% 3 Missing ⚠️
src/config.cpp 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4603      +/-   ##
==========================================
- Coverage   17.91%   16.63%   -1.28%     
==========================================
  Files         106      107       +1     
  Lines       21980    21883      -97     
  Branches     9812     9730      -82     
==========================================
- Hits         3937     3640     -297     
- Misses      13335    15129    +1794     
+ Partials     4708     3114    -1594     
Flag Coverage Δ
Archlinux 11.81% <0.00%> (-0.51%) ⬇️
FreeBSD-14.3-aarch64 ?
FreeBSD-14.3-amd64 ?
Homebrew-ubuntu-22.04 14.10% <0.00%> (-0.58%) ⬇️
Linux-AppImage ?
Windows-AMD64 14.98% <0.00%> (-0.01%) ⬇️
Windows-ARM64 13.39% <0.00%> (+0.01%) ⬆️
macOS-arm64 18.61% <100.00%> (+<0.01%) ⬆️
macOS-x86_64 17.07% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/config.h 0.00% <ø> (ø)
src/platform/common.h 32.40% <ø> (ø)
src/config.cpp 0.00% <0.00%> (-3.19%) ⬇️
src/platform/linux/kmsgrab.cpp 3.83% <0.00%> (ø)
src/platform/linux/portalgrab.cpp 2.22% <0.00%> (-1.34%) ⬇️
src/platform/linux/wlgrab.cpp 0.00% <0.00%> (ø)
src/video.cpp 30.85% <5.00%> (-2.49%) ⬇️
src/platform/linux/vulkan_encode.cpp 0.00% <0.00%> (ø)

... and 52 files with indirect coverage changes

@ReenigneArcher
Copy link
Member

ReenigneArcher commented Mar 17, 2026

The failed tests check that the config is setup properly in all places (cpp, html, docs)

[ RUN      ] ConfigConsistencyTest.AllConfigOptionsExistInAllFiles
D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:466: Failure
Failed
Config options missing from files:
  configuration.md missing: vk_rc_mode
  configuration.md missing: vk_tune


[2026-03-14 19:41:10.719]: Tests: From D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:439
[2026-03-14 19:41:10.719]: Tests:   ConfigConsistencyTest/AllConfigOptionsExistInAllFiles started
[2026-03-14 19:41:10.773]: Tests: At D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:466
[2026-03-14 19:41:10.773]: Tests:   Failure: Failed
Config options missing from files:
  configuration.md missing: vk_rc_mode
  configuration.md missing: vk_tune

[2026-03-14 19:41:10.773]: Tests: ConfigConsistencyTest/AllConfigOptionsExistInAllFiles failed
[  FAILED  ] ConfigConsistencyTest.AllConfigOptionsExistInAllFiles (53 ms)
[ RUN      ] ConfigConsistencyTest.ConfigTabsMatchDocumentationSections
D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:505: Failure
Failed
Tab/Section mapping inconsistencies:
  Tab 'vulkan' has no corresponding documentation section


[2026-03-14 19:41:10.773]: Tests: From D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:470
[2026-03-14 19:41:10.773]: Tests:   ConfigConsistencyTest/ConfigTabsMatchDocumentationSections started
[2026-03-14 19:41:10.808]: Tests: At D:/a/Sunshine/Sunshine/tests/integration/test_config_consistency.cpp:505
[2026-03-14 19:41:10.808]: Tests:   Failure: Failed
Tab/Section mapping inconsistencies:
  Tab 'vulkan' has no corresponding documentation section

[2026-03-14 19:41:10.808]: Tests: ConfigConsistencyTest/ConfigTabsMatchDocumentationSections failed
[  FAILED  ] ConfigConsistencyTest.ConfigTabsMatchDocumentationSections (35 ms)

Also, a number of lint errors: https://github.com/LizardByte/Sunshine/actions/runs/23094267559/job/67084016198?pr=4603

- cmake-lint: remove set(Vulkan_FOUND OFF), use SUNSHINE_ENABLE_VULKAN guard
- clang-format: apply formatting to vulkan_encode.cpp and config.h
- trailing whitespace: clean blank line in video.cpp
- docs: add Vulkan Encoder section with vk_tune and vk_rc_mode
- tests: add Vulkan Encoder tab-to-section mapping
@neatnoise
Copy link
Author

@ReenigneArcher fixed, please check now

Keep both vulkan-headers (our addition) and python-jinja/python-setuptools (upstream addition) in Arch PKGBUILD.
@TerjeTL
Copy link

TerjeTL commented Mar 17, 2026

Tried this out on cachyos using rx 9070 xt and working really well on KMS! however portal appears as a green window and immediately disconnects, while wlroots produces a mangled picture running in sway gles2 (expected?). Very positive feedback from my side on KMS, I'll dig into my other issues and get some logs.

@psyke83
Copy link
Contributor

psyke83 commented Mar 17, 2026

Tested latest PR changes and it's working well on RX 6600 via KMS and Portal.

Tried this out on cachyos using rx 9070 xt and working really well on KMS! however portal appears as a green window and immediately disconnects, while wlroots produces a mangled picture running in sway gles2 (expected?). Very positive feedback from my side on KMS, I'll dig into my other issues and get some logs.

It's a known transient issue that's not the fault of this PR. Workaround is available: #4824 (comment)

Copy link
Member

@ReenigneArcher ReenigneArcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just have a few comments. I think this is pretty close to being able to merge!

Sway's GLES2 renderer exports framebuffers in OpenGL's bottom-up
convention and signals this via the Y_INVERT flag. The wlroots capture
stored this flag but never passed it to the Vulkan encoder, resulting
in a mangled picture.

Propagate y_invert through img_descriptor_t to the Vulkan compute
shader, which now flips the source texture Y coordinate when set.
@neatnoise
Copy link
Author

@TerjeTL could you test wlroots with sway gles2? I applied the fix

@TerjeTL
Copy link

TerjeTL commented Mar 18, 2026

@neatnoise pulled the fix and made a new build, can't see any errors in the logs but this is the image i get when i run in that config. Not very confident i haven't messed up on my end, only been running Linux for a few weeks, but does work with main branch.

Steam Big Picture (supposedly :p)
image

@neatnoise
Copy link
Author

When wlroots used GBM can silently allocate tiled buffers but report an unknown modifier. Vulkan then imports the buffer assuming linear layout while the actual memory is tiled. I made a change again @TerjeTL . We might stick with KMS and portal for now otherwise.

Force linear GBM buffer allocation to prevent tiling/modifier mismatch
when importing DMA-BUF into Vulkan.
@TerjeTL
Copy link

TerjeTL commented Mar 18, 2026

@neatnoise That solved the issue on my end, image looks clean now! Thanks for the rapid fixes :)

@neatnoise neatnoise force-pushed the vulkan-pr branch 2 times, most recently from fcfb1df to 8f98e0d Compare March 18, 2026 15:47
… SPIR-V

- Move rgb2yuv.comp to src_assets/linux/assets/shaders/vulkan/
- Remove pre-compiled .spv and .spv.h from repo
- Add CMake rules to compile .comp -> .spv -> C include at build time
- Prefer glslc, fall back to glslangValidator for Ubuntu 22.04 support
- Add shader compiler build dependencies for all supported distros
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
4.3% Duplication on New Code (required ≤ 2%)
2 Duplicated Blocks on New Code (required ≤ 0)
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants