On Sat, Sep 3, 2016 at 12:14 AM, Pohjolainen, Topi < topi.pohjolai...@gmail.com> wrote:
> On Wed, Aug 31, 2016 at 02:22:33PM -0700, Jason Ekstrand wrote: > > --- > > src/intel/blorp/blorp.h | 10 ++++ > > src/intel/blorp/blorp_blit.c | 133 ++++++++++++++++++++++++++++++ > +++++++++++++ > > So the idea is to copy a compression block as a pixel (by choosing large > enough format), right? And this is only for compression schemes that do not > use auxiliary buffers? > Yes. Particularly, it's for the sort of compressed formats that get provided directly by users. It is also useful if you want to, for instance, copy from RGBA8_UNORM to RG16_FLOAT bit-for-bit without doing any conversion. In short, it's a memcpy() for image data. GL and Vulkan both have such APIs: glCopyImageSubData and vkCopyImage. > A few small comments further down. > > > 2 files changed, 143 insertions(+) > > > > diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h > > index c1e93fd..6574124 100644 > > --- a/src/intel/blorp/blorp.h > > +++ b/src/intel/blorp/blorp.h > > @@ -109,6 +109,16 @@ blorp_blit(struct blorp_batch *batch, > > uint32_t filter, bool mirror_x, bool mirror_y); > > > > void > > +blorp_copy(struct blorp_batch *batch, > > + const struct blorp_surf *src_surf, > > + unsigned src_level, unsigned src_layer, > > + const struct blorp_surf *dst_surf, > > + unsigned dst_level, unsigned dst_layer, > > + uint32_t src_x, uint32_t src_y, > > + uint32_t dst_x, uint32_t dst_y, > > + uint32_t src_width, uint32_t src_height); > > + > > +void > > blorp_fast_clear(struct blorp_batch *batch, > > const struct blorp_surf *surf, > > uint32_t level, uint32_t layer, enum isl_format format, > > diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c > > index 3ab39a3..42a502c 100644 > > --- a/src/intel/blorp/blorp_blit.c > > +++ b/src/intel/blorp/blorp_blit.c > > @@ -1685,3 +1685,136 @@ blorp_blit(struct blorp_batch *batch, > > dst_x0, dst_y0, dst_x1, dst_y1, > > mirror_x, mirror_y); > > } > > + > > +static enum isl_format > > +get_copy_format_for_bpb(unsigned bpb) > > +{ > > + /* The choice of UNORM and UINT formats is very intentional here. > Most of > > + * the time, we want to use a UINT format to avoid any rounding > error in > > + * the blit. For stencil blits, R8_UINT is required by the hardware. > > + * (It's the only format allowed in conjunction with W-tiling.) > Also we > > + * intentionally use the 4-channel formats whenever we can. This is > so > > + * that, when we do a RGB <-> RGBX copy, the two formats will line > up even > > + * though one of them is 3/4 the size of the other. The choice of > UNORM > > + * vs. UINT is also very intentional because Haswell doesn't handle > 8 or > > + * 16-bit RGB UINT formats at all so we have to use UNORM there. > > + * Fortunately, the only time we should ever use two different > formats in > > + * the table below is for RGB -> RGBA blits and so we will never > have any > > + * UNORM/UINT mismatch. > > + */ > > + switch (bpb) { > > + case 8: return ISL_FORMAT_R8_UINT; > > + case 16: return ISL_FORMAT_R8G8_UINT; > > + case 24: return ISL_FORMAT_R8G8B8_UNORM; > > + case 32: return ISL_FORMAT_R8G8B8A8_UNORM; > > + case 48: return ISL_FORMAT_R16G16B16_UNORM; > > + case 64: return ISL_FORMAT_R16G16B16A16_UNORM; > > + case 96: return ISL_FORMAT_R32G32B32_UINT; > > + case 128:return ISL_FORMAT_R32G32B32A32_UINT; > > + default: > > + unreachable("Unknown format bpb"); > > + } > > +} > > + > > +static void > > +surf_convert_to_uncompressed(const struct isl_device *isl_dev, > > + struct brw_blorp_surface_info *info, > > + uint32_t *x, uint32_t *y, > > + uint32_t *width, uint32_t *height) > > +{ > > + const struct isl_format_layout *fmtl = > > + isl_format_get_layout(info->surf.format); > > + > > + assert(fmtl->bw > 1 || fmtl->bh > 1); > > + > > + /* This is a compressed surface. We need to convert it to a single > > + * slice (becase compressed layouts don't perfectly match > uncompressed > > because > Yup > > + * ones with the same bpb) and divide x, y, width, and height by the > > + * block size. > > + */ > > + surf_convert_to_single_slice(isl_dev, info); > > + > > + if (width || height) { > > + assert(*width % fmtl->bw == 0 || > > + *x + *width == info->surf.logical_level0_px.width); > > + assert(*height % fmtl->bh == 0 || > > + *y + *height == info->surf.logical_level0_px.height); > > + *width = DIV_ROUND_UP(*width, fmtl->bw); > > + *height = DIV_ROUND_UP(*height, fmtl->bh); > > + } > > + > > + assert(*x % fmtl->bw == 0); > > + assert(*y % fmtl->bh == 0); > > + *x /= fmtl->bw; > > + *y /= fmtl->bh; > > + > > + info->surf.logical_level0_px.width = > > + DIV_ROUND_UP(info->surf.logical_level0_px.width, fmtl->bw); > > + info->surf.logical_level0_px.height = > > + DIV_ROUND_UP(info->surf.logical_level0_px.height, fmtl->bh); > > + > > + assert(info->surf.phys_level0_sa.width % fmtl->bw == 0); > > + assert(info->surf.phys_level0_sa.height % fmtl->bh == 0); > > + info->surf.phys_level0_sa.width /= fmtl->bw; > > + info->surf.phys_level0_sa.height /= fmtl->bh; > > + > > + assert(info->tile_x_sa % fmtl->bw == 0); > > + assert(info->tile_y_sa % fmtl->bh == 0); > > + info->tile_x_sa /= fmtl->bw; > > + info->tile_y_sa /= fmtl->bh; > > + > > + /* It's now an uncompressed surface so we need an uncompressed > format */ > > + info->surf.format = get_copy_format_for_bpb(fmtl->bpb); > > +} > > + > > +void > > +blorp_copy(struct blorp_batch *batch, > > + const struct blorp_surf *src_surf, > > + unsigned src_level, unsigned src_layer, > > + const struct blorp_surf *dst_surf, > > + unsigned dst_level, unsigned dst_layer, > > + uint32_t src_x, uint32_t src_y, > > + uint32_t dst_x, uint32_t dst_y, > > + uint32_t src_width, uint32_t src_height) > > +{ > > + struct blorp_params params; > > + blorp_params_init(¶ms); > > + > > + brw_blorp_surface_info_init(batch->blorp, ¶ms.src, src_surf, > src_level, > > + src_layer, ISL_FORMAT_UNSUPPORTED, > false); > > + brw_blorp_surface_info_init(batch->blorp, ¶ms.dst, dst_surf, > dst_level, > > + dst_layer, ISL_FORMAT_UNSUPPORTED, true); > > + > > + struct brw_blorp_blit_prog_key wm_prog_key; > > + memset(&wm_prog_key, 0, sizeof(wm_prog_key)); > > + > > + const struct isl_format_layout *src_fmtl = > > + isl_format_get_layout(params.src.surf.format); > > + const struct isl_format_layout *dst_fmtl = > > + isl_format_get_layout(params.dst.surf.format); > > + > > + params.src.view.format = get_copy_format_for_bpb(src_fmtl->bpb); > > + if (src_fmtl->bw > 1 || src_fmtl->bh > 1) { > > + surf_convert_to_uncompressed(batch->blorp->isl_dev, ¶ms.src, > > + &src_x, &src_y, &src_width, > &src_height); > > + wm_prog_key.need_dst_offset = true; > > I think you mean wm_prog_key.need_src_offset instead? > Drp... Thanks! > > + } > > + > > + params.dst.view.format = get_copy_format_for_bpb(dst_fmtl->bpb); > > + if (dst_fmtl->bw > 1 || dst_fmtl->bh > 1) { > > + surf_convert_to_uncompressed(batch->blorp->isl_dev, ¶ms.dst, > > + &dst_x, &dst_y, NULL, NULL); > > + wm_prog_key.need_dst_offset = true; > > + } > > + > > + /* Once both surfaces are stompped to uncompressed as needed, the > > + * destination size is the same as the source size. > > + */ > > + uint32_t dst_width = src_width; > > + uint32_t dst_height = src_height; > > + > > + do_blorp_blit(batch, ¶ms, &wm_prog_key, > > + src_x, src_y, src_x + src_width, src_y + src_height, > > + dst_x, dst_y, dst_x + dst_width, dst_y + dst_height, > > + false, false); > > +} > > -- > > 2.5.0.400.gff86faf > > > > _______________________________________________ > > mesa-dev mailing list > > mesa-dev@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev