<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Jan 29, 2018 at 7:21 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"><div class="HOEnZb"><div class="h5">On Fri, Jan 26, 2018 at 05:58:25PM +0200, Pohjolainen, Topi wrote:<br>
> On Wed, Jan 24, 2018 at 12:29:05PM -0800, Jason Ekstrand wrote:<br>
> > On Wed, Jan 24, 2018 at 6:15 AM, Pohjolainen, Topi <<br>
> > <a href="mailto:topi.pohjolainen@gmail.com">topi.pohjolainen@gmail.com</a>> wrote:<br>
> ><br>
> > > On Fri, Jan 19, 2018 at 03:47:31PM -0800, Jason Ekstrand wrote:<br>
> > > > This pass performs an "ambiguate" operation on a CCS-compressed surface<br>
> > > > by manually writing zeros into the CCS. On gen8+, ISL gives us a fairly<br>
> > > > detailed notion of how the CCS is laid out so this is fairly simple to<br>
> > > > do. On gen7, the CCS tiling is quite crazy but that isn't an issue<br>
> > > > because we can only do CCS on single-slice images so we can just blast<br>
> > > > over the entire CCS buffer if we want to.<br>
> > > > ---<br>
> > > > src/intel/blorp/blorp.h | 5 ++<br>
> > > > src/intel/blorp/blorp_clear.c | 149 ++++++++++++++++++++++++++++++<br>
> > > ++++++++++++<br>
> > > > 2 files changed, 154 insertions(+)<br>
> > > ><br>
> > > > diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h<br>
> > > > index a1dd571..478a9af 100644<br>
> > > > --- a/src/intel/blorp/blorp.h<br>
> > > > +++ b/src/intel/blorp/blorp.h<br>
> > > > @@ -204,6 +204,11 @@ blorp_ccs_resolve(struct blorp_batch *batch,<br>
> > > > enum blorp_fast_clear_op resolve_op);<br>
> > > ><br>
> > > > void<br>
> > > > +blorp_ccs_ambiguate(struct blorp_batch *batch,<br>
> > > > + struct blorp_surf *surf,<br>
> > > > + uint32_t level, uint32_t layer);<br>
> > > > +<br>
> > > > +void<br>
> > > > blorp_mcs_partial_resolve(<wbr>struct blorp_batch *batch,<br>
> > > > struct blorp_surf *surf,<br>
> > > > enum isl_format format,<br>
> > > > diff --git a/src/intel/blorp/blorp_clear.<wbr>c<br>
> > > b/src/intel/blorp/blorp_clear.<wbr>c<br>
> > > > index 8e7bc9f..fa2abd9 100644<br>
> > > > --- a/src/intel/blorp/blorp_clear.<wbr>c<br>
> > > > +++ b/src/intel/blorp/blorp_clear.<wbr>c<br>
> > > > @@ -881,3 +881,152 @@ blorp_mcs_partial_resolve(<wbr>struct blorp_batch<br>
> > > *batch,<br>
> > > ><br>
> > > > batch->blorp->exec(batch, ¶ms);<br>
> > > > }<br>
> > > > +<br>
> > > > +/** Clear a CCS to the "uncompressed" state<br>
> > > > + *<br>
> > > > + * This pass is the CCS equivalent of a "HiZ resolve". It sets the CCS<br>
> > > values<br>
> > > > + * for a given layer/level of a surface to 0x0 which is the<br>
> > > "uncompressed"<br>
> > > > + * state which tells the sampler to go look at the main surface.<br>
> > > > + */<br>
> > > > +void<br>
> > > > +blorp_ccs_ambiguate(struct blorp_batch *batch,<br>
> > > > + struct blorp_surf *surf,<br>
> > > > + uint32_t level, uint32_t layer)<br>
> > > > +{<br>
> > > > + struct blorp_params params;<br>
> > > > + blorp_params_init(¶ms);<br>
> > > > +<br>
> > > > + assert(ISL_DEV_GEN(batch-><wbr>blorp->isl_dev) >= 7);<br>
> > > > +<br>
> > > > + const struct isl_format_layout *aux_fmtl =<br>
> > > > + isl_format_get_layout(surf-><wbr>aux_surf->format);<br>
> > > > + assert(aux_fmtl->txc == ISL_TXC_CCS);<br>
> > > > +<br>
> > > > + params.dst = (struct brw_blorp_surface_info) {<br>
> > > > + .enabled = true,<br>
> > > > + .addr = surf->aux_addr,<br>
> > > > + .view = {<br>
> > > > + .usage = ISL_SURF_USAGE_RENDER_TARGET_<wbr>BIT,<br>
> > > > + .format = ISL_FORMAT_R32G32B32A32_UINT,<br>
> > > > + .base_level = 0,<br>
> > > > + .base_array_layer = 0,<br>
> > > > + .levels = 1,<br>
> > > > + .array_len = 1,<br>
> > > > + .swizzle = ISL_SWIZZLE_IDENTITY,<br>
> > > > + },<br>
> > > > + };<br>
> > > > +<br>
> > > > + uint32_t z = 0;<br>
> > > > + if (surf->surf->dim == ISL_SURF_DIM_3D) {<br>
> > > > + z = layer;<br>
> > > > + layer = 0;<br>
> > > > + }<br>
> > > > +<br>
> > > > + uint32_t offset_B, x_offset_el, y_offset_el;<br>
> > > > + isl_surf_get_image_offset_el(<wbr>surf->aux_surf, level, layer, z,<br>
> > > > + &x_offset_el, &y_offset_el);<br>
> > > > + isl_tiling_get_intratile_<wbr>offset_el(surf->aux_surf-><wbr>tiling,<br>
> > > aux_fmtl->bpb,<br>
> > > > + surf->aux_surf->row_pitch,<br>
> > > > + x_offset_el, y_offset_el,<br>
> > > > + &offset_B, &x_offset_el,<br>
> > > &y_offset_el);<br>
> > > > + params.dst.addr.offset += offset_B;<br>
> > > > +<br>
> > > > + const uint32_t width_px = minify(surf->surf->logical_<wbr>level0_px.width,<br>
> > > level);<br>
> > > > + const uint32_t height_px = minify(surf->surf->logical_<wbr>level0_px.height,<br>
> > > level);<br>
> > > > + const uint32_t width_el = DIV_ROUND_UP(width_px, aux_fmtl->bw);<br>
> > > > + const uint32_t height_el = DIV_ROUND_UP(height_px, aux_fmtl->bh);<br>
><br>
> I need to think about these numbers a little more. I think I got the other<br>
> sources of my confusion figured out further down. See further down.<br>
<br>
</div></div>Right. I got a little confused when "width_px" and "height_px" where<br>
calculated against the main surface dimensions. I think I had forgotten how<br>
the aux surface actually got defined. It has the same dimensions as the main,<br>
block/element structure mapping it against pixels. I somehow remembered the<br>
aux dimensions were already scaled.<br></blockquote><div><br></div><div>Glad to hear it. :) I can change this to use surf->aux_surf instead. That might make things more clear.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I read the whole patch again and it makes perfect sense to me now:<br>
<br>
Reviewed-by: Topi Pohjolainen <<a href="mailto:topi.pohjolainen@intel.com">topi.pohjolainen@intel.com</a>><br><div class="HOEnZb"><div class="h5"></div></div></blockquote><div><br></div><div>Thanks!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
><br>
> > > > +<br>
> > > > + struct isl_tile_info ccs_tile_info;<br>
> > > > + isl_surf_get_tile_info(surf-><wbr>aux_surf, &ccs_tile_info);<br>
> > > > +<br>
> > > > + /* We're going to map it as a regular RGBA32_UINT surface. We need<br>
> > > to<br>
> > > > + * downscale a good deal. We start by computing the area on the CCS<br>
> > > to<br>
> > > > + * clear in units of Y-tiled cache lines.<br>
> > > > + */<br>
> > > > + uint32_t x_offset_y_cl, y_offset_y_cl, width_y_cl, height_y_cl;<br>
> > > > + if (ISL_DEV_GEN(batch->blorp-><wbr>isl_dev) >= 8) {<br>
> > > > + /* From the Sky Lake PRM Vol. 12 in the section on planes:<br>
> > > > + *<br>
> > > > + * "The Color Control Surface (CCS) contains the compression<br>
> > > status<br>
> > > > + * of the cache-line pairs. The compression state of the<br>
> > > cache-line<br>
> > > > + * pair is specified by 2 bits in the CCS. Each CCS cache-line<br>
> > > > + * represents an area on the main surface of 16x16 sets of 128<br>
> > > byte<br>
> > > > + * Y-tiled cache-line-pairs. CCS is always Y tiled."<br>
> > > > + *<br>
> > > > + * Each 2-bit surface element in the CCS corresponds to a single<br>
> > > > + * cache-line pair in the main surface. This means that 16x16 el<br>
> > > block<br>
> > > > + * in the CCS maps to a Y-tiled cache line. Fortunately, CCS<br>
> > > layouts<br>
> > > > + * are calculated with a very large alignment so we can round up<br>
> > > to a<br>
> > > > + * whole cache line without worrying about overdraw.<br>
> > > > + */<br>
> > > > +<br>
> > > > + /* On Broadwell and above, a CCS tile is the same as a Y tile when<br>
> > > > + * viewed at the cache-line granularity. Fortunately, the<br>
> > > horizontal<br>
> > > > + * and vertical alignment requirements of the CCS are such that<br>
> > > we can<br>
> > > > + * align to an entire cache line without worrying about crossing<br>
> > > over<br>
> > > > + * from one LOD to another.<br>
> > > > + */<br>
> > > > + const uint32_t scale_x = ccs_tile_info.logical_extent_<wbr>el.w / 8;<br>
> > > > + const uint32_t scale_y = ccs_tile_info.logical_extent_<wbr>el.h / 8;<br>
> > ><br>
> > > These are now CCS tile dimensions in number of bytes, right?<br>
> > ><br>
> ><br>
> > No. They are the number of 2-bit CCS elements in a single CCS cache line.<br>
><br>
> Okay, thanks. I went to read isl_tiling_get_info() and "case ISL_TILING_CCS".<br>
> There the sentence "The CCS being Y-tiled implies that it's an 8x8 grid of<br>
> cache-lines" helped me quite a bit.<br>
><br>
> ><br>
> ><br>
> > > > + assert(surf->aux_surf->image_<wbr>alignment_el.w % scale_x == 0);<br>
> > > > + assert(surf->aux_surf->image_<wbr>alignment_el.h % scale_y == 0);<br>
> > > > +<br>
> > > > + assert(x_offset_el % scale_x == 0 && y_offset_el % scale_y == 0);<br>
> > > > + x_offset_y_cl = x_offset_el / scale_x;<br>
> > > > + y_offset_y_cl = y_offset_el / scale_y;<br>
> > > > + width_y_cl = DIV_ROUND_UP(width_el, scale_x);<br>
> > > > + height_y_cl = DIV_ROUND_UP(height_el, scale_y);<br>
> > ><br>
> > > This talks about cache lines but I'm reading that these *_cl are actually<br>
> > > numbers in CCS tiles. What am I missing/misunderstanding?<br>
> > ><br>
> ><br>
> > They are in terms of CCS cache lines. Maybe the "y_cl" is misleading and<br>
> > "ccs_cl" would be better?<br>
><br>
> You do document above that "CCS tile is the same as a Y tile when viewed at<br>
> the cache-line granularity" so I think it is fine.<br>
><br>
> ><br>
> ><br>
> > > > + } else {<br>
> > > > + /* On gen7, the CCS tiling is not so nice. However, there we are<br>
> > > > + * guaranteed that we only have a single level and slice so we<br>
> > > don't<br>
> > > > + * have to worry about it and can just align to a whole tile.<br>
> > > > + */<br>
> > > > + assert(x_offset_el == 0 && y_offset_el == 0);<br>
> > > > + const uint32_t width_tl =<br>
> > > > + DIV_ROUND_UP(width_el, ccs_tile_info.logical_extent_<wbr>el.w);<br>
> > > > + const uint32_t height_tl =<br>
> > > > + DIV_ROUND_UP(height_el, ccs_tile_info.logical_extent_<wbr>el.h);<br>
> > > > + x_offset_y_cl = 0;<br>
> > > > + y_offset_y_cl = 0;<br>
> > > > + width_y_cl = width_tl * 8;<br>
> > > > + height_y_cl = height_tl * 8;<br>
> > ><br>
> > > I am probably badly off in the weeds, and just need to ask. Here I'm<br>
> > > thinking<br>
> > > that width_tl, for example, is something in number of bits and width_tl<br>
> > > becomes width in CCS tiles.<br>
> > ><br>
> ><br>
> > width_tl is width in CCS tiles. width_y_cl is width in cache lines.<br>
> ><br>
> ><br>
> > > > + }<br>
> > > > +<br>
> > > > + /* We're going to use a RGBA32 format so as to write data as quickly<br>
> > > as<br>
> > > > + * possible. A y-tiled cache line will then be 1x4 px.<br>
> > > > + */<br>
> > > > + const uint32_t x_offset_rgba_px = x_offset_y_cl;<br>
> > > > + const uint32_t y_offset_rgba_px = y_offset_y_cl * 4;<br>
> > > > + const uint32_t width_rgba_px = width_y_cl;<br>
> > > > + const uint32_t height_rgba_px = height_y_cl * 4;<br>
> > ><br>
> > > And my confusion continues here. Numbers denoted as *_cl represent<br>
> > > something<br>
> > > four times as small as pixels. I'd thought one would need to divide the<br>
> > > number<br>
> > > instead of multiplying it. One is about to represent the same amount with<br>
> > > larger units (pixels).<br>
> > ><br>
> > > > +<br>
> > > > + MAYBE_UNUSED bool ok =<br>
> > > > + isl_surf_init(batch->blorp-><wbr>isl_dev, ¶ms.dst.surf,<br>
> > > > + .dim = ISL_SURF_DIM_2D,<br>
> > > > + .format = ISL_FORMAT_R32G32B32A32_UINT,<br>
> > > > + .width = width_rgba_px + x_offset_rgba_px,<br>
> > > > + .height = height_rgba_px + y_offset_rgba_px,<br>
> > > > + .depth = 1,<br>
> > > > + .levels = 1,<br>
> > > > + .array_len = 1,<br>
> > > > + .samples = 1,<br>
> > > > + .row_pitch = surf->aux_surf->row_pitch,<br>
> > > > + .usage = ISL_SURF_USAGE_RENDER_TARGET_<wbr>BIT,<br>
> > > > + .tiling_flags = ISL_TILING_Y0_BIT);<br>
> > > > + assert(ok);<br>
> > > > + assert(offset_B + params.dst.surf.size <= surf->aux_surf->size);<br>
> > > > +<br>
> > > > + params.x0 = x_offset_rgba_px;<br>
> > > > + params.y0 = y_offset_rgba_px;<br>
> > > > + params.x1 = x_offset_rgba_px + width_rgba_px;<br>
> > > > + params.y1 = y_offset_rgba_px + height_rgba_px;<br>
> > > > +<br>
> > > > + /* A CCS value of 0 means "uncompressed." */<br>
> > > > + memset(¶ms.wm_inputs.<wbr>clear_color, 0,<br>
> > > > + sizeof(params.wm_inputs.clear_<wbr>color));<br>
> > > > +<br>
> > > > + if (!blorp_params_get_clear_<wbr>kernel(batch->blorp, ¶ms, true))<br>
> > > > + return;<br>
> > > > +<br>
> > > > + batch->blorp->exec(batch, ¶ms);<br>
> > > > +}<br>
> > > > --<br>
> > > > 2.5.0.400.gff86faf<br>
> > > ><br>
> > > > ______________________________<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>
> > ><br>
</div></div></blockquote></div><br></div></div>