radeon/vce: implement VCE dual instance support
authorLeo Liu <leo.liu@amd.com>
Thu, 25 Jun 2015 14:14:14 +0000 (10:14 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 14 Aug 2015 13:02:31 +0000 (15:02 +0200)
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 <leo.liu@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/radeon/radeon_vce.c
src/gallium/drivers/radeon/radeon_vce.h
src/gallium/drivers/radeon/radeon_vce_50.c

index 0b667fd489b6d70480e980c436ba40db89d76f87..bc8f36db355d0ff35d02201e7cbd877725df250e 100644 (file)
@@ -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;
index 06e9868ca960330494ce6991c59608ba5e48fc52..624bda479f8ed5f37510a3aa82e74bcddfd1a992 100644 (file)
@@ -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 */
index 5bf221944189a4a6f3065e119ba2df00a2e2ec92..afdab18c0d3578810d1118079df74579742bc159 100644 (file)
@@ -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();