radv/video: Use new video codec caps

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Reviewed-by: Benjamin Cheng <benjamin.cheng@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35431>
This commit is contained in:
David Rosca 2026-05-05 10:16:40 +02:00 committed by Marge Bot
parent 4487162a7a
commit 280cb489ae
5 changed files with 256 additions and 404 deletions

View file

@ -789,19 +789,25 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.KHR_video_maintenance1 = pdev->video_decode_enabled || pdev->video_encode_enabled,
.KHR_video_maintenance2 = pdev->video_decode_enabled || pdev->video_encode_enabled,
.KHR_video_queue = pdev->video_decode_enabled || pdev->video_encode_enabled,
.KHR_video_decode_av1 = (pdev->info.vcn_ip_version >= VCN_3_0_0 && pdev->info.vcn_ip_version != VCN_3_0_33 &&
VIDEO_CODEC_AV1DEC && pdev->video_decode_enabled),
.KHR_video_decode_av1 =
VIDEO_CODEC_AV1DEC && pdev->video_decode_enabled && pdev->info.video_caps.dec[AC_VIDEO_CODEC_AV1].supported,
.KHR_video_decode_queue = pdev->video_decode_enabled,
.KHR_video_decode_h264 = VIDEO_CODEC_H264DEC && pdev->video_decode_enabled,
.KHR_video_decode_h265 = pdev->info.family >= CHIP_TONGA && VIDEO_CODEC_H265DEC && pdev->video_decode_enabled,
.KHR_video_decode_vp9 =
(radv_video_decode_vp9_supported(pdev) && VIDEO_CODEC_VP9DEC && pdev->video_decode_enabled),
.KHR_video_encode_h264 = VIDEO_CODEC_H264ENC && pdev->video_encode_enabled,
.KHR_video_encode_h265 = VIDEO_CODEC_H265ENC && pdev->video_encode_enabled,
.KHR_video_decode_h264 =
VIDEO_CODEC_H264DEC && pdev->video_decode_enabled && pdev->info.video_caps.dec[AC_VIDEO_CODEC_AVC].supported,
.KHR_video_decode_h265 =
VIDEO_CODEC_H265DEC && pdev->video_decode_enabled && pdev->info.video_caps.dec[AC_VIDEO_CODEC_HEVC].supported,
.KHR_video_decode_vp9 = VIDEO_CODEC_VP9DEC && pdev->video_decode_enabled &&
pdev->info.video_caps.dec[AC_VIDEO_CODEC_VP9].supported &&
pdev->info.video_caps.dec[AC_VIDEO_CODEC_VP9].vp9.uncompressed_header_offset,
.KHR_video_encode_h264 =
VIDEO_CODEC_H264ENC && pdev->video_encode_enabled && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC].supported,
.KHR_video_encode_h265 =
VIDEO_CODEC_H265ENC && pdev->video_encode_enabled && pdev->info.video_caps.enc[AC_VIDEO_CODEC_HEVC].supported,
.KHR_video_encode_av1 =
(radv_video_encode_av1_supported(pdev) && VIDEO_CODEC_AV1ENC && pdev->video_encode_enabled),
VIDEO_CODEC_AV1ENC && pdev->video_encode_enabled && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AV1].supported,
.KHR_video_encode_intra_refresh = pdev->video_encode_enabled,
.KHR_video_encode_quantization_map = pdev->video_encode_enabled && radv_video_encode_qp_map_supported(pdev),
.KHR_video_encode_quantization_map =
pdev->video_encode_enabled && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC].qp_map,
.KHR_video_encode_queue = pdev->video_encode_enabled,
.KHR_vulkan_memory_model = true,
.KHR_workgroup_memory_explicit_layout = true,
@ -950,7 +956,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.VALVE_mutable_descriptor_type = true,
.VALVE_shader_mixed_float_dot_product = pdev->info.compiler_info.has_accelerated_dot_product,
.VALVE_video_encode_rgb_conversion =
pdev->video_encode_enabled && pdev->info.vcn_ip_version >= VCN_2_0_0 && pdev->info.vcn_ip_version != VCN_2_2_0,
pdev->video_encode_enabled && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC].efc,
};
*out_ext = ext;
}
@ -3010,22 +3016,22 @@ radv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, ui
VkQueueFamilyVideoPropertiesKHR *prop = (VkQueueFamilyVideoPropertiesKHR *)ext;
prop->videoCodecOperations = 0;
if (pQueueFamilyProperties[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
if (VIDEO_CODEC_H264DEC)
if (VIDEO_CODEC_H264DEC && pdev->info.video_caps.dec[AC_VIDEO_CODEC_AVC].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR;
if (VIDEO_CODEC_H265DEC)
if (VIDEO_CODEC_H265DEC && pdev->info.video_caps.dec[AC_VIDEO_CODEC_HEVC].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR;
if (VIDEO_CODEC_AV1DEC && pdev->info.vcn_ip_version >= VCN_3_0_0 &&
pdev->info.vcn_ip_version != VCN_3_0_33)
if (VIDEO_CODEC_AV1DEC && pdev->info.video_caps.dec[AC_VIDEO_CODEC_AV1].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
if (VIDEO_CODEC_VP9DEC)
if (VIDEO_CODEC_VP9DEC && pdev->info.video_caps.dec[AC_VIDEO_CODEC_VP9].supported &&
pdev->info.video_caps.dec[AC_VIDEO_CODEC_VP9].vp9.uncompressed_header_offset)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR;
}
if (pQueueFamilyProperties[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) {
if (VIDEO_CODEC_H264ENC)
if (VIDEO_CODEC_H264ENC && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR;
if (VIDEO_CODEC_H265ENC)
if (VIDEO_CODEC_H265ENC && pdev->info.video_caps.enc[AC_VIDEO_CODEC_HEVC].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR;
if (VIDEO_CODEC_AV1ENC && radv_video_encode_av1_supported(pdev))
if (VIDEO_CODEC_AV1ENC && pdev->info.video_caps.enc[AC_VIDEO_CODEC_AV1].supported)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR;
}
break;

View file

@ -2367,7 +2367,8 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
break;
}
case VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR: {
const bool write_memory = radv_video_write_memory_supported(pdev) == RADV_VIDEO_WRITE_MEMORY_SUPPORT_FULL;
const bool write_memory =
pdev->info.video_caps.queue[AMD_IP_VCN_ENC].write_memory == AC_VIDEO_WRITE_MEMORY_SUPPORT_FULL;
uint32_t *src32 = (uint32_t *)src;
uint32_t ready_idx = write_memory ? RADV_ENC_FEEDBACK_STATUS_IDX : 1;
uint32_t value;

View file

@ -45,34 +45,6 @@ set_reg(struct radv_cmd_buffer *cmd_buffer, unsigned reg, uint32_t val)
radeon_end();
}
bool
radv_check_vcn_fw_version(const struct radv_physical_device *pdev, uint32_t dec, uint32_t enc, uint32_t rev)
{
return pdev->info.vcn_dec_version > dec || pdev->info.vcn_enc_minor_version > enc ||
(pdev->info.vcn_dec_version == dec && pdev->info.vcn_enc_minor_version == enc &&
pdev->info.vcn_fw_revision >= rev);
}
static bool
radv_enable_tier3(struct radv_physical_device *pdev, VkVideoCodecOperationFlagBitsKHR operation)
{
if (pdev->info.vcn_ip_version < VCN_5_0_0)
return false;
if (operation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
return radv_check_vcn_fw_version(pdev, 9, 9, 14);
return true;
}
static bool
radv_enable_tier2(struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_3_0_0)
return true;
return false;
}
static uint32_t
radv_video_get_db_alignment(struct radv_physical_device *pdev, int width, bool is_h265_main_10_or_av1)
{
@ -124,12 +96,12 @@ radv_vcn_write_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t va, unsigned
struct radv_physical_device *pdev = radv_device_physical(device);
struct rvcn_sq_var sq;
struct radv_cmd_stream *cs = cmd_buffer->cs;
enum radv_video_write_memory_support support = radv_video_write_memory_supported(pdev);
enum ac_video_write_memory_support support = pdev->info.video_caps.queue[cs->hw_ip].write_memory;
if (support == RADV_VIDEO_WRITE_MEMORY_SUPPORT_NONE)
if (support == AC_VIDEO_WRITE_MEMORY_SUPPORT_NONE)
return;
if (support == RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS) {
if (support == AC_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS) {
fprintf(stderr, "radv: VCN WRITE_MEMORY requires PCIe atomics support. Expect issues "
"if PCIe atomics are not enabled on current device.\n");
}
@ -165,12 +137,7 @@ radv_vcn_write_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t va, unsigned
void
radv_init_physical_device_decoder(struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_4_0_0)
pdev->vid_decode_ip = AMD_IP_VCN_UNIFIED;
else if (radv_has_uvd(pdev))
pdev->vid_decode_ip = AMD_IP_UVD;
else
pdev->vid_decode_ip = AMD_IP_VCN_DEC;
pdev->vid_decode_ip = pdev->info.video_caps.dec[AC_VIDEO_CODEC_AVC].ip_type;
switch (pdev->info.vcn_ip_version) {
case VCN_1_0_0:
@ -220,7 +187,9 @@ radv_probe_video_decode(struct radv_physical_device *pdev)
return;
/* WRITE_MEMORY is needed for SetEvent and is required to pass CTS */
pdev->video_decode_enabled = radv_video_write_memory_supported(pdev);
enum amd_ip_type decode_ip = pdev->info.video_caps.dec[AC_VIDEO_CODEC_AVC].ip_type;
pdev->video_decode_enabled =
pdev->info.video_caps.queue[decode_ip].write_memory != AC_VIDEO_WRITE_MEMORY_SUPPORT_NONE;
if (instance->experimental_flags & RADV_EXPERIMENTAL_VIDEO_DECODE) {
pdev->video_decode_enabled = true;
@ -463,6 +432,9 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
if (result != VK_SUCCESS)
return result;
struct ac_video_dec_codec_caps *dec_caps;
struct ac_video_enc_codec_caps *enc_caps;
switch (pVideoProfile->videoCodecOperation) {
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: {
const struct VkVideoDecodeH264ProfileInfoKHR *h264_profile =
@ -479,12 +451,13 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
break;
}
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: {
const bool have_10bit = pdev->info.family >= CHIP_STONEY;
const struct VkVideoDecodeH265ProfileInfoKHR *h265_profile =
vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_H265_PROFILE_INFO_KHR);
dec_caps = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_HEVC];
if (h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN &&
(!have_10bit || h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10) &&
(!dec_caps->hevc.main10 || h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10) &&
h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE)
return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
@ -494,12 +467,13 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
break;
}
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: {
const bool have_12bit = pdev->info.vcn_ip_version >= VCN_5_0_0 || pdev->info.vcn_ip_version == VCN_4_0_0;
const struct VkVideoDecodeAV1ProfileInfoKHR *av1_profile =
vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_AV1_PROFILE_INFO_KHR);
dec_caps = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_AV1];
if (av1_profile->stdProfile != STD_VIDEO_AV1_PROFILE_MAIN &&
(!have_12bit || av1_profile->stdProfile != STD_VIDEO_AV1_PROFILE_PROFESSIONAL))
(!dec_caps->av1.profile2 || av1_profile->stdProfile != STD_VIDEO_AV1_PROFILE_PROFESSIONAL))
return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
if (pVideoProfile->chromaSubsampling != VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR &&
@ -535,12 +509,13 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
break;
}
case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
const bool have_10bit = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2;
const struct VkVideoEncodeH265ProfileInfoKHR *h265_profile =
vk_find_struct_const(pVideoProfile->pNext, VIDEO_ENCODE_H265_PROFILE_INFO_KHR);
enc_caps = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_HEVC];
if (h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN &&
(!have_10bit || h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10) &&
(!enc_caps->hevc.main10 || h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10) &&
h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE)
return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
@ -571,17 +546,34 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
return VK_SUCCESS;
}
uint32_t
radv_video_get_qp_map_texel_size(VkVideoCodecOperationFlagBitsKHR codec)
void
radv_video_get_caps(struct radv_physical_device *pdev, VkVideoCodecOperationFlagBitsKHR op,
struct ac_video_dec_codec_caps **dec, struct ac_video_enc_codec_caps **enc)
{
switch (codec) {
switch (op) {
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
*dec = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_AVC];
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
*dec = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_HEVC];
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
*dec = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_AV1];
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
return 16;
*enc = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC];
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
*enc = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_HEVC];
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR:
*dec = &pdev->info.video_caps.dec[AC_VIDEO_CODEC_VP9];
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR:
return 64;
*enc = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_AV1];
break;
default:
UNREACHABLE("Unsupported video codec operation");
UNREACHABLE("unsupported operation");
}
}
@ -590,93 +582,43 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
VkVideoCapabilitiesKHR *pCapabilities)
{
VK_FROM_HANDLE(radv_physical_device, pdev, physicalDevice);
const struct video_codec_cap *cap = NULL;
bool is_encode = false;
struct ac_video_dec_codec_caps *dcap = NULL;
struct ac_video_enc_codec_caps *ecap = NULL;
struct VkVideoDecodeCapabilitiesKHR *dec_caps = NULL;
struct VkVideoEncodeCapabilitiesKHR *enc_caps = NULL;
VkResult res = radv_video_is_profile_supported(pdev, pVideoProfile);
if (res != VK_SUCCESS)
return res;
switch (pVideoProfile->videoCodecOperation) {
#ifndef _WIN32
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
cap = &pdev->info.dec_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC];
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
cap = &pdev->info.dec_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC];
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
cap = &pdev->info.dec_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1];
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
cap = &pdev->info.enc_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC];
is_encode = true;
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
cap = &pdev->info.enc_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC];
is_encode = true;
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR:
cap = &pdev->info.dec_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9];
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR:
cap = &pdev->info.enc_caps.codec_info[AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1];
is_encode = true;
break;
#endif
default:
UNREACHABLE("unsupported operation");
}
if (cap && !cap->valid)
cap = NULL;
if (cap) {
pCapabilities->maxCodedExtent.width = cap->max_width;
pCapabilities->maxCodedExtent.height = cap->max_height;
} else {
switch (pVideoProfile->videoCodecOperation) {
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
pCapabilities->maxCodedExtent.width = (pdev->info.family < CHIP_TONGA) ? 2048 : 4096;
pCapabilities->maxCodedExtent.height = (pdev->info.family < CHIP_TONGA) ? 1152 : 4096;
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
pCapabilities->maxCodedExtent.width =
(pdev->info.family < CHIP_RENOIR) ? ((pdev->info.family < CHIP_TONGA) ? 2048 : 4096) : 8192;
pCapabilities->maxCodedExtent.height =
(pdev->info.family < CHIP_RENOIR) ? ((pdev->info.family < CHIP_TONGA) ? 1152 : 4096) : 4352;
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR:
pCapabilities->maxCodedExtent.width =
(pdev->info.family < CHIP_RENOIR) ? ((pdev->info.family < CHIP_TONGA) ? 2048 : 4096) : 8192;
pCapabilities->maxCodedExtent.height =
(pdev->info.family < CHIP_RENOIR) ? ((pdev->info.family < CHIP_TONGA) ? 1152 : 4096) : 4352;
break;
default:
break;
}
}
radv_video_get_caps(pdev, pVideoProfile->videoCodecOperation, &dcap, &ecap);
pCapabilities->flags = 0;
pCapabilities->pictureAccessGranularity.width = VK_VIDEO_H264_MACROBLOCK_WIDTH;
pCapabilities->pictureAccessGranularity.height = VK_VIDEO_H264_MACROBLOCK_HEIGHT;
pCapabilities->minCodedExtent.width = 64;
pCapabilities->minCodedExtent.height = 64;
struct VkVideoDecodeCapabilitiesKHR *dec_caps = NULL;
struct VkVideoEncodeCapabilitiesKHR *enc_caps = NULL;
if (!is_encode) {
if (dcap) {
pCapabilities->minBitstreamBufferOffsetAlignment = dcap->bitstream_address_alignment;
pCapabilities->minBitstreamBufferSizeAlignment = dcap->bitstream_size_alignment;
pCapabilities->pictureAccessGranularity.width = VK_VIDEO_H264_MACROBLOCK_WIDTH;
pCapabilities->pictureAccessGranularity.height = VK_VIDEO_H264_MACROBLOCK_HEIGHT;
pCapabilities->minCodedExtent.width = dcap->min_width;
pCapabilities->minCodedExtent.height = dcap->min_height;
pCapabilities->maxCodedExtent.width = dcap->max_width;
pCapabilities->maxCodedExtent.height = dcap->max_height;
pCapabilities->maxDpbSlots = dcap->max_dpb_slots;
pCapabilities->maxActiveReferencePictures = dcap->max_active_refs;
if (dcap->tiers & (AC_VIDEO_DEC_TIER2 | AC_VIDEO_DEC_TIER3))
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
dec_caps =
(struct VkVideoDecodeCapabilitiesKHR *)vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_CAPABILITIES_KHR);
if (dec_caps) {
dec_caps->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
if (radv_enable_tier3(pdev, pVideoProfile->videoCodecOperation))
if (dcap->tiers & AC_VIDEO_DEC_TIER3)
dec_caps->flags |= VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
}
pCapabilities->minBitstreamBufferOffsetAlignment = 128;
pCapabilities->minBitstreamBufferSizeAlignment = 128;
} else {
enc_caps = vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_CAPABILITIES_KHR);
struct VkVideoEncodeIntraRefreshCapabilitiesKHR *intra_refresh_caps =
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR);
struct VkVideoEncodeQuantizationMapCapabilitiesKHR *qp_map_caps =
@ -684,21 +626,39 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
struct VkVideoEncodeRgbConversionCapabilitiesVALVE *rgb_caps =
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_RGB_CONVERSION_CAPABILITIES_VALVE);
pCapabilities->minBitstreamBufferOffsetAlignment = ecap->bitstream_address_alignment;
pCapabilities->minBitstreamBufferSizeAlignment = ecap->bitstream_size_alignment;
pCapabilities->pictureAccessGranularity.width = ecap->width_alignment;
pCapabilities->pictureAccessGranularity.height = ecap->height_alignment;
pCapabilities->minCodedExtent.width = ecap->min_width;
pCapabilities->minCodedExtent.height = ecap->min_height;
pCapabilities->maxCodedExtent.width = ecap->max_width;
pCapabilities->maxCodedExtent.height = ecap->max_height;
pCapabilities->maxDpbSlots = ecap->max_dpb_slots;
pCapabilities->maxActiveReferencePictures = ecap->max_active_refs;
if (ecap->separate_refs)
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
enc_caps = vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_CAPABILITIES_KHR);
if (enc_caps) {
enc_caps->flags = 0;
enc_caps->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR |
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR |
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
enc_caps->maxRateControlLayers = RADV_ENC_MAX_RATE_LAYER;
enc_caps->maxBitrate = 1000000000;
enc_caps->maxQualityLevels = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_4 ? 4 : 3;
enc_caps->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
if (ecap->qp_map)
enc_caps->flags |= VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
if (ecap->rc.cbr)
enc_caps->rateControlModes |= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
if (ecap->rc.vbr)
enc_caps->rateControlModes |= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
enc_caps->maxRateControlLayers = ecap->max_temporal_layers;
enc_caps->maxBitrate = ecap->max_bitrate;
enc_caps->maxQualityLevels = ecap->quality_levels;
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;
if (radv_video_encode_qp_map_supported(pdev))
enc_caps->flags |= VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
}
if (intra_refresh_caps) {
intra_refresh_caps->intraRefreshModes = VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_BASED_BIT_KHR |
VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_ROW_BASED_BIT_KHR |
@ -708,11 +668,12 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
intra_refresh_caps->partitionIndependentIntraRefreshRegions = true;
intra_refresh_caps->nonRectangularIntraRefreshRegions = false;
}
if (qp_map_caps) {
const uint32_t qp_map_texel_size = radv_video_get_qp_map_texel_size(pVideoProfile->videoCodecOperation);
qp_map_caps->maxQuantizationMapExtent.width = pCapabilities->maxCodedExtent.width / qp_map_texel_size;
qp_map_caps->maxQuantizationMapExtent.height = pCapabilities->maxCodedExtent.height / qp_map_texel_size;
qp_map_caps->maxQuantizationMapExtent.width = pCapabilities->maxCodedExtent.width / ecap->qp_map_texel_size;
qp_map_caps->maxQuantizationMapExtent.height = pCapabilities->maxCodedExtent.height / ecap->qp_map_texel_size;
}
if (rgb_caps) {
rgb_caps->rgbModels = VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_709_BIT_VALVE |
VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_2020_BIT_VALVE;
@ -722,10 +683,6 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
rgb_caps->yChromaOffsets = VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_MIDPOINT_BIT_VALVE |
VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_COSITED_EVEN_BIT_VALVE;
}
pCapabilities->minBitstreamBufferOffsetAlignment = 256;
pCapabilities->minBitstreamBufferSizeAlignment = 8;
if (pdev->info.vcn_ip_version >= VCN_5_0_0)
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
}
switch (pVideoProfile->videoCodecOperation) {
@ -733,15 +690,9 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
struct VkVideoDecodeH264CapabilitiesKHR *ext =
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H264_CAPABILITIES_KHR);
pCapabilities->maxDpbSlots = RADV_VIDEO_H264_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures = RADV_VIDEO_H264_MAX_NUM_REF_FRAME;
/* for h264 on navi21+ separate dpb images should work */
if (radv_enable_tier2(pdev))
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
ext->fieldOffsetGranularity.x = 0;
ext->fieldOffsetGranularity.y = 0;
ext->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1;
ext->maxLevelIdc = dcap->max_level;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION;
break;
@ -750,12 +701,7 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
struct VkVideoDecodeH265CapabilitiesKHR *ext =
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H265_CAPABILITIES_KHR);
pCapabilities->maxDpbSlots = RADV_VIDEO_H265_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures = RADV_VIDEO_H265_MAX_NUM_REF_FRAME;
/* for h265 on navi21+ separate dpb images should work */
if (radv_enable_tier2(pdev))
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
ext->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_1;
ext->maxLevelIdc = dcap->max_level;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION;
break;
@ -763,37 +709,24 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: {
struct VkVideoDecodeAV1CapabilitiesKHR *ext =
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_AV1_CAPABILITIES_KHR);
const struct VkVideoDecodeAV1ProfileInfoKHR *av1_profile =
vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_AV1_PROFILE_INFO_KHR);
if (av1_profile->stdProfile == STD_VIDEO_AV1_PROFILE_PROFESSIONAL)
if (av1_profile->stdProfile == STD_VIDEO_AV1_PROFILE_PROFESSIONAL && !dcap->av1.profile2_tier3)
dec_caps->flags &= ~VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
pCapabilities->maxDpbSlots = RADV_VIDEO_AV1_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures = RADV_VIDEO_AV1_MAX_NUM_REF_FRAME;
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
ext->maxLevel = STD_VIDEO_AV1_LEVEL_6_1; /* For VCN3/4, the only h/w currently with AV1 decode support */
ext->maxLevel = dcap->max_level;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION;
pCapabilities->minCodedExtent.width = 16;
pCapabilities->minCodedExtent.height = 16;
break;
}
case VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR: {
struct VkVideoDecodeVP9CapabilitiesKHR *ext =
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_VP9_CAPABILITIES_KHR);
pCapabilities->maxDpbSlots = RADV_VIDEO_VP9_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures = RADV_VIDEO_VP9_MAX_NUM_REF_FRAME;
if (pdev->info.vcn_ip_version >= VCN_3_0_0)
pCapabilities->flags |= VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
ext->maxLevel = STD_VIDEO_VP9_LEVEL_6_2;
ext->maxLevel = dcap->max_level;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_SPEC_VERSION;
pCapabilities->minCodedExtent.width = 16;
pCapabilities->minCodedExtent.height = 16;
break;
}
case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: {
@ -805,15 +738,15 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
ext->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR |
VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR |
VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3)
if (ecap->avc.b_l0_refs)
ext->flags |= VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR;
ext->maxLevelIdc = cap ? cap->max_level : 0;
ext->maxSliceCount = 128;
ext->maxPPictureL0ReferenceCount = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3 ? 2 : 1;
ext->maxBPictureL0ReferenceCount = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3 ? 1 : 0;
ext->maxL1ReferenceCount = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3 ? 1 : 0;
ext->maxTemporalLayerCount = 4;
ext->maxLevelIdc = ecap->max_level;
ext->maxSliceCount = ecap->max_slices;
ext->maxPPictureL0ReferenceCount = ecap->avc.p_l0_refs;
ext->maxBPictureL0ReferenceCount = ecap->avc.b_l0_refs;
ext->maxL1ReferenceCount = ecap->avc.l1_refs;
ext->maxTemporalLayerCount = ecap->max_temporal_layers;
ext->expectDyadicTemporalLayerPattern = false;
ext->minQp = 0;
ext->maxQp = 51;
@ -822,18 +755,13 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
ext->stdSyntaxFlags = VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR |
VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_KHR |
VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_KHR;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3)
if (ecap->avc.l1_refs)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_KHR;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5)
if (ecap->avc.transform_8x8)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION;
pCapabilities->maxDpbSlots = RADV_VIDEO_H264_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures =
MAX2(ext->maxPPictureL0ReferenceCount, ext->maxBPictureL0ReferenceCount + ext->maxL1ReferenceCount);
pCapabilities->minCodedExtent.width = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 96 : 128;
pCapabilities->minCodedExtent.height = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 32 : 128;
if (qp_map_caps) {
qp_map_caps->minQpDelta = -51;
@ -847,31 +775,27 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
struct VkVideoEncodeH265QuantizationMapCapabilitiesKHR *qp_map_caps =
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_H265_QUANTIZATION_MAP_CAPABILITIES_KHR);
pCapabilities->pictureAccessGranularity.width = VK_VIDEO_H265_CTU_MAX_WIDTH;
if (enc_caps) {
enc_caps->encodeInputPictureGranularity = pCapabilities->pictureAccessGranularity;
/* VCN1 can't enable rate control modes or qp maps due to missing cu_qp_delta FW interface. */
if (pdev->enc_hw_ver == RADV_VIDEO_ENC_HW_1_2) {
enc_caps->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
enc_caps->flags &= ~VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
}
if (enc_caps && !ecap->hevc.cu_qp_delta) {
enc_caps->flags &= ~VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
enc_caps->rateControlModes &=
~(VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR);
}
ext->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR |
VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR |
VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR;
ext->maxLevelIdc = cap ? cap->max_level : 0;
ext->maxSliceSegmentCount = 128;
ext->maxLevelIdc = ecap->max_level;
ext->maxSliceSegmentCount = ecap->max_slices;
ext->maxTiles.width = 1;
ext->maxTiles.height = 1;
ext->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
ext->transformBlockSizes =
VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR |
VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR;
ext->maxPPictureL0ReferenceCount = 1;
ext->maxBPictureL0ReferenceCount = 0;
ext->maxL1ReferenceCount = 0;
ext->maxSubLayerCount = 4;
ext->maxPPictureL0ReferenceCount = ecap->hevc.p_l0_refs;
ext->maxBPictureL0ReferenceCount = ecap->hevc.b_l0_refs;
ext->maxL1ReferenceCount = ecap->hevc.l1_refs;
ext->maxSubLayerCount = ecap->max_temporal_layers;
ext->expectDyadicTemporalSubLayerPattern = false;
ext->minQp = 0;
ext->maxQp = 51;
@ -879,22 +803,16 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
ext->requiresGopRemainingFrames = false;
ext->stdSyntaxFlags = VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR |
VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_KHR |
VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR |
VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_KHR;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2)
if (ecap->hevc.sao)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_3)
if (ecap->hevc.transform_skip)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR |
VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_KHR;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION;
pCapabilities->maxDpbSlots = RADV_VIDEO_H265_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures =
MAX2(ext->maxPPictureL0ReferenceCount, ext->maxBPictureL0ReferenceCount + ext->maxL1ReferenceCount);
pCapabilities->minCodedExtent.width = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 384 : 130;
pCapabilities->minCodedExtent.height = 128;
if (qp_map_caps) {
qp_map_caps->minQpDelta = -51;
@ -908,64 +826,53 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
struct VkVideoEncodeAV1QuantizationMapCapabilitiesKHR *qp_map_caps =
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR);
pCapabilities->maxDpbSlots = RADV_VIDEO_AV1_MAX_DPB_SLOTS;
pCapabilities->maxActiveReferencePictures = RADV_VIDEO_AV1_MAX_NUM_REF_FRAME;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION;
ext->flags = VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR |
VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR |
VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR;
ext->maxLevel = STD_VIDEO_AV1_LEVEL_6_0;
ext->codedPictureAlignment.width = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 8 : 64;
ext->codedPictureAlignment.height = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 2 : 16;
pCapabilities->pictureAccessGranularity = ext->codedPictureAlignment;
if (enc_caps)
enc_caps->encodeInputPictureGranularity = pCapabilities->pictureAccessGranularity;
ext->maxTiles.width = 2;
ext->maxTiles.height = 16;
ext->minTileSize.width = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 256 : 128;
ext->minTileSize.height = 64;
ext->maxLevel = ecap->max_level;
ext->codedPictureAlignment.width = ecap->width_alignment;
ext->codedPictureAlignment.height = ecap->height_alignment;
ext->maxTiles.width = ecap->av1.max_tile_cols;
ext->maxTiles.height = ecap->av1.max_tile_rows;
ext->minTileSize.width = ecap->av1.min_tile_width;
ext->minTileSize.height = ecap->av1.min_tile_height;
ext->maxTileSize.width = 4096;
ext->maxTileSize.height = 4096;
ext->superblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR;
ext->maxSingleReferenceCount = 1;
ext->maxSingleReferenceCount = ecap->av1.single_refs;
ext->singleReferenceNameMask =
(1 << (STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME - STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME));
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5) {
ext->maxUnidirectionalCompoundReferenceCount = 2;
ext->maxUnidirectionalCompoundGroup1ReferenceCount = 2;
ext->maxUnidirectionalCompoundReferenceCount = ecap->av1.unidir_refs;
ext->maxUnidirectionalCompoundGroup1ReferenceCount = ecap->av1.unidir_refs;
ext->unidirectionalCompoundReferenceNameMask = 0;
if (ext->maxUnidirectionalCompoundReferenceCount) {
ext->unidirectionalCompoundReferenceNameMask =
(1 << (STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME - STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME)) |
(1 << (STD_VIDEO_AV1_REFERENCE_NAME_GOLDEN_FRAME - STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME));
ext->maxBidirectionalCompoundReferenceCount = 2;
ext->maxBidirectionalCompoundGroup1ReferenceCount = 1;
ext->maxBidirectionalCompoundGroup2ReferenceCount = 1;
}
ext->maxBidirectionalCompoundReferenceCount = ecap->av1.bidir_refs;
ext->maxBidirectionalCompoundGroup1ReferenceCount = ecap->av1.bidir_g1_refs;
ext->maxBidirectionalCompoundGroup2ReferenceCount = ecap->av1.bidir_g2_refs;
ext->bidirectionalCompoundReferenceNameMask = 0;
if (ext->maxBidirectionalCompoundReferenceCount) {
ext->bidirectionalCompoundReferenceNameMask =
(1 << (STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME - STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME)) |
(1 << (STD_VIDEO_AV1_REFERENCE_NAME_ALTREF_FRAME - STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME));
} else {
ext->maxUnidirectionalCompoundReferenceCount = 0;
ext->maxUnidirectionalCompoundGroup1ReferenceCount = 0;
ext->unidirectionalCompoundReferenceNameMask = 0;
ext->maxBidirectionalCompoundReferenceCount = 0;
ext->maxBidirectionalCompoundGroup1ReferenceCount = 0;
ext->maxBidirectionalCompoundGroup2ReferenceCount = 0;
ext->bidirectionalCompoundReferenceNameMask = 0;
}
ext->maxTemporalLayerCount = 4;
ext->maxTemporalLayerCount = ecap->max_temporal_layers;
ext->maxSpatialLayerCount = 1;
ext->maxOperatingPoints = 4;
ext->maxOperatingPoints = ecap->max_temporal_layers;
ext->minQIndex = 1;
ext->maxQIndex = 255;
ext->prefersGopRemainingFrames = false;
ext->requiresGopRemainingFrames = false;
ext->stdSyntaxFlags = 0;
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5) {
ext->stdSyntaxFlags |=
VK_VIDEO_ENCODE_AV1_STD_SKIP_MODE_PRESENT_UNSET_BIT_KHR | VK_VIDEO_ENCODE_AV1_STD_DELTA_Q_BIT_KHR;
}
pCapabilities->minCodedExtent.width = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? 320 : 128;
pCapabilities->minCodedExtent.height = 128;
if (ecap->av1.delta_q)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_AV1_STD_DELTA_Q_BIT_KHR;
if (ecap->av1.skip_mode_present)
ext->stdSyntaxFlags |= VK_VIDEO_ENCODE_AV1_STD_SKIP_MODE_PRESENT_UNSET_BIT_KHR;
if (qp_map_caps) {
qp_map_caps->minQIndexDelta = -255;
@ -1012,63 +919,66 @@ radv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice,
uint32_t qp_map_texel_size = 0;
const struct VkVideoProfileListInfoKHR *prof_list =
vk_find_struct_const(pVideoFormatInfo->pNext, VIDEO_PROFILE_LIST_INFO_KHR);
if (prof_list) {
for (unsigned i = 0; i < prof_list->profileCount; i++) {
const VkVideoProfileInfoKHR *profile = &prof_list->pProfiles[i];
const VkVideoEncodeProfileRgbConversionInfoVALVE *rgbProfile =
vk_find_struct_const(profile, VIDEO_ENCODE_PROFILE_RGB_CONVERSION_INFO_VALVE);
bool rgb = rgbProfile && rgbProfile->performEncodeRgbConversion &&
(pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR);
assert(prof_list);
/* "If any of the video profiles specified via VkVideoProfileListInfoKHR::pProfiles are not
* supported, then this command returns one of the video-profile-specific error codes."
*/
VkResult res = radv_video_is_profile_supported(pdev, profile);
if (res != VK_SUCCESS)
return res;
for (unsigned i = 0; i < prof_list->profileCount; i++) {
const VkVideoProfileInfoKHR *profile = &prof_list->pProfiles[i];
const VkVideoEncodeProfileRgbConversionInfoVALVE *rgbProfile =
vk_find_struct_const(profile, VIDEO_ENCODE_PROFILE_RGB_CONVERSION_INFO_VALVE);
bool rgb = rgbProfile && rgbProfile->performEncodeRgbConversion &&
(pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR);
struct ac_video_dec_codec_caps *dcap = NULL;
struct ac_video_enc_codec_caps *ecap = NULL;
VkFormat profile_formats[2] = {VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED};
if (pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR) {
const uint32_t profile_qp_map_texel_size = radv_video_get_qp_map_texel_size(profile->videoCodecOperation);
/* "If any of the video profiles specified via VkVideoProfileListInfoKHR::pProfiles are not
* supported, then this command returns one of the video-profile-specific error codes."
*/
VkResult res = radv_video_is_profile_supported(pdev, profile);
if (res != VK_SUCCESS)
return res;
/* All profiles must share the same qp_map texel size. */
if (qp_map_texel_size != 0 && qp_map_texel_size != profile_qp_map_texel_size)
return VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR;
radv_video_get_caps(pdev, profile->videoCodecOperation, &dcap, &ecap);
qp_map_texel_size = profile_qp_map_texel_size;
VkFormat profile_formats[2] = {VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED};
if (pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR) {
/* All profiles must share the same qp_map texel size. */
if (qp_map_texel_size != 0 && qp_map_texel_size != ecap->qp_map_texel_size)
return VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR;
profile_formats[0] = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? VK_FORMAT_R16_SINT : VK_FORMAT_R32_SINT;
} else if (rgb) {
if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR) {
profile_formats[0] = VK_FORMAT_B8G8R8A8_UNORM;
profile_formats[1] = VK_FORMAT_R8G8B8A8_UNORM;
} else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR) {
profile_formats[0] = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
profile_formats[1] = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
}
} else {
if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
qp_map_texel_size = ecap->qp_map_texel_size;
if (ecap->qp_map_formats.r16_sint)
profile_formats[0] = VK_FORMAT_R16_SINT;
else if (ecap->qp_map_formats.r32_sint)
profile_formats[0] = VK_FORMAT_R32_SINT;
} else if (rgb) {
if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR) {
profile_formats[0] = VK_FORMAT_B8G8R8A8_UNORM;
profile_formats[1] = VK_FORMAT_R8G8B8A8_UNORM;
} else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR) {
profile_formats[0] = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
profile_formats[1] = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
}
} else {
union ac_video_format_caps fmts = dcap ? dcap->formats : ecap->formats;
if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR) {
if (fmts.nv12)
profile_formats[0] = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
} else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR) {
if (fmts.p010)
profile_formats[0] = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR)
} else if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR) {
if (fmts.p012)
profile_formats[0] = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16;
}
for (int j = 0; j < 2; j++) {
/* All profiles must share the same format. */
if (formats[j] != VK_FORMAT_UNDEFINED && formats[j] != profile_formats[j])
return VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR;
formats[j] = profile_formats[j];
}
}
} else {
/* On AMD, we need a codec specified for qp map as the extents differ. */
if (pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR)
return VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR;
formats[0] = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
for (int j = 0; j < 2; j++) {
/* All profiles must share the same format. */
if (formats[j] != VK_FORMAT_UNDEFINED && formats[j] != profile_formats[j])
return VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR;
formats[j] = profile_formats[j];
}
}
if (formats[0] == VK_FORMAT_UNDEFINED)
@ -1821,7 +1731,7 @@ get_av1_param(struct radv_video_session *vid, struct vk_video_session_parameters
av1->ref_frame_id_list[i] = 0x7f;
uint16_t used_slots = 1 << av1->cur_id;
int idxs[RADV_VIDEO_AV1_MAX_DPB_SLOTS];
int idxs[STD_VIDEO_AV1_NUM_REF_FRAMES + 1];
unsigned i = 0;
for (i = 0; i < frame_info->referenceSlotCount; i++) {
int idx = frame_info->pReferenceSlots[i].slotIndex;
@ -2013,15 +1923,12 @@ fill_surface(struct radv_cmd_buffer *cmd_buf, struct radv_image *img, uint32_t s
static enum ac_video_dec_tier
select_tier(struct radv_device *device, struct radv_video_session *vid, const struct VkVideoDecodeInfoKHR *frame_info)
{
struct radv_physical_device *pdev = radv_device_physical(device);
struct radv_image_view *dst_iv = radv_image_view_from_handle(frame_info->dstPictureResource.imageViewBinding);
struct radv_image_plane *luma = &dst_iv->image->planes[0];
if (vid->dec->tiers & AC_VIDEO_DEC_TIER3 && radv_enable_tier3(pdev, vid->vk.op)) {
if (vid->dec->tiers & AC_VIDEO_DEC_TIER3) {
VkImageUsageFlags coincide = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
if (luma->surface.is_linear || (dst_iv->image->vk.usage & coincide) != coincide)
return AC_VIDEO_DEC_TIER2;
else
if (!luma->surface.is_linear && (dst_iv->image->vk.usage & coincide) == coincide)
return AC_VIDEO_DEC_TIER3;
}
@ -2206,18 +2113,3 @@ radv_video_get_uvd_dpb_image(struct radv_physical_device *pdev, const struct VkV
image->size = MAX2(image->size, ac_video_dec_dpb_size(&pdev->info, &param));
}
}
bool
radv_video_decode_vp9_supported(const struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_5_0_0)
return radv_check_vcn_fw_version(pdev, 9, 7, 18);
else if (pdev->info.vcn_ip_version >= VCN_4_0_0)
return radv_check_vcn_fw_version(pdev, 9, 23, 13);
else if (pdev->info.vcn_ip_version >= VCN_3_0_0)
return radv_check_vcn_fw_version(pdev, 4, 33, 7);
else if (pdev->info.vcn_ip_version >= VCN_2_0_0)
return radv_check_vcn_fw_version(pdev, 8, 24, 4);
else
return false;
}

View file

@ -57,19 +57,6 @@ struct radv_video_session {
uint32_t enc_wa_flags;
};
/**
* WRITE_MEMORY support in FW.
*
* none: Not supported at all. Old VCN FW and all UVD.
* pcie_atomics: Supported, relies on PCIe atomics.
* full: Supported, works also without PCIe atomics.
*/
enum radv_video_write_memory_support {
RADV_VIDEO_WRITE_MEMORY_SUPPORT_NONE = 0,
RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS,
RADV_VIDEO_WRITE_MEMORY_SUPPORT_FULL,
};
VK_DEFINE_NONDISP_HANDLE_CASTS(radv_video_session, vk.base, VkVideoSessionKHR, VK_OBJECT_TYPE_VIDEO_SESSION_KHR)
void radv_init_physical_device_decoder(struct radv_physical_device *pdev);
@ -96,11 +83,7 @@ void radv_video_get_uvd_dpb_image(struct radv_physical_device *pdev,
const struct VkVideoProfileListInfoKHR *profile_list, struct radv_image *image);
void radv_video_get_enc_dpb_image(struct radv_device *device, const struct VkVideoProfileListInfoKHR *profile_list,
struct radv_image *image, struct radv_image_create_info *create_info);
bool radv_video_decode_vp9_supported(const struct radv_physical_device *pdev);
bool radv_video_encode_av1_supported(const struct radv_physical_device *pdev);
bool radv_video_encode_qp_map_supported(const struct radv_physical_device *pdev);
enum radv_video_write_memory_support radv_video_write_memory_supported(const struct radv_physical_device *pdev);
uint32_t radv_video_get_qp_map_texel_size(VkVideoCodecOperationFlagBitsKHR codec);
bool radv_check_vcn_fw_version(const struct radv_physical_device *pdev, uint32_t dec, uint32_t enc, uint32_t rev);
void radv_video_get_caps(struct radv_physical_device *pdev, VkVideoCodecOperationFlagBitsKHR op,
struct ac_video_dec_codec_caps **dec, struct ac_video_enc_codec_caps **enc);
#endif /* RADV_VIDEO_H */

View file

@ -74,7 +74,7 @@ radv_probe_video_encode(struct radv_physical_device *pdev)
return;
/* WRITE_MEMORY is needed for SetEvent and is required to pass CTS */
if (radv_video_write_memory_supported(pdev)) {
if (pdev->info.video_caps.queue[AMD_IP_VCN_ENC].write_memory != AC_VIDEO_WRITE_MEMORY_SUPPORT_NONE) {
pdev->video_encode_enabled = true;
return;
}
@ -3090,7 +3090,8 @@ radv_vcn_encode_video(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInf
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2) {
radv_vcn_sq_tail(cs, &cmd_buffer->video.sq);
if (feedback_query_va && radv_video_write_memory_supported(pdev) == RADV_VIDEO_WRITE_MEMORY_SUPPORT_FULL)
if (feedback_query_va &&
pdev->info.video_caps.queue[AMD_IP_VCN_ENC].write_memory == AC_VIDEO_WRITE_MEMORY_SUPPORT_FULL)
radv_vcn_write_memory(cmd_buffer, feedback_query_va + RADV_ENC_FEEDBACK_STATUS_IDX * sizeof(uint32_t), 1);
}
}
@ -3417,14 +3418,15 @@ void
radv_video_patch_encode_session_parameters(struct radv_device *device, struct vk_video_session_parameters *params)
{
struct radv_physical_device *pdev = radv_device_physical(device);
struct ac_video_enc_codec_caps *caps;
switch (params->op) {
case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
caps = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_AVC];
for (unsigned i = 0; i < params->h264_enc.h264_pps_count; i++) {
params->h264_enc.h264_pps[i].base.pic_init_qp_minus26 = 0;
params->h264_enc.h264_pps[i].base.pic_init_qs_minus26 = 0;
if (pdev->enc_hw_ver < RADV_VIDEO_ENC_HW_5 ||
!params->h264_enc.h264_pps[i].base.flags.entropy_coding_mode_flag)
if (!caps->avc.transform_8x8 || !params->h264_enc.h264_pps[i].base.flags.entropy_coding_mode_flag)
params->h264_enc.h264_pps[i].base.flags.transform_8x8_mode_flag = 0;
params->h264_enc.h264_pps[i].base.num_ref_idx_l0_default_active_minus1 = 0;
@ -3432,12 +3434,16 @@ radv_video_patch_encode_session_parameters(struct radv_device *device, struct vk
}
break;
case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
caps = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_HEVC];
for (unsigned i = 0; i < params->h265_enc.h265_sps_count; i++) {
VkExtent2D extent = {
.width = params->h265_enc.h265_sps[i].base.pic_width_in_luma_samples,
.height = params->h265_enc.h265_sps[i].base.pic_height_in_luma_samples,
};
VkExtent2D aligned_extent = radv_enc_aligned_coded_extent(pdev, params->op, extent);
VkExtent2D aligned_extent = {
.width = align(extent.width, caps->width_alignment),
.height = align(extent.height, caps->height_alignment),
};
/* Override the unaligned pic_{width,height} and make up for it with conformance window
* cropping */
@ -3450,25 +3456,22 @@ radv_video_patch_encode_session_parameters(struct radv_device *device, struct vk
params->h265_enc.h265_sps[i].base.conf_win_bottom_offset += (aligned_extent.height - extent.height) / 2;
}
/* VCN supports only the following block sizes (resulting in 64x64 CTBs with any coding
* block size) */
params->h265_enc.h265_sps[i].base.log2_min_luma_coding_block_size_minus3 = 0;
params->h265_enc.h265_sps[i].base.log2_diff_max_min_luma_coding_block_size = 3;
params->h265_enc.h265_sps[i].base.log2_min_luma_transform_block_size_minus2 = 0;
params->h265_enc.h265_sps[i].base.log2_diff_max_min_luma_transform_block_size = 3;
params->h265_enc.h265_sps[i].base.log2_min_luma_coding_block_size_minus3 =
caps->hevc.log2_min_luma_coding_block_size_minus3;
params->h265_enc.h265_sps[i].base.log2_diff_max_min_luma_coding_block_size =
caps->hevc.log2_diff_max_min_luma_coding_block_size;
params->h265_enc.h265_sps[i].base.log2_min_luma_transform_block_size_minus2 =
caps->hevc.log2_min_luma_transform_block_size_minus2;
params->h265_enc.h265_sps[i].base.log2_diff_max_min_luma_transform_block_size =
caps->hevc.log2_diff_max_min_luma_transform_block_size;
}
for (unsigned i = 0; i < params->h265_enc.h265_pps_count; i++) {
/* cu_qp_delta needs to be enabled if rate control is enabled. VCN2 and newer can also enable
* it with rate control disabled. Since we don't know what rate control will be used, we
* need to always force enable it.
* On VCN1 rate control modes are disabled.
*/
params->h265_enc.h265_pps[i].base.flags.cu_qp_delta_enabled_flag = !!(pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2);
params->h265_enc.h265_pps[i].base.flags.cu_qp_delta_enabled_flag = caps->hevc.cu_qp_delta ? 1 : 0;
params->h265_enc.h265_pps[i].base.diff_cu_qp_delta_depth = 0;
params->h265_enc.h265_pps[i].base.init_qp_minus26 = 0;
params->h265_enc.h265_pps[i].base.flags.dependent_slice_segments_enabled_flag = 1;
if (pdev->enc_hw_ver < RADV_VIDEO_ENC_HW_3)
if (!caps->hevc.transform_skip)
params->h265_enc.h265_pps[i].base.flags.transform_skip_enabled_flag = 0;
params->h265_enc.h265_pps[i].base.num_ref_idx_l0_default_active_minus1 = 0;
@ -3477,12 +3480,16 @@ radv_video_patch_encode_session_parameters(struct radv_device *device, struct vk
break;
}
case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR: {
caps = &pdev->info.video_caps.enc[AC_VIDEO_CODEC_AV1];
/* If the resolution isn't aligned, we need to override it. */
VkExtent2D extent = {
.width = params->av1_enc.seq_hdr.base.max_frame_width_minus_1 + 1,
.height = params->av1_enc.seq_hdr.base.max_frame_height_minus_1 + 1,
};
VkExtent2D aligned_extent = radv_enc_aligned_coded_extent(pdev, params->op, extent);
VkExtent2D aligned_extent = {
.width = align(extent.width, caps->width_alignment),
.height = align(extent.height, caps->height_alignment),
};
params->av1_enc.seq_hdr.base.max_frame_width_minus_1 = aligned_extent.width - 1;
params->av1_enc.seq_hdr.base.max_frame_height_minus_1 = aligned_extent.height - 1;
@ -3651,9 +3658,10 @@ radv_video_get_encode_session_memory_requirements(struct radv_device *device, st
if (vid->vk.flags & VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR &&
pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5) {
const uint32_t texel_size = radv_video_get_qp_map_texel_size(vid->vk.op);
const uint32_t map_width = DIV_ROUND_UP(vid->vk.max_coded.width, texel_size);
const uint32_t map_height = DIV_ROUND_UP(vid->vk.max_coded.height, texel_size);
struct ac_video_enc_codec_caps *caps;
radv_video_get_caps(pdev, vid->vk.op, NULL, &caps);
const uint32_t map_width = DIV_ROUND_UP(vid->vk.max_coded.width, caps->qp_map_texel_size);
const uint32_t map_height = DIV_ROUND_UP(vid->vk.max_coded.height, caps->qp_map_texel_size);
vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, m)
{
@ -3726,41 +3734,3 @@ radv_video_get_enc_dpb_image(struct radv_device *device, const struct VkVideoPro
}
image->alignment = ENC_ALIGNMENT;
}
bool
radv_video_encode_av1_supported(const struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_5_0_0) {
return true;
} else if (pdev->info.vcn_ip_version >= VCN_4_0_0) {
return pdev->info.vcn_ip_version != VCN_4_0_3 && pdev->info.vcn_enc_minor_version >= 20;
} else {
return false;
}
}
bool
radv_video_encode_qp_map_supported(const struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_5_0_0)
return radv_check_vcn_fw_version(pdev, 9, 9, 28);
return true;
}
enum radv_video_write_memory_support
radv_video_write_memory_supported(const struct radv_physical_device *pdev)
{
if (pdev->info.vcn_ip_version >= VCN_5_0_0) {
return RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS;
} else if (pdev->info.vcn_ip_version >= VCN_4_0_0) {
if (pdev->info.vcn_enc_minor_version >= 22)
return RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS;
} else if (pdev->info.vcn_ip_version >= VCN_3_0_0) {
if (pdev->info.vcn_enc_minor_version >= 33)
return RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS;
} else if (pdev->info.vcn_ip_version >= VCN_2_0_0) {
if (pdev->info.vcn_enc_minor_version >= 24)
return RADV_VIDEO_WRITE_MEMORY_SUPPORT_PCIE_ATOMICS;
}
return RADV_VIDEO_WRITE_MEMORY_SUPPORT_NONE;
}