diff --git a/src/gallium/drivers/radeonsi/radeon_vce.c b/src/gallium/drivers/radeonsi/radeon_vce.c index 7b24db3b6be..a4d82253169 100644 --- a/src/gallium/drivers/radeonsi/radeon_vce.c +++ b/src/gallium/drivers/radeonsi/radeon_vce.c @@ -116,13 +116,13 @@ static void sort_cpb(struct rvce_encoder *enc) /** * get number of cpbs based on dpb */ -static unsigned get_cpb_num(struct rvce_encoder *enc) +static unsigned get_cpb_num(struct rvce_encoder *enc, unsigned level_idc) { unsigned w = align(enc->base.width, 16) / 16; unsigned h = align(enc->base.height, 16) / 16; unsigned dpb; - switch (enc->base.level) { + switch (level_idc) { case 10: dpb = 396; break; @@ -251,11 +251,47 @@ static void rvce_begin_frame(struct pipe_video_codec *encoder, struct pipe_video enc->pic.rate_ctrl[0].frame_rate_den != pic->rate_ctrl[0].frame_rate_den; enc->pic = *pic; + enc->base.max_references = pic->seq.max_num_ref_frames; enc->si_get_pic_param(enc, pic); enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma); enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma); + if (!enc->cpb_num) { + struct si_screen *sscreen = (struct si_screen *)encoder->context->screen; + unsigned cpb_size; + + /* TODO enable B frame with dual instance */ + if ((sscreen->info.family >= CHIP_TONGA) && (enc->base.max_references == 1) && + (sscreen->info.vce_harvest_config == 0)) + enc->dual_inst = true; + + enc->cpb_num = get_cpb_num(enc, enc->pic.seq.level_idc); + if (!enc->cpb_num) + return; + + enc->cpb_array = CALLOC(enc->cpb_num, sizeof(struct rvce_cpb_slot)); + if (!enc->cpb_array) + return; + + cpb_size = (sscreen->info.gfx_level < GFX9) + ? align(enc->luma->u.legacy.level[0].nblk_x * enc->luma->bpe, 128) * + align(enc->luma->u.legacy.level[0].nblk_y, 32) + : + + align(enc->luma->u.gfx9.surf_pitch * enc->luma->bpe, 256) * + align(enc->luma->u.gfx9.surf_height, 32); + + cpb_size = cpb_size * 3 / 2; + cpb_size = cpb_size * enc->cpb_num; + if (enc->dual_pipe) + cpb_size += RVCE_MAX_AUX_BUFFER_NUM * RVCE_MAX_BITSTREAM_OUTPUT_ROW_SIZE * 2; + if (!si_vid_create_buffer(enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) { + RVID_ERR("Can't create CPB buffer.\n"); + return; + } + } + if (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) reset_cpb(enc); else if (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_P || @@ -376,9 +412,6 @@ struct pipe_video_codec *si_vce_create_encoder(struct pipe_context *context, struct si_screen *sscreen = (struct si_screen *)context->screen; struct si_context *sctx = (struct si_context *)context; struct rvce_encoder *enc; - struct pipe_video_buffer *tmp_buf, templat = {}; - struct radeon_surf *tmp_surf; - unsigned cpb_size; if (!sscreen->info.vce_fw_version) { RVID_ERR("Kernel doesn't supports VCE!\n"); @@ -402,10 +435,6 @@ struct pipe_video_codec *si_vce_create_encoder(struct pipe_context *context, sscreen->info.family != CHIP_POLARIS11 && sscreen->info.family != CHIP_POLARIS12 && sscreen->info.family != CHIP_VEGAM) enc->dual_pipe = true; - /* TODO enable B frame with dual instance */ - if ((sscreen->info.family >= CHIP_TONGA) && (templ->max_references == 1) && - (sscreen->info.vce_harvest_config == 0)) - enc->dual_inst = true; enc->base = *templ; enc->base.context = context; @@ -427,45 +456,6 @@ struct pipe_video_codec *si_vce_create_encoder(struct pipe_context *context, goto error; } - templat.buffer_format = PIPE_FORMAT_NV12; - templat.width = enc->base.width; - templat.height = enc->base.height; - templat.interlaced = false; - if (!(tmp_buf = context->create_video_buffer(context, &templat))) { - RVID_ERR("Can't create video buffer.\n"); - goto error; - } - - enc->cpb_num = get_cpb_num(enc); - if (!enc->cpb_num) - goto error; - - get_buffer(((struct vl_video_buffer *)tmp_buf)->resources[0], NULL, &tmp_surf); - - cpb_size = (sscreen->info.gfx_level < GFX9) - ? align(tmp_surf->u.legacy.level[0].nblk_x * tmp_surf->bpe, 128) * - align(tmp_surf->u.legacy.level[0].nblk_y, 32) - : - - align(tmp_surf->u.gfx9.surf_pitch * tmp_surf->bpe, 256) * - align(tmp_surf->u.gfx9.surf_height, 32); - - cpb_size = cpb_size * 3 / 2; - cpb_size = cpb_size * enc->cpb_num; - if (enc->dual_pipe) - cpb_size += RVCE_MAX_AUX_BUFFER_NUM * RVCE_MAX_BITSTREAM_OUTPUT_ROW_SIZE * 2; - tmp_buf->destroy(tmp_buf); - if (!si_vid_create_buffer(enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) { - RVID_ERR("Can't create CPB buffer.\n"); - goto error; - } - - enc->cpb_array = CALLOC(enc->cpb_num, sizeof(struct rvce_cpb_slot)); - if (!enc->cpb_array) - goto error; - - reset_cpb(enc); - switch (sscreen->info.vce_fw_version) { case FW_40_2_2: si_vce_40_2_2_init(enc); @@ -496,9 +486,6 @@ struct pipe_video_codec *si_vce_create_encoder(struct pipe_context *context, error: enc->ws->cs_destroy(&enc->cs); - si_vid_destroy_buffer(&enc->cpb); - - FREE(enc->cpb_array); FREE(enc); return NULL; } diff --git a/src/gallium/drivers/radeonsi/radeon_vce_40_2_2.c b/src/gallium/drivers/radeonsi/radeon_vce_40_2_2.c index 731cfece96c..13b31266707 100644 --- a/src/gallium/drivers/radeonsi/radeon_vce_40_2_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vce_40_2_2.c @@ -59,7 +59,7 @@ static void create(struct rvce_encoder *enc) RVCE_BEGIN(0x01000001); // create cmd RVCE_CS(0x00000000); // encUseCircularBuffer RVCE_CS(u_get_h264_profile_idc(enc->base.profile)); // encProfile - RVCE_CS(enc->base.level); // encLevel + RVCE_CS(enc->pic.seq.level_idc); // encLevel RVCE_CS(0x00000000); // encPicStructRestriction RVCE_CS(enc->base.width); // encImageWidth RVCE_CS(enc->base.height); // encImageHeight diff --git a/src/gallium/drivers/radeonsi/radeon_vce_52.c b/src/gallium/drivers/radeonsi/radeon_vce_52.c index a8b5fd48aca..0b0462bf064 100644 --- a/src/gallium/drivers/radeonsi/radeon_vce_52.c +++ b/src/gallium/drivers/radeonsi/radeon_vce_52.c @@ -180,7 +180,7 @@ static void create(struct rvce_encoder *enc) RVCE_BEGIN(0x01000001); // create cmd RVCE_CS(enc->enc_pic.ec.enc_use_circular_buffer); RVCE_CS(u_get_h264_profile_idc(enc->base.profile)); // encProfile - RVCE_CS(enc->base.level); // encLevel + RVCE_CS(enc->pic.seq.level_idc); // encLevel RVCE_CS(enc->enc_pic.ec.enc_pic_struct_restriction); RVCE_CS(enc->base.width); // encImageWidth RVCE_CS(enc->base.height); // encImageHeight