From 363447b7d03a576eafdf4aaf58e7fb825bdeda89 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Thu, 2 Apr 2026 15:57:19 +0200 Subject: [PATCH] radv/video: Use quality level for encode preset instead of tuning mode qualityLevel as a speed/quality tradeoff is better match for encode presets than the tuning mode. In addition we can support more quality levels than what is available from tuning modes, this adds support for High Quality preset on VCN4+. This also makes it possible to use Low Latency tuning with balance and quality presets. Reviewed-by: Benjamin Cheng Part-of: --- src/amd/vulkan/radv_video.c | 44 +-------------------------- src/amd/vulkan/radv_video.h | 1 - src/amd/vulkan/radv_video_enc.c | 53 ++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 64 deletions(-) diff --git a/src/amd/vulkan/radv_video.c b/src/amd/vulkan/radv_video.c index 38d2839f535..3d6a63f24b6 100644 --- a/src/amd/vulkan/radv_video.c +++ b/src/amd/vulkan/radv_video.c @@ -354,38 +354,10 @@ radv_CreateVideoSessionKHR(VkDevice _device, const VkVideoSessionCreateInfoKHR * case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: vid->encode = true; vid->enc_standard = RENCODE_ENCODE_STANDARD_H264; - switch (vid->vk.enc_usage.tuning_mode) { - case VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR: - default: - vid->enc_preset_mode = RENCODE_PRESET_MODE_BALANCE; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_SPEED; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_QUALITY; - break; - } break; case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: vid->encode = true; vid->enc_standard = RENCODE_ENCODE_STANDARD_HEVC; - switch (vid->vk.enc_usage.tuning_mode) { - case VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR: - default: - vid->enc_preset_mode = RENCODE_PRESET_MODE_BALANCE; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_SPEED; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_QUALITY; - break; - } break; case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR: vid->encode = true; @@ -394,20 +366,6 @@ radv_CreateVideoSessionKHR(VkDevice _device, const VkVideoSessionCreateInfoKHR * pdev->info.vcn_ip_version == VCN_4_0_6) { vid->enc_wa_flags = 1; } - switch (vid->vk.enc_usage.tuning_mode) { - case VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR: - default: - vid->enc_preset_mode = RENCODE_PRESET_MODE_BALANCE; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_SPEED; - break; - case VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR: - case VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR: - vid->enc_preset_mode = RENCODE_PRESET_MODE_QUALITY; - break; - } break; default: return VK_ERROR_FEATURE_NOT_PRESENT; @@ -751,7 +709,7 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; enc_caps->maxRateControlLayers = RADV_ENC_MAX_RATE_LAYER; enc_caps->maxBitrate = 1000000000; - enc_caps->maxQualityLevels = 2; + enc_caps->maxQualityLevels = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_4 ? 4 : 3; enc_caps->encodeInputPictureGranularity = pCapabilities->pictureAccessGranularity; enc_caps->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; diff --git a/src/amd/vulkan/radv_video.h b/src/amd/vulkan/radv_video.h index 3d0074aa652..6c019179c66 100644 --- a/src/amd/vulkan/radv_video.h +++ b/src/amd/vulkan/radv_video.h @@ -55,7 +55,6 @@ struct radv_video_session { uint32_t enc_standard; uint32_t enc_wa_flags; - uint32_t enc_preset_mode; }; /** diff --git a/src/amd/vulkan/radv_video_enc.c b/src/amd/vulkan/radv_video_enc.c index 176935096fa..cfdaa1a49b4 100644 --- a/src/amd/vulkan/radv_video_enc.c +++ b/src/amd/vulkan/radv_video_enc.c @@ -2330,30 +2330,30 @@ radv_enc_op_init_rc_vbv(struct radv_cmd_buffer *cmd_buffer) } static void -radv_enc_op_preset(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInfoKHR *enc_info) +radv_enc_op_preset(struct radv_cmd_buffer *cmd_buffer, uint32_t quality_level) { + struct radv_device *device = radv_cmd_buffer_device(cmd_buffer); + const struct radv_physical_device *pdev = radv_device_physical(device); struct radv_video_session *vid = cmd_buffer->video.vid; + uint32_t preset_mode; - if (vid->enc_preset_mode == RENCODE_PRESET_MODE_QUALITY) - preset_mode = RENCODE_IB_OP_SET_QUALITY_ENCODING_MODE; - else if (vid->enc_preset_mode == RENCODE_PRESET_MODE_BALANCE) + switch (quality_level) { + case 1: preset_mode = RENCODE_IB_OP_SET_BALANCE_ENCODING_MODE; - else - preset_mode = RENCODE_IB_OP_SET_SPEED_ENCODING_MODE; - - switch (vid->vk.op) { - case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: { - const struct VkVideoEncodeH265PictureInfoKHR *h265_picture_info = - vk_find_struct_const(enc_info->pNext, VIDEO_ENCODE_H265_PICTURE_INFO_KHR); - const StdVideoEncodeH265PictureInfo *pic = h265_picture_info->pStdPictureInfo; - const StdVideoH265SequenceParameterSet *sps = - vk_video_find_h265_enc_std_sps(cmd_buffer->video.params, pic->pps_seq_parameter_set_id); - if (sps->flags.sample_adaptive_offset_enabled_flag && vid->enc_preset_mode == RENCODE_PRESET_MODE_SPEED) - preset_mode = RENCODE_IB_OP_SET_BALANCE_ENCODING_MODE; break; - } + case 2: + preset_mode = RENCODE_IB_OP_SET_QUALITY_ENCODING_MODE; + break; + case 3: + preset_mode = RENCODE_IB_OP_SET_HIGH_QUALITY_ENCODING_MODE; + break; + case 0: default: + if (pdev->enc_hw_ver < RADV_VIDEO_ENC_HW_5 && vid->vk.op == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) + preset_mode = RENCODE_IB_OP_SET_BALANCE_ENCODING_MODE; + else + preset_mode = RENCODE_IB_OP_SET_SPEED_ENCODING_MODE; break; } @@ -3065,8 +3065,6 @@ radv_vcn_encode_video(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInf } // v2 output format - // op_preset - radv_enc_op_preset(cmd_buffer, enc_info); // op_enc radv_enc_op_enc(cmd_buffer); @@ -3099,7 +3097,9 @@ radv_video_enc_control_video_coding(struct radv_cmd_buffer *cmd_buffer, const Vk bool session_init = false; bool rate_control_init = false; + bool quality_preset_init = false; uint32_t vbv_buffer_level = 64; + uint32_t quality_level = 0; rvcn_enc_rate_ctl_layer_init_t rc_layer_init[RADV_ENC_MAX_RATE_LAYER]; rvcn_enc_rate_ctl_per_picture_t rc_per_pic[RADV_ENC_MAX_RATE_LAYER]; @@ -3123,6 +3123,7 @@ radv_video_enc_control_video_coding(struct radv_cmd_buffer *cmd_buffer, const Vk session_init = true; rate_control_init = true; + quality_preset_init = true; } if (control_info->flags & VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR) { @@ -3235,7 +3236,16 @@ radv_video_enc_control_video_coding(struct radv_cmd_buffer *cmd_buffer, const Vk rate_control_init = true; } - if (!session_init && !rate_control_init) + if (control_info->flags & VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR) { + const struct VkVideoEncodeQualityLevelInfoKHR *quality_info = + vk_find_struct_const(control_info->pNext, VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR); + assert(quality_info); + + quality_level = quality_info->qualityLevel; + quality_preset_init = true; + } + + if (!session_init && !rate_control_init && !quality_preset_init) return; radeon_check_space(device->ws, cmd_buffer->cs->b, 256); @@ -3267,6 +3277,9 @@ radv_video_enc_control_video_coding(struct radv_cmd_buffer *cmd_buffer, const Vk radv_enc_op_init_rc_vbv(cmd_buffer); } + if (quality_preset_init) + radv_enc_op_preset(cmd_buffer, quality_level); + *cmd_buffer->video.enc.p_task_size = cmd_buffer->video.enc.total_task_size; if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2)