anv/pipeline: Grow the param array for images
[mesa.git] / src / intel / vulkan / genX_cmd_buffer.c
index 67fc3f33df616208155fd789c1b40e9d75efa176..43437c8eb0f6b81d4d2a8c9e001f75be1078eba5 100644 (file)
@@ -179,34 +179,47 @@ add_surface_state_reloc(struct anv_cmd_buffer *cmd_buffer,
 }
 
 static void
-add_image_relocs(struct anv_cmd_buffer * const cmd_buffer,
-                 const struct anv_image * const image,
-                 const VkImageAspectFlags aspect_mask,
-                 const enum isl_aux_usage aux_usage,
-                 const struct anv_state state)
+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;
-   const uint32_t surf_offset = image->offset +
-      anv_image_get_surface_for_aspect_mask(image, aspect_mask)->offset;
 
-   add_surface_state_reloc(cmd_buffer, state, image->bo, surf_offset);
+   add_surface_state_reloc(cmd_buffer, state.state,
+                           image->planes[plane].bo, state.address);
 
-   if (aux_usage != ISL_AUX_USAGE_NONE) {
-      uint32_t aux_offset = image->offset + image->aux_surface.offset;
+   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[plane].bo,
+                            state.aux_address);
+      if (result != VK_SUCCESS)
+         anv_batch_set_error(&cmd_buffer->batch, result);
+   }
+}
 
-      /* On gen7 and prior, the bottom 12 bits of the MCS base address are
-       * used to store other information.  This should be ok, however, because
-       * surface buffer addresses are always 4K page alinged.
-       */
-      assert((aux_offset & 0xfff) == 0);
-      uint32_t *aux_addr_dw = state.map + isl_dev->ss.aux_addr_offset;
-      aux_offset += *aux_addr_dw & 0xfff;
+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.offset + isl_dev->ss.aux_addr_offset,
-                            image->bo, aux_offset);
+                            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);
    }
@@ -239,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, VK_IMAGE_ASPECT_COLOR_BIT,
+                            iview->planes[0].isl.base_level)) {
       /* There is no aux buffer which corresponds to the level and layer(s)
        * being accessed.
        */
@@ -248,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 {
@@ -269,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
@@ -288,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 &&
@@ -323,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, VK_IMAGE_ASPECT_COLOR_BIT,
+                               iview->planes[0].isl.base_level)) {
          att_state->fast_clear = false;
          if (GEN_GEN == 7) {
             anv_perf_warn(device->instance, iview->image,
@@ -339,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;
       }
 
@@ -384,15 +401,15 @@ 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,
-                              initial_layout);
+      anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
+                              VK_IMAGE_ASPECT_DEPTH_BIT, initial_layout);
    const bool enable_hiz = ISL_AUX_USAGE_HIZ ==
-      anv_layout_to_aux_usage(&cmd_buffer->device->info, image, image->aspects,
-                              final_layout);
+      anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
+                              VK_IMAGE_ASPECT_DEPTH_BIT, final_layout);
 
    enum blorp_hiz_op hiz_op;
    if (hiz_enabled && !enable_hiz) {
@@ -414,17 +431,23 @@ enum fast_clear_state_field {
    FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE,
 };
 
-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)
+static inline struct anv_address
+get_fast_clear_state_address(const struct anv_device *device,
+                             const struct anv_image *image,
+                             VkImageAspectFlagBits aspect,
+                             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, aspect));
+
+   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+
+   /* 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:
@@ -434,8 +457,12 @@ get_fast_clear_state_offset(const struct anv_device *device,
       break;
    }
 
-   assert(offset < image->offset + image->size);
-   return offset;
+   assert(offset < image->planes[plane].surface.offset + image->planes[plane].size);
+
+   return (struct anv_address) {
+      .bo = image->planes[plane].bo,
+      .offset = offset,
+   };
 }
 
 #define MI_PREDICATE_SRC0  0x2400
@@ -447,22 +474,23 @@ 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,
+                        VkImageAspectFlagBits aspect,
                         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, aspect));
 
-   const uint32_t resolve_flag_offset =
-      get_fast_clear_state_offset(cmd_buffer->device, image, level,
-                                  FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
+   const struct anv_address resolve_flag_addr =
+      get_fast_clear_state_address(cmd_buffer->device, image, aspect, level,
+                                   FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
 
    /* The HW docs say that there is no way to guarantee the completion of
     * the following command. We use it nevertheless because it shows no
     * 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 = resolve_flag_addr;
       sdi.ImmediateData = needs_resolve;
    }
 }
@@ -470,15 +498,16 @@ 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,
+                                   VkImageAspectFlagBits aspect,
                                    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, aspect));
 
-   const uint32_t resolve_flag_offset =
-      get_fast_clear_state_offset(cmd_buffer->device, image, level,
-                                  FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
+   const struct anv_address resolve_flag_addr =
+      get_fast_clear_state_address(cmd_buffer->device, image, aspect, level,
+                                   FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
 
    /* Make the pending predicated resolve a no-op if one is not needed.
     * predicate = do_resolve = resolve_flag != 0;
@@ -487,7 +516,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);
+            resolve_flag_addr.bo, resolve_flag_addr.offset);
    anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) {
       mip.LoadOperation    = LOAD_LOADINV;
       mip.CombineOperation = COMBINE_SET;
@@ -498,11 +527,15 @@ 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,
+                            VkImageAspectFlagBits aspect,
                             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, aspect));
+
+   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+   enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
 
    /* The resolve flag should updated to signify that fast-clear/compression
     * data needs to be removed when leaving the undefined layout. Such data
@@ -510,8 +543,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, aspect, level,
+                                 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.
@@ -527,14 +560,13 @@ init_fast_clear_state_entry(struct anv_cmd_buffer *cmd_buffer,
    unsigned i = 0;
    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,
-                                        FAST_CLEAR_STATE_FIELD_CLEAR_COLOR);
-         sdi.Address = (struct anv_address) { image->bo, entry_offset + i };
+         sdi.Address =
+            get_fast_clear_state_address(cmd_buffer->device, image, aspect, level,
+                                         FAST_CLEAR_STATE_FIELD_CLEAR_COLOR);
 
          if (GEN_GEN >= 9) {
             /* MCS buffers on SKL+ can only have 1/0 clear colors. */
-            assert(image->aux_usage == ISL_AUX_USAGE_MCS);
+            assert(aux_usage == ISL_AUX_USAGE_MCS);
             sdi.ImmediateData = 0;
          } else if (GEN_VERSIONx10 >= 75) {
             /* Pre-SKL, the dword containing the clear values also contains
@@ -564,28 +596,29 @@ static void
 genX(copy_fast_clear_dwords)(struct anv_cmd_buffer *cmd_buffer,
                              struct anv_state surface_state,
                              const struct anv_image *image,
+                             VkImageAspectFlagBits aspect,
                              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, aspect));
 
    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,
-                                  FAST_CLEAR_STATE_FIELD_CLEAR_COLOR);
+   const struct anv_address entry_addr =
+      get_fast_clear_state_address(cmd_buffer->device, image, aspect, 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, entry_addr.bo, entry_addr.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);
+                                 entry_addr.bo, entry_addr.offset, copy_size);
 
       /* Updating a surface state object may require that the state cache be
        * invalidated. From the SKL PRM, Shared Functions -> State -> State
@@ -617,6 +650,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,
+                        VkImageAspectFlagBits aspect,
                         const uint32_t base_level, uint32_t level_count,
                         uint32_t base_layer, uint32_t layer_count,
                         VkImageLayout initial_layout,
@@ -624,7 +658,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);
@@ -641,8 +675,28 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
    /* No work is necessary if the layout stays the same or if this subresource
     * range lacks auxiliary data.
     */
-   if (initial_layout == final_layout ||
-       base_layer >= anv_image_aux_layers(image, base_level))
+   if (initial_layout == final_layout)
+      return;
+
+   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+
+   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->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));
+      assert(plane == 0);
+      anv_image_copy_to_shadow(cmd_buffer, image,
+                               base_level, level_count,
+                               base_layer, layer_count);
+   }
+
+   if (base_layer >= anv_image_aux_layers(image, aspect, base_level))
       return;
 
    /* A transition of a 3D subresource works on all slices at a time. */
@@ -652,9 +706,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, aspect) - base_level);
    layer_count = MIN2(layer_count,
-                      anv_image_aux_layers(image, base_level) - base_layer);
+                      anv_image_aux_layers(image, aspect, base_level) - base_layer);
    last_level_num = base_level + level_count;
 
    /* Record whether or not the layout is undefined. Pre-initialized images
@@ -675,7 +729,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, aspect, 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
@@ -699,7 +753,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, aspect,
+                              base_level, level_count,
                               base_layer, layer_count);
       }
       /* At this point, some elements of the CCS buffer may have the fast-clear
@@ -711,7 +766,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.
@@ -763,44 +819,43 @@ 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, aspect, level));
       }
 
-      genX(load_needs_resolve_predicate)(cmd_buffer, image, level);
+      genX(load_needs_resolve_predicate)(cmd_buffer, image, aspect, level);
+
+      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.
        */
-      struct anv_state surface_state =
-         anv_cmd_buffer_alloc_surface_state(cmd_buffer);
-      isl_surf_fill_state(&cmd_buffer->device->isl_dev, surface_state.map,
-                          .surf = &image->color_surface.isl,
-                          .view = &(struct isl_view) {
-                              .usage = ISL_SURF_USAGE_RENDER_TARGET_BIT,
-                              .format = image->color_surface.isl.format,
-                              .swizzle = ISL_SWIZZLE_IDENTITY,
-                              .base_level = level,
-                              .levels = 1,
-                              .base_array_layer = base_layer,
-                              .array_len = layer_count,
-                           },
-                          .aux_surf = &image->aux_surface.isl,
-                          .aux_usage = image->aux_usage == ISL_AUX_USAGE_NONE ?
-                                       ISL_AUX_USAGE_CCS_D : image->aux_usage,
-                          .mocs = cmd_buffer->device->default_mocs);
-      add_image_relocs(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
-                       image->aux_usage == ISL_AUX_USAGE_CCS_E ?
-                       ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D,
-                       surface_state);
-      anv_state_flush(cmd_buffer->device, surface_state);
-      genX(copy_fast_clear_dwords)(cmd_buffer, surface_state, image, level,
-                                   false /* copy to ss */);
-      anv_ccs_resolve(cmd_buffer, surface_state, image, level, layer_count,
-                      image->aux_usage == ISL_AUX_USAGE_CCS_E ?
+      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,
+                                   &(struct isl_view) {
+                                      .format = image->planes[plane].surface.isl.format,
+                                      .swizzle = ISL_SWIZZLE_IDENTITY,
+                                      .base_level = level,
+                                      .levels = 1,
+                                      .base_array_layer = base_layer,
+                                      .array_len = layer_count,
+                                   },
+                                   ISL_SURF_USAGE_RENDER_TARGET_BIT,
+                                   aux_usage, NULL, 0,
+                                   &surface_state, NULL);
+      add_image_relocs(cmd_buffer, image, 0, surface_state);
+      genX(copy_fast_clear_dwords)(cmd_buffer, surface_state.state, image,
+                                   aspect, level, false /* copy to ss */);
+      anv_ccs_resolve(cmd_buffer, surface_state.state, image,
+                      aspect, 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, aspect, level, false);
    }
 
    cmd_buffer->state.pending_pipe_bits |=
@@ -858,13 +913,13 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
 
    for (uint32_t i = 0; i < pass->attachment_count; ++i) {
       if (vk_format_is_color(pass->attachments[i].format)) {
-         state->attachments[i].color_rt_state = next_state;
+         state->attachments[i].color.state = next_state;
          next_state.offset += ss_stride;
          next_state.map += ss_stride;
       }
 
       if (need_input_attachment_state(&pass->attachments[i])) {
-         state->attachments[i].input_att_state = next_state;
+         state->attachments[i].input.state = next_state;
          next_state.offset += ss_stride;
          next_state.map += ss_stride;
       }
@@ -886,7 +941,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;
@@ -910,28 +965,28 @@ 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) {
+            assert(att_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
             color_attachment_compute_aux_usage(cmd_buffer->device,
                                                state, i, begin->renderArea,
                                                &clear_color);
 
-            struct isl_view view = iview->isl;
-            view.usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
-            view.swizzle = anv_swizzle_for_render(view.swizzle);
-            isl_surf_fill_state(isl_dev,
-                                state->attachments[i].color_rt_state.map,
-                                .surf = &iview->image->color_surface.isl,
-                                .view = &view,
-                                .aux_surf = &iview->image->aux_surface.isl,
-                                .aux_usage = state->attachments[i].aux_usage,
-                                .clear_color = clear_color,
-                                .mocs = cmd_buffer->device->default_mocs);
-
-            add_image_relocs(cmd_buffer, iview->image, iview->aspect_mask,
-                             state->attachments[i].aux_usage,
-                             state->attachments[i].color_rt_state);
+            anv_image_fill_surface_state(cmd_buffer->device,
+                                         iview->image,
+                                         VK_IMAGE_ASPECT_COLOR_BIT,
+                                         &iview->planes[0].isl,
+                                         ISL_SURF_USAGE_RENDER_TARGET_BIT,
+                                         state->attachments[i].aux_usage,
+                                         &clear_color,
+                                         0,
+                                         &state->attachments[i].color,
+                                         NULL);
+
+            add_image_view_relocs(cmd_buffer, iview, 0,
+                                  state->attachments[i].color);
          } else {
             /* This field will be initialized after the first subpass
              * transition.
@@ -942,24 +997,21 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
          }
 
          if (need_input_attachment_state(&pass->attachments[i])) {
-            struct isl_view view = iview->isl;
-            view.usage |= ISL_SURF_USAGE_TEXTURE_BIT;
-            isl_surf_fill_state(isl_dev,
-                                state->attachments[i].input_att_state.map,
-                                .surf = &iview->image->color_surface.isl,
-                                .view = &view,
-                                .aux_surf = &iview->image->aux_surface.isl,
-                                .aux_usage = state->attachments[i].input_aux_usage,
-                                .clear_color = clear_color,
-                                .mocs = cmd_buffer->device->default_mocs);
-
-            add_image_relocs(cmd_buffer, iview->image, iview->aspect_mask,
-                             state->attachments[i].input_aux_usage,
-                             state->attachments[i].input_att_state);
+            anv_image_fill_surface_state(cmd_buffer->device,
+                                         iview->image,
+                                         VK_IMAGE_ASPECT_COLOR_BIT,
+                                         &iview->planes[0].isl,
+                                         ISL_SURF_USAGE_TEXTURE_BIT,
+                                         state->attachments[i].input_aux_usage,
+                                         &clear_color,
+                                         0,
+                                         &state->attachments[i].input,
+                                         NULL);
+
+            add_image_view_relocs(cmd_buffer, iview, 0,
+                                  state->attachments[i].input);
          }
       }
-
-      anv_state_flush(cmd_buffer->device, state->render_pass_states);
    }
 
    return VK_SUCCESS;
@@ -1010,6 +1062,7 @@ genX(BeginCommandBuffer)(
    VkResult result = VK_SUCCESS;
    if (cmd_buffer->usage_flags &
        VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
+      assert(pBeginInfo->pInheritanceInfo);
       cmd_buffer->state.pass =
          anv_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass);
       cmd_buffer->state.subpass =
@@ -1381,14 +1434,20 @@ 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_expand_aspects(image, range->aspectMask);
+         uint32_t aspect_bit;
+
+         anv_foreach_image_aspect_bit(aspect_bit, image, color_aspects) {
+            transition_color_buffer(cmd_buffer, image, 1UL << aspect_bit,
+                                    range->baseMipLevel,
+                                    anv_get_levelCount(image, range),
+                                    range->baseArrayLayer,
+                                    anv_get_layerCount(image, range),
+                                    pImageMemoryBarriers[i].oldLayout,
+                                    pImageMemoryBarriers[i].newLayout);
+         }
       }
    }
 
@@ -1555,7 +1614,7 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
             if (att == VK_ATTACHMENT_UNUSED) {
                surface_state = cmd_buffer->state.null_surface_state;
             } else {
-               surface_state = cmd_buffer->state.attachments[att].color_rt_state;
+               surface_state = cmd_buffer->state.attachments[att].color.state;
             }
          } else {
             surface_state = cmd_buffer->state.null_surface_state;
@@ -1577,38 +1636,30 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
 
       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
-         enum isl_aux_usage aux_usage;
-         if (desc->layout == VK_IMAGE_LAYOUT_GENERAL) {
-            surface_state = desc->image_view->general_sampler_surface_state;
-            aux_usage = desc->image_view->general_sampler_aux_usage;
-         } else {
-            surface_state = desc->image_view->optimal_sampler_surface_state;
-            aux_usage = desc->image_view->optimal_sampler_aux_usage;
-         }
+         struct anv_surface_state sstate =
+            (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
+            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,
-                          desc->image_view->aspect_mask,
-                          aux_usage, surface_state);
+         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.
              */
-            enum isl_aux_usage aux_usage;
-            if (desc->layout == VK_IMAGE_LAYOUT_GENERAL) {
-               surface_state = desc->image_view->general_sampler_surface_state;
-               aux_usage = desc->image_view->general_sampler_aux_usage;
-            } else {
-               surface_state = desc->image_view->optimal_sampler_surface_state;
-               aux_usage = desc->image_view->optimal_sampler_aux_usage;
-            }
+            struct anv_surface_state sstate =
+               (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
+               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,
-                             desc->image_view->aspect_mask,
-                             aux_usage, surface_state);
+            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
@@ -1617,23 +1668,23 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
             assert(binding->input_attachment_index < subpass->input_count);
             const unsigned subpass_att = binding->input_attachment_index;
             const unsigned att = subpass->input_attachments[subpass_att].attachment;
-            surface_state = cmd_buffer->state.attachments[att].input_att_state;
+            surface_state = cmd_buffer->state.attachments[att].input.state;
          }
          break;
 
       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
-         surface_state = (binding->write_only)
-            ? desc->image_view->writeonly_storage_surface_state
-            : desc->image_view->storage_surface_state;
+         struct anv_surface_state sstate = (binding->write_only)
+            ? 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,
-                          desc->image_view->aspect_mask,
-                          desc->image_view->image->aux_usage, surface_state);
+         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;
       }
@@ -1756,7 +1807,7 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer,
          continue;
 
       memcpy(state->map + (s * 16),
-             sampler->state, sizeof(sampler->state));
+             sampler->state[binding->plane], sizeof(sampler->state[0]));
    }
 
    anv_state_flush(cmd_buffer->device, *state);
@@ -2492,7 +2543,8 @@ verify_cmd_parser(const struct anv_device *device,
                   const char *function)
 {
    if (device->instance->physicalDevice.cmd_parser_version < required_version) {
-      return vk_errorf(VK_ERROR_FEATURE_NOT_PRESENT,
+      return vk_errorf(device->instance, device->instance,
+                       VK_ERROR_FEATURE_NOT_PRESENT,
                        "cmd parser version %d is required for %s",
                        required_version, function);
    } else {
@@ -2761,41 +2813,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);
@@ -2885,7 +2947,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
@@ -2903,12 +2965,13 @@ 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,
+                                    VK_IMAGE_ASPECT_DEPTH_BIT, target_layout);
+      } else if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
+         assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+         transition_color_buffer(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
+                                 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);
       }
 
@@ -2933,10 +2996,11 @@ cmd_buffer_subpass_sync_fast_clear_values(struct anv_cmd_buffer *cmd_buffer)
        * render pass and used in the subpass.
        */
       const uint32_t a = state->subpass->color_attachments[i].attachment;
-      assert(a < state->pass->attachment_count);
       if (a == VK_ATTACHMENT_UNUSED)
          continue;
 
+      assert(a < state->pass->attachment_count);
+
       /* Store some information regarding this attachment. */
       const struct anv_attachment_state *att_state = &state->attachments[a];
       const struct anv_image_view *iview = state->framebuffer->attachments[a];
@@ -2952,12 +3016,14 @@ 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_rt_state,
-                                      iview->image, iview->isl.base_level,
+         genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
+                                      iview->image,
+                                      VK_IMAGE_ASPECT_COLOR_BIT,
+                                      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
@@ -2965,10 +3031,14 @@ cmd_buffer_subpass_sync_fast_clear_values(struct anv_cmd_buffer *cmd_buffer)
              * being used for sampling.
              */
             genX(set_image_needs_resolve)(cmd_buffer, iview->image,
-                                          iview->isl.base_level, false);
+                                          VK_IMAGE_ASPECT_COLOR_BIT,
+                                          iview->planes[0].isl.base_level,
+                                          false);
          } else {
             genX(set_image_needs_resolve)(cmd_buffer, iview->image,
-                                          iview->isl.base_level, true);
+                                          VK_IMAGE_ASPECT_COLOR_BIT,
+                                          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
@@ -2976,14 +3046,18 @@ 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_rt_state,
-                                      iview->image, iview->isl.base_level,
+         genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
+                                      iview->image,
+                                      VK_IMAGE_ASPECT_COLOR_BIT,
+                                      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_att_state,
-                                         iview->image, iview->isl.base_level,
+            genX(copy_fast_clear_dwords)(cmd_buffer, att_state->input.state,
+                                         iview->image,
+                                         VK_IMAGE_ASPECT_COLOR_BIT,
+                                         iview->planes[0].isl.base_level,
                                          false /* copy to ss */);
          }
       }