radv/video: Support quantization map on VCN5

VCN5 needs to convert the input map image to internal format.

Reviewed-by: Autumn Ashton <misyl@froggi.es>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37156>
This commit is contained in:
David Rosca
2025-09-02 16:29:41 +02:00
committed by Marge Bot
parent a03e055cd3
commit 5e7b6df860
5 changed files with 110 additions and 19 deletions
+6 -2
View File
@@ -492,8 +492,12 @@ radv_physical_device_get_format_properties(struct radv_physical_device *pdev, Vk
tiled |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
}
if (pdev->video_encode_enabled && format == VK_FORMAT_R32_SINT) {
linear |= VK_FORMAT_FEATURE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
if (pdev->video_encode_enabled) {
const VkFormat map_format = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? VK_FORMAT_R16_SINT : VK_FORMAT_R32_SINT;
if (format == map_format) {
linear |= VK_FORMAT_FEATURE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
tiled |= VK_FORMAT_FEATURE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
}
}
out_properties->linearTilingFeatures = linear;
+1 -1
View File
@@ -649,7 +649,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.KHR_video_encode_av1 =
(radv_video_encode_av1_supported(pdev) && VIDEO_CODEC_AV1ENC && pdev->video_encode_enabled),
.KHR_video_encode_intra_refresh = pdev->video_encode_enabled,
.KHR_video_encode_quantization_map = pdev->video_encode_enabled && pdev->info.vcn_ip_version < VCN_5_0_0,
.KHR_video_encode_quantization_map = pdev->video_encode_enabled && radv_video_encode_qp_map_supported(pdev),
.KHR_video_encode_queue = pdev->video_encode_enabled,
.KHR_vulkan_memory_model = true,
.KHR_workgroup_memory_explicit_layout = true,
+7 -4
View File
@@ -40,7 +40,7 @@
static void set_reg(struct radv_cmd_buffer *cmd_buffer, unsigned reg, uint32_t val);
static inline bool
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 ||
@@ -804,7 +804,7 @@ radv_video_is_profile_supported(struct radv_physical_device *pdev, const VkVideo
return VK_SUCCESS;
}
static uint32_t
uint32_t
radv_video_get_qp_map_texel_size(VkVideoCodecOperationFlagBitsKHR codec)
{
switch (codec) {
@@ -902,7 +902,7 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
enc_caps->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR |
VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
if (pdev->info.vcn_ip_version < VCN_5_0_0)
if (radv_video_encode_qp_map_supported(pdev))
enc_caps->flags |= VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
}
if (intra_refresh_caps) {
@@ -1254,7 +1254,7 @@ radv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice,
qp_map_texel_size = profile_qp_map_texel_size;
profile_format = VK_FORMAT_R32_SINT;
profile_format = pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5 ? VK_FORMAT_R16_SINT : VK_FORMAT_R32_SINT;
} else {
if (profile->lumaBitDepth == VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
profile_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
@@ -1468,6 +1468,9 @@ radv_BindVideoSessionMemoryKHR(VkDevice _device, VkVideoSessionKHR videoSession,
case RADV_BIND_INTRA_ONLY:
copy_bind(&vid->intra_only_dpb, &pBindSessionMemoryInfos[i]);
break;
case RADV_BIND_ENCODE_QP_MAP:
copy_bind(&vid->qp_map, &pBindSessionMemoryInfos[i]);
break;
default:
assert(0);
break;
+5
View File
@@ -30,6 +30,7 @@ struct radv_cmd_stream;
#define RADV_BIND_SESSION_CTX 0
#define RADV_BIND_DECODER_CTX 1
#define RADV_BIND_INTRA_ONLY 2
#define RADV_BIND_ENCODE_QP_MAP 3
#define RADV_BIND_ENCODE_AV1_CDF_STORE RADV_BIND_DECODER_CTX
struct radv_vid_mem {
@@ -51,6 +52,7 @@ struct radv_video_session {
struct radv_vid_mem ctx;
struct radv_vid_mem intra_only_dpb;
struct radv_vid_mem qp_map;
unsigned dbg_frame_cnt;
rvcn_enc_session_init_t enc_session;
@@ -93,5 +95,8 @@ void radv_video_get_enc_dpb_image(struct radv_device *device, const struct VkVid
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);
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);
#endif /* RADV_VIDEO_H */
+91 -12
View File
@@ -1707,6 +1707,52 @@ radv_enc_intra_refresh(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeIn
RADEON_ENC_END();
}
static void
radv_enc_qp_map_input(struct radv_cmd_buffer *cmd_buffer, const struct VkVideoEncodeInfoKHR *enc_info)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
const struct VkVideoEncodeQuantizationMapInfoKHR *quantization_map_info =
vk_find_struct_const(enc_info->pNext, VIDEO_ENCODE_QUANTIZATION_MAP_INFO_KHR);
const struct radv_image_view *qp_map_view =
quantization_map_info ? radv_image_view_from_handle(quantization_map_info->quantizationMap) : NULL;
const struct radv_image *qp_map = qp_map_view ? qp_map_view->image : NULL;
struct radv_cmd_stream *cs = cmd_buffer->cs;
if (!(enc_info->flags & VK_VIDEO_ENCODE_WITH_QUANTIZATION_DELTA_MAP_BIT_KHR) || !qp_map)
return;
const uint64_t va_in = qp_map->bindings[0].addr;
radv_cs_add_buffer(device->ws, cs->b, qp_map->bindings[0].bo);
const uint64_t va_out =
radv_buffer_get_va(cmd_buffer->video.vid->qp_map.mem->bo) + cmd_buffer->video.vid->qp_map.offset;
radv_cs_add_buffer(device->ws, cmd_buffer->cs->b, cmd_buffer->video.vid->qp_map.mem->bo);
radv_vcn_sq_header(cs, &cmd_buffer->video.sq, RADEON_VCN_ENGINE_TYPE_COMMON, false);
struct rvcn_cmn_engine_ib_package *ib_header = (struct rvcn_cmn_engine_ib_package *)&(cs->b->buf[cs->b->cdw]);
ib_header->package_size =
sizeof(struct rvcn_cmn_engine_ib_package) + sizeof(struct rvcn_cmn_engine_op_resolveinputparamlayout);
cs->b->cdw++;
ib_header->package_type = RADEON_VCN_IB_COMMON_OP_RESOLVEINPUTPARAMLAYOUT;
cs->b->cdw++;
struct rvcn_cmn_engine_op_resolveinputparamlayout *resolve_input =
(struct rvcn_cmn_engine_op_resolveinputparamlayout *)&(cs->b->buf[cs->b->cdw]);
resolve_input->map_type = RADEON_VCN_RESOLVE_INPUT_PARAM_LAYOUT_TYPE_QPMAP_INT16;
resolve_input->map_width = qp_map->vk.extent.width;
resolve_input->map_height = qp_map->vk.extent.height;
resolve_input->input_buffer_address_lo = va_in & 0xffffffff;
resolve_input->input_buffer_address_hi = va_in >> 32;
resolve_input->input_buffer_pitch = qp_map->planes[0].surface.u.gfx9.surf_pitch;
resolve_input->input_buffer_swizzle_mode = qp_map->planes[0].surface.u.gfx9.swizzle_mode;
resolve_input->output_buffer_address_lo = va_out & 0xffffffff;
resolve_input->output_buffer_address_hi = va_out >> 32;
cs->b->cdw += sizeof(*resolve_input) / 4;
radv_vcn_sq_tail(cs, &cmd_buffer->video.sq);
}
static void
radv_enc_qp_map(struct radv_cmd_buffer *cmd_buffer, const struct VkVideoEncodeInfoKHR *enc_info)
{
@@ -1720,18 +1766,24 @@ radv_enc_qp_map(struct radv_cmd_buffer *cmd_buffer, const struct VkVideoEncodeIn
RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.enc_qp_map);
if (enc_info->flags & VK_VIDEO_ENCODE_WITH_QUANTIZATION_DELTA_MAP_BIT_KHR && qp_map) {
/* VCN < 5 uses a 32-bit signed integer for QP maps. */
assert(qp_map->vk.format == VK_FORMAT_R32_SINT);
const uint32_t qp_map_type = cmd_buffer->video.vid->enc_rate_control_method == RENCODE_RATE_CONTROL_METHOD_NONE
? RENCODE_QP_MAP_TYPE_DELTA
: RENCODE_QP_MAP_TYPE_MAP_PA;
radv_cs_add_buffer(device->ws, cmd_buffer->cs->b, qp_map->bindings[0].bo);
const uint64_t va = qp_map->bindings[0].addr;
RADEON_ENC_CS(qp_map_type);
RADEON_ENC_CS(va >> 32);
RADEON_ENC_CS(va & 0xffffffff);
RADEON_ENC_CS(qp_map->planes[0].surface.u.gfx9.surf_pitch);
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5) {
uint64_t va = radv_buffer_get_va(cmd_buffer->video.vid->qp_map.mem->bo);
va += cmd_buffer->video.vid->qp_map.offset;
RADEON_ENC_CS(RENCODE_QP_MAP_TYPE_DELTA);
RADEON_ENC_CS(va >> 32);
RADEON_ENC_CS(va & 0xffffffff);
RADEON_ENC_CS(0);
} else {
const uint32_t qp_map_type = cmd_buffer->video.vid->enc_rate_control_method == RENCODE_RATE_CONTROL_METHOD_NONE
? RENCODE_QP_MAP_TYPE_DELTA
: RENCODE_QP_MAP_TYPE_MAP_PA;
radv_cs_add_buffer(device->ws, cmd_buffer->cs->b, qp_map->bindings[0].bo);
const uint64_t va = qp_map->bindings[0].addr;
RADEON_ENC_CS(qp_map_type);
RADEON_ENC_CS(va >> 32);
RADEON_ENC_CS(va & 0xffffffff);
RADEON_ENC_CS(qp_map->planes[0].surface.u.gfx9.surf_pitch);
}
} else {
RADEON_ENC_CS(RENCODE_QP_MAP_TYPE_NONE);
RADEON_ENC_CS(0);
@@ -2732,6 +2784,9 @@ radv_vcn_encode_video(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInf
radeon_check_space(device->ws, cs->b, 1600);
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_5)
radv_enc_qp_map_input(cmd_buffer, enc_info);
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_4)
radv_vcn_sq_header(cs, &cmd_buffer->video.sq, RADEON_VCN_ENGINE_TYPE_ENCODE, false);
@@ -3304,6 +3359,22 @@ radv_video_get_encode_session_memory_requirements(struct radv_device *device, st
m->memoryRequirements.memoryTypeBits |= (1 << i);
}
}
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);
vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, m)
{
m->memoryBindIndex = RADV_BIND_ENCODE_QP_MAP;
m->memoryRequirements.size = map_width * map_height * sizeof(int16_t);
m->memoryRequirements.alignment = 0;
m->memoryRequirements.memoryTypeBits = memory_type_bits;
}
}
return vk_outarray_status(&out);
}
@@ -3365,3 +3436,11 @@ radv_video_encode_av1_supported(const struct radv_physical_device *pdev)
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;
}