amd/common: add declare_vs_input_vgprs() helper
[mesa.git] / src / amd / vulkan / radv_image.c
index 8d3ff1a515ea416ac7d8308ee22c02dbb0d1e932..b1c4f3340eddd75011e1db77cd34fc0ec46278a2 100644 (file)
@@ -25,6 +25,7 @@
  * IN THE SOFTWARE.
  */
 
+#include "radv_debug.h"
 #include "radv_private.h"
 #include "vk_format.h"
 #include "vk_util.h"
@@ -34,7 +35,7 @@
 #include "util/debug.h"
 #include "util/u_atomic.h"
 static unsigned
-radv_choose_tiling(struct radv_device *Device,
+radv_choose_tiling(struct radv_device *device,
                   const struct radv_image_create_info *create_info)
 {
        const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
@@ -44,12 +45,17 @@ radv_choose_tiling(struct radv_device *Device,
                return RADEON_SURF_MODE_LINEAR_ALIGNED;
        }
 
-       /* Textures with a very small height are recommended to be linear. */
-       if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D ||
-           /* Only very thin and long 2D textures should benefit from
-            * linear_aligned. */
-           (pCreateInfo->extent.width > 8 && pCreateInfo->extent.height <= 2))
-               return RADEON_SURF_MODE_LINEAR_ALIGNED;
+       if (!vk_format_is_compressed(pCreateInfo->format) &&
+           !vk_format_is_depth_or_stencil(pCreateInfo->format)
+           && device->physical_device->rad_info.chip_class <= VI) {
+               /* this causes hangs in some VK CTS tests on GFX9. */
+               /* Textures with a very small height are recommended to be linear. */
+               if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D ||
+                   /* Only very thin and long 2D textures should benefit from
+                    * linear_aligned. */
+                   (pCreateInfo->extent.width > 8 && pCreateInfo->extent.height <= 2))
+                       return RADEON_SURF_MODE_LINEAR_ALIGNED;
+       }
 
        /* MSAA resources must be 2D tiled. */
        if (pCreateInfo->samples > 1)
@@ -103,6 +109,17 @@ radv_init_surface(struct radv_device *device,
 
        if (is_depth) {
                surface->flags |= RADEON_SURF_ZBUFFER;
+               if (!(pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
+                   !(pCreateInfo->flags & (VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
+                                           VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR)) &&
+                   pCreateInfo->tiling != VK_IMAGE_TILING_LINEAR &&
+                   pCreateInfo->mipLevels <= 1 &&
+                   device->physical_device->rad_info.chip_class >= VI &&
+                   ((pCreateInfo->format == VK_FORMAT_D32_SFLOAT ||
+                     pCreateInfo->format == VK_FORMAT_D32_SFLOAT_S8_UINT) ||
+                    (device->physical_device->rad_info.chip_class >= GFX9 &&
+                     pCreateInfo->format == VK_FORMAT_D16_UNORM)))
+                       surface->flags |= RADEON_SURF_TC_COMPATIBLE_HTILE;
        }
 
        if (is_stencil)
@@ -110,19 +127,42 @@ radv_init_surface(struct radv_device *device,
 
        surface->flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE;
 
+       bool dcc_compatible_formats = radv_is_colorbuffer_format_supported(pCreateInfo->format, &blendable);
+       if (pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
+               const struct  VkImageFormatListCreateInfoKHR *format_list =
+                         (const struct  VkImageFormatListCreateInfoKHR *)
+                               vk_find_struct_const(pCreateInfo->pNext,
+                                                    IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
+
+               /* We have to ignore the existence of the list if viewFormatCount = 0 */
+               if (format_list && format_list->viewFormatCount) {
+                       /* compatibility is transitive, so we only need to check
+                        * one format with everything else. */
+                       for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {
+                               if (!radv_dcc_formats_compatible(pCreateInfo->format,
+                                                                format_list->pViewFormats[i]))
+                                       dcc_compatible_formats = false;
+                       }
+               } else {
+                       dcc_compatible_formats = false;
+               }
+       }
+
        if ((pCreateInfo->usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                   VK_IMAGE_USAGE_STORAGE_BIT)) ||
-           (pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) ||
+           (pCreateInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR) ||
+           !dcc_compatible_formats ||
             (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) ||
+            pCreateInfo->mipLevels > 1 || pCreateInfo->arrayLayers > 1 ||
             device->physical_device->rad_info.chip_class < VI ||
-            create_info->scanout || (device->debug_flags & RADV_DEBUG_NO_DCC) ||
-            !radv_is_colorbuffer_format_supported(pCreateInfo->format, &blendable))
+            create_info->scanout || (device->instance->debug_flags & RADV_DEBUG_NO_DCC) ||
+           pCreateInfo->samples >= 2)
                surface->flags |= RADEON_SURF_DISABLE_DCC;
        if (create_info->scanout)
                surface->flags |= RADEON_SURF_SCANOUT;
        return 0;
 }
-#define ATI_VENDOR_ID 0x1002
+
 static uint32_t si_get_bo_metadata_word1(struct radv_device *device)
 {
        return (ATI_VENDOR_ID << 16) | device->physical_device->rad_info.pci_id;
@@ -165,7 +205,7 @@ radv_make_buffer_descriptor(struct radv_device *device,
 {
        const struct vk_format_description *desc;
        unsigned stride;
-       uint64_t gpu_address = device->ws->buffer_get_va(buffer->bo);
+       uint64_t gpu_address = radv_buffer_get_va(buffer->bo);
        uint64_t va = gpu_address + buffer->offset;
        unsigned num_format, data_format;
        int first_non_void;
@@ -181,7 +221,7 @@ radv_make_buffer_descriptor(struct radv_device *device,
        state[1] = S_008F04_BASE_ADDRESS_HI(va >> 32) |
                S_008F04_STRIDE(stride);
 
-       if (device->physical_device->rad_info.chip_class < VI && stride) {
+       if (device->physical_device->rad_info.chip_class != VI && stride) {
                range /= stride;
        }
 
@@ -202,7 +242,7 @@ si_set_mutable_tex_desc_fields(struct radv_device *device,
                               unsigned block_width, bool is_stencil,
                               uint32_t *state)
 {
-       uint64_t gpu_address = image->bo ? device->ws->buffer_get_va(image->bo) + image->offset : 0;
+       uint64_t gpu_address = image->bo ? radv_buffer_get_va(image->bo) + image->offset : 0;
        uint64_t va = gpu_address;
        enum chip_class chip_class = device->physical_device->rad_info.chip_class;
        uint64_t meta_va = 0;
@@ -215,23 +255,27 @@ si_set_mutable_tex_desc_fields(struct radv_device *device,
                va += base_level_info->offset;
 
        state[0] = va >> 8;
-       if (chip_class < GFX9)
-               if (base_level_info->mode == RADEON_SURF_MODE_2D)
-                       state[0] |= image->surface.tile_swizzle;
+       if (chip_class >= GFX9 ||
+           base_level_info->mode == RADEON_SURF_MODE_2D)
+               state[0] |= image->surface.tile_swizzle;
        state[1] &= C_008F14_BASE_ADDRESS_HI;
        state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);
 
        if (chip_class >= VI) {
                state[6] &= C_008F28_COMPRESSION_EN;
                state[7] = 0;
-               if (image->surface.dcc_size && first_level < image->surface.num_dcc_levels) {
+               if (radv_vi_dcc_enabled(image, first_level)) {
                        meta_va = gpu_address + image->dcc_offset;
                        if (chip_class <= VI)
                                meta_va += base_level_info->dcc_offset;
+               } else if(image->tc_compatible_htile && image->surface.htile_size) {
+                       meta_va = gpu_address + image->htile_offset;
+               }
+
+               if (meta_va) {
                        state[6] |= S_008F28_COMPRESSION_EN(1);
                        state[7] = meta_va >> 8;
-                       if (chip_class < GFX9)
-                               state[7] |= image->surface.tile_swizzle;
+                       state[7] |= image->surface.tile_swizzle;
                }
        }
 
@@ -275,10 +319,14 @@ si_set_mutable_tex_desc_fields(struct radv_device *device,
 }
 
 static unsigned radv_tex_dim(VkImageType image_type, VkImageViewType view_type,
-                            unsigned nr_layers, unsigned nr_samples, bool is_storage_image)
+                            unsigned nr_layers, unsigned nr_samples, bool is_storage_image, bool gfx9)
 {
        if (view_type == VK_IMAGE_VIEW_TYPE_CUBE || view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
                return is_storage_image ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_CUBE;
+
+       /* GFX9 allocates 1D textures as 2D. */
+       if (gfx9 && image_type == VK_IMAGE_TYPE_1D)
+               image_type = VK_IMAGE_TYPE_2D;
        switch (image_type) {
        case VK_IMAGE_TYPE_1D:
                return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_1D_ARRAY : V_008F1C_SQ_RSRC_IMG_1D;
@@ -368,8 +416,14 @@ si_make_texture_descriptor(struct radv_device *device,
                data_format = 0;
        }
 
+       /* S8 with Z32 HTILE needs a special format. */
+       if (device->physical_device->rad_info.chip_class >= GFX9 &&
+           vk_format == VK_FORMAT_S8_UINT &&
+           image->tc_compatible_htile)
+               data_format = V_008F14_IMG_DATA_FORMAT_S8_32;
+
        type = radv_tex_dim(image->type, view_type, image->info.array_size, image->info.samples,
-                           is_storage_image);
+                           is_storage_image, device->physical_device->rad_info.chip_class >= GFX9);
        if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
                height = 1;
                depth = image->info.array_size;
@@ -415,7 +469,7 @@ si_make_texture_descriptor(struct radv_device *device,
                state[4] |= S_008F20_BC_SWIZZLE(bc_swizzle);
                state[5] |= S_008F24_MAX_MIP(image->info.samples > 1 ?
                                             util_logbase2(image->info.samples) :
-                                            last_level);
+                                            image->info.levels - 1);
        } else {
                state[3] |= S_008F1C_POW2_PAD(image->info.levels > 1);
                state[4] |= S_008F20_DEPTH(depth - 1);
@@ -440,7 +494,7 @@ si_make_texture_descriptor(struct radv_device *device,
        /* Initialize the sampler view for FMASK. */
        if (image->fmask.size) {
                uint32_t fmask_format, num_format;
-               uint64_t gpu_address = device->ws->buffer_get_va(image->bo);
+               uint64_t gpu_address = radv_buffer_get_va(image->bo);
                uint64_t va;
 
                va = gpu_address + image->offset + image->fmask.offset;
@@ -479,8 +533,7 @@ si_make_texture_descriptor(struct radv_device *device,
                }
 
                fmask_state[0] = va >> 8;
-               if (device->physical_device->rad_info.chip_class < GFX9)
-                       fmask_state[0] |= image->fmask.tile_swizzle;
+               fmask_state[0] |= image->fmask.tile_swizzle;
                fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
                        S_008F14_DATA_FORMAT_GFX6(fmask_format) |
                        S_008F14_NUM_FORMAT_GFX6(num_format);
@@ -490,7 +543,7 @@ si_make_texture_descriptor(struct radv_device *device,
                        S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
                        S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
                        S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
-                       S_008F1C_TYPE(radv_tex_dim(image->type, view_type, 1, 0, false));
+                       S_008F1C_TYPE(radv_tex_dim(image->type, view_type, 1, 0, false, false));
                fmask_state[4] = 0;
                fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);
                fmask_state[6] = 0;
@@ -555,10 +608,11 @@ radv_query_opaque_metadata(struct radv_device *device,
        memcpy(&md->metadata[2], desc, sizeof(desc));
 
        /* Dwords [10:..] contain the mipmap level offsets. */
-       for (i = 0; i <= image->info.levels - 1; i++)
-               md->metadata[10+i] = image->surface.u.legacy.level[i].offset >> 8;
-
-       md->size_metadata = (11 + image->info.levels - 1) * 4;
+       if (device->physical_device->rad_info.chip_class <= VI) {
+               for (i = 0; i <= image->info.levels - 1; i++)
+                       md->metadata[10+i] = image->surface.u.legacy.level[i].offset >> 8;
+               md->size_metadata = (11 + image->info.levels - 1) * 4;
+       }
 }
 
 void
@@ -734,8 +788,7 @@ radv_image_alloc_cmask(struct radv_device *device,
 }
 
 static void
-radv_image_alloc_dcc(struct radv_device *device,
-                      struct radv_image *image)
+radv_image_alloc_dcc(struct radv_image *image)
 {
        image->dcc_offset = align64(image->size, image->surface.dcc_alignment);
        /* + 16 for storing the clear values + dcc pred */
@@ -746,14 +799,8 @@ radv_image_alloc_dcc(struct radv_device *device,
 }
 
 static void
-radv_image_alloc_htile(struct radv_device *device,
-                      struct radv_image *image)
+radv_image_alloc_htile(struct radv_image *image)
 {
-       if ((device->debug_flags & RADV_DEBUG_NO_HIZ) || image->info.levels > 1) {
-               image->surface.htile_size = 0;
-               return;
-       }
-
        image->htile_offset = align64(image->size, image->surface.htile_alignment);
 
        /* + 8 for storing the clear values */
@@ -762,6 +809,59 @@ radv_image_alloc_htile(struct radv_device *device,
        image->alignment = align64(image->alignment, image->surface.htile_alignment);
 }
 
+static inline bool
+radv_image_can_enable_dcc_or_cmask(struct radv_image *image)
+{
+       if (image->info.samples <= 1 &&
+           image->info.width * image->info.height <= 512 * 512) {
+               /* Do not enable CMASK or DCC for small surfaces where the cost
+                * of the eliminate pass can be higher than the benefit of fast
+                * clear. RadeonSI does this, but the image threshold is
+                * different.
+                */
+               return false;
+       }
+
+       return image->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT &&
+              (image->exclusive || image->queue_family_mask == 1);
+}
+
+static inline bool
+radv_image_can_enable_dcc(struct radv_image *image)
+{
+       return radv_image_can_enable_dcc_or_cmask(image) &&
+              image->surface.dcc_size;
+}
+
+static inline bool
+radv_image_can_enable_cmask(struct radv_image *image)
+{
+       if (image->surface.bpe > 8 && image->info.samples == 1) {
+               /* Do not enable CMASK for non-MSAA images (fast color clear)
+                * because 128 bit formats are not supported, but FMASK might
+                * still be used.
+                */
+               return false;
+       }
+
+       return radv_image_can_enable_dcc_or_cmask(image) &&
+              image->info.levels == 1 &&
+              image->info.depth == 1 &&
+              !image->surface.is_linear;
+}
+
+static inline bool
+radv_image_can_enable_fmask(struct radv_image *image)
+{
+       return image->info.samples > 1 && vk_format_is_color(image->vk_format);
+}
+
+static inline bool
+radv_image_can_enable_htile(struct radv_image *image)
+{
+       return image->info.levels == 1 && vk_format_is_depth(image->vk_format);
+}
+
 VkResult
 radv_image_create(VkDevice _device,
                  const struct radv_image_create_info *create_info,
@@ -771,7 +871,6 @@ radv_image_create(VkDevice _device,
        RADV_FROM_HANDLE(radv_device, device, _device);
        const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
        struct radv_image *image = NULL;
-       bool can_cmask_dcc = false;
        assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
 
        radv_assert(pCreateInfo->mipLevels > 0);
@@ -781,12 +880,11 @@ radv_image_create(VkDevice _device,
        radv_assert(pCreateInfo->extent.height > 0);
        radv_assert(pCreateInfo->extent.depth > 0);
 
-       image = vk_alloc2(&device->alloc, alloc, sizeof(*image), 8,
-                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
+                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        if (!image)
                return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-       memset(image, 0, sizeof(*image));
        image->type = pCreateInfo->imageType;
        image->info.width = pCreateInfo->extent.width;
        image->info.height = pCreateInfo->extent.height;
@@ -822,24 +920,29 @@ radv_image_create(VkDevice _device,
        image->size = image->surface.surf_size;
        image->alignment = image->surface.surf_alignment;
 
-       if (image->exclusive || image->queue_family_mask == 1)
-               can_cmask_dcc = true;
-
-       if ((pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
-           image->surface.dcc_size && can_cmask_dcc)
-               radv_image_alloc_dcc(device, image);
-       else
+       /* Try to enable DCC first. */
+       if (radv_image_can_enable_dcc(image)) {
+               radv_image_alloc_dcc(image);
+       } else {
+               /* When DCC cannot be enabled, try CMASK. */
                image->surface.dcc_size = 0;
+               if (radv_image_can_enable_cmask(image)) {
+                       radv_image_alloc_cmask(device, image);
+               }
+       }
 
-       if ((pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
-           pCreateInfo->mipLevels == 1 &&
-           !image->surface.dcc_size && image->info.depth == 1 && can_cmask_dcc)
-               radv_image_alloc_cmask(device, image);
-       if (image->info.samples > 1 && vk_format_is_color(pCreateInfo->format)) {
+       /* Try to enable FMASK for multisampled images. */
+       if (radv_image_can_enable_fmask(image)) {
                radv_image_alloc_fmask(device, image);
-       } else if (vk_format_is_depth(pCreateInfo->format)) {
-
-               radv_image_alloc_htile(device, image);
+       } else {
+               /* Otherwise, try to enable HTILE for depth surfaces. */
+               if (radv_image_can_enable_htile(image) &&
+                   !(device->instance->debug_flags & RADV_DEBUG_NO_HIZ)) {
+                       radv_image_alloc_htile(image);
+                       image->tc_compatible_htile = image->surface.flags & RADEON_SURF_TC_COMPATIBLE_HTILE;
+               } else {
+                       image->surface.htile_size = 0;
+               }
        }
 
        if (pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
@@ -863,44 +966,50 @@ radv_image_create(VkDevice _device,
 static void
 radv_image_view_make_descriptor(struct radv_image_view *iview,
                                struct radv_device *device,
-                               const VkImageViewCreateInfo* pCreateInfo,
+                               const VkComponentMapping *components,
                                bool is_storage_image)
 {
-       RADV_FROM_HANDLE(radv_image, image, pCreateInfo->image);
-       const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
+       struct radv_image *image = iview->image;
        bool is_stencil = iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT;
        uint32_t blk_w;
        uint32_t *descriptor;
-       uint32_t *fmask_descriptor;
+       uint32_t hw_level = 0;
 
        if (is_storage_image) {
                descriptor = iview->storage_descriptor;
-               fmask_descriptor = iview->storage_fmask_descriptor;
        } else {
                descriptor = iview->descriptor;
-               fmask_descriptor = iview->fmask_descriptor;
        }
 
        assert(image->surface.blk_w % vk_format_get_blockwidth(image->vk_format) == 0);
        blk_w = image->surface.blk_w / vk_format_get_blockwidth(image->vk_format) * vk_format_get_blockwidth(iview->vk_format);
 
+       if (device->physical_device->rad_info.chip_class >= GFX9)
+               hw_level = iview->base_mip;
        si_make_texture_descriptor(device, image, is_storage_image,
                                   iview->type,
                                   iview->vk_format,
-                                  &pCreateInfo->components,
-                                  0, radv_get_levelCount(image, range) - 1,
-                                  range->baseArrayLayer,
-                                  range->baseArrayLayer + radv_get_layerCount(image, range) - 1,
+                                  components,
+                                  hw_level, hw_level + iview->level_count - 1,
+                                  iview->base_layer,
+                                  iview->base_layer + iview->layer_count - 1,
                                   iview->extent.width,
                                   iview->extent.height,
                                   iview->extent.depth,
                                   descriptor,
-                                  fmask_descriptor);
+                                  descriptor + 8);
+
+       const struct legacy_surf_level *base_level_info = NULL;
+       if (device->physical_device->rad_info.chip_class <= GFX9) {
+               if (is_stencil)
+                       base_level_info = &image->surface.u.legacy.stencil_level[iview->base_mip];
+               else
+                       base_level_info = &image->surface.u.legacy.level[iview->base_mip];
+       }
        si_set_mutable_tex_desc_fields(device, image,
-                                      is_stencil ? &image->surface.u.legacy.stencil_level[range->baseMipLevel]
-                                                 : &image->surface.u.legacy.level[range->baseMipLevel],
-                                      range->baseMipLevel,
-                                      range->baseMipLevel,
+                                      base_level_info,
+                                      iview->base_mip,
+                                      iview->base_mip,
                                       blk_w, is_stencil, descriptor);
 }
 
@@ -936,29 +1045,43 @@ radv_image_view_init(struct radv_image_view *iview,
                iview->vk_format = vk_format_depth_only(iview->vk_format);
        }
 
-       iview->extent = (VkExtent3D) {
-               .width  = radv_minify(image->info.width , range->baseMipLevel),
-               .height = radv_minify(image->info.height, range->baseMipLevel),
-               .depth  = radv_minify(image->info.depth , range->baseMipLevel),
-       };
+       if (device->physical_device->rad_info.chip_class >= GFX9) {
+               iview->extent = (VkExtent3D) {
+                       .width = image->info.width,
+                       .height = image->info.height,
+                       .depth = image->info.depth,
+               };
+       } else {
+               iview->extent = (VkExtent3D) {
+                       .width  = radv_minify(image->info.width , range->baseMipLevel),
+                       .height = radv_minify(image->info.height, range->baseMipLevel),
+                       .depth  = radv_minify(image->info.depth , range->baseMipLevel),
+               };
+       }
 
-       iview->extent.width = round_up_u32(iview->extent.width * vk_format_get_blockwidth(iview->vk_format),
-                                          vk_format_get_blockwidth(image->vk_format));
-       iview->extent.height = round_up_u32(iview->extent.height * vk_format_get_blockheight(iview->vk_format),
-                                           vk_format_get_blockheight(image->vk_format));
+       if (iview->vk_format != image->vk_format) {
+               iview->extent.width = round_up_u32(iview->extent.width * vk_format_get_blockwidth(iview->vk_format),
+                                                  vk_format_get_blockwidth(image->vk_format));
+               iview->extent.height = round_up_u32(iview->extent.height * vk_format_get_blockheight(iview->vk_format),
+                                                   vk_format_get_blockheight(image->vk_format));
+       }
 
        iview->base_layer = range->baseArrayLayer;
        iview->layer_count = radv_get_layerCount(image, range);
        iview->base_mip = range->baseMipLevel;
+       iview->level_count = radv_get_levelCount(image, range);
 
-       radv_image_view_make_descriptor(iview, device, pCreateInfo, false);
-       radv_image_view_make_descriptor(iview, device, pCreateInfo, true);
+       radv_image_view_make_descriptor(iview, device, &pCreateInfo->components, false);
+       radv_image_view_make_descriptor(iview, device, &pCreateInfo->components, true);
 }
 
 bool radv_layout_has_htile(const struct radv_image *image,
                            VkImageLayout layout,
                            unsigned queue_mask)
 {
+       if (image->surface.htile_size && image->tc_compatible_htile)
+               return layout != VK_IMAGE_LAYOUT_GENERAL;
+
        return image->surface.htile_size &&
               (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
                layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) &&
@@ -969,6 +1092,9 @@ bool radv_layout_is_htile_compressed(const struct radv_image *image,
                                      VkImageLayout layout,
                                      unsigned queue_mask)
 {
+       if (image->surface.htile_size && image->tc_compatible_htile)
+               return layout != VK_IMAGE_LAYOUT_GENERAL;
+
        return image->surface.htile_size &&
               (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
                layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) &&
@@ -1001,11 +1127,15 @@ radv_CreateImage(VkDevice device,
                 const VkAllocationCallbacks *pAllocator,
                 VkImage *pImage)
 {
+       const struct wsi_image_create_info *wsi_info =
+               vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+       bool scanout = wsi_info && wsi_info->scanout;
+
        return radv_image_create(device,
                                 &(struct radv_image_create_info) {
                                         .vk_info = pCreateInfo,
-                                                .scanout = false,
-                                                },
+                                        .scanout = scanout,
+                                },
                                 pAllocator,
                                 pImage);
 }
@@ -1027,23 +1157,34 @@ radv_DestroyImage(VkDevice _device, VkImage _image,
 }
 
 void radv_GetImageSubresourceLayout(
-       VkDevice                                    device,
+       VkDevice                                    _device,
        VkImage                                     _image,
        const VkImageSubresource*                   pSubresource,
        VkSubresourceLayout*                        pLayout)
 {
        RADV_FROM_HANDLE(radv_image, image, _image);
+       RADV_FROM_HANDLE(radv_device, device, _device);
        int level = pSubresource->mipLevel;
        int layer = pSubresource->arrayLayer;
        struct radeon_surf *surface = &image->surface;
 
-       pLayout->offset = surface->u.legacy.level[level].offset + surface->u.legacy.level[level].slice_size * layer;
-       pLayout->rowPitch = surface->u.legacy.level[level].nblk_x * surface->bpe;
-       pLayout->arrayPitch = surface->u.legacy.level[level].slice_size;
-       pLayout->depthPitch = surface->u.legacy.level[level].slice_size;
-       pLayout->size = surface->u.legacy.level[level].slice_size;
-       if (image->type == VK_IMAGE_TYPE_3D)
-               pLayout->size *= u_minify(image->info.depth, level);
+       if (device->physical_device->rad_info.chip_class >= GFX9) {
+               pLayout->offset = surface->u.gfx9.offset[level] + surface->u.gfx9.surf_slice_size * layer;
+               pLayout->rowPitch = surface->u.gfx9.surf_pitch * surface->bpe;
+               pLayout->arrayPitch = surface->u.gfx9.surf_slice_size;
+               pLayout->depthPitch = surface->u.gfx9.surf_slice_size;
+               pLayout->size = surface->u.gfx9.surf_slice_size;
+               if (image->type == VK_IMAGE_TYPE_3D)
+                       pLayout->size *= u_minify(image->info.depth, level);
+       } else {
+               pLayout->offset = surface->u.legacy.level[level].offset + (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4 * layer;
+               pLayout->rowPitch = surface->u.legacy.level[level].nblk_x * surface->bpe;
+               pLayout->arrayPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
+               pLayout->depthPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
+               pLayout->size = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
+               if (image->type == VK_IMAGE_TYPE_3D)
+                       pLayout->size *= u_minify(image->info.depth, level);
+       }
 }
 
 
@@ -1082,8 +1223,7 @@ radv_DestroyImageView(VkDevice _device, VkImageView _iview,
 
 void radv_buffer_view_init(struct radv_buffer_view *view,
                           struct radv_device *device,
-                          const VkBufferViewCreateInfo* pCreateInfo,
-                          struct radv_cmd_buffer *cmd_buffer)
+                          const VkBufferViewCreateInfo* pCreateInfo)
 {
        RADV_FROM_HANDLE(radv_buffer, buffer, pCreateInfo->buffer);
 
@@ -1110,7 +1250,7 @@ radv_CreateBufferView(VkDevice _device,
        if (!view)
                return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-       radv_buffer_view_init(view, device, pCreateInfo, NULL);
+       radv_buffer_view_init(view, device, pCreateInfo);
 
        *pView = radv_buffer_view_to_handle(view);