radv/video: add event support for VCN4

This was the main missing piece for passing vulkan video CTS
as the video firmwares couldn't do proper vulkan events.

With new enough firmware this is now possible.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30837>
This commit is contained in:
Benjamin Cheng 2024-06-12 10:12:44 -04:00 committed by Marge Bot
parent c340862555
commit 95a980b61f
5 changed files with 55 additions and 6 deletions

View file

@ -28,15 +28,29 @@
#define RADEON_VCN_ENGINE_INFO (0x30000001)
#define RADEON_VCN_SIGNATURE (0x30000002)
#define RADEON_VCN_ENGINE_TYPE_COMMON (0x00000001)
#define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002)
#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003)
#define RADEON_VCN_ENGINE_INFO_SIZE (0x00000010)
#define RADEON_VCN_SIGNATURE_SIZE (0x00000010)
#define RADEON_VCN_IB_COMMON_OP_WRITEMEMORY (0x33000001)
struct rvcn_sq_var {
unsigned int *ib_total_size_in_dw;
unsigned int *ib_checksum;
};
struct rvcn_cmn_engine_ib_package {
unsigned int package_size;
unsigned int package_type;
};
struct rvcn_cmn_engine_op_writememory {
unsigned int dest_addr_lo; // Low address of memory
unsigned int dest_addr_hi; // High address of memory
unsigned int data; // data to be written
};
#endif

View file

@ -13052,8 +13052,10 @@ write_event(struct radv_cmd_buffer *cmd_buffer, struct radv_event *event, VkPipe
struct radeon_cmdbuf *cs = cmd_buffer->cs;
uint64_t va = radv_buffer_get_va(event->bo);
if (cmd_buffer->qf == RADV_QUEUE_VIDEO_DEC || cmd_buffer->qf == RADV_QUEUE_VIDEO_ENC)
if (cmd_buffer->qf == RADV_QUEUE_VIDEO_DEC || cmd_buffer->qf == RADV_QUEUE_VIDEO_ENC) {
radv_vcn_write_event(cmd_buffer, event, value);
return;
}
radv_emit_cache_flush(cmd_buffer);

View file

@ -61,7 +61,7 @@ radv_vid_buffer_upload_alloc(struct radv_cmd_buffer *cmd_buffer, unsigned size,
/* vcn unified queue (sq) ib header */
void
radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, bool enc)
radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, unsigned type)
{
/* vcn ib signature */
radeon_emit(cs, RADEON_VCN_SIGNATURE_SIZE);
@ -74,7 +74,7 @@ radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, bool enc)
/* vcn ib engine info */
radeon_emit(cs, RADEON_VCN_ENGINE_INFO_SIZE);
radeon_emit(cs, RADEON_VCN_ENGINE_INFO);
radeon_emit(cs, enc ? RADEON_VCN_ENGINE_TYPE_ENCODE : RADEON_VCN_ENGINE_TYPE_DECODE);
radeon_emit(cs, type);
radeon_emit(cs, 0);
}
@ -99,13 +99,44 @@ radv_vcn_sq_tail(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq)
*sq->ib_checksum = checksum;
}
void
radv_vcn_write_event(struct radv_cmd_buffer *cmd_buffer, struct radv_event *event, unsigned value)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
struct radv_physical_device *pdev = radv_device_physical(device);
struct rvcn_sq_var sq;
struct radeon_cmdbuf *cs = cmd_buffer->cs;
if (pdev->vid_decode_ip != AMD_IP_VCN_UNIFIED)
return;
radv_cs_add_buffer(device->ws, cs, event->bo);
uint64_t va = radv_buffer_get_va(event->bo);
radeon_check_space(device->ws, cs, 256);
radv_vcn_sq_header(cs, &sq, RADEON_VCN_ENGINE_TYPE_COMMON);
struct rvcn_cmn_engine_ib_package *ib_header = (struct rvcn_cmn_engine_ib_package *)&(cs->buf[cs->cdw]);
ib_header->package_size = sizeof(struct rvcn_cmn_engine_ib_package) + sizeof(struct rvcn_cmn_engine_op_writememory);
cs->cdw++;
ib_header->package_type = RADEON_VCN_IB_COMMON_OP_WRITEMEMORY;
cs->cdw++;
struct rvcn_cmn_engine_op_writememory *write_memory = (struct rvcn_cmn_engine_op_writememory *)&(cs->buf[cs->cdw]);
write_memory->dest_addr_lo = va & 0xffffffff;
write_memory->dest_addr_hi = va >> 32;
write_memory->data = value;
cs->cdw += sizeof(*write_memory) / 4;
radv_vcn_sq_tail(cs, &sq);
}
static void
radv_vcn_sq_start(struct radv_cmd_buffer *cmd_buffer)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
radeon_check_space(device->ws, cmd_buffer->cs, 256);
radv_vcn_sq_header(cmd_buffer->cs, &cmd_buffer->video.sq, false);
radv_vcn_sq_header(cmd_buffer->cs, &cmd_buffer->video.sq, RADEON_VCN_ENGINE_TYPE_DECODE);
rvcn_decode_ib_package_t *ib_header = (rvcn_decode_ib_package_t *)&(cmd_buffer->cs->buf[cmd_buffer->cs->cdw]);
ib_header->package_size = sizeof(struct rvcn_decode_buffer_s) + sizeof(struct rvcn_decode_ib_package_s);
cmd_buffer->cs->cdw++;

View file

@ -12,6 +12,7 @@
#define RADV_VIDEO_H
#include "vk_video.h"
#include "radv_event.h"
#include "ac_vcn.h"
@ -70,9 +71,10 @@ void radv_init_physical_device_decoder(struct radv_physical_device *pdev);
void radv_video_get_profile_alignments(struct radv_physical_device *pdev, const VkVideoProfileListInfoKHR *profile_list,
uint32_t *width_align_out, uint32_t *height_align_out);
void radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, bool enc);
void radv_vcn_sq_header(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq, unsigned type);
void radv_vcn_sq_tail(struct radeon_cmdbuf *cs, struct rvcn_sq_var *sq);
void radv_vcn_write_event(struct radv_cmd_buffer *cmd_buffer, struct radv_event *event, unsigned value);
void radv_init_physical_device_encoder(struct radv_physical_device *pdevice);
void radv_probe_video_encode(struct radv_physical_device *pdev);

View file

@ -2012,7 +2012,7 @@ radv_video_enc_begin_coding(struct radv_cmd_buffer *cmd_buffer)
radeon_check_space(device->ws, cmd_buffer->cs, 1024);
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_4)
radv_vcn_sq_header(cmd_buffer->cs, &cmd_buffer->video.sq, true);
radv_vcn_sq_header(cmd_buffer->cs, &cmd_buffer->video.sq, RADEON_VCN_ENGINE_TYPE_ENCODE);
}
void