[Mesa-dev] [PATCH v2 10/11] anv: enable multiple planes per image/imageView

Jason Ekstrand jason at jlekstrand.net
Wed Oct 4 01:16:06 UTC 2017


On Tue, Oct 3, 2017 at 9:29 AM, Lionel Landwerlin <
lionel.g.landwerlin at intel.com> wrote:

> This change introduce the concept of planes for image & views. It
> matches the planes available in new formats.
>
> We also refactor depth & stencil support through the usage of planes
> for the sake of uniformity. In the backend (genX_cmd_buffer.c) we have
> to take some care though with regard to auxilliary surfaces.
> Multiplanar color buffers can have multiple auxilliary surfaces but
> depth & stencil share the same HiZ one (only store in the depth
> plane).
>
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> ---
>  src/intel/vulkan/anv_blorp.c       | 302 ++++++++++++------
>  src/intel/vulkan/anv_dump.c        |  17 +-
>  src/intel/vulkan/anv_formats.c     |   3 +-
>  src/intel/vulkan/anv_image.c       | 632 +++++++++++++++++++++++-------
> -------
>  src/intel/vulkan/anv_intel.c       |   4 +-
>  src/intel/vulkan/anv_private.h     | 244 ++++++++++----
>  src/intel/vulkan/anv_wsi.c         |   8 +-
>  src/intel/vulkan/gen8_cmd_buffer.c |   2 +-
>  src/intel/vulkan/genX_cmd_buffer.c | 312 ++++++++++--------
>  9 files changed, 985 insertions(+), 539 deletions(-)
>
> diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
> index 72f482625aa..a181630a2f9 100644
> --- a/src/intel/vulkan/anv_blorp.c
> +++ b/src/intel/vulkan/anv_blorp.c
> @@ -177,30 +177,34 @@ get_blorp_surf_for_anv_buffer(struct anv_device
> *device,
>
>  static void
>  get_blorp_surf_for_anv_image(const struct anv_image *image,
> +                             uint32_t plane,
>                               VkImageAspectFlags aspect,
>

Ok, maybe I'm being a bit dense, but doesn't the aspect imply the plane?
Why can't we just use anv_image_aspect_to_plane here?  That would reduce
the churn by a good bit.


>                               enum isl_aux_usage aux_usage,
>                               struct blorp_surf *blorp_surf)
>  {
> +   /* For the stencil surface aux_usage is always NONE. */
>     if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT ||
>         aux_usage == ISL_AUX_USAGE_HIZ)
>        aux_usage = ISL_AUX_USAGE_NONE;
>
> -   const struct anv_surface *surface =
> -      anv_image_get_surface_for_aspect_mask(image, aspect);
> +   const struct anv_surface *surface = &image->planes[plane].surface;
>
>     *blorp_surf = (struct blorp_surf) {
>        .surf = &surface->isl,
>        .addr = {
> -         .buffer = image->bo,
> -         .offset = image->offset + surface->offset,
> +         .buffer = image->planes[plane].bo,
> +         .offset = image->planes[plane].bo_offset + surface->offset,
>        },
>     };
>
>     if (aux_usage != ISL_AUX_USAGE_NONE) {
> -      blorp_surf->aux_surf = &image->aux_surface.isl,
> +      const struct anv_surface *aux_surface =
> +         &image->planes[plane].aux_surface;
> +
> +      blorp_surf->aux_surf = &aux_surface->isl,
>        blorp_surf->aux_addr = (struct blorp_address) {
> -         .buffer = image->bo,
> -         .offset = image->offset + image->aux_surface.offset,
> +         .buffer = image->planes[plane].bo,
> +         .offset = image->planes[plane].bo_offset + aux_surface->offset,
>        };
>        blorp_surf->aux_usage = aux_usage;
>     }
> @@ -249,17 +253,44 @@ void anv_CmdCopyImage(
>                  anv_get_layerCount(src_image,
> &pRegions[r].srcSubresource));
>        }
>
> -      assert(pRegions[r].srcSubresource.aspectMask ==
> -             pRegions[r].dstSubresource.aspectMask);
> -
> -      uint32_t a;
> -      for_each_bit(a, pRegions[r].dstSubresource.aspectMask) {
> -         VkImageAspectFlagBits aspect = (1 << a);
> -
> +      VkImageAspectFlags src_mask = pRegions[r].srcSubresource.
> aspectMask,
> +         dst_mask = pRegions[r].dstSubresource.aspectMask;
> +
> +      assert(anv_image_aspects_compatible(src_mask, dst_mask));
> +
> +      if (_mesa_bitcount(src_mask) > 1) {
> +         uint32_t plane, bit_aspect;
> +         anv_foreach_plane_aspect_bit(plane, bit_aspect, src_mask,
> +                                      src_image->aspects) {
> +            struct blorp_surf src_surf, dst_surf;
> +            get_blorp_surf_for_anv_image(src_image, plane, 1UL <<
> bit_aspect,
> +                                         src_image->planes[plane].aux_
> usage,
> +                                         &src_surf);
> +            get_blorp_surf_for_anv_image(dst_image, plane, 1UL <<
> bit_aspect,
> +                                         dst_image->planes[plane].aux_
> usage,
> +                                         &dst_surf);
> +
> +            for (unsigned i = 0; i < layer_count; i++) {
> +               blorp_copy(&batch, &src_surf, pRegions[r].srcSubresource.
> mipLevel,
> +                          src_base_layer + i,
> +                          &dst_surf, pRegions[r].dstSubresource.mipLevel,
> +                          dst_base_layer + i,
> +                          srcOffset.x, srcOffset.y,
> +                          dstOffset.x, dstOffset.y,
> +                          extent.width, extent.height);
> +            }
> +         }
> +      } else {
> +         uint32_t src_plane = anv_image_aspect_to_plane(src_
> image->aspects,
> +                                                        src_mask),
> +            dst_plane = anv_image_aspect_to_plane(dst_image->aspects,
> +                                                  dst_mask);
>           struct blorp_surf src_surf, dst_surf;
> -         get_blorp_surf_for_anv_image(src_image, aspect,
> src_image->aux_usage,
> +         get_blorp_surf_for_anv_image(src_image, src_plane, src_mask,
> +                                      src_image->planes[src_plane].
> aux_usage,
>                                        &src_surf);
> -         get_blorp_surf_for_anv_image(dst_image, aspect,
> dst_image->aux_usage,
> +         get_blorp_surf_for_anv_image(dst_image, dst_plane, dst_mask,
> +                                      dst_image->planes[dst_plane].
> aux_usage,
>                                        &dst_surf);
>
>           for (unsigned i = 0; i < layer_count; i++) {
> @@ -307,8 +338,10 @@ copy_buffer_to_image(struct anv_cmd_buffer
> *cmd_buffer,
>
>     for (unsigned r = 0; r < regionCount; r++) {
>        const VkImageAspectFlags aspect = pRegions[r].imageSubresource.
> aspectMask;
> +      uint32_t plane = anv_image_aspect_to_plane(anv_image->aspects,
> aspect);
>
> -      get_blorp_surf_for_anv_image(anv_image, aspect,
> anv_image->aux_usage,
> +      get_blorp_surf_for_anv_image(anv_image, plane, aspect,
> +                                   anv_image->planes[plane].aux_usage,
>                                     &image.surf);
>        image.offset =
>           anv_sanitize_image_offset(anv_image->type,
> pRegions[r].imageOffset);
> @@ -455,10 +488,15 @@ void anv_CmdBlitImage(
>        const VkImageSubresourceLayers *src_res =
> &pRegions[r].srcSubresource;
>        const VkImageSubresourceLayers *dst_res =
> &pRegions[r].dstSubresource;
>
> -      get_blorp_surf_for_anv_image(src_image, src_res->aspectMask,
> -                                   src_image->aux_usage, &src);
> -      get_blorp_surf_for_anv_image(dst_image, dst_res->aspectMask,
> -                                   dst_image->aux_usage, &dst);
> +      const uint32_t src_plane = anv_image_aspect_to_plane(src_
> image->aspects,
> +
>  src_res->aspectMask),
> +         dst_plane = anv_image_aspect_to_plane(dst_image->aspects,
> +                                               dst_res->aspectMask);
> +
> +      get_blorp_surf_for_anv_image(src_image, src_plane,
> src_res->aspectMask,
> +                                   src_image->planes[src_plane].aux_usage,
> &src);
> +      get_blorp_surf_for_anv_image(dst_image, dst_plane,
> dst_res->aspectMask,
> +                                   dst_image->planes[dst_plane].aux_usage,
> &dst);
>
>        struct anv_format_plane src_format =
>           anv_get_plane_format(&cmd_buffer->device->info,
> src_image->vk_format,
> @@ -749,15 +787,19 @@ void anv_CmdClearColorImage(
>     struct blorp_batch batch;
>     blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
> -   struct blorp_surf surf;
> -   get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> -                                image->aux_usage, &surf);
>
>     for (unsigned r = 0; r < rangeCount; r++) {
>        if (pRanges[r].aspectMask == 0)
>           continue;
>
> -      assert(pRanges[r].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
> +      assert(pRanges[r].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +
> +      const uint32_t plane = anv_image_aspect_to_plane(image->aspects,
> +
>  pRanges[r].aspectMask);
> +
> +      struct blorp_surf surf;
> +      get_blorp_surf_for_anv_image(image, plane, pRanges[r].aspectMask,
> +                                   image->planes[plane].aux_usage,
> &surf);
>
>        struct anv_format_plane src_format =
>           anv_get_plane_format(&cmd_buffer->device->info,
> image->vk_format,
> @@ -803,14 +845,20 @@ void anv_CmdClearDepthStencilImage(
>
>     struct blorp_surf depth, stencil;
>     if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
> -      get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_DEPTH_BIT,
> +      uint32_t depth_plane =
> +         anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_DEPTH_BIT);
> +      get_blorp_surf_for_anv_image(image, depth_plane,
> +                                   VK_IMAGE_ASPECT_DEPTH_BIT,
>                                     ISL_AUX_USAGE_NONE, &depth);
>     } else {
>        memset(&depth, 0, sizeof(depth));
>     }
>
>     if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
> -      get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_STENCIL_BIT,
> +      uint32_t stencil_plane =
> +         anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_STENCIL_BIT);
> +      get_blorp_surf_for_anv_image(image, stencil_plane,
> +                                   VK_IMAGE_ASPECT_STENCIL_BIT,
>                                     ISL_AUX_USAGE_NONE, &stencil);
>     } else {
>        memset(&stencil, 0, sizeof(stencil));
> @@ -1044,7 +1092,7 @@ void anv_CmdClearAttachments(
>                      BLORP_BATCH_NO_EMIT_DEPTH_STENCIL);
>
>     for (uint32_t a = 0; a < attachmentCount; ++a) {
> -      if (pAttachments[a].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
> +      if (pAttachments[a].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
>           clear_color_attachment(cmd_buffer, &batch,
>                                  &pAttachments[a],
>                                  rectCount, pRects);
> @@ -1130,7 +1178,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
>        struct anv_image_view *iview = fb->attachments[a];
>        const struct anv_image *image = iview->image;
>        struct blorp_surf surf;
> -      get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> +      get_blorp_surf_for_anv_image(image, 0, VK_IMAGE_ASPECT_COLOR_BIT,
>                                     att_state->aux_usage, &surf);
>
>        if (att_state->fast_clear) {
> @@ -1155,24 +1203,26 @@ anv_cmd_buffer_clear_subpass(struct
> anv_cmd_buffer *cmd_buffer)
>           cmd_buffer->state.pending_pipe_bits |=
>              ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT |
> ANV_PIPE_CS_STALL_BIT;
>
> -         blorp_fast_clear(&batch, &surf, iview->isl.format,
> -                          iview->isl.base_level,
> -                          iview->isl.base_array_layer, fb->layers,
> -                          render_area.offset.x, render_area.offset.y,
> -                          render_area.offset.x + render_area.extent.width,
> -                          render_area.offset.y +
> render_area.extent.height);
> +         for (unsigned p = 0; p < iview->n_planes; p++)
> +            blorp_fast_clear(&batch, &surf, iview->planes[p].isl.format,
> +                             iview->planes[p].isl.base_level,
> +                             iview->planes[p].isl.base_array_layer,
> fb->layers,
> +                             render_area.offset.x, render_area.offset.y,
> +                             render_area.offset.x +
> render_area.extent.width,
> +                             render_area.offset.y +
> render_area.extent.height);
>
>           cmd_buffer->state.pending_pipe_bits |=
>              ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT |
> ANV_PIPE_CS_STALL_BIT;
>        } else {
> -         blorp_clear(&batch, &surf, iview->isl.format,
> -                     anv_swizzle_for_render(iview->isl.swizzle),
> -                     iview->isl.base_level,
> -                     iview->isl.base_array_layer, fb->layers,
> -                     render_area.offset.x, render_area.offset.y,
> -                     render_area.offset.x + render_area.extent.width,
> -                     render_area.offset.y + render_area.extent.height,
> -                     vk_to_isl_color(att_state->clear_value.color),
> NULL);
> +         for (unsigned p = 0; p < iview->n_planes; p++)
> +            blorp_clear(&batch, &surf, iview->planes[p].isl.format,
> +                        anv_swizzle_for_render(iview->
> planes[p].isl.swizzle),
> +                        iview->planes[p].isl.base_level,
> +                        iview->planes[p].isl.base_array_layer,
> fb->layers,
> +                        render_area.offset.x, render_area.offset.y,
> +                        render_area.offset.x + render_area.extent.width,
> +                        render_area.offset.y + render_area.extent.height,
> +                        vk_to_isl_color(att_state->clear_value.color),
> NULL);
>        }
>
>        att_state->pending_clear_aspects = 0;
> @@ -1207,7 +1257,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
>            * a stencil clear in addition to using the BLORP-fallback for
> depth.
>            */
>           if (clear_depth) {
> -            if (!blorp_can_hiz_clear_depth(gen, iview->isl.format,
> +            if (!blorp_can_hiz_clear_depth(gen,
> iview->planes[0].isl.format,
>                                             iview->image->samples,
>                                             render_area.offset.x,
>                                             render_area.offset.y,
> @@ -1224,8 +1274,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
>                 clear_with_hiz = false;
>              } else if (gen == 8 &&
>                         anv_can_sample_with_hiz(&cmd_buffer->device->info,
> -                                               iview->aspect_mask,
> -                                               iview->image->samples)) {
> +                                               iview->image)) {
>                 /* Only gen9+ supports returning ANV_HZ_FC_VAL when
> sampling a
>                  * fast-cleared portion of a HiZ buffer. Testing has
> revealed
>                  * that Gen8 only supports returning 0.0f. Gens prior to
> gen8 do
> @@ -1276,13 +1325,30 @@ anv_cmd_buffer_clear_subpass(struct
> anv_cmd_buffer *cmd_buffer)
>     blorp_batch_finish(&batch);
>  }
>
> +static void
> +resolve_surface(struct blorp_batch *batch,
> +                struct blorp_surf *src_surf,
> +                uint32_t src_level, uint32_t src_layer,
> +                struct blorp_surf *dst_surf,
> +                uint32_t dst_level, uint32_t dst_layer,
> +                uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t
> dst_y,
> +                uint32_t width, uint32_t height)
> +{
> +   blorp_blit(batch,
> +              src_surf, src_level, src_layer,
> +              ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> +              dst_surf, dst_level, dst_layer,
> +              ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> +              src_x, src_y, src_x + width, src_y + height,
> +              dst_x, dst_y, dst_x + width, dst_y + height,
> +              0x2600 /* GL_NEAREST */, false, false);
> +}
> +
>  static void
>  resolve_image(struct blorp_batch *batch,
>                const struct anv_image *src_image,
> -              enum isl_aux_usage src_aux_usage,
>                uint32_t src_level, uint32_t src_layer,
>                const struct anv_image *dst_image,
> -              enum isl_aux_usage dst_aux_usage,
>                uint32_t dst_level, uint32_t dst_layer,
>                VkImageAspectFlags aspect_mask,
>                uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t
> dst_y,
> @@ -1292,25 +1358,31 @@ resolve_image(struct blorp_batch *batch,
>     assert(src_image->samples > 1);
>     assert(dst_image->type == VK_IMAGE_TYPE_2D);
>     assert(dst_image->samples == 1);
> +   assert(src_image->n_planes == dst_image->n_planes);
>
> -   uint32_t a;
> -   for_each_bit(a, aspect_mask) {
> -      VkImageAspectFlagBits aspect = 1 << a;
> -
> +   uint32_t plane, aspect_bit;
> +   anv_foreach_plane_aspect_bit(plane, aspect_bit, aspect_mask,
> +                                src_image->aspects) {
>        struct blorp_surf src_surf, dst_surf;
> -      get_blorp_surf_for_anv_image(src_image, aspect,
> -                                   src_aux_usage, &src_surf);
> -      get_blorp_surf_for_anv_image(dst_image, aspect,
> -                                   dst_aux_usage, &dst_surf);
> -
> -      blorp_blit(batch,
> -                 &src_surf, src_level, src_layer,
> -                 ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> -                 &dst_surf, dst_level, dst_layer,
> -                 ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> -                 src_x, src_y, src_x + width, src_y + height,
> -                 dst_x, dst_y, dst_x + width, dst_y + height,
> -                 0x2600 /* GL_NEAREST */, false, false);
> +      get_blorp_surf_for_anv_image(src_image, plane, 1UL << aspect_bit,
> +                                   src_image->planes[plane].aux_usage,
> +                                   &src_surf);
> +      get_blorp_surf_for_anv_image(dst_image, plane, 1UL << aspect_bit,
> +                                   dst_image->planes[plane].aux_usage,
> +                                   &dst_surf);
> +
> +      uint32_t width_div = src_image->format->planes[
> plane].denominator_scales[0],
> +         height_div = src_image->format->planes[
> plane].denominator_scales[1];
>

Multisample YUV isn't a thing.  I don't think we need to do anything here
except assert that we're not YUV.


> +
> +      resolve_surface(batch,
> +                      &src_surf, src_level, src_layer,
> +                      &dst_surf, dst_level, dst_layer,
> +                      src_x / width_div,
> +                      src_y / height_div,
> +                      dst_x / width_div,
> +                      dst_y / height_div,
> +                      width / width_div,
> +                      height / height_div);
>     }
>  }
>
> @@ -1339,12 +1411,17 @@ void anv_CmdResolveImage(
>        const uint32_t layer_count =
>           anv_get_layerCount(dst_image, &pRegions[r].dstSubresource);
>
> +      VkImageAspectFlags src_mask = pRegions[r].srcSubresource.
> aspectMask,
> +         dst_mask = pRegions[r].dstSubresource.aspectMask;
> +
> +      assert(anv_image_aspects_compatible(src_mask, dst_mask));
> +
>        for (uint32_t layer = 0; layer < layer_count; layer++) {
>           resolve_image(&batch,
> -                       src_image, src_image->aux_usage,
> +                       src_image,
>                         pRegions[r].srcSubresource.mipLevel,
>                         pRegions[r].srcSubresource.baseArrayLayer + layer,
> -                       dst_image, dst_image->aux_usage,
> +                       dst_image,
>                         pRegions[r].dstSubresource.mipLevel,
>                         pRegions[r].dstSubresource.baseArrayLayer + layer,
>                         pRegions[r].dstSubresource.aspectMask,
> @@ -1360,6 +1437,7 @@ void anv_CmdResolveImage(
>  void
>  anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
>                       const struct anv_image *image,
> +                     const uint32_t plane,
>                       const uint32_t base_level, const uint32_t
> level_count,
>                       const uint32_t base_layer, uint32_t layer_count)
>  {
> @@ -1374,9 +1452,9 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
>     blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
>     struct blorp_surf surf;
> -   get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> -                                image->aux_usage == ISL_AUX_USAGE_NONE ?
> -                                ISL_AUX_USAGE_CCS_D : image->aux_usage,
> +   get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
> +                                image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_NONE ?
> +                                ISL_AUX_USAGE_CCS_D :
> image->planes[plane].aux_usage,
>                                  &surf);
>
>     /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
> @@ -1397,6 +1475,9 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
>     cmd_buffer->state.pending_pipe_bits |=
>        ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
>
> +   uint32_t width_div = image->format->planes[plane].
> denominator_scales[0],
> +      height_div = image->format->planes[plane].denominator_scales[1];
> +
>     for (uint32_t l = 0; l < level_count; l++) {
>        const uint32_t level = base_level + l;
>
> @@ -1409,11 +1490,13 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
>        if (image->type == VK_IMAGE_TYPE_3D)
>           layer_count = extent.depth;
>
> -      assert(level < anv_image_aux_levels(image));
> -      assert(base_layer + layer_count <= anv_image_aux_layers(image,
> level));
> +      assert(level < anv_image_aux_levels(image, plane));
> +      assert(base_layer + layer_count <= anv_image_aux_layers(image,
> plane, level));
>        blorp_fast_clear(&batch, &surf, surf.surf->format,
>                         level, base_layer, layer_count,
> -                       0, 0, extent.width, extent.height);
> +                       0, 0,
> +                       extent.width / width_div,
> +                       extent.height / height_div);
>     }
>
>     cmd_buffer->state.pending_pipe_bits |=
> @@ -1470,17 +1553,34 @@ anv_cmd_buffer_resolve_subpass(struct
> anv_cmd_buffer *cmd_buffer)
>           const VkRect2D render_area = cmd_buffer->state.render_area;
>
>           assert(src_iview->aspect_mask == dst_iview->aspect_mask);
> +         assert(src_iview->n_planes == 1);
> +         assert(dst_iview->n_planes == 1);
>
> -         resolve_image(&batch, src_iview->image, src_aux_usage,
> -                       src_iview->isl.base_level,
> -                       src_iview->isl.base_array_layer,
> -                       dst_iview->image, dst_aux_usage,
> -                       dst_iview->isl.base_level,
> -                       dst_iview->isl.base_array_layer,
> -                       src_iview->aspect_mask,
> -                       render_area.offset.x, render_area.offset.y,
> -                       render_area.offset.x, render_area.offset.y,
> -                       render_area.extent.width,
> render_area.extent.height);
> +         const struct anv_format *format = src_iview->image->format;
> +
> +         uint32_t width_div = format->planes[0].denominator_scales[0],
> +            height_div = format->planes[0].denominator_scales[1];
>

YUV is not going to be used as an input/output attachment.  We should just
assert here and not pretend to support it.


> +
> +         struct blorp_surf src_surf, dst_surf;
> +         get_blorp_surf_for_anv_image(src_iview->image, 0,
> +                                      src_iview->aspect_mask,
> +                                      src_aux_usage, &src_surf);
> +         get_blorp_surf_for_anv_image(dst_iview->image, 0,
> +                                      dst_iview->aspect_mask,
> +                                      dst_aux_usage, &dst_surf);
> +
> +         resolve_surface(&batch, &src_surf,
> +                         src_iview->planes[0].isl.base_level,
> +                         src_iview->planes[0].isl.base_array_layer,
> +                         &dst_surf,
> +                         dst_iview->planes[0].isl.base_level,
> +                         dst_iview->planes[0].isl.base_array_layer,
> +                         render_area.offset.x / width_div,
> +                         render_area.offset.y / height_div,
> +                         render_area.offset.x / width_div,
> +                         render_area.offset.y / height_div,
> +                         render_area.extent.width / width_div,
> +                         render_area.extent.height / height_div);
>        }
>
>        blorp_batch_finish(&batch);
> @@ -1490,7 +1590,7 @@ anv_cmd_buffer_resolve_subpass(struct
> anv_cmd_buffer *cmd_buffer)
>  void
>  anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
>                           const struct anv_image *image,
> -                         VkImageAspectFlagBits aspect,
> +                         uint32_t plane,
>                           uint32_t base_level, uint32_t level_count,
>                           uint32_t base_layer, uint32_t layer_count)
>  {
> @@ -1498,14 +1598,15 @@ anv_image_copy_to_shadow(struct anv_cmd_buffer
> *cmd_buffer,
>     blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
>     struct blorp_surf surf;
> -   get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> +   get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
>                                  ISL_AUX_USAGE_NONE, &surf);
>

Ugh... This function takes an aspect and then entirely ignores it. :-(  We
can just hard-code plane to 0 here because it's for compressed textures
which will never be YUV.


>
>     struct blorp_surf shadow_surf = {
> -      .surf = &image->shadow_surface.isl,
> +      .surf = &image->planes[plane].shadow_surface.isl,
>        .addr = {
> -         .buffer = image->bo,
> -         .offset = image->offset + image->shadow_surface.offset,
> +         .buffer = image->planes[plane].bo,
> +         .offset = image->planes[plane].bo_offset +
> +                   image->planes[plane].shadow_surface.offset,
>        },
>     };
>
> @@ -1544,7 +1645,7 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer
> *cmd_buffer,
>      * don't perform such a resolve on gens that don't support it.
>      */
>     if (cmd_buffer->device->info.gen < 8 ||
> -       image->aux_usage != ISL_AUX_USAGE_HIZ)
> +       image->planes[0].aux_usage != ISL_AUX_USAGE_HIZ)
>        return;
>
>     assert(op == BLORP_HIZ_OP_HIZ_RESOLVE ||
> @@ -1554,14 +1655,15 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer
> *cmd_buffer,
>     blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
>     struct blorp_surf surf;
> -   get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_DEPTH_BIT,
> +   get_blorp_surf_for_anv_image(image, 0, VK_IMAGE_ASPECT_DEPTH_BIT,
>                                  ISL_AUX_USAGE_NONE, &surf);
>
>     /* Manually add the aux HiZ surf */
> -   surf.aux_surf = &image->aux_surface.isl,
> +   surf.aux_surf = &image->planes[0].aux_surface.isl,
>     surf.aux_addr = (struct blorp_address) {
> -      .buffer = image->bo,
> -      .offset = image->offset + image->aux_surface.offset,
> +      .buffer = image->planes[0].bo,
> +      .offset = image->planes[0].bo_offset +
> +                image->planes[0].aux_surface.offset,
>     };
>     surf.aux_usage = ISL_AUX_USAGE_HIZ;
>
> @@ -1575,15 +1677,16 @@ void
>  anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
>                  const struct anv_state surface_state,
>                  const struct anv_image * const image,
> +                const uint32_t plane,
>                  const uint8_t level, const uint32_t layer_count,
>                  const enum blorp_fast_clear_op op)
>  {
>     assert(cmd_buffer && image);
>
>     /* The resolved subresource range must have a CCS buffer. */
> -   assert(level < anv_image_aux_levels(image));
> -   assert(layer_count <= anv_image_aux_layers(image, level));
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT && image->samples
> == 1);
> +   assert(level < anv_image_aux_levels(image, plane));
> +   assert(layer_count <= anv_image_aux_layers(image, plane, level));
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT &&
> image->samples == 1);
>
>     /* Create a binding table for this surface state. */
>     uint32_t binding_table;
> @@ -1598,13 +1701,14 @@ anv_ccs_resolve(struct anv_cmd_buffer * const
> cmd_buffer,
>                      BLORP_BATCH_PREDICATE_ENABLE);
>
>     struct blorp_surf surf;
> -   get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> -                                image->aux_usage == ISL_AUX_USAGE_CCS_E ?
> +   get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
> +                                image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_CCS_E ?
>                                  ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D,
>                                  &surf);
>
>     blorp_ccs_resolve_attachment(&batch, binding_table, &surf, level,
> -                                layer_count, image->color_surface.isl.
> format,
> +                                layer_count,
> +                                image->planes[plane].surface.isl.format,
>                                  op);
>
>     blorp_batch_finish(&batch);
> diff --git a/src/intel/vulkan/anv_dump.c b/src/intel/vulkan/anv_dump.c
> index 0608904219e..160c18c4f17 100644
> --- a/src/intel/vulkan/anv_dump.c
> +++ b/src/intel/vulkan/anv_dump.c
> @@ -424,20 +424,25 @@ anv_dump_add_framebuffer(struct anv_cmd_buffer
> *cmd_buffer,
>        uint32_t b;
>        for_each_bit(b, iview->image->aspects) {
>           VkImageAspectFlagBits aspect = (1 << b);
> -         char suffix;
> +         const char *suffix;
>           switch (aspect) {
> -         case VK_IMAGE_ASPECT_COLOR_BIT:     suffix = 'c'; break;
> -         case VK_IMAGE_ASPECT_DEPTH_BIT:     suffix = 'd'; break;
> -         case VK_IMAGE_ASPECT_STENCIL_BIT:   suffix = 's'; break;
> +         case VK_IMAGE_ASPECT_COLOR_BIT:       suffix = "c"; break;
> +         case VK_IMAGE_ASPECT_DEPTH_BIT:       suffix = "d"; break;
> +         case VK_IMAGE_ASPECT_STENCIL_BIT:     suffix = "s"; break;
> +         case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR: suffix = "c0"; break;
> +         case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR: suffix = "c1"; break;
> +         case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR: suffix = "c2"; break;
>           default:
>              unreachable("Invalid aspect");
>           }
>
> -         char *filename = ralloc_asprintf(dump_ctx,
> "framebuffer%04d-%d%c.ppm",
> +         char *filename = ralloc_asprintf(dump_ctx,
> "framebuffer%04d-%d%s.ppm",
>                                            dump_idx, i, suffix);
>
> +         unsigned plane = anv_image_aspect_to_plane(iview->image->aspects,
> aspect);
>           dump_add_image(cmd_buffer, (struct anv_image *)iview->image,
> aspect,
> -                        iview->isl.base_level,
> iview->isl.base_array_layer,
> +                        iview->planes[plane].isl.base_level,
> +                        iview->planes[plane].isl.base_array_layer,
>                          filename);
>        }
>     }
> diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_
> formats.c
> index 303531a6ab9..3a941d4bd06 100644
> --- a/src/intel/vulkan/anv_formats.c
> +++ b/src/intel/vulkan/anv_formats.c
> @@ -423,8 +423,7 @@ anv_get_plane_format(const struct gen_device_info
> *devinfo, VkFormat vk_format,
>        return plane_format;
>     }
>
> -   assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(vk_format_aspects(vk_format) == VK_IMAGE_ASPECT_COLOR_BIT);
> +   assert((aspect & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
>
>     const struct isl_format_layout *isl_layout =
>        isl_format_get_layout(plane_format.isl_format);
> diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
> index 262be68575a..6b3b70803d0 100644
> --- a/src/intel/vulkan/anv_image.c
> +++ b/src/intel/vulkan/anv_image.c
> @@ -68,6 +68,9 @@ choose_isl_surf_usage(VkImageCreateFlags
> vk_create_flags,
>        isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
>        break;
>     case VK_IMAGE_ASPECT_COLOR_BIT:
> +   case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR:
> +   case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR:
> +   case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
>        break;
>     default:
>        unreachable("bad VkImageAspect");
> @@ -95,26 +98,31 @@ choose_isl_surf_usage(VkImageCreateFlags
> vk_create_flags,
>  static struct anv_surface *
>  get_surface(struct anv_image *image, VkImageAspectFlags aspect)
>  {
> -   switch (aspect) {
> -   default:
> -      unreachable("bad VkImageAspect");
> -   case VK_IMAGE_ASPECT_COLOR_BIT:
> -      return &image->color_surface;
> -   case VK_IMAGE_ASPECT_DEPTH_BIT:
> -      return &image->depth_surface;
> -   case VK_IMAGE_ASPECT_STENCIL_BIT:
> -      return &image->stencil_surface;
> -   }
> +   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
> +   return &image->planes[plane].surface;
>  }
>
>  static void
> -add_surface(struct anv_image *image, struct anv_surface *surf)
> +add_surface(struct anv_image *image, struct anv_surface *surf, uint32_t
> plane)
>  {
>     assert(surf->isl.size > 0); /* isl surface must be initialized */
>
> -   surf->offset = align_u32(image->size, surf->isl.alignment);
> +   if (image->disjoint) {
> +      surf->offset = align_u32(image->planes[plane].size,
> surf->isl.alignment);
> +      /* Plane offset is always 0 when it's disjoint. */
> +   } else {
> +      surf->offset = align_u32(image->size, surf->isl.alignment);
> +      /* Determine plane's offset only once when the first surface is
> added. */
> +      if (image->planes[plane].size == 0)
> +         image->planes[plane].offset = image->size;
>

This seems to be in conflict with code below (A)


> +   }
> +
>     image->size = surf->offset + surf->isl.size;
> +   image->planes[plane].size = (surf->offset + surf->isl.size) -
> image->planes[plane].offset;
>

Is surf->offset relative to the image or the plane?  I think, based on what
you have here, that it's relative to the image but it's confusing. :(

Also, what do we use the plane size for?  Does it even make sense for
non-disjoint?


> +
>     image->alignment = MAX2(image->alignment, surf->isl.alignment);
> +   image->planes[plane].alignment = MAX2(image->planes[plane].alignment,
> +                                         surf->isl.alignment);
>  }
>
>
> @@ -194,11 +202,12 @@ all_formats_ccs_e_compatible(const struct
> gen_device_info *devinfo,
>   */
>  static void
>  add_fast_clear_state_buffer(struct anv_image *image,
> +                            uint32_t plane,
>                              const struct anv_device *device)
>  {
>     assert(image && device);
> -   assert(image->aux_surface.isl.size > 0 &&
> -          image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> +   assert(image->planes[plane].aux_surface.isl.size > 0 &&
> +          image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>
>     /* The offset to the buffer of clear values must be dword-aligned for
> GPU
>      * memcpy operations. It is located immediately after the auxiliary
> surface.
> @@ -212,18 +221,31 @@ add_fast_clear_state_buffer(struct anv_image *image,
>     /* Auxiliary buffers should be a multiple of 4K, so the start of the
> clear
>      * values buffer should already be dword-aligned.
>      */
> -   assert(image->aux_surface.isl.size % 4 == 0);
> +   assert((image->planes[plane].offset + image->planes[plane].size) % 4
> == 0);
>
> -   /* This buffer should be at the very end of the image. */
> -   assert(image->size ==
> -          image->aux_surface.offset + image->aux_surface.isl.size);
> +   /* This buffer should be at the very end of the plane. */
> +   if (image->disjoint) {
> +      assert(image->planes[plane].size ==
> +             (image->planes[plane].offset + image->planes[plane].size));
> +   } else {
> +      assert(image->size ==
> +             (image->planes[plane].offset + image->planes[plane].size));
> +   }
>
>     const unsigned entry_size = anv_fast_clear_state_entry_size(device);
>     /* There's no padding between entries, so ensure that they're always a
>      * multiple of 32 bits in order to enable GPU memcpy operations.
>      */
>     assert(entry_size % 4 == 0);
> -   image->size += entry_size * anv_image_aux_levels(image);
> +
> +   const unsigned plane_state_size =
> +      entry_size * anv_image_aux_levels(image, plane);
> +
> +   image->planes[plane].fast_clear_state_offset =
> +      image->planes[plane].offset + image->planes[plane].size;
> +
> +   image->planes[plane].size += plane_state_size;
> +   image->size += plane_state_size;
>  }
>
>  /**
> @@ -259,15 +281,13 @@ make_surface(const struct anv_device *dev,
>
>     assert(tiling_flags);
>
> -   struct anv_surface *anv_surf = get_surface(image, aspect);
> -
>     image->extent = anv_sanitize_image_extent(vk_info->imageType,
>                                               vk_info->extent);
>
> -   enum isl_format format =
> -      anv_get_isl_plane_format(&dev->info, vk_info->format,
> -                               aspect, vk_info->tiling);
> -   assert(format != ISL_FORMAT_UNSUPPORTED);
> +   const unsigned plane = anv_image_aspect_to_plane(image->aspects,
> aspect);
> +   const  struct anv_format_plane plane_format =
> +      anv_get_plane_format(&dev->info, image->vk_format, aspect,
> image->tiling);
> +   struct anv_surface *anv_surf = &image->planes[plane].surface;
>
>     /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need
> to
>      * fall back to linear on Broadwell and earlier because we aren't
> @@ -279,16 +299,16 @@ make_surface(const struct anv_device *dev,
>     if (dev->info.gen <= 8 &&
>         (vk_info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR)
> &&
>         vk_info->tiling == VK_IMAGE_TILING_OPTIMAL) {
> -      assert(isl_format_is_compressed(format));
> +      assert(isl_format_is_compressed(plane_format.isl_format));
>        tiling_flags = ISL_TILING_LINEAR_BIT;
>        needs_shadow = true;
>     }
>
>     ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
>        .dim = vk_to_isl_surf_dim[vk_info->imageType],
> -      .format = format,
> -      .width = image->extent.width,
> -      .height = image->extent.height,
> +      .format = plane_format.isl_format,
> +      .width = image->extent.width / plane_format.denominator_scales[0],
> +      .height = image->extent.height / plane_format.denominator_
> scales[1],
>        .depth = image->extent.depth,
>        .levels = vk_info->mipLevels,
>        .array_len = vk_info->arrayLayers,
> @@ -303,7 +323,18 @@ make_surface(const struct anv_device *dev,
>      */
>     assert(ok);
>
> -   add_surface(image, anv_surf);
> +   image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
> +
> +   if (!image->disjoint) {
> +      /* With non disjoint planes, align the plane to its surface
> alignment.
> +       */
> +      uint32_t previous_plane_size = plane == 0 ? 0 :
> +         (image->planes[plane - 1].offset + image->planes[plane -
> 1].size);
> +      image->planes[plane].offset = align_u32(previous_plane_size,
> +                                              anv_surf->isl.alignment);
> +   }
>

(A) add_surface already does this for us as far as I can tell.


> +
> +   add_surface(image, anv_surf, plane);
>
>     /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need
> to
>      * create an identical tiled shadow surface for use while texturing so
> we
> @@ -313,9 +344,9 @@ make_surface(const struct anv_device *dev,
>        assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
>        assert(tiling_flags == ISL_TILING_LINEAR_BIT);
>
> -      ok = isl_surf_init(&dev->isl_dev, &image->shadow_surface.isl,
> +      ok = isl_surf_init(&dev->isl_dev, &image->planes[plane].shadow_
> surface.isl,
>           .dim = vk_to_isl_surf_dim[vk_info->imageType],
> -         .format = format,
> +         .format = plane_format.isl_format,
>           .width = image->extent.width,
>           .height = image->extent.height,
>           .depth = image->extent.depth,
> @@ -332,7 +363,7 @@ make_surface(const struct anv_device *dev,
>         */
>        assert(ok);
>
> -      add_surface(image, &image->shadow_surface);
> +      add_surface(image, &image->planes[plane].shadow_surface, plane);
>     }
>
>     /* Add a HiZ surface to a depth buffer that will be used for rendering.
> @@ -358,24 +389,43 @@ make_surface(const struct anv_device *dev,
>        } else if (dev->info.gen == 8 && vk_info->samples > 1) {
>           anv_perf_warn(dev->instance, image, "Enable gen8 multisampled
> HiZ");
>        } else if (!unlikely(INTEL_DEBUG & DEBUG_NO_HIZ)) {
> -         assert(image->aux_surface.isl.size == 0);
> -         ok = isl_surf_get_hiz_surf(&dev->isl_dev,
> &image->depth_surface.isl,
> -                                    &image->aux_surface.isl);
> +         assert(image->planes[plane].aux_surface.isl.size == 0);
> +         ok = isl_surf_get_hiz_surf(&dev->isl_dev,
> +                                    &image->planes[plane].surface.isl,
> +                                    &image->planes[plane].aux_
> surface.isl);
>           assert(ok);
> -         add_surface(image, &image->aux_surface);
> -         image->aux_usage = ISL_AUX_USAGE_HIZ;
> +         add_surface(image, &image->planes[plane].aux_surface, plane);
> +         image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
>        }
> -   } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples ==
> 1) {
> -      if (!unlikely(INTEL_DEBUG & DEBUG_NO_RBC)) {
> -         assert(image->aux_surface.isl.size == 0);
> -         ok = isl_surf_get_ccs_surf(&dev->isl_dev, &anv_surf->isl,
> -                                    &image->aux_surface.isl, 0);
> +   } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT) &&
> vk_info->samples == 1) {
> +      /* TODO: Allow compression on :
> +       *
> +       *     1) non multiplanar images (We appear to hit a sampler bug
> with CCS &
> +       *          R16G16 format. Putting the clear state a page (4096
> bytes)
> +       *          further fixes the issue.
>

Did we never get anywhere on this?  I know we talked about it and I thought
we had it sorted but I don't remember.


> +       *
> +       *     2) alias images, because they might be aliases of images
> described
> +       *        in 1)
> +       *
> +       *     3) if compression is disabled by debug
> +       */
> +      const bool allow_compression =
> +         image->n_planes == 1 &&
> +         (vk_info->flags & VK_IMAGE_CREATE_ALIAS_BIT_KHR) == 0 &&
> +         likely((INTEL_DEBUG & DEBUG_NO_RBC) == 0);
> +
> +      if (allow_compression) {
> +         assert(image->planes[plane].aux_surface.isl.size == 0);
> +         ok = isl_surf_get_ccs_surf(&dev->isl_dev,
> +                                    &image->planes[plane].surface.isl,
> +                                    &image->planes[plane].aux_surface.isl,
> 0);
>           if (ok) {
>
>              /* Disable CCS when it is not useful (i.e., when you can't
> render
>               * to the image with CCS enabled).
>               */
> -            if (!isl_format_supports_rendering(&dev->info, format)) {
> +            if (!isl_format_supports_rendering(&dev->info,
> +                                               plane_format.isl_format)) {
>                 /* While it may be technically possible to enable CCS for
> this
>                  * image, we currently don't have things hooked up to get
> it
>                  * working.
> @@ -383,12 +433,12 @@ make_surface(const struct anv_device *dev,
>                 anv_perf_warn(dev->instance, image,
>                               "This image format doesn't support
> rendering. "
>                               "Not allocating an CCS buffer.");
> -               image->aux_surface.isl.size = 0;
> +               image->planes[plane].aux_surface.isl.size = 0;
>                 return VK_SUCCESS;
>              }
>
> -            add_surface(image, &image->aux_surface);
> -            add_fast_clear_state_buffer(image, dev);
> +            add_surface(image, &image->planes[plane].aux_surface, plane);
> +            add_fast_clear_state_buffer(image, plane, dev);
>
>              /* For images created without MUTABLE_FORMAT_BIT set, we know
> that
>               * they will always be used with the original format.  In
> @@ -400,22 +450,42 @@ make_surface(const struct anv_device *dev,
>               */
>              if (!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
>                  all_formats_ccs_e_compatible(&dev->info, vk_info)) {
> -               image->aux_usage = ISL_AUX_USAGE_CCS_E;
> +               image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
>              }
>           }
>        }
> -   } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples >
> 1) {
> -      assert(image->aux_surface.isl.size == 0);
> +   } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT) &&
> vk_info->samples > 1) {
>        assert(!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT));
> -      ok = isl_surf_get_mcs_surf(&dev->isl_dev, &anv_surf->isl,
> -                                 &image->aux_surface.isl);
> +      assert(image->planes[plane].aux_surface.isl.size == 0);
> +      ok = isl_surf_get_mcs_surf(&dev->isl_dev,
> +                                 &image->planes[plane].surface.isl,
> +                                 &image->planes[plane].aux_surface.isl);
>        if (ok) {
> -         add_surface(image, &image->aux_surface);
> -         add_fast_clear_state_buffer(image, dev);
> -         image->aux_usage = ISL_AUX_USAGE_MCS;
> +         add_surface(image, &image->planes[plane].aux_surface, plane);
> +         add_fast_clear_state_buffer(image, plane, dev);
> +         image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
>        }
>     }
>
> +   assert((image->planes[plane].offset + image->planes[plane].size) ==
> image->size);
> +
> +   /* Upper bound of the last surface should be smaller than the plane's
> +    * size.
> +    */
> +   assert((MAX2(image->planes[plane].surface.offset,
> +                image->planes[plane].aux_surface.offset) +
> +           (image->planes[plane].aux_surface.isl.size > 0 ?
> +            image->planes[plane].aux_surface.isl.size :
> +            image->planes[plane].surface.isl.size)) <=
> +          (image->planes[plane].offset + image->planes[plane].size));
> +
> +   if (image->planes[plane].aux_surface.isl.size) {
> +      /* assert(image->planes[plane].fast_clear_state_offset == */
> +      /*        (image->planes[plane].aux_surface.offset +
> image->planes[plane].aux_surface.isl.size)); */
> +      assert(image->planes[plane].fast_clear_state_offset <
> +             (image->planes[plane].offset + image->planes[plane].size));
> +   }
> +
>     return VK_SUCCESS;
>  }
>
> @@ -447,13 +517,18 @@ anv_image_create(VkDevice _device,
>     image->type = pCreateInfo->imageType;
>     image->extent = pCreateInfo->extent;
>     image->vk_format = pCreateInfo->format;
> +   image->format = anv_get_format(pCreateInfo->format);
>     image->aspects = vk_format_aspects(image->vk_format);
>     image->levels = pCreateInfo->mipLevels;
>     image->array_size = pCreateInfo->arrayLayers;
>     image->samples = pCreateInfo->samples;
>     image->usage = pCreateInfo->usage;
>     image->tiling = pCreateInfo->tiling;
> -   image->aux_usage = ISL_AUX_USAGE_NONE;
> +
> +   const struct anv_format *format = anv_get_format(image->vk_format);
> +   assert(format != NULL);
> +
> +   image->n_planes = format->n_planes;
>
>     uint32_t b;
>     for_each_bit(b, image->aspects) {
> @@ -500,37 +575,41 @@ anv_DestroyImage(VkDevice _device, VkImage _image,
>     vk_free2(&device->alloc, pAllocator, image);
>  }
>
> -static void
> -anv_bind_image_memory(const VkBindImageMemoryInfoKHR *pBindInfo)
> +static VkResult anv_image_bind_memory_plane(struct anv_device *device,
> +                                            struct anv_image *image,
> +                                            uint32_t plane,
> +                                            struct anv_device_memory
> *memory,
> +                                            uint32_t memory_offset)
>  {
> -   ANV_FROM_HANDLE(anv_device_memory, mem, pBindInfo->memory);
> -   ANV_FROM_HANDLE(anv_image, image, pBindInfo->image);
> -
> -   assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_
> MEMORY_INFO_KHR);
> -
> -   if (mem == NULL) {
> -      image->bo = NULL;
> -      image->offset = 0;
> -      return;
> +   if (memory) {
> +      image->planes[plane].bo = memory->bo;
> +      image->planes[plane].bo_offset = memory_offset;
> +   } else {
> +      image->planes[plane].bo = NULL;
> +      image->planes[plane].bo_offset = 0;
>     }
>
> -   image->bo = mem->bo;
> -   image->offset = pBindInfo->memoryOffset;
> +   return VK_SUCCESS;
>  }
>
>  VkResult anv_BindImageMemory(
> -    VkDevice                                    device,
> -    VkImage                                     image,
> -    VkDeviceMemory                              memory,
> +    VkDevice                                    _device,
> +    VkImage                                     _image,
> +    VkDeviceMemory                              _memory,
>      VkDeviceSize                                memoryOffset)
>  {
> -   anv_bind_image_memory(
> -      &(VkBindImageMemoryInfoKHR) {
> -         .sType         = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
> -         .image         = image,
> -         .memory        = memory,
> -         .memoryOffset  = memoryOffset,
> -      });
> +   ANV_FROM_HANDLE(anv_device, device, _device);
> +   ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
> +   ANV_FROM_HANDLE(anv_image, image, _image);
> +
> +   uint32_t plane, aspect_bit;
> +   anv_foreach_plane_aspect_bit(plane, aspect_bit,
> +                                image->aspects, image->aspects) {
> +      VkResult result = anv_image_bind_memory_plane(device, image, plane,
> +                                                    mem, memoryOffset);
> +      if (result != VK_SUCCESS)
> +         return vk_error(result);
> +   }
>
>     return VK_SUCCESS;
>  }
> @@ -540,10 +619,27 @@ VkResult anv_BindImageMemory2KHR(
>      uint32_t                                    bindInfoCount,
>      const VkBindImageMemoryInfoKHR*             pBindInfos)
>  {
> -   for (uint32_t i = 0; i < bindInfoCount; i++)
> -      anv_bind_image_memory(&pBindInfos[i]);
> +   VkResult result = VK_SUCCESS;
>
> -   return VK_SUCCESS;
> +   for (uint32_t i = 0; i < bindInfoCount; i++) {
> +      const VkBindImageMemoryInfoKHR *bind_info = &pBindInfos[i];
> +
> +      if (pBindInfos->pNext == NULL) {
> +         result = anv_BindImageMemory(device, bind_info->image,
> +                                      bind_info->memory,
> +                                      bind_info->memoryOffset);
>

This isn't right.  We're supposed to ignore extension structs we don't know
about.  We can't just not bind the memory if pNext != NULL.


> +      } else {
> +         vk_foreach_struct_const(s, bind_info->pNext) {
> +            switch (s->sType) {
> +            default:
> +               anv_debug_ignored_stype(s->sType);
> +               break;
> +            }
> +         }
> +      }
> +   }
> +
> +   return result;
>  }
>
>  static void
> @@ -575,22 +671,10 @@ void anv_GetImageSubresourceLayout(
>
>     assert(__builtin_popcount(pSubresource->aspectMask) == 1);
>
> -   switch (pSubresource->aspectMask) {
> -   case VK_IMAGE_ASPECT_COLOR_BIT:
> -      anv_surface_get_subresource_layout(image, &image->color_surface,
> -                                         pSubresource, pLayout);
> -      break;
> -   case VK_IMAGE_ASPECT_DEPTH_BIT:
> -      anv_surface_get_subresource_layout(image, &image->depth_surface,
> -                                         pSubresource, pLayout);
> -      break;
> -   case VK_IMAGE_ASPECT_STENCIL_BIT:
> -      anv_surface_get_subresource_layout(image, &image->stencil_surface,
> -                                         pSubresource, pLayout);
> -      break;
> -   default:
> -      assert(!"Invalid image aspect");
> -   }
> +   anv_surface_get_subresource_layout(image,
> +                                      get_surface(image,
> +
> pSubresource->aspectMask),
> +                                      pSubresource, pLayout);
>  }
>
>  /**
> @@ -601,7 +685,7 @@ void anv_GetImageSubresourceLayout(
>   *
>   * @param devinfo The device information of the Intel GPU.
>   * @param image The image that may contain a collection of buffers.
> - * @param aspects The aspect(s) of the image to be accessed.
> + * @param plane The plane of the image to be accessed.
>   * @param layout The current layout of the image aspect(s).
>   *
>   * @return The primary buffer that should be used for the given layout.
> @@ -609,7 +693,7 @@ void anv_GetImageSubresourceLayout(
>  enum isl_aux_usage
>  anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
>                          const struct anv_image * const image,
> -                        const VkImageAspectFlags aspects,
> +                        const uint32_t plane,
>                          const VkImageLayout layout)
>  {
>     /* Validate the inputs. */
> @@ -620,35 +704,41 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
>     /* The layout of a NULL image is not properly defined. */
>     assert(image != NULL);
>
> -   /* The aspects must be a subset of the image aspects. */
> -   assert(aspects & image->aspects && aspects <= image->aspects);
> -
>     /* Determine the optimal buffer. */
>
> -   /* If there is no auxiliary surface allocated, we must use the one and
> only
> -    * main buffer.
> +   /* Depth & stencil buffers share the same auxilliary buffer, we need to
> +    * process them differently from color buffers.
>      */
> -   if (image->aux_surface.isl.size == 0)
> -      return ISL_AUX_USAGE_NONE;
> +   if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> +      /* If there is no auxiliary surface allocated, we must use the one
> and
> +       * only main buffer.
> +       */
> +      if (image->planes[plane].aux_surface.isl.size == 0)
> +         return ISL_AUX_USAGE_NONE;
> +   } else {
> +      /* If there is no auxiliary surface allocated, we must use the one
> and
> +       * only main buffer.
> +       */
> +      if (image->planes[plane].aux_surface.isl.size == 0)
> +         return ISL_AUX_USAGE_NONE;
> +
> +      /* On BDW+, when clearing the stencil aspect of a depth stencil
> image,
> +       * the HiZ buffer allows us to record the clear with a relatively
> small
> +       * number of packets. Prior to BDW, the HiZ buffer provides no known
> +       * benefit to the stencil aspect.
> +       */
> +      if (devinfo->gen < 8 && plane != 0 /* aka stencil */)
> +         return ISL_AUX_USAGE_NONE;
> +   }
>
>     /* All images that use an auxiliary surface are required to be tiled.
> */
>     assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);
>
> -   /* On BDW+, when clearing the stencil aspect of a depth stencil image,
> -    * the HiZ buffer allows us to record the clear with a relatively small
> -    * number of packets. Prior to BDW, the HiZ buffer provides no known
> benefit
> -    * to the stencil aspect.
> -    */
> -   if (devinfo->gen < 8 && aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
> -      return ISL_AUX_USAGE_NONE;
> -
> -   const bool color_aspect = aspects == VK_IMAGE_ASPECT_COLOR_BIT;
> -
>     /* The following switch currently only handles depth stencil aspects.
>      * TODO: Handle the color aspect.
>      */
> -   if (color_aspect)
> -      return image->aux_usage;
> +   if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT)
> +      return image->planes[plane].aux_usage;
>
>     switch (layout) {
>
> @@ -682,17 +772,17 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
>
>     /* Sampling Layouts */
>     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
> -      assert(!color_aspect);
> +      assert((image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
>        /* Fall-through */
>     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
>     case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR:
> -      if (anv_can_sample_with_hiz(devinfo, aspects, image->samples))
> +      if (anv_can_sample_with_hiz(devinfo, image))
>           return ISL_AUX_USAGE_HIZ;
>        else
>           return ISL_AUX_USAGE_NONE;
>
>     case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
> -      assert(color_aspect);
> +      assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>
>        /* On SKL+, the render buffer can be decompressed by the
> presentation
>         * engine. Support for this feature has not yet landed in the wider
> @@ -714,12 +804,12 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
>
>     /* Rendering Layouts */
>     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
> -      assert(color_aspect);
> +      assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>        unreachable("Color images are not yet supported.");
>
>     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
>     case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR:
> -      assert(!color_aspect);
> +      assert((image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
>        return ISL_AUX_USAGE_HIZ;
>
>     case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
> @@ -761,7 +851,7 @@ remap_swizzle(VkComponentSwizzle swizzle,
> VkComponentSwizzle component,
>  void
>  anv_image_fill_surface_state(struct anv_device *device,
>                               const struct anv_image *image,
> -                             VkImageAspectFlagBits aspect,
> +                             uint32_t plane,
>                               const struct isl_view *view_in,
>                               isl_surf_usage_flags_t view_usage,
>                               enum isl_aux_usage aux_usage,
> @@ -770,8 +860,8 @@ anv_image_fill_surface_state(struct anv_device
> *device,
>                               struct anv_surface_state *state_inout,
>                               struct brw_image_param *image_param_out)
>  {
> -   const struct anv_surface *surface =
> -      anv_image_get_surface_for_aspect_mask(image, aspect);
> +   const struct anv_surface *surface = &image->planes[plane].surface,
> +      *aux_surface = &image->planes[plane].aux_surface;
>
>     struct isl_view view = *view_in;
>     view.usage |= view_usage;
> @@ -781,13 +871,13 @@ anv_image_fill_surface_state(struct anv_device
> *device,
>      * the primary surface.  The shadow surface will be tiled, unlike the
> main
>      * surface, so it should get significantly better performance.
>      */
> -   if (image->shadow_surface.isl.size > 0 &&
> +   if (image->planes[plane].shadow_surface.isl.size > 0 &&
>         isl_format_is_compressed(view.format) &&
>         (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
>        assert(isl_format_is_compressed(surface->isl.format));
>        assert(surface->isl.tiling == ISL_TILING_LINEAR);
> -      assert(image->shadow_surface.isl.tiling != ISL_TILING_LINEAR);
> -      surface = &image->shadow_surface;
> +      assert(image->planes[plane].shadow_surface.isl.tiling !=
> ISL_TILING_LINEAR);
> +      surface = &image->planes[plane].shadow_surface;
>     }
>
>     if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
> @@ -802,9 +892,9 @@ anv_image_fill_surface_state(struct anv_device
> *device,
>     if (!clear_color)
>        clear_color = &default_clear_color;
>
> -   const uint64_t address = image->offset + surface->offset;
> -   const uint64_t aux_address = (aux_usage == ISL_AUX_USAGE_NONE) ? 0 :
> -                                image->offset + image->aux_surface.offset;
> +   const uint64_t address = image->planes[plane].bo_offset +
> surface->offset;
> +   const uint64_t aux_address = aux_usage == ISL_AUX_USAGE_NONE ?
> +      0 : (image->planes[plane].bo_offset + aux_surface->offset);
>
>     if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
>         !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) &&
> @@ -893,7 +983,7 @@ anv_image_fill_surface_state(struct anv_device
> *device,
>                            .view = &view,
>                            .address = address + offset_B,
>                            .clear_color = *clear_color,
> -                          .aux_surf = &image->aux_surface.isl,
> +                          .aux_surf = &aux_surface->isl,
>                            .aux_usage = aux_usage,
>                            .aux_address = aux_address,
>                            .mocs = device->default_mocs,
> @@ -924,6 +1014,22 @@ anv_image_fill_surface_state(struct anv_device
> *device,
>     }
>  }
>
> +static VkImageAspectFlags
> +remap_aspect_flags(VkImageAspectFlags view_aspects)
> +{
> +   if (view_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> +      if (_mesa_bitcount(view_aspects) == 1)
> +         return VK_IMAGE_ASPECT_COLOR_BIT;
> +
> +      VkImageAspectFlags color_aspects = 0;
> +      for (uint32_t i = 0; i < _mesa_bitcount(view_aspects); i++)
> +         color_aspects |= VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << i;
> +      return color_aspects;
> +   }
> +   /* No special remapping needed for depth & stencil aspects. */
> +   return view_aspects;
> +}
> +
>  VkResult
>  anv_CreateImageView(VkDevice _device,
>                      const VkImageViewCreateInfo *pCreateInfo,
> @@ -968,106 +1074,125 @@ anv_CreateImageView(VkDevice _device,
>        break;
>     }
>
> +   /* First expand aspects to the image's ones (for example
> +    * VK_IMAGE_ASPECT_COLOR_BIT will be converted to
> +    * VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR |
> +    * VK_IMAGE_ASPECT_PLANE_2_BIT_KHR for an image of format
> +    * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR.
> +    */
> +   VkImageAspectFlags expanded_aspects =
> +      anv_image_color_aspects(image, range->aspectMask);
> +
>     iview->image = image;
>
> -   iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
> +   /* Remap the expanded aspects for the image view. For example if only
> +    * VK_IMAGE_ASPECT_PLANE_1_BIT_KHR was given in range->aspectMask, we
> will
> +    * convert it to VK_IMAGE_ASPECT_COLOR_BIT since from the point of
> view of
> +    * the image view, it only has a single plane.
> +    */
> +   iview->aspect_mask = remap_aspect_flags(expanded_aspects);
> +   iview->n_planes = anv_image_aspect_get_planes(iview->aspect_mask);
>     iview->vk_format = pCreateInfo->format;
>
> -   struct anv_format_plane format =
> -      anv_get_plane_format(&device->info, pCreateInfo->format,
> -                           range->aspectMask ==
> (VK_IMAGE_ASPECT_DEPTH_BIT |
> -
>  VK_IMAGE_ASPECT_STENCIL_BIT) ?
> -                           VK_IMAGE_ASPECT_DEPTH_BIT : range->aspectMask,
> -                           image->tiling);
> -
> -   iview->isl = (struct isl_view) {
> -      .format = format.isl_format,
> -      .base_level = range->baseMipLevel,
> -      .levels = anv_get_levelCount(image, range),
> -      .base_array_layer = range->baseArrayLayer,
> -      .array_len = anv_get_layerCount(image, range),
> -      .swizzle = {
> -         .r = remap_swizzle(pCreateInfo->components.r,
> -                            VK_COMPONENT_SWIZZLE_R, format.swizzle),
> -         .g = remap_swizzle(pCreateInfo->components.g,
> -                            VK_COMPONENT_SWIZZLE_G, format.swizzle),
> -         .b = remap_swizzle(pCreateInfo->components.b,
> -                            VK_COMPONENT_SWIZZLE_B, format.swizzle),
> -         .a = remap_swizzle(pCreateInfo->components.a,
> -                            VK_COMPONENT_SWIZZLE_A, format.swizzle),
> -      },
> -   };
> -
>     iview->extent = (VkExtent3D) {
>        .width  = anv_minify(image->extent.width , range->baseMipLevel),
>        .height = anv_minify(image->extent.height, range->baseMipLevel),
>        .depth  = anv_minify(image->extent.depth , range->baseMipLevel),
>     };
>
> -   if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
> -      iview->isl.base_array_layer = 0;
> -      iview->isl.array_len = iview->extent.depth;
> -   }
> +   /* Now go through the underlying image selected planes (computed in
> +    * expanded_aspects) and map them to planes in the image view.
> +    */
> +   uint32_t iaspect_bit, vplane = 0, iplane;
> +   anv_foreach_plane_aspect_bit(iplane, iaspect_bit,
> +                                expanded_aspects, image->aspects) {
> +      VkImageAspectFlags vplane_aspect =
> +         anv_plane_to_aspect(iview->aspect_mask, vplane);
> +      struct anv_format_plane format =
> +         anv_get_plane_format(&device->info, pCreateInfo->format,
> +                              vplane_aspect, image->tiling);
> +
> +      iview->planes[vplane].image_plane = iplane;
> +
> +      iview->planes[vplane].isl = (struct isl_view) {
> +         .format = format.isl_format,
> +         .base_level = range->baseMipLevel,
> +         .levels = anv_get_levelCount(image, range),
> +         .base_array_layer = range->baseArrayLayer,
> +         .array_len = anv_get_layerCount(image, range),
> +         .swizzle = {
> +            .r = remap_swizzle(pCreateInfo->components.r,
> +                               VK_COMPONENT_SWIZZLE_R, format.swizzle),
> +            .g = remap_swizzle(pCreateInfo->components.g,
> +                               VK_COMPONENT_SWIZZLE_G, format.swizzle),
> +            .b = remap_swizzle(pCreateInfo->components.b,
> +                               VK_COMPONENT_SWIZZLE_B, format.swizzle),
> +            .a = remap_swizzle(pCreateInfo->components.a,
> +                               VK_COMPONENT_SWIZZLE_A, format.swizzle),
> +         },
> +      };
> +
> +      if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
> +         iview->planes[vplane].isl.base_array_layer = 0;
> +         iview->planes[vplane].isl.array_len = iview->extent.depth;
> +      }
>
> -   if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
> -       pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
> -      iview->isl.usage = ISL_SURF_USAGE_CUBE_BIT;
> -   } else {
> -      iview->isl.usage = 0;
> -   }
> +      if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
> +          pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
> +         iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
> +      } else {
> +         iview->planes[vplane].isl.usage = 0;
> +      }
>
> -   /* Input attachment surfaces for color are allocated and filled
> -    * out at BeginRenderPass time because they need compression
> information.
> -    * Compression is not yet enabled for depth textures and stencil
> doesn't
> -    * allow compression so we can just use the texture surface state from
> the
> -    * view.
> -    */
> -   if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
> -       (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
> -        !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
> -      iview->optimal_sampler_surface_state.state =
> alloc_surface_state(device);
> -      iview->general_sampler_surface_state.state =
> alloc_surface_state(device);
> -
> -      enum isl_aux_usage general_aux_usage =
> -         anv_layout_to_aux_usage(&device->info, image,
> iview->aspect_mask,
> -                                 VK_IMAGE_LAYOUT_GENERAL);
> -      enum isl_aux_usage optimal_aux_usage =
> -         anv_layout_to_aux_usage(&device->info, image,
> iview->aspect_mask,
> -                                 VK_IMAGE_LAYOUT_SHADER_READ_
> ONLY_OPTIMAL);
> -
> -      anv_image_fill_surface_state(device, image, iview->aspect_mask,
> -                                   &iview->isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> -                                   optimal_aux_usage, NULL,
> -                                   ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
> -                                   &iview->optimal_sampler_surface_state,
> -                                   NULL);
> -
> -      anv_image_fill_surface_state(device, image, iview->aspect_mask,
> -                                   &iview->isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> -                                   general_aux_usage, NULL,
> -                                   0,
> -                                   &iview->general_sampler_surface_state,
> -                                   NULL);
> -   }
> +      if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
> +          (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
> +           !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
> +         iview->planes[vplane].optimal_sampler_surface_state.state =
> alloc_surface_state(device);
> +         iview->planes[vplane].general_sampler_surface_state.state =
> alloc_surface_state(device);
> +
> +         enum isl_aux_usage general_aux_usage =
> +            anv_layout_to_aux_usage(&device->info, image, iplane,
> +                                    VK_IMAGE_LAYOUT_GENERAL);
> +         enum isl_aux_usage optimal_aux_usage =
> +            anv_layout_to_aux_usage(&device->info, image, iplane,
> +                                    VK_IMAGE_LAYOUT_SHADER_READ_
> ONLY_OPTIMAL);
> +
> +         anv_image_fill_surface_state(device, image, iplane,
> +                                      &iview->planes[vplane].isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> +                                      optimal_aux_usage, NULL,
> +                                      ANV_IMAGE_VIEW_STATE_TEXTURE_
> OPTIMAL,
> +                                      &iview->planes[vplane].
> optimal_sampler_surface_state,
> +                                      NULL);
> +
> +         anv_image_fill_surface_state(device, image, iplane,
> +                                      &iview->planes[vplane].isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> +                                      general_aux_usage, NULL,
> +                                      0,
> +                                      &iview->planes[vplane].
> general_sampler_surface_state,
> +                                      NULL);
> +      }
> +
> +      /* NOTE: This one needs to go last since it may stomp
> isl_view.format */
> +      if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
> +         iview->planes[vplane].storage_surface_state.state =
> alloc_surface_state(device);
> +         iview->planes[vplane].writeonly_storage_surface_state.state =
> alloc_surface_state(device);
> +
> +         anv_image_fill_surface_state(device, image, iplane,
> +                                      &iview->planes[vplane].isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> +                                      ISL_AUX_USAGE_NONE, NULL,
> +                                      0,
> +                                      &iview->planes[vplane].
> storage_surface_state,
> +                                      &iview->planes[vplane].
> storage_image_param);
> +
> +         anv_image_fill_surface_state(device, image, iplane,
> +                                      &iview->planes[vplane].isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> +                                      ISL_AUX_USAGE_NONE, NULL,
> +                                      ANV_IMAGE_VIEW_STATE_STORAGE_
> WRITE_ONLY,
> +                                      &iview->planes[vplane].
> writeonly_storage_surface_state,
> +                                      NULL);
> +      }
>
> -   /* NOTE: This one needs to go last since it may stomp isl_view.format
> */
> -   if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
> -      iview->storage_surface_state.state = alloc_surface_state(device);
> -      iview->writeonly_storage_surface_state.state =
> alloc_surface_state(device);
> -
> -      anv_image_fill_surface_state(device, image, iview->aspect_mask,
> -                                   &iview->isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> -                                   ISL_AUX_USAGE_NONE, NULL,
> -                                   0,
> -                                   &iview->storage_surface_state,
> -                                   &iview->storage_image_param);
> -
> -      anv_image_fill_surface_state(device, image, iview->aspect_mask,
> -                                   &iview->isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> -                                   ISL_AUX_USAGE_NONE, NULL,
> -                                   ANV_IMAGE_VIEW_STATE_STORAGE_
> WRITE_ONLY,
> -                                   &iview->writeonly_storage_
> surface_state,
> -                                   NULL);
> +      vplane++;
>     }
>
>     *pView = anv_image_view_to_handle(iview);
> @@ -1085,24 +1210,26 @@ anv_DestroyImageView(VkDevice _device, VkImageView
> _iview,
>     if (!iview)
>        return;
>
> -   if (iview->optimal_sampler_surface_state.state.alloc_size > 0) {
> -      anv_state_pool_free(&device->surface_state_pool,
> -                          iview->optimal_sampler_surface_state.state);
> -   }
> +   for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
> +      if (iview->planes[plane].optimal_sampler_surface_state.state.alloc_size
> > 0) {
> +         anv_state_pool_free(&device->surface_state_pool,
> +                             iview->planes[plane].optimal_
> sampler_surface_state.state);
> +      }
>
> -   if (iview->general_sampler_surface_state.state.alloc_size > 0) {
> -      anv_state_pool_free(&device->surface_state_pool,
> -                          iview->general_sampler_surface_state.state);
> -   }
> +      if (iview->planes[plane].general_sampler_surface_state.state.alloc_size
> > 0) {
> +         anv_state_pool_free(&device->surface_state_pool,
> +                             iview->planes[plane].general_
> sampler_surface_state.state);
> +      }
>
> -   if (iview->storage_surface_state.state.alloc_size > 0) {
> -      anv_state_pool_free(&device->surface_state_pool,
> -                          iview->storage_surface_state.state);
> -   }
> +      if (iview->planes[plane].storage_surface_state.state.alloc_size >
> 0) {
> +         anv_state_pool_free(&device->surface_state_pool,
> +                             iview->planes[plane].storage_
> surface_state.state);
> +      }
>
> -   if (iview->writeonly_storage_surface_state.state.alloc_size > 0) {
> -      anv_state_pool_free(&device->surface_state_pool,
> -                          iview->writeonly_storage_surface_state.state);
> +      if (iview->planes[plane].writeonly_storage_surface_state.state.alloc_size
> > 0) {
> +         anv_state_pool_free(&device->surface_state_pool,
> +                             iview->planes[plane].
> writeonly_storage_surface_state.state);
> +      }
>     }
>
>     vk_free2(&device->alloc, pAllocator, iview);
> @@ -1210,16 +1337,21 @@ const struct anv_surface *
>  anv_image_get_surface_for_aspect_mask(const struct anv_image *image,
>                                        VkImageAspectFlags aspect_mask)
>  {
> +   VkImageAspectFlags sanitized_mask;
> +
>     switch (aspect_mask) {
>     case VK_IMAGE_ASPECT_COLOR_BIT:
>        assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -      return &image->color_surface;
> +      sanitized_mask = VK_IMAGE_ASPECT_COLOR_BIT;
> +      break;
>     case VK_IMAGE_ASPECT_DEPTH_BIT:
>        assert(image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
> -      return &image->depth_surface;
> +      sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
> +      break;
>     case VK_IMAGE_ASPECT_STENCIL_BIT:
>        assert(image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
> -      return &image->stencil_surface;
> +      sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
> +      break;
>     case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
>        /* FINISHME: The Vulkan spec (git a511ba2) requires support for
>         * combined depth stencil formats. Specifically, it states:
> @@ -1233,13 +1365,29 @@ anv_image_get_surface_for_aspect_mask(const
> struct anv_image *image,
>         * stencil surfaces from the underlying surface.
>         */
>        if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
> -         return &image->depth_surface;
> +         sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
>        } else {
>           assert(image->aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
> -         return &image->stencil_surface;
> +         sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
>        }
>

Does this case actually happen?  I know it's in there for some reason but I
have a feeling that reason is now bogus.  If so, then we can get rid of
this whole switch mess and replace it all with the two lines you added
below.


> -    default:
> +      break;
> +   case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR:
> +      assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> +      sanitized_mask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR;
> +      break;
> +   case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR:
> +      assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> +      sanitized_mask = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR;
> +      break;
> +   case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
> +      assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> +      sanitized_mask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR;
> +      break;
> +   default:
>         unreachable("image does not have aspect");
>         return NULL;
>     }
> +
> +   uint32_t plane = anv_image_aspect_to_plane(image->aspects,
> sanitized_mask);
> +   return &image->planes[plane].surface;
>  }
> diff --git a/src/intel/vulkan/anv_intel.c b/src/intel/vulkan/anv_intel.c
> index 991a93542d2..d4ef3beb743 100644
> --- a/src/intel/vulkan/anv_intel.c
> +++ b/src/intel/vulkan/anv_intel.c
> @@ -80,8 +80,8 @@ VkResult anv_CreateDmaBufImageINTEL(
>        pAllocator, &image_h);
>
>     image = anv_image_from_handle(image_h);
> -   image->bo = mem->bo;
> -   image->offset = 0;
> +   image->planes[0].bo = mem->bo;
> +   image->planes[0].bo_offset = 0;
>
>     assert(image->extent.width > 0);
>     assert(image->extent.height > 0);
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_
> private.h
> index 5e14f49b196..cb324a3995e 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -1566,6 +1566,16 @@ anv_pipe_invalidate_bits_for_access_flags(VkAccessFlags
> flags)
>     return pipe_bits;
>  }
>
> +#define VK_IMAGE_ASPECT_ANY_COLOR_BIT (         \
> +   VK_IMAGE_ASPECT_COLOR_BIT | \
> +   VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | \
> +   VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | \
> +   VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> +#define VK_IMAGE_ASPECT_PLANES_BITS ( \
> +   VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | \
> +   VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | \
> +   VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> +
>  struct anv_vertex_binding {
>     struct anv_buffer *                          buffer;
>     VkDeviceSize                                 offset;
> @@ -2236,10 +2246,48 @@ anv_image_aspect_to_plane(VkImageAspectFlags
> image_aspects,
>     case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
>        return 2;
>     default:
> +      /* Purposefully assert with depth/stencil aspects. */
>        unreachable("invalid image aspect");
>     }
>  }
>
> +static inline uint32_t
> +anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
> +{
> +   uint32_t planes = 0;
> +
> +   if (aspect_mask & (VK_IMAGE_ASPECT_COLOR_BIT |
> +                      VK_IMAGE_ASPECT_DEPTH_BIT |
> +                      VK_IMAGE_ASPECT_STENCIL_BIT |
> +                      VK_IMAGE_ASPECT_PLANE_0_BIT_KHR))
> +      planes++;
> +   if (aspect_mask & VK_IMAGE_ASPECT_PLANE_1_BIT_KHR)
> +      planes++;
> +   if (aspect_mask & VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> +      planes++;
> +
> +   return planes;
> +}
> +
> +static inline VkImageAspectFlags
> +anv_plane_to_aspect(VkImageAspectFlags image_aspects,
> +                    uint32_t plane)
> +{
> +   if (image_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> +      if (_mesa_bitcount(image_aspects) > 1)
> +         return VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << plane;
> +      return VK_IMAGE_ASPECT_COLOR_BIT;
> +   }
> +   if (image_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
> +      return VK_IMAGE_ASPECT_DEPTH_BIT << plane;
> +   assert(image_aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
> +   return VK_IMAGE_ASPECT_STENCIL_BIT;
> +}
> +
> +#define anv_foreach_plane_aspect_bit(p, b, aspects, image_aspects) \
> +   for_each_bit(b, aspects) \
> +      for (p = anv_image_aspect_to_plane(image_aspects, 1 << b); p !=
> ~0; p = ~0)
>

Why not something like this:

VkImageAspectFlags
anv_image_expand_aspects(struct anv_image *image, VkImageAspectFlags
aspects)
{
   if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
      assert(aspects == VK_IMAGE_ASPECT_COLOR_BIT);
      if (!(image->aspects & VK_IMAGE_ASPECT_COLOR_BIT) &&
          (image->aspects & VK_IMAGE_ASPECT_PLANE0_BIT)) {
         aspects &= VK_IMAGE_ASPECT_COLOR_BIT;
         aspects |= image->aspects & VK_IMAGE_ASPECT_PLANES_BITS;
      }
   }

   assert((aspects & image->aspects) == aspects);
   return aspects;
}

#define anv_image_foreach_aspect(a, image, aspects) \
   for (VkImageAspectFlags _bits = anv_image_expand_aspects(image,
aspects), \
                                         a = (1 << (ffs(_bits) - 1)); \
        a; \
        _bits &= ~a, a = (1 << (ffs(_bits) - 1)))

I think I got that more-or-less right; I did type it blind. :)  Anyway, I
think something like that would be much nicer to use.  Also, it's not a
double loop so break works the way you would expect.

+
>  const struct anv_format *
>  anv_get_format(VkFormat format);
>
> @@ -2300,72 +2348,115 @@ struct anv_image {
>      * of the actual surface formats.
>      */
>     VkFormat vk_format;
> +   const struct anv_format *format;
> +
>     VkImageAspectFlags aspects;
>     VkExtent3D extent;
>     uint32_t levels;
>     uint32_t array_size;
>     uint32_t samples; /**< VkImageCreateInfo::samples */
> +   uint32_t n_planes;
>     VkImageUsageFlags usage; /**< Superset of VkImageCreateInfo::usage. */
>     VkImageTiling tiling; /** VkImageCreateInfo::tiling */
>
>     VkDeviceSize size;
>     uint32_t alignment;
>
> -   /* Set when bound */
> -   struct anv_bo *bo;
> -   VkDeviceSize offset;
> +   bool disjoint;
>
>     /**
>      * Image subsurfaces
>      *
> -    * For each foo, anv_image::foo_surface is valid if and only if
> -    * anv_image::aspects has a foo aspect.
> +    * For each foo, anv_image::planes[x].surface is valid if and only if
> +    * anv_image::aspects has a x aspect. Refer to
> anv_image_aspect_to_plane()
> +    * to figure the number associated with a given aspect.
>      *
>      * The hardware requires that the depth buffer and stencil buffer be
>      * separate surfaces.  From Vulkan's perspective, though, depth and
> stencil
>      * reside in the same VkImage.  To satisfy both the hardware and
> Vulkan, we
>      * allocate the depth and stencil buffers as separate surfaces in the
> same
>      * bo.
> +    *
> +    * Memory layout :
> +    *
> +    * -----------------------
> +    * |     surface0        |   /|\
> +    * -----------------------    |
> +    * |   shadow surface0   |    |
> +    * -----------------------    | Plane 0
> +    * |    aux surface0     |    |
> +    * -----------------------    |
> +    * | fast clear colors0  |   \|/
> +    * -----------------------
> +    * |     surface1        |   /|\
> +    * -----------------------    |
> +    * |   shadow surface1   |    |
> +    * -----------------------    | Plane 1
> +    * |    aux surface1     |    |
> +    * -----------------------    |
> +    * | fast clear colors1  |   \|/
> +    * -----------------------
> +    * |        ...          |
> +    * |                     |
> +    * -----------------------
>      */
> -   union {
> -      struct anv_surface color_surface;
> +   struct {
> +      /**
> +       * Offset of the entire plane (whenever the image is disjoint this
> is
> +       * set to 0).
> +       */
> +      uint32_t offset;
>
> -      struct {
> -         struct anv_surface depth_surface;
> -         struct anv_surface stencil_surface;
> -      };
> -   };
> +      VkDeviceSize size;
> +      uint32_t alignment;
>
> -   /**
> -    * A surface which shadows the main surface and may have different
> tiling.
> -    * This is used for sampling using a tiling that isn't supported for
> other
> -    * operations.
> -    */
> -   struct anv_surface shadow_surface;
> +      struct anv_surface surface;
>
> -   /**
> -    * For color images, this is the aux usage for this image when not
> used as a
> -    * color attachment.
> -    *
> -    * For depth/stencil images, this is set to ISL_AUX_USAGE_HIZ if the
> image
> -    * has a HiZ buffer.
> -    */
> -   enum isl_aux_usage aux_usage;
> +      /**
> +       * A surface which shadows the main surface and may have different
> +       * tiling. This is used for sampling using a tiling that isn't
> supported
> +       * for other operations.
> +       */
> +      struct anv_surface shadow_surface;
> +
> +      /**
> +       * For color images, this is the aux usage for this image when not
> used
> +       * as a color attachment.
> +       *
> +       * For depth/stencil images, this is set to ISL_AUX_USAGE_HIZ if the
> +       * image has a HiZ buffer.
> +       */
> +      enum isl_aux_usage aux_usage;
>
> -   struct anv_surface aux_surface;
> +      struct anv_surface aux_surface;
> +
> +      /**
> +       * Offset of the fast clear state (used to compute the
> +       * fast_clear_state_offset of the following planes).
> +       */
> +      uint32_t fast_clear_state_offset;
> +
> +      /**
> +       * BO associated with this plane, set when bound.
> +       */
> +      struct anv_bo *bo;
> +      VkDeviceSize bo_offset;
> +   } planes[3];
>  };
>
>  /* Returns the number of auxiliary buffer levels attached to an image. */
>  static inline uint8_t
> -anv_image_aux_levels(const struct anv_image * const image)
> +anv_image_aux_levels(const struct anv_image * const image, uint8_t plane)
>  {
>     assert(image);
> -   return image->aux_surface.isl.size > 0 ? image->aux_surface.isl.levels
> : 0;
> +   return image->planes[plane].aux_surface.isl.size > 0 ?
> +          image->planes[plane].aux_surface.isl.levels : 0;
>  }
>
>  /* Returns the number of auxiliary buffer layers attached to an image. */
>  static inline uint32_t
>  anv_image_aux_layers(const struct anv_image * const image,
> +                     const uint32_t plane,
>                       const uint8_t miplevel)
>  {
>     assert(image);
> @@ -2373,14 +2464,14 @@ anv_image_aux_layers(const struct anv_image *
> const image,
>     /* The miplevel must exist in the main buffer. */
>     assert(miplevel < image->levels);
>
> -   if (miplevel >= anv_image_aux_levels(image)) {
> +   if (miplevel >= anv_image_aux_levels(image, plane)) {
>        /* There are no layers with auxiliary data because the miplevel has
> no
>         * auxiliary data.
>         */
>        return 0;
>     } else {
> -      return MAX2(image->aux_surface.isl.logical_level0_px.array_len,
> -                  image->aux_surface.isl.logical_level0_px.depth >>
> miplevel);
> +      return MAX2(image->planes[plane].aux_surface.isl.logical_level0_px.
> array_len,
> +                  image->planes[plane].aux_surface.isl.logical_level0_px.depth
> >> miplevel);
>     }
>  }
>
> @@ -2404,13 +2495,12 @@ anv_fast_clear_state_entry_size(const struct
> anv_device *device)
>  /* Returns true if a HiZ-enabled depth buffer can be sampled from. */
>  static inline bool
>  anv_can_sample_with_hiz(const struct gen_device_info * const devinfo,
> -                        const VkImageAspectFlags aspect_mask,
> -                        const uint32_t samples)
> +                        const struct anv_image *image)
>  {
>     /* Validate the inputs. */
> -   assert(devinfo && aspect_mask && samples);
> -   return devinfo->gen >= 8 && (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
> &&
> -          samples == 1;
> +   assert(devinfo && image && image->samples);
> +   return devinfo->gen >= 8 && (image->aspects &
> VK_IMAGE_ASPECT_DEPTH_BIT) &&
> +          image->samples == 1;
>  }
>
>  void
> @@ -2421,19 +2511,21 @@ void
>  anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
>                  const struct anv_state surface_state,
>                  const struct anv_image * const image,
> +                const uint32_t plane,
>                  const uint8_t level, const uint32_t layer_count,
>                  const enum blorp_fast_clear_op op);
>
>  void
>  anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
>                       const struct anv_image *image,
> +                     const uint32_t plane,
>                       const uint32_t base_level, const uint32_t
> level_count,
>                       const uint32_t base_layer, uint32_t layer_count);
>
>  void
>  anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
>                           const struct anv_image *image,
> -                         VkImageAspectFlagBits aspect,
> +                         uint32_t plane,
>

Why do we need both the plane and the aspect on all these?  Just the aspect
should be sufficient.  This same question applies to a lot of functions in
this patch.


>                           uint32_t base_level, uint32_t level_count,
>                           uint32_t base_layer, uint32_t layer_count);
>
> @@ -2458,37 +2550,71 @@ anv_get_levelCount(const struct anv_image *image,
>            image->levels - range->baseMipLevel : range->levelCount;
>  }
>
> +static inline VkImageAspectFlags
> +anv_image_color_aspects(struct anv_image *image, VkImageAspectFlags
> aspects)
> +{
> +   /* If the underlying image has color plane aspects and
> +    * VK_IMAGE_ASPECT_COLOR_BIT has been requested, then return the
> aspects of
> +    * the underlying image. */
> +   if ((image->aspects & VK_IMAGE_ASPECT_PLANES_BITS) != 0 &&
> +       aspects == VK_IMAGE_ASPECT_COLOR_BIT)
> +      return image->aspects;
> +
> +   return aspects;
> +}
>

I guess this is basically the expand_aspects function I wrote above.


> +
> +static inline bool
> +anv_image_aspects_compatible(VkImageAspectFlags aspects1,
> +                             VkImageAspectFlags aspects2)
> +{
> +   if (aspects1 == aspects2)
> +      return true;
> +
> +   /* Only 1 color aspects are compatibles. */
> +   if ((aspects1 & VK_IMAGE_ASPECT_ANY_COLOR_BIT) != 0 &&
> +       (aspects2 & VK_IMAGE_ASPECT_ANY_COLOR_BIT) != 0 &&
> +       _mesa_bitcount(aspects1) == _mesa_bitcount(aspects2))
> +      return true;
> +
> +   return false;
> +}
>
>  struct anv_image_view {
>     const struct anv_image *image; /**< VkImageViewCreateInfo::image */
>
> -   struct isl_view isl;
> -
>     VkImageAspectFlags aspect_mask;
>     VkFormat vk_format;
>     VkExtent3D extent; /**< Extent of VkImageViewCreateInfo::baseMipLevel.
> */
>
> -   /**
> -    * RENDER_SURFACE_STATE when using image as a sampler surface with an
> image
> -    * layout of SHADER_READ_ONLY_OPTIMAL or DEPTH_STENCIL_READ_ONLY_
> OPTIMAL.
> -    */
> -   struct anv_surface_state optimal_sampler_surface_state;
> +   unsigned n_planes;
> +   struct {
> +      uint32_t image_plane;
>
> -   /**
> -    * RENDER_SURFACE_STATE when using image as a sampler surface with an
> image
> -    * layout of GENERAL.
> -    */
> -   struct anv_surface_state general_sampler_surface_state;
> +      struct isl_view isl;
>
> -   /**
> -    * RENDER_SURFACE_STATE when using image as a storage image. Separate
> states
> -    * for write-only and readable, using the real format for write-only
> and the
> -    * lowered format for readable.
> -    */
> -   struct anv_surface_state storage_surface_state;
> -   struct anv_surface_state writeonly_storage_surface_state;
> +      /**
> +       * RENDER_SURFACE_STATE when using image as a sampler surface with
> an
> +       * image layout of SHADER_READ_ONLY_OPTIMAL or
> +       * DEPTH_STENCIL_READ_ONLY_OPTIMAL.
> +       */
> +      struct anv_surface_state optimal_sampler_surface_state;
>
> -   struct brw_image_param storage_image_param;
> +      /**
> +       * RENDER_SURFACE_STATE when using image as a sampler surface with
> an
> +       * image layout of GENERAL.
> +       */
> +      struct anv_surface_state general_sampler_surface_state;
> +
> +      /**
> +       * RENDER_SURFACE_STATE when using image as a storage image.
> Separate
> +       * states for write-only and readable, using the real format for
> +       * write-only and the lowered format for readable.
> +       */
> +      struct anv_surface_state storage_surface_state;
> +      struct anv_surface_state writeonly_storage_surface_state;
> +
> +      struct brw_image_param storage_image_param;
> +   } planes[3];
>  };
>
>  enum anv_image_view_state_flags {
> @@ -2498,7 +2624,7 @@ enum anv_image_view_state_flags {
>
>  void anv_image_fill_surface_state(struct anv_device *device,
>                                    const struct anv_image *image,
> -                                  VkImageAspectFlagBits aspect,
> +                                  uint32_t plane,
>                                    const struct isl_view *view,
>                                    isl_surf_usage_flags_t view_usage,
>                                    enum isl_aux_usage aux_usage,
> diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
> index c3e5dc1870b..3fca076894c 100644
> --- a/src/intel/vulkan/anv_wsi.c
> +++ b/src/intel/vulkan/anv_wsi.c
> @@ -221,7 +221,7 @@ anv_wsi_image_create(VkDevice device_h,
>     result = anv_AllocateMemory(anv_device_to_handle(device),
>        &(VkMemoryAllocateInfo) {
>           .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
> -         .allocationSize = image->size,
> +         .allocationSize = image->planes[0].surface.isl.size,
>           .memoryTypeIndex = 0,
>        },
>        NULL /* XXX: pAllocator */,
> @@ -240,7 +240,7 @@ anv_wsi_image_create(VkDevice device_h,
>
>     anv_BindImageMemory(device_h, image_h, memory_h, 0);
>
> -   struct anv_surface *surface = &image->color_surface;
> +   struct anv_surface *surface = &image->planes[0].surface;
>     assert(surface->isl.tiling == ISL_TILING_X);
>
>     *row_pitch = surface->isl.row_pitch;
> @@ -266,8 +266,8 @@ anv_wsi_image_create(VkDevice device_h,
>     *image_p = image_h;
>     *memory_p = memory_h;
>     *fd_p = fd;
> -   *size = image->size;
> -   *offset = image->offset;
> +   *size = image->planes[0].surface.isl.size;
> +   *offset = image->planes[0].surface.offset;
>     return VK_SUCCESS;
>  fail_alloc_memory:
>     anv_FreeMemory(device_h, memory_h, pAllocator);
> diff --git a/src/intel/vulkan/gen8_cmd_buffer.c
> b/src/intel/vulkan/gen8_cmd_buffer.c
> index 7bea231ea76..f19867ca320 100644
> --- a/src/intel/vulkan/gen8_cmd_buffer.c
> +++ b/src/intel/vulkan/gen8_cmd_buffer.c
> @@ -323,7 +323,7 @@ want_stencil_pma_fix(struct anv_cmd_buffer *cmd_buffer)
>     /* HiZ is enabled so we had better have a depth buffer with HiZ */
>     const struct anv_image_view *ds_iview =
>        anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
> -   assert(ds_iview && ds_iview->image->aux_usage == ISL_AUX_USAGE_HIZ);
> +   assert(ds_iview && ds_iview->image->planes[0].aux_usage ==
> ISL_AUX_USAGE_HIZ);
>
>     /* 3DSTATE_PS_EXTRA::PixelShaderValid */
>     struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
> diff --git a/src/intel/vulkan/genX_cmd_buffer.c
> b/src/intel/vulkan/genX_cmd_buffer.c
> index dc5cf687dc6..71e46acfe4d 100644
> --- a/src/intel/vulkan/genX_cmd_buffer.c
> +++ b/src/intel/vulkan/genX_cmd_buffer.c
> @@ -181,18 +181,45 @@ add_surface_state_reloc(struct anv_cmd_buffer
> *cmd_buffer,
>  static void
>  add_image_relocs(struct anv_cmd_buffer *cmd_buffer,
>                   const struct anv_image *image,
> +                 const uint32_t plane,
>                   struct anv_surface_state state)
>  {
>     const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
>
> -   add_surface_state_reloc(cmd_buffer, state.state, image->bo,
> state.address);
> +   add_surface_state_reloc(cmd_buffer, state.state,
> +                           image->planes[plane].bo, state.address);
>
>     if (state.aux_address) {
>        VkResult result =
>           anv_reloc_list_add(&cmd_buffer->surface_relocs,
>                              &cmd_buffer->pool->alloc,
>                              state.state.offset +
> isl_dev->ss.aux_addr_offset,
> -                            image->bo, state.aux_address);
> +                            image->planes[plane].bo,
> +                            state.aux_address);
> +      if (result != VK_SUCCESS)
> +         anv_batch_set_error(&cmd_buffer->batch, result);
> +   }
> +}
> +
> +static void
> +add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,
> +                      const struct anv_image_view *image_view,
> +                      const uint32_t plane,
> +                      struct anv_surface_state state)
> +{
> +   const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
> +   const struct anv_image *image = image_view->image;
> +   uint32_t image_plane = image_view->planes[plane].image_plane;
> +
> +   add_surface_state_reloc(cmd_buffer, state.state,
> +                           image->planes[image_plane].bo, state.address);
> +
> +   if (state.aux_address) {
> +      VkResult result =
> +         anv_reloc_list_add(&cmd_buffer->surface_relocs,
> +                            &cmd_buffer->pool->alloc,
> +                            state.state.offset +
> isl_dev->ss.aux_addr_offset,
> +                            image->planes[image_plane].bo,
> state.aux_address);
>        if (result != VK_SUCCESS)
>           anv_batch_set_error(&cmd_buffer->batch, result);
>     }
> @@ -225,8 +252,11 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
>     struct anv_attachment_state *att_state = &cmd_state->attachments[att];
>     struct anv_image_view *iview = cmd_state->framebuffer->
> attachments[att];
>
> -   if (iview->isl.base_array_layer >=
> -       anv_image_aux_layers(iview->image, iview->isl.base_level)) {
> +   assert(iview->n_planes == 1);
> +
> +   if (iview->planes[0].isl.base_array_layer >=
> +       anv_image_aux_layers(iview->image, 0,
> +                            iview->planes[0].isl.base_level)) {
>        /* There is no aux buffer which corresponds to the level and
> layer(s)
>         * being accessed.
>         */
> @@ -234,12 +264,12 @@ color_attachment_compute_aux_usage(struct
> anv_device * device,
>        att_state->input_aux_usage = ISL_AUX_USAGE_NONE;
>        att_state->fast_clear = false;
>        return;
> -   } else if (iview->image->aux_usage == ISL_AUX_USAGE_MCS) {
> +   } else if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_MCS) {
>        att_state->aux_usage = ISL_AUX_USAGE_MCS;
>        att_state->input_aux_usage = ISL_AUX_USAGE_MCS;
>        att_state->fast_clear = false;
>        return;
> -   } else if (iview->image->aux_usage == ISL_AUX_USAGE_CCS_E) {
> +   } else if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_CCS_E) {
>        att_state->aux_usage = ISL_AUX_USAGE_CCS_E;
>        att_state->input_aux_usage = ISL_AUX_USAGE_CCS_E;
>     } else {
> @@ -255,7 +285,7 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
>         * In other words, we can only sample from a fast-cleared image if
> it
>         * also supports color compression.
>         */
> -      if (isl_format_supports_ccs_e(&device->info, iview->isl.format)) {
> +      if (isl_format_supports_ccs_e(&device->info,
> iview->planes[0].isl.format)) {
>           att_state->input_aux_usage = ISL_AUX_USAGE_CCS_D;
>
>           /* While fast-clear resolves and partial resolves are fairly
> cheap in the
> @@ -274,10 +304,10 @@ color_attachment_compute_aux_usage(struct
> anv_device * device,
>        }
>     }
>
> -   assert(iview->image->aux_surface.isl.usage & ISL_SURF_USAGE_CCS_BIT);
> +   assert(iview->image->planes[0].aux_surface.isl.usage &
> ISL_SURF_USAGE_CCS_BIT);
>
>     att_state->clear_color_is_zero_one =
> -      color_is_zero_one(att_state->clear_value.color, iview->isl.format);
> +      color_is_zero_one(att_state->clear_value.color,
> iview->planes[0].isl.format);
>     att_state->clear_color_is_zero =
>        att_state->clear_value.color.uint32[0] == 0 &&
>        att_state->clear_value.color.uint32[1] == 0 &&
> @@ -309,7 +339,8 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
>         * layers.
>         */
>        if (cmd_state->framebuffer->layers !=
> -          anv_image_aux_layers(iview->image, iview->isl.base_level)) {
> +          anv_image_aux_layers(iview->image, 0,
> +                               iview->planes[0].isl.base_level)) {
>           att_state->fast_clear = false;
>           if (GEN_GEN == 7) {
>              anv_perf_warn(device->instance, iview->image,
> @@ -325,7 +356,7 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
>        if (cmd_state->pass->attachments[att].first_subpass_layout ==
>            VK_IMAGE_LAYOUT_GENERAL &&
>            (!att_state->clear_color_is_zero ||
> -           iview->image->aux_usage == ISL_AUX_USAGE_NONE)) {
> +           iview->image->planes[0].aux_usage == ISL_AUX_USAGE_NONE)) {
>           att_state->fast_clear = false;
>        }
>
> @@ -370,14 +401,14 @@ transition_depth_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>      * that's currently in the buffer. Therefore, a data-preserving resolve
>      * operation is not needed.
>      */
> -   if (image->aux_usage != ISL_AUX_USAGE_HIZ || initial_layout ==
> final_layout)
> +   if (image->planes[0].aux_usage != ISL_AUX_USAGE_HIZ || initial_layout
> == final_layout)
>        return;
>
>     const bool hiz_enabled = ISL_AUX_USAGE_HIZ ==
> -      anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> image->aspects,
> +      anv_layout_to_aux_usage(&cmd_buffer->device->info, image, 0,
>                                initial_layout);
>     const bool enable_hiz = ISL_AUX_USAGE_HIZ ==
> -      anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> image->aspects,
> +      anv_layout_to_aux_usage(&cmd_buffer->device->info, image, 0,
>                                final_layout);
>
>     enum blorp_hiz_op hiz_op;
> @@ -403,14 +434,16 @@ enum fast_clear_state_field {
>  static inline uint32_t
>  get_fast_clear_state_offset(const struct anv_device *device,
>                              const struct anv_image *image,
> -                            unsigned level, enum fast_clear_state_field
> field)
> +                            unsigned plane, unsigned level,
> +                            enum fast_clear_state_field field)
>  {
>     assert(device && image);
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(level < anv_image_aux_levels(image));
> -   uint32_t offset = image->offset + image->aux_surface.offset +
> -                     image->aux_surface.isl.size +
> -                     anv_fast_clear_state_entry_size(device) * level;
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +   assert(level < anv_image_aux_levels(image, plane));
> +   /* Refer to the definition of anv_image for the memory layout. */
> +   uint32_t offset = image->planes[plane].fast_clear_state_offset;
> +
> +   offset += anv_fast_clear_state_entry_size(device) * level;
>
>     switch (field) {
>     case FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE:
> @@ -420,7 +453,8 @@ get_fast_clear_state_offset(const struct anv_device
> *device,
>        break;
>     }
>
> -   assert(offset < image->offset + image->size);
> +   assert(offset < image->planes[plane].surface.offset +
> image->planes[plane].size);
> +
>     return offset;
>  }
>
> @@ -433,14 +467,14 @@ get_fast_clear_state_offset(const struct anv_device
> *device,
>  static void
>  genX(set_image_needs_resolve)(struct anv_cmd_buffer *cmd_buffer,
>                          const struct anv_image *image,
> -                        unsigned level, bool needs_resolve)
> +                        unsigned plane, unsigned level, bool
> needs_resolve)
>  {
>     assert(cmd_buffer && image);
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(level < anv_image_aux_levels(image));
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +   assert(level < anv_image_aux_levels(image, plane));
>
>     const uint32_t resolve_flag_offset =
> -      get_fast_clear_state_offset(cmd_buffer->device, image, level,
> +      get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
>                                    FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
>
>     /* The HW docs say that there is no way to guarantee the completion of
> @@ -448,7 +482,8 @@ genX(set_image_needs_resolve)(struct anv_cmd_buffer
> *cmd_buffer,
>      * issues in testing is currently being used in the GL driver.
>      */
>     anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
> -      sdi.Address = (struct anv_address) { image->bo, resolve_flag_offset
> };
> +      sdi.Address = (struct anv_address) { image->planes[plane].bo,
> +                                           resolve_flag_offset };
>        sdi.ImmediateData = needs_resolve;
>     }
>  }
> @@ -456,14 +491,14 @@ genX(set_image_needs_resolve)(struct anv_cmd_buffer
> *cmd_buffer,
>  static void
>  genX(load_needs_resolve_predicate)(struct anv_cmd_buffer *cmd_buffer,
>                                     const struct anv_image *image,
> -                                   unsigned level)
> +                                   unsigned plane, unsigned level)
>  {
>     assert(cmd_buffer && image);
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(level < anv_image_aux_levels(image));
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +   assert(level < anv_image_aux_levels(image, plane));
>
>     const uint32_t resolve_flag_offset =
> -      get_fast_clear_state_offset(cmd_buffer->device, image, level,
> +      get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
>                                    FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
>
>     /* Make the pending predicated resolve a no-op if one is not needed.
> @@ -473,7 +508,7 @@ genX(load_needs_resolve_predicate)(struct
> anv_cmd_buffer *cmd_buffer,
>     emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC1 + 4, 0);
>     emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC0    , 0);
>     emit_lrm(&cmd_buffer->batch, MI_PREDICATE_SRC0 + 4,
> -            image->bo, resolve_flag_offset);
> +            image->planes[plane].bo, resolve_flag_offset);
>     anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) {
>        mip.LoadOperation    = LOAD_LOADINV;
>        mip.CombineOperation = COMBINE_SET;
> @@ -484,11 +519,11 @@ genX(load_needs_resolve_predicate)(struct
> anv_cmd_buffer *cmd_buffer,
>  static void
>  init_fast_clear_state_entry(struct anv_cmd_buffer *cmd_buffer,
>                              const struct anv_image *image,
> -                            unsigned level)
> +                            unsigned plane, unsigned level)
>  {
>     assert(cmd_buffer && image);
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(level < anv_image_aux_levels(image));
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +   assert(level < anv_image_aux_levels(image, plane));
>
>     /* The resolve flag should updated to signify that
> fast-clear/compression
>      * data needs to be removed when leaving the undefined layout. Such
> data
> @@ -496,8 +531,8 @@ init_fast_clear_state_entry(struct anv_cmd_buffer
> *cmd_buffer,
>      * to return incorrect data. The fast clear data in CCS_D buffers
> should
>      * be removed because CCS_D isn't enabled all the time.
>      */
> -   genX(set_image_needs_resolve)(cmd_buffer, image, level,
> -                                 image->aux_usage == ISL_AUX_USAGE_NONE);
> +   genX(set_image_needs_resolve)(cmd_buffer, image, plane, level,
> +                                 image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_NONE);
>
>     /* The fast clear value dword(s) will be copied into a surface state
> object.
>      * Ensure that the restrictions of the fields in the dword(s) are
> followed.
> @@ -514,13 +549,14 @@ init_fast_clear_state_entry(struct anv_cmd_buffer
> *cmd_buffer,
>     for (; i < cmd_buffer->device->isl_dev.ss.clear_value_size; i += 4) {
>        anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
>           const uint32_t entry_offset =
> -            get_fast_clear_state_offset(cmd_buffer->device, image, level,
> +            get_fast_clear_state_offset(cmd_buffer->device, image,
> plane, level,
>                                          FAST_CLEAR_STATE_FIELD_CLEAR_
> COLOR);
> -         sdi.Address = (struct anv_address) { image->bo, entry_offset + i
> };
> +         sdi.Address = (struct anv_address) { image->planes[plane].bo,
> +                                              entry_offset + i };
>
>           if (GEN_GEN >= 9) {
>              /* MCS buffers on SKL+ can only have 1/0 clear colors. */
> -            assert(image->aux_usage == ISL_AUX_USAGE_MCS);
> +            assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS);
>              sdi.ImmediateData = 0;
>           } else if (GEN_VERSIONx10 >= 75) {
>              /* Pre-SKL, the dword containing the clear values also
> contains
> @@ -550,28 +586,31 @@ static void
>  genX(copy_fast_clear_dwords)(struct anv_cmd_buffer *cmd_buffer,
>                               struct anv_state surface_state,
>                               const struct anv_image *image,
> -                             unsigned level,
> +                             unsigned plane, unsigned level,
>                               bool copy_from_surface_state)
>  {
>     assert(cmd_buffer && image);
> -   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(level < anv_image_aux_levels(image));
> +   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +   assert(level < anv_image_aux_levels(image, plane));
>
>     struct anv_bo *ss_bo =
>        &cmd_buffer->device->surface_state_pool.block_pool.bo;
>     uint32_t ss_clear_offset = surface_state.offset +
>        cmd_buffer->device->isl_dev.ss.clear_value_offset;
>     uint32_t entry_offset =
> -      get_fast_clear_state_offset(cmd_buffer->device, image, level,
> +      get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
>                                    FAST_CLEAR_STATE_FIELD_CLEAR_COLOR);
>     unsigned copy_size = cmd_buffer->device->isl_dev.ss.clear_value_size;
>
>     if (copy_from_surface_state) {
> -      genX(cmd_buffer_mi_memcpy)(cmd_buffer, image->bo, entry_offset,
> +      genX(cmd_buffer_mi_memcpy)(cmd_buffer,
> +                                 image->planes[plane].bo,
> +                                 entry_offset,
>                                   ss_bo, ss_clear_offset, copy_size);
>     } else {
>        genX(cmd_buffer_mi_memcpy)(cmd_buffer, ss_bo, ss_clear_offset,
> -                                 image->bo, entry_offset, copy_size);
> +                                 image->planes[plane].bo,
> +                                 entry_offset, copy_size);
>
>        /* Updating a surface state object may require that the state cache
> be
>         * invalidated. From the SKL PRM, Shared Functions -> State -> State
> @@ -603,6 +642,7 @@ genX(copy_fast_clear_dwords)(struct anv_cmd_buffer
> *cmd_buffer,
>  static void
>  transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
>                          const struct anv_image *image,
> +                        const uint32_t plane,
>                          const uint32_t base_level, uint32_t level_count,
>                          uint32_t base_layer, uint32_t layer_count,
>                          VkImageLayout initial_layout,
> @@ -610,7 +650,7 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>  {
>     /* Validate the inputs. */
>     assert(cmd_buffer);
> -   assert(image && image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> +   assert(image && image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>     /* These values aren't supported for simplicity's sake. */
>     assert(level_count != VK_REMAINING_MIP_LEVELS &&
>            layer_count != VK_REMAINING_ARRAY_LAYERS);
> @@ -630,22 +670,22 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>     if (initial_layout == final_layout)
>        return;
>
> -   if (image->shadow_surface.isl.size > 0 &&
> +   if (image->planes[plane].shadow_surface.isl.size > 0 &&
>         final_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
>        /* This surface is a linear compressed image with a tiled shadow
> surface
>         * for texturing.  The client is about to use it in
> READ_ONLY_OPTIMAL so
>         * we need to ensure the shadow copy is up-to-date.
>         */
>        assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> -      assert(image->color_surface.isl.tiling == ISL_TILING_LINEAR);
> -      assert(image->shadow_surface.isl.tiling != ISL_TILING_LINEAR);
> -      assert(isl_format_is_compressed(image->color_surface.isl.format));
> -      anv_image_copy_to_shadow(cmd_buffer, image,
> VK_IMAGE_ASPECT_COLOR_BIT,
> +      assert(image->planes[plane].surface.isl.tiling ==
> ISL_TILING_LINEAR);
> +      assert(image->planes[plane].shadow_surface.isl.tiling !=
> ISL_TILING_LINEAR);
> +      assert(isl_format_is_compressed(image->planes[
> plane].surface.isl.format));
> +      anv_image_copy_to_shadow(cmd_buffer, image, plane,
>                                 base_level, level_count,
>                                 base_layer, layer_count);
>     }
>
> -   if (base_layer >= anv_image_aux_layers(image, base_level))
> +   if (base_layer >= anv_image_aux_layers(image, plane, base_level))
>        return;
>
>     /* A transition of a 3D subresource works on all slices at a time. */
> @@ -655,9 +695,9 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>     }
>
>     /* We're interested in the subresource range subset that has aux data.
> */
> -   level_count = MIN2(level_count, anv_image_aux_levels(image) -
> base_level);
> +   level_count = MIN2(level_count, anv_image_aux_levels(image, plane) -
> base_level);
>     layer_count = MIN2(layer_count,
> -                      anv_image_aux_layers(image, base_level) -
> base_layer);
> +                      anv_image_aux_layers(image, plane, base_level) -
> base_layer);
>     last_level_num = base_level + level_count;
>
>     /* Record whether or not the layout is undefined. Pre-initialized
> images
> @@ -678,7 +718,7 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>         * Initialize the relevant clear buffer entries.
>         */
>        for (unsigned level = base_level; level < last_level_num; level++)
> -         init_fast_clear_state_entry(cmd_buffer, image, level);
> +         init_fast_clear_state_entry(cmd_buffer, image, plane, level);
>
>        /* Initialize the aux buffers to enable correct rendering. This
> operation
>         * requires up to two steps: one to rid the aux buffer of data that
> may
> @@ -702,7 +742,8 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>                            "define an MCS buffer.");
>           }
>
> -         anv_image_fast_clear(cmd_buffer, image, base_level, level_count,
> +         anv_image_fast_clear(cmd_buffer, image, plane,
> +                              base_level, level_count,
>                                base_layer, layer_count);
>        }
>        /* At this point, some elements of the CCS buffer may have the
> fast-clear
> @@ -714,7 +755,8 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>         * enabled. In this case, we must force the associated CCS buffers
> of the
>         * specified range to enter the ambiguated state in advance.
>         */
> -      if (image->samples == 1 && image->aux_usage != ISL_AUX_USAGE_CCS_E
> &&
> +      if (image->samples == 1 &&
> +          image->planes[plane].aux_usage != ISL_AUX_USAGE_CCS_E &&
>            final_layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
>           /* The CCS_D buffer may not be enabled in the final layout.
> Continue
>            * executing this function to perform a resolve.
> @@ -766,13 +808,14 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>
>        /* The number of layers changes at each 3D miplevel. */
>        if (image->type == VK_IMAGE_TYPE_3D) {
> -         layer_count = MIN2(layer_count, anv_image_aux_layers(image,
> level));
> +         layer_count = MIN2(layer_count, anv_image_aux_layers(image,
> plane, level));
>        }
>
> -      genX(load_needs_resolve_predicate)(cmd_buffer, image, level);
> +      genX(load_needs_resolve_predicate)(cmd_buffer, image, plane,
> level);
>
> -      enum isl_aux_usage aux_usage = image->aux_usage ==
> ISL_AUX_USAGE_NONE ?
> -                                     ISL_AUX_USAGE_CCS_D :
> image->aux_usage;
> +      enum isl_aux_usage aux_usage =
> +         image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE ?
> +         ISL_AUX_USAGE_CCS_D : image->planes[plane].aux_usage;
>
>        /* Create a surface state with the right clear color and perform the
>         * resolve.
> @@ -780,9 +823,9 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>        struct anv_surface_state surface_state;
>        surface_state.state = anv_cmd_buffer_alloc_surface_
> state(cmd_buffer);
>        anv_image_fill_surface_state(cmd_buffer->device,
> -                                   image, VK_IMAGE_ASPECT_COLOR_BIT,
> +                                   image, plane,
>                                     &(struct isl_view) {
> -                                      .format = image->color_surface.isl.
> format,
> +                                      .format =
> image->planes[plane].surface.isl.format,
>                                        .swizzle = ISL_SWIZZLE_IDENTITY,
>                                        .base_level = level,
>                                        .levels = 1,
> @@ -792,16 +835,16 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>                                     ISL_SURF_USAGE_RENDER_TARGET_BIT,
>                                     aux_usage, NULL, 0,
>                                     &surface_state, NULL);
> -      add_image_relocs(cmd_buffer, image, surface_state);
> +      add_image_relocs(cmd_buffer, image, 0, surface_state);
>        genX(copy_fast_clear_dwords)(cmd_buffer, surface_state.state,
> image,
> -                                   level, false /* copy to ss */);
> +                                   plane, level, false /* copy to ss */);
>        anv_ccs_resolve(cmd_buffer, surface_state.state, image,
> -                      level, layer_count,
> -                      image->aux_usage == ISL_AUX_USAGE_CCS_E ?
> +                      plane, level, layer_count,
> +                      image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_CCS_E ?
>                        BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL :
>                        BLORP_FAST_CLEAR_OP_RESOLVE_FULL);
>
> -      genX(set_image_needs_resolve)(cmd_buffer, image, level, false);
> +      genX(set_image_needs_resolve)(cmd_buffer, image, plane, level,
> false);
>     }
>
>     cmd_buffer->state.pending_pipe_bits |=
> @@ -887,7 +930,7 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>           VkImageAspectFlags att_aspects = vk_format_aspects(att->format);
>           VkImageAspectFlags clear_aspects = 0;
>
> -         if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> +         if (att_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
>              /* color attachment */
>              if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
>                 clear_aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
> @@ -911,17 +954,17 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>
>           struct anv_image_view *iview = framebuffer->attachments[i];
>           anv_assert(iview->vk_format == att->format);
> +         anv_assert(iview->n_planes == 1);
>
>           union isl_color_value clear_color = { .u32 = { 0, } };
> -         if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> +         if (att_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
>              color_attachment_compute_aux_usage(cmd_buffer->device,
>                                                 state, i,
> begin->renderArea,
>                                                 &clear_color);
>
>              anv_image_fill_surface_state(cmd_buffer->device,
> -                                         iview->image,
> -                                         VK_IMAGE_ASPECT_COLOR_BIT,
> -                                         &iview->isl,
> +                                         iview->image, 0,
> +                                         &iview->planes[0].isl,
>                                           ISL_SURF_USAGE_RENDER_TARGET_
> BIT,
>                                           state->attachments[i].aux_usage,
>                                           &clear_color,
> @@ -929,8 +972,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>                                           &state->attachments[i].color,
>                                           NULL);
>
> -            add_image_relocs(cmd_buffer, iview->image,
> -                             state->attachments[i].color);
> +            add_image_view_relocs(cmd_buffer, iview, 0,
> +                                  state->attachments[i].color);
>           } else {
>              /* This field will be initialized after the first subpass
>               * transition.
> @@ -942,9 +985,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>
>           if (need_input_attachment_state(&pass->attachments[i])) {
>              anv_image_fill_surface_state(cmd_buffer->device,
> -                                         iview->image,
> -                                         VK_IMAGE_ASPECT_COLOR_BIT,
> -                                         &iview->isl,
> +                                         iview->image, 0,
> +                                         &iview->planes[0].isl,
>                                           ISL_SURF_USAGE_TEXTURE_BIT,
>                                           state->attachments[i].input_
> aux_usage,
>                                           &clear_color,
> @@ -952,8 +994,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>                                           &state->attachments[i].input,
>                                           NULL);
>
> -            add_image_relocs(cmd_buffer, iview->image,
> -                             state->attachments[i].input);
> +            add_image_view_relocs(cmd_buffer, iview, 0,
> +                                  state->attachments[i].input);
>           }
>        }
>     }
> @@ -1378,14 +1420,21 @@ void genX(CmdPipelineBarrier)(
>           transition_depth_buffer(cmd_buffer, image,
>                                   pImageMemoryBarriers[i].oldLayout,
>                                   pImageMemoryBarriers[i].newLayout);
> -      } else if (range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
> -         transition_color_buffer(cmd_buffer, image,
> -                                 range->baseMipLevel,
> -                                 anv_get_levelCount(image, range),
> -                                 range->baseArrayLayer,
> -                                 anv_get_layerCount(image, range),
> -                                 pImageMemoryBarriers[i].oldLayout,
> -                                 pImageMemoryBarriers[i].newLayout);
> +      } else if (range->aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> +         VkImageAspectFlags color_aspects =
> +            anv_image_color_aspects(image, range->aspectMask);
> +         uint32_t aspect_bit, plane;
> +
> +         anv_foreach_plane_aspect_bit(plane, aspect_bit, color_aspects,
> +                                      image->aspects) {
> +            transition_color_buffer(cmd_buffer, image, plane,
> +                                    range->baseMipLevel,
> +                                    anv_get_levelCount(image, range),
> +                                    range->baseArrayLayer,
> +                                    anv_get_layerCount(image, range),
> +                                    pImageMemoryBarriers[i].oldLayout,
> +                                    pImageMemoryBarriers[i].newLayout);
> +         }
>        }
>     }
>
> @@ -1574,26 +1623,28 @@ emit_binding_table(struct anv_cmd_buffer
> *cmd_buffer,
>        case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
>           struct anv_surface_state sstate =
>              (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
> -            desc->image_view->general_sampler_surface_state :
> -            desc->image_view->optimal_sampler_surface_state;
> +            desc->image_view->planes[binding->plane].general_sampler_surface_state
> :
> +            desc->image_view->planes[binding->plane].optimal_
> sampler_surface_state;
>           surface_state = sstate.state;
>           assert(surface_state.alloc_size);
> -         add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> +         add_image_view_relocs(cmd_buffer, desc->image_view,
> +                               binding->plane, sstate);
>           break;
>        }
>        case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
>           assert(stage == MESA_SHADER_FRAGMENT);
> -         if (desc->image_view->aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT) {
> +         if ((desc->image_view->aspect_mask &
> VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0) {
>              /* For depth and stencil input attachments, we treat it like
> any
>               * old texture that a user may have bound.
>               */
>              struct anv_surface_state sstate =
>                 (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
> -               desc->image_view->general_sampler_surface_state :
> -               desc->image_view->optimal_sampler_surface_state;
> +               desc->image_view->planes[binding->plane].general_sampler_surface_state
> :
> +               desc->image_view->planes[binding->plane].optimal_
> sampler_surface_state;
>              surface_state = sstate.state;
>              assert(surface_state.alloc_size);
> -            add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> +            add_image_view_relocs(cmd_buffer, desc->image_view,
> +                                  binding->plane, sstate);
>           } else {
>              /* For color input attachments, we create the surface state at
>               * vkBeginRenderPass time so that we can include aux and clear
> @@ -1608,16 +1659,17 @@ emit_binding_table(struct anv_cmd_buffer
> *cmd_buffer,
>
>        case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
>           struct anv_surface_state sstate = (binding->write_only)
> -            ? desc->image_view->writeonly_storage_surface_state
> -            : desc->image_view->storage_surface_state;
> +            ? desc->image_view->planes[binding->plane].writeonly_
> storage_surface_state
> +            : desc->image_view->planes[binding->plane].storage_
> surface_state;
>           surface_state = sstate.state;
>           assert(surface_state.alloc_size);
> -         add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> +         add_image_view_relocs(cmd_buffer, desc->image_view,
> +                               binding->plane, sstate);
>
>           struct brw_image_param *image_param =
>              &cmd_buffer->state.push_constants[stage]->images[image++];
>
> -         *image_param = desc->image_view->storage_image_param;
> +         *image_param = desc->image_view->planes[
> binding->plane].storage_image_param;
>           image_param->surface_idx = bias + s;
>           break;
>        }
> @@ -2753,41 +2805,51 @@ cmd_buffer_emit_depth_stencil(struct
> anv_cmd_buffer *cmd_buffer)
>     };
>
>     if (iview)
> -      info.view = &iview->isl;
> +      info.view = &iview->planes[0].isl;
>
>     if (image && (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
> -      info.depth_surf = &image->depth_surface.isl;
> +      uint32_t depth_plane =
> +         anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_DEPTH_BIT);
> +      const struct anv_surface *surface = &image->planes[depth_plane].
> surface;
> +
> +      info.depth_surf = &surface->isl;
>
>        info.depth_address =
>           anv_batch_emit_reloc(&cmd_buffer->batch,
>                                dw + device->isl_dev.ds.depth_offset / 4,
> -                              image->bo,
> -                              image->offset +
> image->depth_surface.offset);
> +                              image->planes[depth_plane].bo,
> +                              image->planes[depth_plane].bo_offset +
> +                              surface->offset);
>
>        const uint32_t ds =
>           cmd_buffer->state.subpass->depth_stencil_attachment.attachment;
>        info.hiz_usage = cmd_buffer->state.attachments[ds].aux_usage;
>        if (info.hiz_usage == ISL_AUX_USAGE_HIZ) {
> -         info.hiz_surf = &image->aux_surface.isl;
> +         info.hiz_surf = &image->planes[depth_plane].aux_surface.isl;
>
>           info.hiz_address =
>              anv_batch_emit_reloc(&cmd_buffer->batch,
>                                   dw + device->isl_dev.ds.hiz_offset / 4,
> -                                 image->bo,
> -                                 image->offset +
> image->aux_surface.offset);
> +                                 image->planes[depth_plane].bo,
> +                                 image->planes[depth_plane].bo_offset +
> +                                 image->planes[depth_plane].
> aux_surface.offset);
>
>           info.depth_clear_value = ANV_HZ_FC_VAL;
>        }
>     }
>
>     if (image && (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {
> -      info.stencil_surf = &image->stencil_surface.isl;
> +      uint32_t stencil_plane =
> +         anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_STENCIL_BIT);
> +      const struct anv_surface *surface = &image->planes[stencil_plane].
> surface;
> +
> +      info.stencil_surf = &surface->isl;
>
>        info.stencil_address =
>           anv_batch_emit_reloc(&cmd_buffer->batch,
>                                dw + device->isl_dev.ds.stencil_offset / 4,
> -                              image->bo,
> -                              image->offset +
> image->stencil_surface.offset);
> +                              image->planes[stencil_plane].bo,
> +                              image->planes[stencil_plane].bo_offset +
> surface->offset);
>     }
>
>     isl_emit_depth_stencil_hiz_s(&device->isl_dev, dw, &info);
> @@ -2877,7 +2939,7 @@ cmd_buffer_subpass_transition_layouts(struct
> anv_cmd_buffer * const cmd_buffer,
>              att_state->input_aux_usage != att_state->aux_usage;
>        if (subpass_end) {
>           target_layout = att_desc->final_layout;
> -      } else if (iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT &&
> +      } else if (iview->aspect_mask & VK_IMAGE_ASPECT_ANY_COLOR_BIT &&
>                   !input_needs_resolve) {
>           /* Layout transitions before the final only help to enable
> sampling as
>            * an input attachment. If the input attachment supports sampling
> @@ -2895,12 +2957,12 @@ cmd_buffer_subpass_transition_layouts(struct
> anv_cmd_buffer * const cmd_buffer,
>                                   att_state->current_layout,
> target_layout);
>           att_state->aux_usage =
>              anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> -                                    image->aspects, target_layout);
> -      } else if (image->aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> -         transition_color_buffer(cmd_buffer, image,
> -                                 iview->isl.base_level, 1,
> -                                 iview->isl.base_array_layer,
> -                                 iview->isl.array_len,
> +                                    0, target_layout);
> +      } else if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> +         transition_color_buffer(cmd_buffer, image, 0,
> +                                 iview->planes[0].isl.base_level, 1,
> +                                 iview->planes[0].isl.base_array_layer,
> +                                 iview->planes[0].isl.array_len,
>                                   att_state->current_layout,
> target_layout);
>        }
>
> @@ -2945,22 +3007,24 @@ cmd_buffer_subpass_sync_fast_clear_values(struct
> anv_cmd_buffer *cmd_buffer)
>        if (att_state->pending_clear_aspects && att_state->fast_clear) {
>           /* Update the fast clear state entry. */
>           genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
> -                                      iview->image, iview->isl.base_level,
> +                                      iview->image, 0,
> iview->planes[0].isl.base_level,
>                                        true /* copy from ss */);
>
>           /* Fast-clears impact whether or not a resolve will be
> necessary. */
> -         if (iview->image->aux_usage == ISL_AUX_USAGE_CCS_E &&
> +         if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_CCS_E &&
>               att_state->clear_color_is_zero) {
>              /* This image always has the auxiliary buffer enabled. We can
> mark
>               * the subresource as not needing a resolve because the clear
> color
>               * will match what's in every RENDER_SURFACE_STATE object
> when it's
>               * being used for sampling.
>               */
> -            genX(set_image_needs_resolve)(cmd_buffer, iview->image,
> -                                          iview->isl.base_level, false);
> +            genX(set_image_needs_resolve)(cmd_buffer, iview->image, 0,
> +                                          iview->planes[0].isl.base_
> level,
> +                                          false);
>           } else {
> -            genX(set_image_needs_resolve)(cmd_buffer, iview->image,
> -                                          iview->isl.base_level, true);
> +            genX(set_image_needs_resolve)(cmd_buffer, iview->image, 0,
> +                                          iview->planes[0].isl.base_
> level,
> +                                          true);
>           }
>        } else if (rp_att->load_op == VK_ATTACHMENT_LOAD_OP_LOAD) {
>           /* The attachment may have been fast-cleared in a previous render
> @@ -2969,13 +3033,13 @@ cmd_buffer_subpass_sync_fast_clear_values(struct
> anv_cmd_buffer *cmd_buffer)
>            * TODO: Do this only once per render pass instead of every
> subpass.
>            */
>           genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
> -                                      iview->image, iview->isl.base_level,
> +                                      iview->image, 0,
> iview->planes[0].isl.base_level,
>                                        false /* copy to ss */);
>
>           if (need_input_attachment_state(rp_att) &&
>               att_state->input_aux_usage != ISL_AUX_USAGE_NONE) {
>              genX(copy_fast_clear_dwords)(cmd_buffer,
> att_state->input.state,
> -                                         iview->image,
> iview->isl.base_level,
> +                                         iview->image, 0,
> iview->planes[0].isl.base_level,
>                                           false /* copy to ss */);
>           }
>        }
> --
> 2.14.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20171003/8d4e7b4a/attachment-0001.html>


More information about the mesa-dev mailing list