17ec681f3SmrgHierarchical Depth (HiZ)
27ec681f3Smrg========================
37ec681f3Smrg
47ec681f3SmrgTODO: Add detailed docs like we have for CCS
57ec681f3Smrg
67ec681f3SmrgHiZ/stencil on Sandy Bridge
77ec681f3Smrg---------------------------
87ec681f3Smrg
97ec681f3SmrgProperly enabling HiZ on Sandy Bridge requires certain special considerations.
107ec681f3SmrgFrom the Sandy Bridge PRM Vol. 2, Pt. 1, 7.5.3 "Hierarchical Depth Buffer" (p.
117ec681f3Smrg312):
127ec681f3Smrg
137ec681f3Smrg   The hierarchical depth buffer does not support the LOD field, it is assumed
147ec681f3Smrg   by hardware to be zero. A separate hierarachical depth buffer is required
157ec681f3Smrg   for each LOD used, and the corresponding buffer’s state delivered to
167ec681f3Smrg   hardware each time a new depth buffer state with modified LOD is delivered.
177ec681f3Smrg
187ec681f3SmrgThe ``3DSTATE_STENCIL_BUFFER`` packet for separate stencil (required for HiZ)
197ec681f3Smrgon sandy bridge also lacks an LOD field.  Empirically, the hardware doesn't
207ec681f3Smrgpull the stencil LOD from ``3DSTATE_DEPTH_BUFFER``, it's just always 0 like
217ec681f3Smrgwith HiZ.
227ec681f3Smrg
237ec681f3SmrgAs stated in the PRM, this means we need a separate HiZ or stencil buffer for
247ec681f3Smrgeach LOD.  However, it's not quite as simple as that.  If you ignore layered
257ec681f3Smrgrendering, things are pretty straightforward: you need one HiZ surface for each
267ec681f3Smrgmain surface slice With layered, rendering, however, we have to be a bit more
277ec681f3Smrgclever because we need a "real" array surface at each LOD.  ISL solves this
287ec681f3Smrgwith a special miptree layout for layered rendering
297ec681f3Smrg:cpp:enumerator:`isl_dim_layout::ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ` which lays
307ec681f3Smrgout the surface as a miptree of layered images instead of an array of miptrees.
317ec681f3SmrgSee the docs for
327ec681f3Smrg:cpp:enumerator:`isl_dim_layout::ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ` for a nice
337ec681f3Smrgdescription along with an ASCII art diagram of the layout.
347ec681f3Smrg
357ec681f3SmrgAlso, neither ``3DSTATE_STENCIL_BUFFER`` nor ``3DSTATE_HIER_DEPTH_BUFFER`` have
367ec681f3Smrgtheir own surface dimensions or layout information on Sandy Bridge.  They're
377ec681f3Smrgjust an address and a surface pitch.  Instead, all that other information is
387ec681f3Smrgpulled from ``3DSTATE_DEPTH_BUFFER``.  When you combine this with the lack of
397ec681f3SmrgLOD, this means that, technically, we have a full-sized single-LOD stencil or
407ec681f3SmrgHiZ surface at each miplevel of which only the upper left-hand corner of each
417ec681f3Smrgarray slice ever gets used.  The net effect of this is that, in
427ec681f3Smrg:cpp:enumerator:`isl_dim_layout::ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ`, all LODs
437ec681f3Smrgshare the same QPitch even though it's horribly wasteful.  This is actually
447ec681f3Smrgpretty convenient for ISL because we only have the one
457ec681f3Smrg:cpp:member:`isl_surf::array_pitch_el_rows` field.
467ec681f3Smrg
477ec681f3SmrgDue to difficulties with plumbing relocation deltas through ISL's
487ec681f3Smrgdepth/stencil/hiz emit interface, we can't handle this all automatically in
497ec681f3SmrgISL.  Instead, it's left up to the driver to do this offsetting.  ISL does
507ec681f3Smrgprovide helpers for computing the offsets and they work fine with
517ec681f3Smrg:cpp:enumerator:`isl_dim_layout::ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ` so all that's
527ec681f3Smrgreally required is to call the ISL helper and add the computed offset to the
537ec681f3SmrgHiZ or stencil buffer address.  The following is an excerpt from BLORP where we
547ec681f3Smrgdo this as an example:
557ec681f3Smrg
567ec681f3Smrg.. code-block:: c
577ec681f3Smrg
587ec681f3Smrg   struct blorp_address hiz_address = params->depth.aux_addr;
597ec681f3Smrg   #if GFX_VER == 6
607ec681f3Smrg   /* Sandy bridge hardware does not technically support mipmapped HiZ.
617ec681f3Smrg    * However, we have a special layout that allows us to make it work
627ec681f3Smrg    * anyway by manually offsetting to the specified miplevel.
637ec681f3Smrg    */
647ec681f3Smrg   assert(info.hiz_surf->dim_layout == ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ);
657ec681f3Smrg   uint32_t offset_B;
667ec681f3Smrg   isl_surf_get_image_offset_B_tile_sa(info.hiz_surf,
677ec681f3Smrg                                       info.view->base_level, 0, 0,
687ec681f3Smrg                                       &offset_B, NULL, NULL);
697ec681f3Smrg   hiz_address.offset += offset_B;
707ec681f3Smrg   #endif
717ec681f3Smrg
727ec681f3Smrg   info.hiz_address =
737ec681f3Smrg      blorp_emit_reloc(batch, dw + isl_dev->ds.hiz_offset / 4,
747ec681f3Smrg                       hiz_address, 0);
75