aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Liu <[email protected]>2015-06-25 10:14:14 -0400
committerMarek Olšák <[email protected]>2015-08-14 15:02:31 +0200
commit09def7e1e06827ab1eae091f0e765d91c6715cf9 (patch)
tree61761c5eb3be69ec387471a3a90f335e39423c0b
parent4dfcf6e3a91be97fcf9d3f44e76a7a389f8f40b2 (diff)
radeon/vce: implement VCE dual instance support
VCE dual instances are encoding in parallel, it needs two frames for encoding with their own parameters in one IB. Master instance will check the task info to find another frame, assign it to the slave instance Signed-off-by: Leo Liu <[email protected]> Signed-off-by: Christian König <[email protected]> Acked-by: Alex Deucher <[email protected]>
-rw-r--r--src/gallium/drivers/radeon/radeon_vce.c13
-rw-r--r--src/gallium/drivers/radeon/radeon_vce.h3
-rw-r--r--src/gallium/drivers/radeon/radeon_vce_50.c19
3 files changed, 30 insertions, 5 deletions
diff --git a/src/gallium/drivers/radeon/radeon_vce.c b/src/gallium/drivers/radeon/radeon_vce.c
index 0b667fd489b..bc8f36db355 100644
--- a/src/gallium/drivers/radeon/radeon_vce.c
+++ b/src/gallium/drivers/radeon/radeon_vce.c
@@ -57,6 +57,7 @@ static void flush(struct rvce_encoder *enc)
{
enc->ws->cs_flush(enc->cs, RADEON_FLUSH_ASYNC, NULL, 0);
enc->task_info_idx = 0;
+ enc->bs_idx = 0;
}
#if 0
@@ -310,7 +311,8 @@ static void rvce_encode_bitstream(struct pipe_video_codec *encoder,
RVID_ERR("Can't create feedback buffer.\n");
return;
}
- enc->session(enc);
+ if (!enc->cs->cdw)
+ enc->session(enc);
enc->encode(enc);
enc->feedback(enc);
}
@@ -323,7 +325,8 @@ static void rvce_end_frame(struct pipe_video_codec *encoder,
struct rvce_cpb_slot *slot = LIST_ENTRY(
struct rvce_cpb_slot, enc->cpb_slots.prev, list);
- flush(enc);
+ if (!enc->dual_inst || enc->bs_idx > 1)
+ flush(enc);
/* update the CPB backtrack with the just encoded frame */
slot->picture_type = enc->pic.picture_type;
@@ -362,6 +365,9 @@ static void rvce_get_feedback(struct pipe_video_codec *encoder,
*/
static void rvce_flush(struct pipe_video_codec *encoder)
{
+ struct rvce_encoder *enc = (struct rvce_encoder*)encoder;
+
+ flush(enc);
}
static void rvce_cs_flush(void *ctx, unsigned flags,
@@ -401,6 +407,9 @@ struct pipe_video_codec *rvce_create_encoder(struct pipe_context *context,
enc->use_vui = true;
if (rscreen->info.family >= CHIP_TONGA)
enc->dual_pipe = true;
+ /* TODO enable B frame with dual instance */
+ if ((rscreen->info.family >= CHIP_TONGA) && (templ->max_references == 1))
+ enc->dual_inst = true;
enc->base = *templ;
enc->base.context = context;
diff --git a/src/gallium/drivers/radeon/radeon_vce.h b/src/gallium/drivers/radeon/radeon_vce.h
index 06e9868ca96..624bda479f8 100644
--- a/src/gallium/drivers/radeon/radeon_vce.h
+++ b/src/gallium/drivers/radeon/radeon_vce.h
@@ -106,11 +106,14 @@ struct rvce_encoder {
struct rvid_buffer *fb;
struct rvid_buffer cpb;
struct pipe_h264_enc_picture_desc pic;
+
unsigned task_info_idx;
+ unsigned bs_idx;
bool use_vm;
bool use_vui;
bool dual_pipe;
+ bool dual_inst;
};
/* CPB handling functions */
diff --git a/src/gallium/drivers/radeon/radeon_vce_50.c b/src/gallium/drivers/radeon/radeon_vce_50.c
index 5bf22194418..afdab18c0d3 100644
--- a/src/gallium/drivers/radeon/radeon_vce_50.c
+++ b/src/gallium/drivers/radeon/radeon_vce_50.c
@@ -78,17 +78,30 @@ static void rate_control(struct rvce_encoder *enc)
static void encode(struct rvce_encoder *enc)
{
- signed luma_offset, chroma_offset;
+ signed luma_offset, chroma_offset, bs_offset;
+ unsigned dep, bs_idx = enc->bs_idx++;
int i;
- enc->task_info(enc, 0x00000003, 0, 0, 0);
+ if (enc->dual_inst) {
+ if (bs_idx == 0)
+ dep = 1;
+ else if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR)
+ dep = 0;
+ else
+ dep = 2;
+ } else
+ dep = 0;
+
+ enc->task_info(enc, 0x00000003, dep, 0, bs_idx);
RVCE_BEGIN(0x05000001); // context buffer
RVCE_READWRITE(enc->cpb.res->cs_buf, enc->cpb.res->domains, 0); // encodeContextAddressHi/Lo
RVCE_END();
+ bs_offset = -(signed)(bs_idx * enc->bs_size);
+
RVCE_BEGIN(0x05000004); // video bitstream buffer
- RVCE_WRITE(enc->bs_handle, RADEON_DOMAIN_GTT, 0); // videoBitstreamRingAddressHi/Lo
+ RVCE_WRITE(enc->bs_handle, RADEON_DOMAIN_GTT, bs_offset); // videoBitstreamRingAddressHi/Lo
RVCE_CS(enc->bs_size); // videoBitstreamRingSize
RVCE_END();