[Mesa-dev] [PATCH 4/4] radv: realign cp dma code with radeonsi

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Thu Jun 1 22:48:41 UTC 2017


Patches 1,2,4 are also

Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>

On Thu, Jun 1, 2017 at 6:43 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This reworks this code to be like radeonsi, which will make it
> easier to add GFX9 support to it in the future.
> ---
>  src/amd/vulkan/si_cmd_buffer.c | 156 ++++++++++++++++++-----------------------
>  1 file changed, 70 insertions(+), 86 deletions(-)
>
> diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c
> index 69f57fd..6a8e2af 100644
> --- a/src/amd/vulkan/si_cmd_buffer.c
> +++ b/src/amd/vulkan/si_cmd_buffer.c
> @@ -982,51 +982,76 @@ si_emit_cache_flush(struct radv_cmd_buffer *cmd_buffer)
>
>  /* Set this if you want the 3D engine to wait until CP DMA is done.
>   * It should be set on the last CP DMA packet. */
> -#define R600_CP_DMA_SYNC       (1 << 0) /* R600+ */
> +#define CP_DMA_SYNC    (1 << 0)
>
>  /* Set this if the source data was used as a destination in a previous CP DMA
>   * packet. It's for preventing a read-after-write (RAW) hazard between two
>   * CP DMA packets. */
> -#define SI_CP_DMA_RAW_WAIT     (1 << 1) /* SI+ */
> -#define CIK_CP_DMA_USE_L2      (1 << 2)
> +#define CP_DMA_RAW_WAIT        (1 << 1)
> +#define CP_DMA_USE_L2  (1 << 2)
> +#define CP_DMA_CLEAR   (1 << 3)
>
>  /* Alignment for optimal performance. */
> -#define CP_DMA_ALIGNMENT       32
> -/* The max number of bytes to copy per packet. */
> -#define CP_DMA_MAX_BYTE_COUNT  ((1 << 21) - CP_DMA_ALIGNMENT)
> +#define SI_CPDMA_ALIGNMENT     32
>
> -static void si_emit_cp_dma_copy_buffer(struct radv_cmd_buffer *cmd_buffer,
> -                                      uint64_t dst_va, uint64_t src_va,
> -                                      unsigned size, unsigned flags)
> +/* The max number of bytes that can be copied per packet. */
> +static inline unsigned cp_dma_max_byte_count(struct radv_cmd_buffer *cmd_buffer)
> +{
> +       unsigned max = S_414_BYTE_COUNT_GFX6(~0u);
> +
> +       /* make it aligned for optimal performance */
> +       return max & ~(SI_CPDMA_ALIGNMENT - 1);
> +}
> +
> +static void si_emit_cp_dma(struct radv_cmd_buffer *cmd_buffer,
> +                          uint64_t dst_va, uint64_t src_va,
> +                          unsigned size, unsigned flags)
>  {
>         struct radeon_winsys_cs *cs = cmd_buffer->cs;
> -       uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? S_411_CP_SYNC(1) : 0;
> -       uint32_t wr_confirm = !(flags & R600_CP_DMA_SYNC) ? S_414_DISABLE_WR_CONFIRM_GFX6(1) : 0;
> -       uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? S_414_RAW_WAIT(1) : 0;
> -       uint32_t sel = flags & CIK_CP_DMA_USE_L2 ?
> -                          S_411_SRC_SEL(V_411_SRC_ADDR_TC_L2) |
> -                          S_411_DSL_SEL(V_411_DST_ADDR_TC_L2) : 0;
> +       uint32_t header = 0, command = 0;
>
>         assert(size);
> -       assert((size & ((1<<21)-1)) == size);
> +       assert(size <= cp_dma_max_byte_count(cmd_buffer));
>
>         radeon_check_space(cmd_buffer->device->ws, cmd_buffer->cs, 9);
>
> +       command |= S_414_BYTE_COUNT_GFX6(size);
> +
> +       /* Sync flags. */
> +       if (flags & CP_DMA_SYNC)
> +               header |= S_411_CP_SYNC(1);
> +       else {
> +               command |= S_414_DISABLE_WR_CONFIRM_GFX6(1);
> +       }
> +
> +       if (flags & CP_DMA_RAW_WAIT)
> +               command |= S_414_RAW_WAIT(1);
> +
> +       /* Src and dst flags. */
> +       if (flags & CP_DMA_USE_L2)
> +               header |= S_411_DSL_SEL(V_411_DST_ADDR_TC_L2);
> +
> +       if (flags & CP_DMA_CLEAR)
> +               header |= S_411_SRC_SEL(V_411_DATA);
> +       else if (flags & CP_DMA_USE_L2)
> +               header |= S_411_SRC_SEL(V_411_SRC_ADDR_TC_L2);
> +
>         if (cmd_buffer->device->physical_device->rad_info.chip_class >= CIK) {
>                 radeon_emit(cs, PKT3(PKT3_DMA_DATA, 5, 0));
> -               radeon_emit(cs, sync_flag | sel);       /* CP_SYNC [31] */
> +               radeon_emit(cs, header);
>                 radeon_emit(cs, src_va);                /* SRC_ADDR_LO [31:0] */
>                 radeon_emit(cs, src_va >> 32);          /* SRC_ADDR_HI [31:0] */
>                 radeon_emit(cs, dst_va);                /* DST_ADDR_LO [31:0] */
>                 radeon_emit(cs, dst_va >> 32);          /* DST_ADDR_HI [31:0] */
> -               radeon_emit(cs, size | wr_confirm | raw_wait);  /* COMMAND [29:22] | BYTE_COUNT [20:0] */
> +               radeon_emit(cs, command);
>         } else {
> +               header |= S_411_SRC_ADDR_HI(src_va >> 32);
>                 radeon_emit(cs, PKT3(PKT3_CP_DMA, 4, 0));
>                 radeon_emit(cs, src_va);                        /* SRC_ADDR_LO [31:0] */
> -               radeon_emit(cs, sync_flag | ((src_va >> 32) & 0xffff)); /* CP_SYNC [31] | SRC_ADDR_HI [15:0] */
> +               radeon_emit(cs, header);                        /* SRC_ADDR_HI [15:0] + flags. */
>                 radeon_emit(cs, dst_va);                        /* DST_ADDR_LO [31:0] */
>                 radeon_emit(cs, (dst_va >> 32) & 0xffff);       /* DST_ADDR_HI [15:0] */
> -               radeon_emit(cs, size | wr_confirm | raw_wait);  /* COMMAND [29:22] | BYTE_COUNT [20:0] */
> +               radeon_emit(cs, command);
>         }
>
>         /* CP DMA is executed in ME, but index buffers are read by PFP.
> @@ -1034,7 +1059,7 @@ static void si_emit_cp_dma_copy_buffer(struct radv_cmd_buffer *cmd_buffer,
>          * indices. If we wanted to execute CP DMA in PFP, this packet
>          * should precede it.
>          */
> -       if (sync_flag && cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL) {
> +       if ((flags & CP_DMA_SYNC) && cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL) {
>                 radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0));
>                 radeon_emit(cs, 0);
>         }
> @@ -1042,55 +1067,14 @@ static void si_emit_cp_dma_copy_buffer(struct radv_cmd_buffer *cmd_buffer,
>         radv_cmd_buffer_trace_emit(cmd_buffer);
>  }
>
> -/* Emit a CP DMA packet to clear a buffer. The size must fit in bits [20:0]. */
> -static void si_emit_cp_dma_clear_buffer(struct radv_cmd_buffer *cmd_buffer,
> -                                       uint64_t dst_va, unsigned size,
> -                                       uint32_t clear_value, unsigned flags)
> -{
> -       struct radeon_winsys_cs *cs = cmd_buffer->cs;
> -       uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? S_411_CP_SYNC(1) : 0;
> -       uint32_t wr_confirm = !(flags & R600_CP_DMA_SYNC) ? S_414_DISABLE_WR_CONFIRM_GFX6(1) : 0;
> -       uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? S_414_RAW_WAIT(1) : 0;
> -       uint32_t dst_sel = flags & CIK_CP_DMA_USE_L2 ? S_411_DSL_SEL(V_411_DST_ADDR_TC_L2) : 0;
> -
> -       assert(size);
> -       assert((size & ((1<<21)-1)) == size);
> -
> -       radeon_check_space(cmd_buffer->device->ws, cmd_buffer->cs, 9);
> -
> -       if (cmd_buffer->device->physical_device->rad_info.chip_class >= CIK) {
> -               radeon_emit(cs, PKT3(PKT3_DMA_DATA, 5, 0));
> -               radeon_emit(cs, sync_flag | dst_sel | S_411_SRC_SEL(V_411_DATA)); /* CP_SYNC [31] | SRC_SEL[30:29] */
> -               radeon_emit(cs, clear_value);           /* DATA [31:0] */
> -               radeon_emit(cs, 0);
> -               radeon_emit(cs, dst_va);                /* DST_ADDR_LO [31:0] */
> -               radeon_emit(cs, dst_va >> 32);          /* DST_ADDR_HI [15:0] */
> -               radeon_emit(cs, size | wr_confirm | raw_wait);  /* COMMAND [29:22] | BYTE_COUNT [20:0] */
> -       } else {
> -               radeon_emit(cs, PKT3(PKT3_CP_DMA, 4, 0));
> -               radeon_emit(cs, clear_value);           /* DATA [31:0] */
> -               radeon_emit(cs, sync_flag | S_411_SRC_SEL(V_411_DATA)); /* CP_SYNC [31] | SRC_SEL[30:29] */
> -               radeon_emit(cs, dst_va);                        /* DST_ADDR_LO [31:0] */
> -               radeon_emit(cs, (dst_va >> 32) & 0xffff);       /* DST_ADDR_HI [15:0] */
> -               radeon_emit(cs, size | wr_confirm | raw_wait);  /* COMMAND [29:22] | BYTE_COUNT [20:0] */
> -       }
> -
> -       /* See "copy_buffer" for explanation. */
> -       if (sync_flag && cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL) {
> -               radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0));
> -               radeon_emit(cs, 0);
> -       }
> -       radv_cmd_buffer_trace_emit(cmd_buffer);
> -}
> -
>  void si_cp_dma_prefetch(struct radv_cmd_buffer *cmd_buffer, uint64_t va,
>                          unsigned size)
>  {
> -       uint64_t aligned_va = va & ~(CP_DMA_ALIGNMENT - 1);
> -       uint64_t aligned_size = ((va + size + CP_DMA_ALIGNMENT -1) & ~(CP_DMA_ALIGNMENT - 1)) - aligned_va;
> +       uint64_t aligned_va = va & ~(SI_CPDMA_ALIGNMENT - 1);
> +       uint64_t aligned_size = ((va + size + SI_CPDMA_ALIGNMENT -1) & ~(SI_CPDMA_ALIGNMENT - 1)) - aligned_va;
>
> -       si_emit_cp_dma_copy_buffer(cmd_buffer, aligned_va, aligned_va,
> -                                  aligned_size, CIK_CP_DMA_USE_L2);
> +       si_emit_cp_dma(cmd_buffer, aligned_va, aligned_va,
> +                      aligned_size, CP_DMA_USE_L2);
>  }
>
>  static void si_cp_dma_prepare(struct radv_cmd_buffer *cmd_buffer, uint64_t byte_count,
> @@ -1102,14 +1086,14 @@ static void si_cp_dma_prepare(struct radv_cmd_buffer *cmd_buffer, uint64_t byte_
>          */
>         if (cmd_buffer->state.flush_bits) {
>                 si_emit_cache_flush(cmd_buffer);
> -               *flags |= SI_CP_DMA_RAW_WAIT;
> +               *flags |= CP_DMA_RAW_WAIT;
>         }
>
>         /* Do the synchronization after the last dma, so that all data
>          * is written to memory.
>          */
>         if (byte_count == remaining_size)
> -               *flags |= R600_CP_DMA_SYNC;
> +               *flags |= CP_DMA_SYNC;
>  }
>
>  static void si_cp_dma_realign_engine(struct radv_cmd_buffer *cmd_buffer, unsigned size)
> @@ -1117,20 +1101,20 @@ static void si_cp_dma_realign_engine(struct radv_cmd_buffer *cmd_buffer, unsigne
>         uint64_t va;
>         uint32_t offset;
>         unsigned dma_flags = 0;
> -       unsigned buf_size = CP_DMA_ALIGNMENT * 2;
> +       unsigned buf_size = SI_CPDMA_ALIGNMENT * 2;
>         void *ptr;
>
> -       assert(size < CP_DMA_ALIGNMENT);
> +       assert(size < SI_CPDMA_ALIGNMENT);
>
> -       radv_cmd_buffer_upload_alloc(cmd_buffer, buf_size, CP_DMA_ALIGNMENT,  &offset, &ptr);
> +       radv_cmd_buffer_upload_alloc(cmd_buffer, buf_size, SI_CPDMA_ALIGNMENT,  &offset, &ptr);
>
>         va = cmd_buffer->device->ws->buffer_get_va(cmd_buffer->upload.upload_bo);
>         va += offset;
>
>         si_cp_dma_prepare(cmd_buffer, size, size, &dma_flags);
>
> -       si_emit_cp_dma_copy_buffer(cmd_buffer, va, va + CP_DMA_ALIGNMENT, size,
> -                                  dma_flags);
> +       si_emit_cp_dma(cmd_buffer, va, va + SI_CPDMA_ALIGNMENT, size,
> +                      dma_flags);
>  }
>
>  void si_cp_dma_buffer_copy(struct radv_cmd_buffer *cmd_buffer,
> @@ -1147,15 +1131,15 @@ void si_cp_dma_buffer_copy(struct radv_cmd_buffer *cmd_buffer,
>                  * just to align the internal counter. Otherwise, the DMA engine
>                  * would slow down by an order of magnitude for following copies.
>                  */
> -               if (size % CP_DMA_ALIGNMENT)
> -                       realign_size = CP_DMA_ALIGNMENT - (size % CP_DMA_ALIGNMENT);
> +               if (size % SI_CPDMA_ALIGNMENT)
> +                       realign_size = SI_CPDMA_ALIGNMENT - (size % SI_CPDMA_ALIGNMENT);
>
>                 /* If the copy begins unaligned, we must start copying from the next
>                  * aligned block and the skipped part should be copied after everything
>                  * else has been copied. Only the src alignment matters, not dst.
>                  */
> -               if (src_va % CP_DMA_ALIGNMENT) {
> -                       skipped_size = CP_DMA_ALIGNMENT - (src_va % CP_DMA_ALIGNMENT);
> +               if (src_va % SI_CPDMA_ALIGNMENT) {
> +                       skipped_size = SI_CPDMA_ALIGNMENT - (src_va % SI_CPDMA_ALIGNMENT);
>                         /* The main part will be skipped if the size is too small. */
>                         skipped_size = MIN2(skipped_size, size);
>                         size -= skipped_size;
> @@ -1166,14 +1150,14 @@ void si_cp_dma_buffer_copy(struct radv_cmd_buffer *cmd_buffer,
>
>         while (size) {
>                 unsigned dma_flags = 0;
> -               unsigned byte_count = MIN2(size, CP_DMA_MAX_BYTE_COUNT);
> +               unsigned byte_count = MIN2(size, cp_dma_max_byte_count(cmd_buffer));
>
>                 si_cp_dma_prepare(cmd_buffer, byte_count,
>                                   size + skipped_size + realign_size,
>                                   &dma_flags);
>
> -               si_emit_cp_dma_copy_buffer(cmd_buffer, main_dest_va, main_src_va,
> -                                          byte_count, dma_flags);
> +               si_emit_cp_dma(cmd_buffer, main_dest_va, main_src_va,
> +                              byte_count, dma_flags);
>
>                 size -= byte_count;
>                 main_src_va += byte_count;
> @@ -1187,8 +1171,8 @@ void si_cp_dma_buffer_copy(struct radv_cmd_buffer *cmd_buffer,
>                                   size + skipped_size + realign_size,
>                                   &dma_flags);
>
> -               si_emit_cp_dma_copy_buffer(cmd_buffer, dest_va, src_va,
> -                                          skipped_size, dma_flags);
> +               si_emit_cp_dma(cmd_buffer, dest_va, src_va,
> +                              skipped_size, dma_flags);
>         }
>         if (realign_size)
>                 si_cp_dma_realign_engine(cmd_buffer, realign_size);
> @@ -1204,14 +1188,14 @@ void si_cp_dma_clear_buffer(struct radv_cmd_buffer *cmd_buffer, uint64_t va,
>         assert(va % 4 == 0 && size % 4 == 0);
>
>         while (size) {
> -               unsigned byte_count = MIN2(size, CP_DMA_MAX_BYTE_COUNT);
> -               unsigned dma_flags = 0;
> +               unsigned byte_count = MIN2(size, cp_dma_max_byte_count(cmd_buffer));
> +               unsigned dma_flags = CP_DMA_CLEAR;
>
>                 si_cp_dma_prepare(cmd_buffer, byte_count, size, &dma_flags);
>
>                 /* Emit the clear packet. */
> -               si_emit_cp_dma_clear_buffer(cmd_buffer, va, byte_count, value,
> -                                           dma_flags);
> +               si_emit_cp_dma(cmd_buffer, va, value, byte_count,
> +                              dma_flags);
>
>                 size -= byte_count;
>                 va += byte_count;
> --
> 2.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list