Skip to content

Conversation

@neatnoise
Copy link

@neatnoise neatnoise commented Jan 19, 2026

Description

This PR adds Vulkan video encoding support for Linux KMS capture, providing an alternative to VAAPI encoding. AI agent was used heavily for code generation, following the existing VAAPI encoder implementation as the reference pattern.

Changes:

  • Vulkan encoder: New FFmpeg-based Vulkan encoder (h264_vulkan, hevc_vulkan, av1_vulkan) with zero-copy DMA-BUF import via EGL interop - no GPU-to-CPU copies in the capture-encode pipeline
  • kms_vblank option: New config option to enable vblank-synchronized KMS capture, reducing tearing and improving frame pacing when display refresh rate exceeds stream FPS (fixes Screen Tearing/VSync Issue in KDE Plasma Wayland, Gnome Wayland #3189 - long-standing vblank sync issue on Linux KMS)
  • HiDPI fix: Fixed KMS framebuffer scaling to use physical framebuffer dimensions (fb->width/fb->height) instead of logical viewport dimensions, fixing capture on HiDPI displays
  • Web UI: Added Vulkan encoder selection and settings to the configuration interface
  • Documentation: Added docs for vulkan encoder and kms_vblank options in docs/configuration.md

Dependencies:

Requires corresponding PR in LizardByte/build-deps (ffmpeg-vulkan branch) to enable BUILD_FFMPEG_VULKAN option, which adds --enable-vulkan and Vulkan encoder support to 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. Requires vulkan-headers and vulkan-icd-loader packages to be installed (or similar on another distros).

Screenshot

image 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

- Add FFmpeg Vulkan encoder with zero-copy DMA-BUF/EGL interop
- Add kms_vblank option for vblank-synchronized capture
- Fix KMS framebuffer scaling for HiDPI displays
- Add Vulkan encoder settings to web UI
- Add documentation for vulkan encoder and kms_vblank options
@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.

Copy link
Member

Choose a reason for hiding this comment

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

When adding/updating localization, only this file should have updates. The other files should be left untouched. It will be handled automatically by CrowdIn.

Comment on lines +123 to +132
# vulkan video encoding (via FFmpeg)
find_package(Vulkan QUIET)
if(Vulkan_FOUND)
add_compile_definitions(SUNSHINE_BUILD_VULKAN)
include_directories(SYSTEM ${Vulkan_INCLUDE_DIRS})
list(APPEND PLATFORM_LIBRARIES ${Vulkan_LIBRARIES})
list(APPEND PLATFORM_TARGET_FILES
"${CMAKE_SOURCE_DIR}/src/platform/linux/vulkan_encode.h"
"${CMAKE_SOURCE_DIR}/src/platform/linux/vulkan_encode.cpp")
endif()
Copy link
Member

Choose a reason for hiding this comment

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

This pattern is wrong. Check the wayland section just below.

We use a cmake option to indicate if the feature should be on or off. It should be on by default. If the required packages are not found it should fail the build.

Comment on lines +2155 to +2160
<tr>
<td>vulkan</td>
<td>Use FFmpeg Vulkan encoder with zero-copy DMA-BUF (AMD, Intel, NVIDIA on Linux).
Requires FFmpeg built with Vulkan support.
@note{Applies to Linux only.}</td>
</tr>
Copy link
Member

@ReenigneArcher ReenigneArcher Jan 19, 2026

Choose a reason for hiding this comment

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

Suggested change
<tr>
<td>vulkan</td>
<td>Use FFmpeg Vulkan encoder with zero-copy DMA-BUF (AMD, Intel, NVIDIA on Linux).
Requires FFmpeg built with Vulkan support.
@note{Applies to Linux only.}</td>
</tr>
<tr>
<td>vulkan</td>
<td>Use FFmpeg Vulkan encoder with zero-copy DMA-BUF (AMD, Intel, NVIDIA on Linux).
@note{Applies to Linux only.}</td>
</tr>

This is too much info for users, and will probably confuse them.

Edit: to add clarification, users do not need to install FFmpeg, as this is a build only dependency.

# vulkan video encoding (via FFmpeg)
find_package(Vulkan QUIET)
if(Vulkan_FOUND)
add_compile_definitions(SUNSHINE_BUILD_VULKAN)
Copy link
Member

Choose a reason for hiding this comment

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

We use a SUNSHINE_DEFINITIONS list for this. This way it carries over to the test binary build.

#include "src/utility.h"
#include "src/video.h"
#include "vaapi.h"
#ifdef SUNSHINE_BUILD_VULKAN
Copy link
Member

Choose a reason for hiding this comment

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

can we avoid the macro for the include?

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
30 New issues
16.2% Duplication on New Code (required ≤ 2%)
26 New Code Smells (required ≤ 0)
C Reliability Rating on New Code (required ≥ A)
4 New Bugs (required ≤ 0)
4 Duplicated Blocks on New Code (required ≤ 0)

See analysis details on SonarQube Cloud

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

@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.

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.

Screen Tearing/VSync Issue in KDE Plasma Wayland, Gnome Wayland

3 participants