From 05cd42417ffabbe3364fb58ddf2a2d4427cd6579 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 Oct 2023 16:51:41 +1000 Subject: [PATCH] radv/video: enable video encoding behind perftest flag This probes the vcn firmware version to make sure it can support the encode extensions properly, then uses the perf test flag if so. Acked-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_debug.h | 1 + src/amd/vulkan/radv_formats.c | 6 ++++ src/amd/vulkan/radv_image.c | 7 ++++- src/amd/vulkan/radv_instance.c | 1 + src/amd/vulkan/radv_physical_device.c | 42 +++++++++++++++++++++++++-- src/amd/vulkan/radv_physical_device.h | 1 + src/amd/vulkan/radv_video.c | 4 +++ src/amd/vulkan/radv_video.h | 1 + src/amd/vulkan/radv_video_enc.c | 31 ++++++++++++++++++++ 9 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h index 5eda709af90..92c16d8f9db 100644 --- a/src/amd/vulkan/radv_debug.h +++ b/src/amd/vulkan/radv_debug.h @@ -78,6 +78,7 @@ enum { RADV_PERFTEST_TRANSFER_QUEUE = 1u << 13, RADV_PERFTEST_NIR_CACHE = 1u << 14, RADV_PERFTEST_RT_WAVE_32 = 1u << 15, + RADV_PERFTEST_VIDEO_ENCODE = 1u << 16, }; bool radv_init_trace(struct radv_device *device); diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c index 7da178dba8b..b819b7f4b1f 100644 --- a/src/amd/vulkan/radv_formats.c +++ b/src/amd/vulkan/radv_formats.c @@ -733,6 +733,12 @@ radv_physical_device_get_format_properties(struct radv_physical_device *pdev, Vk tiling |= VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR | VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR; } + if (pdev->video_encode_enabled) { + if (format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM || + format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16) + tiling |= VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR | VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR; + } + if (multiplanar) tiling |= VK_FORMAT_FEATURE_2_DISJOINT_BIT; diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index b7aafe7b951..eefe35df42a 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -46,6 +46,9 @@ radv_choose_tiling(struct radv_device *device, const VkImageCreateInfo *pCreateI if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR)) return RADEON_SURF_MODE_LINEAR_ALIGNED; + if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR)) + return RADEON_SURF_MODE_LINEAR_ALIGNED; + /* MSAA resources must be 2D tiled. */ if (pCreateInfo->samples > 1) return RADEON_SURF_MODE_2D; @@ -1107,7 +1110,9 @@ radv_image_create_layout(struct radv_device *device, struct radv_image_create_in * to sample it later with a linear filter, it will get garbage after the height it wants, * so we let the user specify the width/height unaligned, and align them preallocation. */ - if (image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR)) { + if (image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)) { assert(profile_list); uint32_t width_align, height_align; radv_video_get_profile_alignments(pdev, profile_list, &width_align, &height_align); diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c index 70525478e34..d671ec2805b 100644 --- a/src/amd/vulkan/radv_instance.c +++ b/src/amd/vulkan/radv_instance.c @@ -98,6 +98,7 @@ static const struct debug_control radv_perftest_options[] = {{"localbos", RADV_P {"transfer_queue", RADV_PERFTEST_TRANSFER_QUEUE}, {"nircache", RADV_PERFTEST_NIR_CACHE}, {"rtwave32", RADV_PERFTEST_RT_WAVE_32}, + {"video_encode", RADV_PERFTEST_VIDEO_ENCODE}, {NULL, 0}}; const char * diff --git a/src/amd/vulkan/radv_physical_device.c b/src/amd/vulkan/radv_physical_device.c index 3654cf5aa14..6825cfbad3d 100644 --- a/src/amd/vulkan/radv_physical_device.c +++ b/src/amd/vulkan/radv_physical_device.c @@ -250,6 +250,13 @@ radv_physical_device_init_queue_table(struct radv_physical_device *pdev) idx++; } + if (pdev->video_encode_enabled) { + if (pdev->info.ip[AMD_IP_VCN_ENC].num_queues > 0) { + pdev->vk_queue_to_radv[idx] = RADV_QUEUE_VIDEO_ENC; + idx++; + } + } + if (radv_sparse_queue_enabled(pdev)) { pdev->vk_queue_to_radv[idx] = RADV_QUEUE_SPARSE; idx++; @@ -568,6 +575,9 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device .KHR_video_decode_queue = !!(instance->perftest_flags & RADV_PERFTEST_VIDEO_DECODE), .KHR_video_decode_h264 = VIDEO_CODEC_H264DEC && !!(instance->perftest_flags & RADV_PERFTEST_VIDEO_DECODE), .KHR_video_decode_h265 = VIDEO_CODEC_H265DEC && !!(instance->perftest_flags & RADV_PERFTEST_VIDEO_DECODE), + .KHR_video_encode_h264 = VIDEO_CODEC_H264ENC && pdev->video_encode_enabled, + .KHR_video_encode_h265 = VIDEO_CODEC_H265ENC && pdev->video_encode_enabled, + .KHR_video_encode_queue = pdev->video_encode_enabled, .KHR_vulkan_memory_model = true, .KHR_workgroup_memory_explicit_layout = true, .KHR_zero_initialize_workgroup_memory = true, @@ -2069,6 +2079,8 @@ radv_physical_device_try_create(struct radv_instance *instance, drmDevicePtr drm pdev->rt_wave_size = 64; } + radv_probe_video_encode(pdev); + pdev->max_shared_size = pdev->info.gfx_level >= GFX7 ? 65536 : 32768; radv_physical_device_init_mem_types(pdev); @@ -2123,6 +2135,7 @@ radv_physical_device_try_create(struct radv_instance *instance, drmDevicePtr drm ac_print_gpu_info(&pdev->info, stdout); radv_init_physical_device_decoder(pdev); + radv_init_physical_device_encoder(pdev); radv_physical_device_init_queue_table(pdev); @@ -2232,6 +2245,11 @@ radv_get_physical_device_queue_family_properties(struct radv_physical_device *pd num_queue_families++; } + if (pdev->video_encode_enabled) { + if (pdev->info.ip[AMD_IP_VCN_ENC].num_queues > 0) + num_queue_families++; + } + if (radv_sparse_queue_enabled(pdev)) { num_queue_families++; } @@ -2299,6 +2317,20 @@ radv_get_physical_device_queue_family_properties(struct radv_physical_device *pd } } + if (pdev->video_encode_enabled) { + if (pdev->info.ip[AMD_IP_VCN_ENC].num_queues > 0) { + if (*pCount > idx) { + *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties){ + .queueFlags = VK_QUEUE_VIDEO_ENCODE_BIT_KHR, + .queueCount = pdev->info.ip[AMD_IP_VCN_ENC].num_queues, + .timestampValidBits = 64, + .minImageTransferGranularity = (VkExtent3D){1, 1, 1}, + }; + idx++; + } + } + } + if (radv_sparse_queue_enabled(pdev)) { if (*pCount > idx) { *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties){ @@ -2333,10 +2365,10 @@ radv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, ui VkQueueFamilyProperties *properties[] = { &pQueueFamilyProperties[0].queueFamilyProperties, &pQueueFamilyProperties[1].queueFamilyProperties, &pQueueFamilyProperties[2].queueFamilyProperties, &pQueueFamilyProperties[3].queueFamilyProperties, - &pQueueFamilyProperties[4].queueFamilyProperties, + &pQueueFamilyProperties[4].queueFamilyProperties, &pQueueFamilyProperties[5].queueFamilyProperties, }; radv_get_physical_device_queue_family_properties(pdev, pCount, properties); - assert(*pCount <= 5); + assert(*pCount <= 6); for (uint32_t i = 0; i < *pCount; i++) { vk_foreach_struct (ext, pQueueFamilyProperties[i].pNext) { @@ -2365,6 +2397,12 @@ radv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, ui pdev->info.vcn_ip_version != VCN_3_0_33) prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR; } + if (pQueueFamilyProperties[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) { + if (VIDEO_CODEC_H264ENC) + prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR; + if (VIDEO_CODEC_H265ENC) + prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR; + } break; } default: diff --git a/src/amd/vulkan/radv_physical_device.h b/src/amd/vulkan/radv_physical_device.h index ddd378ffa13..ae4acc58f6e 100644 --- a/src/amd/vulkan/radv_physical_device.h +++ b/src/amd/vulkan/radv_physical_device.h @@ -181,6 +181,7 @@ struct radv_physical_device { rvcn_enc_cmd_t vcn_enc_cmds; enum radv_video_enc_hw_ver enc_hw_ver; uint32_t encoder_interface_version; + bool video_encode_enabled; struct radv_physical_device_cache_key cache_key; }; diff --git a/src/amd/vulkan/radv_video.c b/src/amd/vulkan/radv_video.c index 26571767db8..8aa253ce96b 100644 --- a/src/amd/vulkan/radv_video.c +++ b/src/amd/vulkan/radv_video.c @@ -783,6 +783,8 @@ radv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice, p->imageType = VK_IMAGE_TYPE_2D; p->imageTiling = VK_IMAGE_TILING_OPTIMAL; p->imageUsageFlags = pVideoFormatInfo->imageUsage; + if (pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) + p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; } if (pVideoFormatInfo->imageUsage & (VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR)) @@ -796,6 +798,8 @@ radv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice, p->imageType = VK_IMAGE_TYPE_2D; p->imageTiling = VK_IMAGE_TILING_OPTIMAL; p->imageUsageFlags = pVideoFormatInfo->imageUsage; + if (pVideoFormatInfo->imageUsage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) + p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; } } diff --git a/src/amd/vulkan/radv_video.h b/src/amd/vulkan/radv_video.h index a0fa2c94a41..025de86fe80 100644 --- a/src/amd/vulkan/radv_video.h +++ b/src/amd/vulkan/radv_video.h @@ -72,6 +72,7 @@ void radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, bool e void radv_vcn_sq_tail(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq); void radv_init_physical_device_encoder(struct radv_physical_device *pdevice); +void radv_probe_video_encode(struct radv_physical_device *pdev); void radv_video_enc_begin_coding(struct radv_cmd_buffer *cmd_buffer); void radv_video_enc_end_coding(struct radv_cmd_buffer *cmd_buffer); void radv_video_enc_control_video_coding(struct radv_cmd_buffer *cmd_buffer, diff --git a/src/amd/vulkan/radv_video_enc.c b/src/amd/vulkan/radv_video_enc.c index 53f6b61655e..bab2135af78 100644 --- a/src/amd/vulkan/radv_video_enc.c +++ b/src/amd/vulkan/radv_video_enc.c @@ -27,6 +27,7 @@ **************************************************************************/ #include "radv_buffer.h" #include "radv_cs.h" +#include "radv_debug.h" #include "radv_device_memory.h" #include "radv_entrypoints.h" #include "radv_image_view.h" @@ -105,6 +106,36 @@ #define RENCODE_FW_INTERFACE_MAJOR_VERSION 1 #define RENCODE_FW_INTERFACE_MINOR_VERSION 9 +void +radv_probe_video_encode(struct radv_physical_device *pdev) +{ + pdev->video_encode_enabled = false; + if (pdev->info.vcn_ip_version >= VCN_4_0_0) { + if (pdev->info.vcn_enc_major_version != RENCODE_V4_FW_INTERFACE_MAJOR_VERSION) + return; + if (pdev->info.vcn_enc_minor_version < RENCODE_V4_FW_INTERFACE_MINOR_VERSION) + return; + } else if (pdev->info.vcn_ip_version >= VCN_3_0_0) { + if (pdev->info.vcn_enc_major_version != RENCODE_V3_FW_INTERFACE_MAJOR_VERSION) + return; + if (pdev->info.vcn_enc_minor_version < RENCODE_V3_FW_INTERFACE_MINOR_VERSION) + return; + } else if (pdev->info.vcn_ip_version >= VCN_2_0_0) { + if (pdev->info.vcn_enc_major_version != RENCODE_V2_FW_INTERFACE_MAJOR_VERSION) + return; + if (pdev->info.vcn_enc_minor_version < RENCODE_V2_FW_INTERFACE_MINOR_VERSION) + return; + } else { + if (pdev->info.vcn_enc_major_version != RENCODE_FW_INTERFACE_MAJOR_VERSION) + return; + if (pdev->info.vcn_enc_minor_version < RENCODE_FW_INTERFACE_MINOR_VERSION) + return; + } + + struct radv_instance *instance = radv_physical_device_instance(pdev); + pdev->video_encode_enabled = !!(instance->perftest_flags & RADV_PERFTEST_VIDEO_ENCODE); +} + void radv_init_physical_device_encoder(struct radv_physical_device *pdev) {