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