<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 8, 2016 at 12: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"><br>
Title says: "anv: Add initial for Sky Lake color compression". Did you mean<br>
to have something after "initial"?<span class=""><br></span></blockquote><div><br></div><div>Yeah, "support" should probably go in there<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
On Fri, Oct 28, 2016 at 02:17:09AM -0700, Jason Ekstrand wrote:<br>
> This commit adds basic support for color compression.  For the moment,<br>
> color compression is only enabled within a render pass and a full resolve<br>
> is done before the render pass finishes.  All texturing operations still<br>
> happen with CCS disabled.<br>
<br>
</span>I'm not that familiar with all the vulkan concepts so far and need to ask a<br>
few things. In this patch CCS_E is enabled whenever there is suitable render<br>
target. For surfaces of the type VK_DESCRIPTOR_TYPE_INPUT_<wbr>ATTACHMENT and<br>
VK_DESCRIPTOR_TYPE_STORAGE_<wbr>IMAGE aux is explicitly disabled. Does this mean<br>
that it is impossible to have one of these surfaces as render target in<br>
the same pass (and having compression turned on for writing)?<br></blockquote><div><br></div><div>No, not quite.  In this patch, we always do a full resolve at the end of the render pass.  Since input attachments aren't really supported yet (my next task), those aren't a problem.  Also, you can't bind one of your render pass attachments as a storage image or texture so those will never be used while it's in an unresolved state.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Otherwise this patch looks good to me.<br>
<div><div class="h5"><br>
><br>
> Signed-off-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> ---<br>
>  src/intel/vulkan/anv_blorp.c       | 139 +++++++++++++++++++++++++++++-<wbr>-------<br>
>  src/intel/vulkan/anv_image.c       |  17 +++--<br>
>  src/intel/vulkan/anv_private.h     |   1 +<br>
>  src/intel/vulkan/genX_cmd_<wbr>buffer.c |  50 ++++++++++++-<br>
>  4 files changed, 171 insertions(+), 36 deletions(-)<br>
><br>
> diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c<br>
> index 0e70e9b..bf317c7 100644<br>
> --- a/src/intel/vulkan/anv_blorp.c<br>
> +++ b/src/intel/vulkan/anv_blorp.c<br>
> @@ -1179,52 +1179,131 @@ void anv_CmdResolveImage(<br>
>     blorp_batch_finish(&batch);<br>
>  }<br>
><br>
> +static void<br>
> +ccs_resolve_attachment(struct anv_cmd_buffer *cmd_buffer,<br>
> +                       struct blorp_batch *batch,<br>
> +                       uint32_t att)<br>
> +{<br>
> +   struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;<br>
> +   struct anv_attachment_state *att_state =<br>
> +      &cmd_buffer->state.<wbr>attachments[att];<br>
> +<br>
> +   assert(att_state->aux_usage != ISL_AUX_USAGE_CCS_D);<br>
> +   if (att_state->aux_usage != ISL_AUX_USAGE_CCS_E)<br>
> +      return; /* Nothing to resolve */<br>
> +<br>
> +   struct anv_render_pass *pass = cmd_buffer->state.pass;<br>
> +   struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
> +   unsigned subpass_idx = subpass - pass->subpasses;<br>
> +   assert(subpass_idx < pass->subpass_count);<br>
> +<br>
> +   /* Scan forward to see what all ways this attachment will be used.<br>
> +    * Ideally, we would like to resolve in the same subpass as the last write<br>
> +    * of a particular attachment.  That way we only resolve once but it's<br>
> +    * still hot in the cache.<br>
> +    */<br>
> +   for (uint32_t s = subpass_idx + 1; s < pass->subpass_count; s++) {<br>
> +      enum anv_subpass_usage usage = pass->attachments[att].<wbr>subpass_usage[s];<br>
<br>
</div></div>I'm wondering if this holds?<br>
<br>
         assert(!(usage & ANV_SUBPASS_USAGE_INPUT));<br>
<div><div class="h5"><br>
> +<br>
> +      if (usage & (ANV_SUBPASS_USAGE_DRAW | ANV_SUBPASS_USAGE_RESOLVE_DST)<wbr>) {<br>
> +         /* We found another subpass that draws to this attachment.  We'll<br>
> +          * wait to resolve until then.<br>
> +          */<br>
> +         return;<br>
> +      }<br>
> +   }<br>
> +<br>
> +   struct anv_image_view *iview = fb->attachments[att];<br>
> +   const struct anv_image *image = iview->image;<br>
> +   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);<br>
> +<br>
> +   struct blorp_surf surf;<br>
> +   get_blorp_surf_for_anv_image(<wbr>image, VK_IMAGE_ASPECT_COLOR_BIT, &surf);<br>
> +   surf.aux_surf = &image->aux_surface.isl;<br>
> +   surf.aux_addr = (struct blorp_address) {<br>
> +      .buffer = image->bo,<br>
> +      .offset = image->offset + image->aux_surface.offset,<br>
> +   };<br>
> +   surf.aux_usage = att_state->aux_usage;<br>
> +<br>
> +   for (uint32_t layer = 0; layer < fb->layers; layer++) {<br>
> +      blorp_ccs_resolve(batch, &surf,<br>
> +                        iview->isl.base_level,<br>
> +                        iview->isl.base_array_layer + layer,<br>
> +                        iview->isl.format,<br>
> +                        BLORP_FAST_CLEAR_OP_RESOLVE_<wbr>FULL);<br>
> +   }<br>
> +}<br>
> +<br>
>  void<br>
>  anv_cmd_buffer_resolve_<wbr>subpass(struct anv_cmd_buffer *cmd_buffer)<br>
>  {<br>
>     struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;<br>
>     struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
><br>
> -   if (!subpass->has_resolve)<br>
> -      return;<br>
><br>
>     struct blorp_batch batch;<br>
>     blorp_batch_init(&cmd_buffer-><wbr>device->blorp, &batch, cmd_buffer, 0);<br>
><br>
> +   /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":<br>
> +    *<br>
> +    *    "When performing a render target resolve, PIPE_CONTROL with end of<br>
> +    *    pipe sync must be delivered."<br>
> +    */<br>
> +   cmd_buffer->state.pending_<wbr>pipe_bits |= ANV_PIPE_CS_STALL_BIT;<br>
> +<br>
>     for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
> -      uint32_t src_att = subpass->color_attachments[i];<br>
> -      uint32_t dst_att = subpass->resolve_attachments[<wbr>i];<br>
> +      ccs_resolve_attachment(cmd_<wbr>buffer, &batch,<br>
> +                             subpass->color_attachments[i])<wbr>;<br>
> +   }<br>
><br>
> -      if (dst_att == VK_ATTACHMENT_UNUSED)<br>
> -         continue;<br>
> +   if (subpass->has_resolve) {<br>
> +      for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
> +         uint32_t src_att = subpass->color_attachments[i];<br>
> +         uint32_t dst_att = subpass->resolve_attachments[<wbr>i];<br>
> +<br>
> +         if (dst_att == VK_ATTACHMENT_UNUSED)<br>
> +            continue;<br>
> +<br>
> +         if (cmd_buffer->state.<wbr>attachments[dst_att].pending_<wbr>clear_aspects) {<br>
> +            /* FINISHME(perf): Skip clears for resolve attachments.<br>
> +             *<br>
> +             * From the Vulkan 1.0 spec:<br>
> +             *<br>
> +             *    If the first use of an attachment in a render pass is as a<br>
> +             *    resolve attachment, then the loadOp is effectively ignored<br>
> +             *    as the resolve is guaranteed to overwrite all pixels in the<br>
> +             *    render area.<br>
> +             */<br>
> +            cmd_buffer->state.attachments[<wbr>dst_att].pending_clear_aspects = 0;<br>
> +         }<br>
><br>
> -      if (cmd_buffer->state.<wbr>attachments[dst_att].pending_<wbr>clear_aspects) {<br>
> -         /* FINISHME(perf): Skip clears for resolve attachments.<br>
> -          *<br>
> -          * From the Vulkan 1.0 spec:<br>
> -          *<br>
> -          *    If the first use of an attachment in a render pass is as a<br>
> -          *    resolve attachment, then the loadOp is effectively ignored<br>
> -          *    as the resolve is guaranteed to overwrite all pixels in the<br>
> -          *    render area.<br>
> -          */<br>
> -         cmd_buffer->state.attachments[<wbr>dst_att].pending_clear_aspects = 0;<br>
> -      }<br>
> +         struct anv_image_view *src_iview = fb->attachments[src_att];<br>
> +         struct anv_image_view *dst_iview = fb->attachments[dst_att];<br>
><br>
> -      struct anv_image_view *src_iview = fb->attachments[src_att];<br>
> -      struct anv_image_view *dst_iview = fb->attachments[dst_att];<br>
> +         const VkRect2D render_area = cmd_buffer->state.render_area;<br>
><br>
> -      const VkRect2D render_area = cmd_buffer->state.render_area;<br>
> +         assert(src_iview->aspect_mask == dst_iview->aspect_mask);<br>
> +         resolve_image(&batch, src_iview->image,<br>
> +                       src_iview->isl.base_level,<br>
> +                       src_iview->isl.base_array_<wbr>layer,<br>
> +                       dst_iview->image,<br>
> +                       dst_iview->isl.base_level,<br>
> +                       dst_iview->isl.base_array_<wbr>layer,<br>
> +                       src_iview->aspect_mask,<br>
> +                       render_area.offset.x, render_area.offset.y,<br>
> +                       render_area.offset.x, render_area.offset.y,<br>
> +                       render_area.extent.width, render_area.extent.height);<br>
><br>
> -      assert(src_iview->aspect_mask == dst_iview->aspect_mask);<br>
> -      resolve_image(&batch, src_iview->image,<br>
> -                    src_iview->isl.base_level, src_iview->isl.base_array_<wbr>layer,<br>
> -                    dst_iview->image,<br>
> -                    dst_iview->isl.base_level, dst_iview->isl.base_array_<wbr>layer,<br>
> -                    src_iview->aspect_mask,<br>
> -                    render_area.offset.x, render_area.offset.y,<br>
> -                    render_area.offset.x, render_area.offset.y,<br>
> -                    render_area.extent.width, render_area.extent.height);<br>
> +         /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":<br>
> +          *<br>
> +          *    "When performing a render target resolve, PIPE_CONTROL with end<br>
> +          *    of pipe sync must be delivered."<br>
> +          */<br>
> +         cmd_buffer->state.pending_<wbr>pipe_bits |= ANV_PIPE_CS_STALL_BIT;<br>
> +<br>
> +         ccs_resolve_attachment(cmd_<wbr>buffer, &batch, dst_att);<br>
> +      }<br>
>     }<br>
><br>
>     blorp_batch_finish(&batch);<br>
> diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
> index bdf8bca..4bef5ce 100644<br>
> --- a/src/intel/vulkan/anv_image.c<br>
> +++ b/src/intel/vulkan/anv_image.c<br>
> @@ -176,23 +176,32 @@ make_surface(const struct anv_device *dev,<br>
><br>
>     /* Add a HiZ surface to a depth buffer that will be used for rendering.<br>
>      */<br>
> -   if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT &&<br>
> -       (image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_<wbr>ATTACHMENT_BIT)) {<br>
> -<br>
> +   if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {<br>
>        /* Allow the user to control HiZ enabling. Disable by default on gen7<br>
>         * because resolves are not currently implemented pre-BDW.<br>
>         */<br>
> -      if (!env_var_as_boolean("INTEL_<wbr>VK_HIZ", dev->info.gen >= 8)) {<br>
> +      if (!(image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_<wbr>ATTACHMENT_BIT)) {<br>
> +         /* It will never be used as an attachment, HiZ is pointless. */<br>
> +      } else if (!env_var_as_boolean("INTEL_<wbr>VK_HIZ", dev->info.gen >= 8)) {<br>
>           anv_finishme("Implement gen7 HiZ");<br>
>        } else if (vk_info->mipLevels > 1) {<br>
>           anv_finishme("Test multi-LOD HiZ");<br>
>        } else if (dev->info.gen == 8 && vk_info->samples > 1) {<br>
>           anv_finishme("Test gen8 multisampled HiZ");<br>
>        } else {<br>
> +         assert(image->aux_surface.isl.<wbr>size == 0);<br>
>           isl_surf_get_hiz_surf(&dev-><wbr>isl_dev, &image->depth_surface.isl,<br>
>                                 &image->aux_surface.isl);<br>
>           add_surface(image, &image->aux_surface);<br>
>        }<br>
> +   } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) {<br>
> +      if (dev->info.gen >= 9 && vk_info->samples == 1) {<br>
> +         assert(image->aux_surface.isl.<wbr>size == 0);<br>
> +         ok = isl_surf_get_ccs_surf(&dev-><wbr>isl_dev, &anv_surf->isl,<br>
> +                                    &image->aux_surface.isl);<br>
> +         if (ok)<br>
> +            add_surface(image, &image->aux_surface);<br>
> +      }<br>
>     }<br>
><br>
>     return VK_SUCCESS;<br>
> diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
> index 531f2d1..6e8f5e0 100644<br>
> --- a/src/intel/vulkan/anv_<wbr>private.h<br>
> +++ b/src/intel/vulkan/anv_<wbr>private.h<br>
> @@ -1059,6 +1059,7 @@ void anv_dynamic_state_copy(struct anv_dynamic_state *dest,<br>
>   * The clear value is valid only if there exists a pending clear.<br>
>   */<br>
>  struct anv_attachment_state {<br>
> +   enum isl_aux_usage                           aux_usage;<br>
>     struct anv_state                             color_rt_state;<br>
><br>
>     VkImageAspectFlags                           pending_clear_aspects;<br>
> diff --git a/src/intel/vulkan/genX_cmd_<wbr>buffer.c b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> index a87e5a3..3b9f946 100644<br>
> --- a/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> +++ b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> @@ -165,6 +165,7 @@ add_surface_state_reloc(struct anv_cmd_buffer *cmd_buffer,<br>
>  static void<br>
>  add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,<br>
>                        const struct anv_image_view *iview,<br>
> +                      enum isl_aux_usage aux_usage,<br>
>                        struct anv_state state)<br>
>  {<br>
>     const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;<br>
> @@ -172,6 +173,41 @@ add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,<br>
>     anv_reloc_list_add(&cmd_<wbr>buffer->surface_relocs, &cmd_buffer->pool->alloc,<br>
>                        state.offset + isl_dev->ss.addr_offset,<br>
>                        iview->bo, iview->offset);<br>
> +<br>
> +   if (aux_usage != ISL_AUX_USAGE_NONE) {<br>
> +      uint32_t aux_offset = iview->offset + iview->image->aux_surface.<wbr>offset;<br>
> +<br>
> +      /* On gen7 and prior, the bottom 12 bits of the MCS base address are<br>
> +       * used to store other information.  This should be ok, however, because<br>
> +       * surface buffer addresses are always 4K page alinged.<br>
> +       */<br>
> +      assert((aux_offset & 0xfff) == 0);<br>
> +      uint32_t *aux_addr_dw = state.map + isl_dev->ss.aux_addr_offset;<br>
> +      aux_offset += *aux_addr_dw & 0xfff;<br>
> +<br>
> +      anv_reloc_list_add(&cmd_<wbr>buffer->surface_relocs, &cmd_buffer->pool->alloc,<br>
> +                         state.offset + isl_dev->ss.aux_addr_offset,<br>
> +                         iview->bo, aux_offset);<br>
> +   }<br>
> +}<br>
> +<br>
> +static enum isl_aux_usage<br>
> +fb_attachment_get_aux_usage(<wbr>struct anv_device *device,<br>
> +                            struct anv_framebuffer *fb,<br>
> +                            uint32_t attachment)<br>
> +{<br>
> +   struct anv_image_view *iview = fb->attachments[attachment];<br>
> +<br>
> +   if (iview->image->aux_surface.<wbr>isl.size == 0)<br>
> +      return ISL_AUX_USAGE_NONE; /* No aux surface */<br>
> +<br>
> +   assert(iview->image->aux_<wbr>surface.isl.usage & ISL_SURF_USAGE_CCS_BIT);<br>
> +<br>
> +   if (isl_format_supports_lossless_<wbr>compression(&device->info,<br>
> +                                                iview->isl.format))<br>
> +      return ISL_AUX_USAGE_CCS_E;<br>
> +<br>
> +   return ISL_AUX_USAGE_NONE;<br>
>  }<br>
><br>
>  /**<br>
> @@ -293,16 +329,24 @@ genX(cmd_buffer_setup_<wbr>attachments)(struct anv_cmd_buffer *cmd_buffer,<br>
>           assert(iview->image->vk_format == att->format);<br>
><br>
>           if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {<br>
> +            state->attachments[i].aux_<wbr>usage =<br>
> +               fb_attachment_get_aux_usage(<wbr>cmd_buffer->device, framebuffer, i);<br>
> +<br>
>              struct isl_view view = iview->isl;<br>
>              view.usage |= ISL_SURF_USAGE_RENDER_TARGET_<wbr>BIT;<br>
>              isl_surf_fill_state(isl_dev,<br>
>                                  state->attachments[i].color_<wbr>rt_state.map,<br>
>                                  .surf = &iview->image->color_surface.<wbr>isl,<br>
>                                  .view = &view,<br>
> +                                .aux_surf = &iview->image->aux_surface.<wbr>isl,<br>
> +                                .aux_usage = state->attachments[i].aux_<wbr>usage,<br>
>                                  .mocs = cmd_buffer->device->default_<wbr>mocs);<br>
><br>
>              add_image_view_relocs(cmd_<wbr>buffer, iview,<br>
> +                                  state->attachments[i].aux_<wbr>usage,<br>
>                                    state->attachments[i].color_<wbr>rt_state);<br>
> +         } else {<br>
> +            state->attachments[i].aux_<wbr>usage = ISL_AUX_USAGE_NONE;<br>
>           }<br>
>        }<br>
><br>
> @@ -912,13 +956,15 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,<br>
>        case VK_DESCRIPTOR_TYPE_INPUT_<wbr>ATTACHMENT:<br>
>           surface_state = desc->image_view->sampler_<wbr>surface_state;<br>
>           assert(surface_state.alloc_<wbr>size);<br>
> -         add_image_view_relocs(cmd_<wbr>buffer, desc->image_view, surface_state);<br>
> +         add_image_view_relocs(cmd_<wbr>buffer, desc->image_view,<br>
> +                               ISL_AUX_USAGE_NONE, surface_state);<br>
>           break;<br>
><br>
>        case VK_DESCRIPTOR_TYPE_STORAGE_<wbr>IMAGE: {<br>
>           surface_state = desc->image_view->storage_<wbr>surface_state;<br>
>           assert(surface_state.alloc_<wbr>size);<br>
> -         add_image_view_relocs(cmd_<wbr>buffer, desc->image_view, surface_state);<br>
> +         add_image_view_relocs(cmd_<wbr>buffer, desc->image_view,<br>
> +                               ISL_AUX_USAGE_NONE, surface_state);<br>
><br>
>           struct brw_image_param *image_param =<br>
>              &cmd_buffer->state.push_<wbr>constants[stage]->images[<wbr>image++];<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div>> ______________________________<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>