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) {