Skip to content

feat(encoder): add VK_VALVE_video_encode_rgb_convertion - #14

Closed
porkloin wants to merge 2 commits into
hgaiser:mainfrom
porkloin:vk-valve-video
Closed

porkloin wants to merge 2 commits into
hgaiser:mainfrom
porkloin:vk-valve-video

Conversation

@porkloin

@porkloin porkloin commented May 8, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in RGB-direct encode path via VK_VALVE_video_encode_rgb_conversion. If a device advertises support for the extension and the caller opts in with `EncodeConfig::with_rgb_input(true), the encoder will take an already RGB formattied input image and functionally skip the conversion step. This has been wired in for H264, HEVC, and AV1.

If support isn't detected, it's a no-op.

For now, this extension only has support on AMD cards, but hopefully additional vendors will get support soon. Tested on 9070XT.

Note: this PR is stacked on top of the commit for #12 because it depends on the work there/would be messy to merge without it. Once #12 is in, I'll rebase without the cherry pick.

@DatCaptainHorse

Copy link
Copy Markdown
Contributor

@porkloin Did you want to still work on this, rebasing against latest main?

If you're too busy with other stuff, I can take it off your hands, considering I'm doing color work in other PRs at this point 🙂

@porkloin

Copy link
Copy Markdown
Contributor Author

@porkloin Did you want to still work on this, rebasing against latest main?

If you're too busy with other stuff, I can take it off your hands, considering I'm doing color work in other PRs at this point 🙂

@DatCaptainHorse My main linux machine other than a steam deck has been in a storage unit for a couple months while I'm traveling and moving to a different state. I'll be moving into my new place and have access to it again on the 15th.

I'd be happy to rebase and update it once the machine is back up and I've got time, but if you're already in the swing of things and it's easy to nab, by all means go for it. I won't be offended to see someone else land the feature!

@hgaiser

hgaiser commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Sorry for never responding here, but we discussed this on Discord :).

If someone wants to pick this up and rebase it, 👍

@porkloin

Copy link
Copy Markdown
Contributor Author

Closing this in favor of #46 which @DatCaptainHorse did an amazing job of putting together. That work supersedes this.

@porkloin porkloin closed this Oct 31, 2026
hgaiser pushed a commit that referenced this pull request Nov 1, 2026
VK_VALVE_video_encode_rgb_conversion lets an encoder take an RGB image and
apply the YUV matrix itself. Where the colour conversion is nothing but
that matrix, which covers ordinary SDR capture, the converter's compute
dispatch and its buffer-to-image copy disappear from the frame entirely.

EncodeConfig::with_rgb_input(format) turns it on. The extension adds one
struct to the video profile, and everything that names the profile has to
name that version of it: the capability and format queries, the input and
DPB images, the query pools and the session. Each codec's one profile
gains it. The input image becomes a single-plane RGB image while the DPB
stays YUV, and Encoder::encode copies an RGB source into it. The matrix
and range come from the configured colour description, checked against
what the driver reports it can do. Encoder::new refuses a configuration
that cannot work before asking the driver anything: a device without the
extension, half-float input, or an encoder not set up for the 4:2:0 at the
input's bit depth that the conversion produces.

VideoContext::supports_rgb_encode_input answers whether that will work for
a codec, input format and colour description, without creating an
encoder: the extension, the codec's RGB profile, the conversion's matrix
and range, and the input format. It shares one profile builder with
supports_encode_format, which now takes the RGB struct as an option rather
than a fourth copy of the per-codec profiles existing.
ColorConverterConfig::rgb_encode_input asks it for a conversion that is
only the matrix, so it no longer says yes for something Encoder::new then
refuses.

On current RADV that matters at once: the conversion reports limited range
only, so full-range RGB input is refused up front rather than producing a
stream whose samples and label disagree.

Chroma siting asks for what a player assumes when the stream does not
say: co-sited with the left luma sample horizontally, midway between rows
vertically (H.264 and H.265 chroma location type 0). A driver that cannot
gets its other option.

The RGB input image is zeroed by the same buffer copy as a YUV one, since
that runs on the transfer queue, where a clear command is not allowed.

On an RX 9060 XT, H.264 lands at 46 dB in luma against the shader path on
the same frames, and H.265 and AV1 at 46 and 48 dB against the H.264
stream. supports_rgb_encode_input agrees with encoder creation for every
codec, input format and colour description tested, here and on an Arc
A310, which has no extension and answers no throughout.

Based on the approach in #14, reworked for the current
encoder structure.

Co-authored-by: Ryan Bateman <rybateman@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

3 participants