[Mesa-dev] [PATCH V2 17/22] i965/gen9: Add XY_FAST_COPY_BLT support to intelEmitCopyBlit()

Ben Widawsky ben at bwidawsk.net
Wed May 27 10:42:07 PDT 2015


On Thu, May 21, 2015 at 05:46:48PM -0700, Anuj Phogat wrote:
> On Thu, May 21, 2015 at 12:26 PM, Ben Widawsky <ben at bwidawsk.net> wrote:

SNIP

> > As I mentioned above wrt the CL alignment, I think it's safe to do for both
> > modes. Something like:
> >
> > /* Check both are at least cacheline aligned */
> > if (brw->gen >= 8 && (src_offset | dst_offset) & 63)
> >     return false;
> >
> We do this check for SRC_COPY_BLT in alignemnet_valid(). I added
> the restrictions for FAST_COPY_BLT in fast_copy_blit_error_check().
> Doing this check for both satisy all alignment restrictions of both modes
> except one in fast copy blit: when src is untiled and dst is tiled, dst
> should be 64 byte aligned and src should be 16 bytes aligned. See
> fast_copy_blit_error_check().
> But we're adding a restriction for it to be 64 byte by the suggested
> change. Is there any advantage of the suggested check for both?
> 

Oh hmm, I hadn't noticed a 16byte alignment requirement anywhere. I thought 64b
was the minimum - if it's not ignore me.

> >>     if ((dst_y_tiled || src_y_tiled) && brw->gen < 6)
> >>        return false;
> >>
> >>     assert(!dst_y_tiled || (dst_pitch % 128) == 0);
> >>     assert(!src_y_tiled || (src_pitch % 128) == 0);
> >>
> >> +   if (use_fast_copy_blit == false &&
> >> +       (src_tr_mode != INTEL_MIPTREE_TRMODE_NONE ||
> >> +        dst_tr_mode != INTEL_MIPTREE_TRMODE_NONE))
> >> +      return false;
> >> +
> >
> > It seems like we should make it an error to use this improperly:
> >
> > /* It's an error for a caller to try to do a regular blit with a yf/ys region */
> > assert(use_fast_copy_blit &&
> >        (src_tr_mode != INTEL_MIPTREE_TRMODE_NONE) &&
> >        (dst_tr_mode != INTEL_MIPTREE_TRMODE_NONE))
> >
> Agree.
> >>     /* do space check before going any further */
> >>     do {
> >>         aper_array[0] = brw->batch.bo;
> >> @@ -334,13 +498,6 @@ intelEmitCopyBlit(struct brw_context *brw,
> >>         src_buffer, src_pitch, src_offset, src_x, src_y,
> >>         dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
> >>
> >> -   /* Blit pitch must be dword-aligned.  Otherwise, the hardware appears to drop
> >> -    * the low bits.  Offsets must be naturally aligned.
> >> -    */
> >> -   if (src_pitch % 4 != 0 || src_offset % cpp != 0 ||
> >> -       dst_pitch % 4 != 0 || dst_offset % cpp != 0)
> >> -      return false;
> >> -
> >>     /* For big formats (such as floating point), do the copy using 16 or 32bpp
> >>      * and multiply the coordinates.
> >>      */
> >> @@ -359,27 +516,76 @@ intelEmitCopyBlit(struct brw_context *brw,
> >>        }
> >>     }
> >>
> >> -   BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16;
> >> +   if (use_fast_copy_blit &&
> >> +       fast_copy_blit_error_check(src_offset, src_pitch, src_tiling,
> >> +                                  dst_offset, dst_pitch, dst_tiling, cpp)) {
> >> +      BR13 = br13_for_cpp(cpp);
> >>
> >
> > If you follow about you can remove the error check here as we know it's safe to
> > proceed.
> >
> Right. As i understand you mean to move the fast_copy_blit_error_check() inside
> can_fast_copy_blit() helper ?
> 
> >> -   switch (cpp) {
> >> -   case 1:
> >> -   case 2:
> >> -      CMD = XY_SRC_COPY_BLT_CMD;
> >> -      break;
> >> -   case 4:
> >> -      CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
> >> -      break;
> >> -   default:
> >> -      return false;
> >> -   }
> >> +      if (src_tr_mode == INTEL_MIPTREE_TRMODE_YF)
> >> +         BR13 |= XY_SRC_TRMODE_YF;
> >>
> >> -   if (dst_tiling != I915_TILING_NONE) {
> >> -      CMD |= XY_DST_TILED;
> >> -      dst_pitch /= 4;
> >> -   }
> >> -   if (src_tiling != I915_TILING_NONE) {
> >> -      CMD |= XY_SRC_TILED;
> >> -      src_pitch /= 4;
> >> +      if (dst_tr_mode == INTEL_MIPTREE_TRMODE_YF)
> >> +         BR13 |= XY_DST_TRMODE_YF;
> >> +
> >> +      CMD = XY_FAST_COPY_BLT_CMD;
> >> +
> >> +      if (dst_tiling != I915_TILING_NONE) {
> >> +         SET_TILING_XY_FAST_COPY_BLT(dst_tiling, dst_tr_mode, XY_DST);
> >> +         /* Pitch value should be specified as a number of Dwords. */
> >> +         dst_pitch /= 4;
> >> +      }
> >> +      if (src_tiling != I915_TILING_NONE) {
> >> +         SET_TILING_XY_FAST_COPY_BLT(src_tiling, src_tr_mode, XY_SRC);
> >> +         /* Pitch value should be specified as a number of Dwords. */
> >> +         src_pitch /= 4;
> >> +      }
> >> +
> >> +      CMD |= get_tr_horizontal_align(src_tr_mode, cpp, true /* is_src */);
> >> +      CMD |= get_tr_vertical_align(src_tr_mode, cpp, true /* is_src */);
> >> +
> >> +      CMD |= get_tr_horizontal_align(dst_tr_mode, cpp, false /* is_src */);
> >> +      CMD |= get_tr_vertical_align(dst_tr_mode, cpp, false /* is_src */);
> >> +
> >> +   } else {
> >> +      /* Source and destination base addresses should be 4 KB aligned. */
> >> +      if (dst_tiling != I915_TILING_NONE) {
> >> +         if (dst_offset & 4095)
> >> +            return false;
> >> +      }
> >> +      if (src_tiling != I915_TILING_NONE) {
> >> +         if (src_offset & 4095)
> >> +            return false;
> >> +      }
> >> +
> >> +      /* Blit pitch must be dword-aligned.  Otherwise, the hardware appears to drop
> >> +       * the low bits.  Offsets must be naturally aligned.
> >> +       */
> >> +      if (src_pitch % 4 != 0 || src_offset % cpp != 0 ||
> >> +          dst_pitch % 4 != 0 || dst_offset % cpp != 0)
> >> +         return false;
> >> +
> >> +      assert(cpp <= 4);
> >> +      BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16;
> >> +      switch (cpp) {
> >> +      case 1:
> >> +      case 2:
> >> +         CMD = XY_SRC_COPY_BLT_CMD;
> >> +         break;
> >> +      case 4:
> >> +         CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
> >> +         break;
> >> +      default:
> >> +         return false;
> >> +      }
> >> +
> >> +      if (dst_tiling != I915_TILING_NONE) {
> >> +         CMD |= XY_DST_TILED;
> >> +         dst_pitch /= 4;
> >> +      }
> >> +      if (src_tiling != I915_TILING_NONE) {
> >> +         CMD |= XY_SRC_TILED;
> >> +         src_pitch /= 4;
> >> +      }
> >
> > I'd be in favor of extracting the CMD out into a helper to cut down the size of
> > this function. Up to you.
> >
> I'll try to make a helper for CMD.
> 
> > CMD = get_copy_blit_cmd()
> > BR_13 = br13_for_cpp(cpp)
> > if (!fast_copy)
> >    BR_13 |=  translate_raster_op(logic_op) << 16;
> >
> > I think also the pitch division is common to both.
> >
> >>     }
> >>
> >>     if (dst_y2 <= dst_y || dst_x2 <= dst_x) {
> >> @@ -533,11 +739,14 @@ intel_emit_linear_blit(struct brw_context *brw,
> >>     pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4);
> >>     height = (pitch == 0) ? 1 : size / pitch;
> >>     ok = intelEmitCopyBlit(brw, 1,
> >> -                       pitch, src_bo, src_offset, I915_TILING_NONE,
> >> -                       pitch, dst_bo, dst_offset, I915_TILING_NONE,
> >> +                       pitch, src_bo, src_offset,
> >> +                       I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
> >> +                       pitch, dst_bo, dst_offset,
> >> +                       I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
> >>                         0, 0, /* src x/y */
> >>                         0, 0, /* dst x/y */
> >>                         pitch, height, /* w, h */
> >> +                       false, /* overlap */
> >>                         GL_COPY);
> >>     if (!ok)
> >>        _mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height);
> >> @@ -549,11 +758,14 @@ intel_emit_linear_blit(struct brw_context *brw,
> >>     pitch = ALIGN(size, 4);
> >>     if (size != 0) {
> >>        ok = intelEmitCopyBlit(brw, 1,
> >> -                          pitch, src_bo, src_offset, I915_TILING_NONE,
> >> -                          pitch, dst_bo, dst_offset, I915_TILING_NONE,
> >> +                          pitch, src_bo, src_offset,
> >> +                          I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
> >> +                          pitch, dst_bo, dst_offset,
> >> +                          I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
> >>                            0, 0, /* src x/y */
> >>                            0, 0, /* dst x/y */
> >>                            size, 1, /* w, h */
> >> +                          false, /* overlap */
> >>                            GL_COPY);
> >>        if (!ok)
> >>           _mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1);
> >> diff --git a/src/mesa/drivers/dri/i965/intel_blit.h b/src/mesa/drivers/dri/i965/intel_blit.h
> >> index f563939..29c9ead 100644
> >> --- a/src/mesa/drivers/dri/i965/intel_blit.h
> >> +++ b/src/mesa/drivers/dri/i965/intel_blit.h
> >> @@ -37,13 +37,16 @@ intelEmitCopyBlit(struct brw_context *brw,
> >>                                drm_intel_bo *src_buffer,
> >>                                GLuint src_offset,
> >>                             uint32_t src_tiling,
> >> +                           uint32_t src_tr_mode,
> >>                                GLshort dst_pitch,
> >>                                drm_intel_bo *dst_buffer,
> >>                                GLuint dst_offset,
> >>                             uint32_t dst_tiling,
> >> +                           uint32_t dst_tr_mode,
> >>                                GLshort srcx, GLshort srcy,
> >>                                GLshort dstx, GLshort dsty,
> >>                                GLshort w, GLshort h,
> >> +                           bool overlap,
> >>                             GLenum logicop );
> >>
> >>  bool intel_miptree_blit(struct brw_context *brw,
> >> diff --git a/src/mesa/drivers/dri/i965/intel_copy_image.c b/src/mesa/drivers/dri/i965/intel_copy_image.c
> >> index f4c7eff..1e4a1e2 100644
> >> --- a/src/mesa/drivers/dri/i965/intel_copy_image.c
> >> +++ b/src/mesa/drivers/dri/i965/intel_copy_image.c
> >> @@ -126,12 +126,15 @@ copy_image_with_blitter(struct brw_context *brw,
> >>                              src_mt->pitch,
> >>                              src_mt->bo, src_mt->offset,
> >>                              src_mt->tiling,
> >> +                            src_mt->tr_mode,
> >>                              dst_mt->pitch,
> >>                              dst_mt->bo, dst_mt->offset,
> >>                              dst_mt->tiling,
> >> +                            dst_mt->tr_mode,
> >>                              src_x, src_y,
> >>                              dst_x, dst_y,
> >>                              src_width, src_height,
> >> +                            false /* overlap */,
> >>                              GL_COPY);
> >>  }
> >>
> >> diff --git a/src/mesa/drivers/dri/i965/intel_reg.h b/src/mesa/drivers/dri/i965/intel_reg.h
> >> index 488fb5b..6830148 100644
> >> --- a/src/mesa/drivers/dri/i965/intel_reg.h
> >> +++ b/src/mesa/drivers/dri/i965/intel_reg.h
> >> @@ -87,6 +87,8 @@
> >>
> >>  #define XY_SRC_COPY_BLT_CMD             (CMD_2D | (0x53 << 22))
> >>
> >> +#define XY_FAST_COPY_BLT_CMD             (CMD_2D | (0x42 << 22))
> >> +
> >>  #define XY_TEXT_IMMEDIATE_BLIT_CMD   (CMD_2D | (0x31 << 22))
> >>  # define XY_TEXT_BYTE_PACKED         (1 << 16)
> >>
> >> @@ -95,11 +97,42 @@
> >>  #define XY_BLT_WRITE_RGB     (1 << 20)
> >>  #define XY_SRC_TILED         (1 << 15)
> >>  #define XY_DST_TILED         (1 << 11)
> >> +#define XY_SRC_TILED_X               (1 << 20)
> >> +#define XY_SRC_TILED_Y               (2 << 20)
> >> +#define XY_SRC_TILED_64K     (3 << 20)
> >> +#define XY_DST_TILED_X               (1 << 13)
> >> +#define XY_DST_TILED_Y               (2 << 13)
> >> +#define XY_DST_TILED_64K     (3 << 13)
> >> +
> >
> > You've mixed bits of two commands. Name these something like XY_FAST_*. Put them
> > in a separate chunk of code.
> OK
> > Also, I'm OCD, but I would have reversed the order here, highest value on top,
> > lowest on the bottom
> >
> I'll follow that order.
> >> +#define XY_SRC_H_ALIGN_32       (0 << 17)
> >> +#define XY_SRC_H_ALIGN_64       (1 << 17)
> >> +#define XY_SRC_H_ALIGN_128      (2 << 17)
> >> +#define XY_SRC_H_ALIGN_256      (3 << 17)
> >> +#define XY_SRC_H_ALIGN_512      (4 << 17)
> >> +
> >> +#define XY_SRC_V_ALIGN_64       (0 << 15)
> >> +#define XY_SRC_V_ALIGN_128      (1 << 15)
> >> +#define XY_SRC_V_ALIGN_256      (2 << 15)
> >> +
> >> +#define XY_DST_H_ALIGN_32       (0 << 10)
> >> +#define XY_DST_H_ALIGN_64       (1 << 10)
> >> +#define XY_DST_H_ALIGN_128      (2 << 10)
> >> +#define XY_DST_H_ALIGN_256      (3 << 10)
> >> +#define XY_DST_H_ALIGN_512      (4 << 10)
> >> +
> >> +#define XY_DST_V_ALIGN_64       (0 << 8)
> >> +#define XY_DST_V_ALIGN_128      (1 << 8)
> >> +#define XY_DST_V_ALIGN_256      (2 << 8)
> >>
> >>  /* BR13 */
> >>  #define BR13_8                       (0x0 << 24)
> >>  #define BR13_565             (0x1 << 24)
> >>  #define BR13_8888            (0x3 << 24)
> >> +#define BR13_16161616                (0x4 << 24)
> >> +#define BR13_32323232                (0x5 << 24)
> >> +
> >> +#define XY_SRC_TRMODE_YF        (1 << 31)
> >> +#define XY_DST_TRMODE_YF        (1 << 30)
> >>
> >>  /* Pipeline Statistics Counter Registers */
> >>  #define IA_VERTICES_COUNT               0x2310
> >
> > One thing I don't see addressed in this patch is
> >
> > "When two sequential fast copy blits have different source surfaces, but their
> > destinations refer to the same destination surface and therefore destinations
> > overlap, a Flush must be inserted between the two blits."
> I didn't notice this. I'll take care of it in V3.

Great.

> >
> >
> > --
> > Ben Widawsky, Intel Open Source Technology Center


More information about the mesa-dev mailing list