Skip to content

vulkan h265 /w 10-bit + fix encoder hang#565

Merged
xytovl merged 8 commits intomasterfrom
feat/vk-hevc-10bit
Nov 2, 2025
Merged

vulkan h265 /w 10-bit + fix encoder hang#565
xytovl merged 8 commits intomasterfrom
feat/vk-hevc-10bit

Conversation

@galister
Copy link
Contributor

@galister galister commented Oct 30, 2025

Vulkan H265 encoding works properly now.

Tested Vulkan encoders (RADV):

  • h264 encode ✅ bitrate change ✅
  • h265 8-bit encode ✅ bitrate change ✅
  • h265 10-bit encode ✅ bitrate change ✅

With 8-bit h265, ffmpeg gives a warning about deprecated format. This also happens with VAAPI, and the picture in the headset looks fine.

[swscaler @ 0x7f2041193e80] deprecated pixel format used, make sure you did set range correctly

@galister galister changed the title vulkan h265 /w 10-bit + fix encoder hang wip: vulkan h265 /w 10-bit + fix encoder hang Oct 30, 2025
@galister
Copy link
Contributor Author

galister commented Oct 30, 2025

hold on with this, just noticed a pretty big flaw

@galister galister force-pushed the feat/vk-hevc-10bit branch 3 times, most recently from 7a3b6d0 to 7beb4d5 Compare November 1, 2025 04:02
@galister galister force-pushed the feat/vk-hevc-10bit branch 4 times, most recently from 56cce32 to 7ee445d Compare November 2, 2025 03:21
@galister galister changed the title wip: vulkan h265 /w 10-bit + fix encoder hang vulkan h265 /w 10-bit + fix encoder hang Nov 2, 2025
@galister
Copy link
Contributor Author

galister commented Nov 2, 2025

removed wip as it is working now. let's continue with the review.

Comment on lines +44 to +60
static uint32_t find_lsb(uint32_t v)
{
for (int i = 0; i < 32; i++)
if (v & (1u << i))
return i;

return UINT32_MAX;
}

static uint32_t find_msb(uint32_t v)
{
for (int i = 31; i >= 0; i--)
if (v & (1u << i))
return i;

return UINT32_MAX;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Those look like countl_one and countr_one from https://en.cppreference.com/w/cpp/utility/bit.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for find_lsb we could technically use std::countr_zero(v) instead, but if v is zero then it'll give the wrong result, so we can't really have a one-liner → would need to keep the helper function either way

for find_msb it'd look something like 31 - std::countl_zero(v) but again v == 0 needs to be handled separately.

keep in mind i'm not familiar with the c++ std library. it's the first time i'm hearing about these functions. but this is the idea i'm getting from reading the reference pages. please correct me if i'm wrong.

i think this for implementation is easier to comprehend for both cases.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If the edge cases (returning UINT32_MAX) are supposed to be used, then

uint32_t max_transform_hierarchy = (find_msb((uint32_t)encode_h265_caps.ctbSizes) + 4) - (find_lsb((uint32_t)encode_h265_caps.transformBlockSizes) + 2);

is going to overflow, is this intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

throwing exception now

@xytovl
Copy link
Collaborator

xytovl commented Nov 2, 2025

Needs doc and dashboard updates to allow vulkan/h265

Comment on lines +422 to +427
if (st_rps.used_by_curr_pic_s0_flag == 0)
{
// ref_slot is too old → encode an IDR instead
ref_slot.reset();
poc_history.clear();
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This happens after video_cmd_buf.beginVideoCodingKHR has been called, which already uses ref_slot. I don't think this will work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did wonder about this. I had no chance to test, but nothing in the spec indicated that it wouldn't work.

  • ref_slot here is the local for encode_info_next.
    • base class will still do setReferenceSlots, but this is fine.
  • no ref_slotencode_info_next configures for IDR instead of P-frames.
  • spec hints that reference slots are ignored in case of IDR/CRA, so they're ok to be set in this case.

Comment on lines 471 to +477
case encoder_name::X264:
case encoder_name::Vulkan:
return {video_codec::H264};
return {
video_codec::CodecAuto,
video_codec::H264,
video_codec::H265,
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

x264 falls through, vulkan should be be its own clause

@xytovl xytovl merged commit 505de3d into master Nov 2, 2025
42 checks passed
@galister galister deleted the feat/vk-hevc-10bit branch November 5, 2025 01:13
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.

2 participants