+anv_image_fill_surface_state(struct anv_device *device,
+ const struct anv_image *image,
+ VkImageAspectFlagBits aspect,
+ const struct isl_view *view_in,
+ isl_surf_usage_flags_t view_usage,
+ enum isl_aux_usage aux_usage,
+ const union isl_color_value *clear_color,
+ enum anv_image_view_state_flags flags,
+ struct anv_surface_state *state_inout,
+ struct brw_image_param *image_param_out)
+{
+ uint32_t plane = anv_image_aspect_to_plane(image->aspects, 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;
+
+ /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
+ * compressed surface with a shadow surface, we use the shadow instead of
+ * the primary surface. The shadow surface will be tiled, unlike the main
+ * surface, so it should get significantly better performance.
+ */
+ 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->planes[plane].shadow_surface.isl.tiling != ISL_TILING_LINEAR);
+ surface = &image->planes[plane].shadow_surface;
+ }
+
+ if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
+ view.swizzle = anv_swizzle_for_render(view.swizzle);
+
+ /* If this is a HiZ buffer we can sample from with a programmable clear
+ * value (SKL+), define the clear value to the optimal constant.
+ */
+ union isl_color_value default_clear_color = { .u32 = { 0, } };
+ if (device->info.gen >= 9 && aux_usage == ISL_AUX_USAGE_HIZ)
+ default_clear_color.f32[0] = ANV_HZ_FC_VAL;
+ if (!clear_color)
+ clear_color = &default_clear_color;
+
+ 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) &&
+ !isl_has_matching_typed_storage_image_format(&device->info,
+ view.format)) {
+ /* In this case, we are a writeable storage buffer which needs to be
+ * lowered to linear. All tiling and offset calculations will be done in
+ * the shader.
+ */
+ assert(aux_usage == ISL_AUX_USAGE_NONE);
+ isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
+ .address = address,
+ .size = surface->isl.size,
+ .format = ISL_FORMAT_RAW,
+ .stride = 1,
+ .mocs = device->default_mocs);
+ state_inout->address = address,
+ state_inout->aux_address = 0;
+ } else {
+ if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
+ !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY)) {
+ /* Typed surface reads support a very limited subset of the shader
+ * image formats. Translate it into the closest format the hardware
+ * supports.
+ */
+ assert(aux_usage == ISL_AUX_USAGE_NONE);
+ view.format = isl_lower_storage_image_format(&device->info,
+ view.format);
+ }
+
+ const struct isl_surf *isl_surf = &surface->isl;
+
+ struct isl_surf tmp_surf;
+ uint32_t offset_B = 0, tile_x_sa = 0, tile_y_sa = 0;
+ if (isl_format_is_compressed(surface->isl.format) &&
+ !isl_format_is_compressed(view.format)) {
+ /* We're creating an uncompressed view of a compressed surface. This
+ * is allowed but only for a single level/layer.
+ */
+ assert(surface->isl.samples == 1);
+ assert(view.levels == 1);
+ assert(view.array_len == 1);
+
+ isl_surf_get_image_surf(&device->isl_dev, isl_surf,
+ view.base_level,
+ surface->isl.dim == ISL_SURF_DIM_3D ?
+ 0 : view.base_array_layer,
+ surface->isl.dim == ISL_SURF_DIM_3D ?
+ view.base_array_layer : 0,
+ &tmp_surf,
+ &offset_B, &tile_x_sa, &tile_y_sa);
+
+ /* The newly created image represents the one subimage we're
+ * referencing with this view so it only has one array slice and
+ * miplevel.
+ */
+ view.base_array_layer = 0;
+ view.base_level = 0;
+
+ /* We're making an uncompressed view here. The image dimensions need
+ * to be scaled down by the block size.
+ */
+ const struct isl_format_layout *fmtl =
+ isl_format_get_layout(surface->isl.format);
+ tmp_surf.format = view.format;
+ tmp_surf.logical_level0_px.width =
+ DIV_ROUND_UP(tmp_surf.logical_level0_px.width, fmtl->bw);
+ tmp_surf.logical_level0_px.height =
+ DIV_ROUND_UP(tmp_surf.logical_level0_px.height, fmtl->bh);
+ tmp_surf.phys_level0_sa.width /= fmtl->bw;
+ tmp_surf.phys_level0_sa.height /= fmtl->bh;
+ tile_x_sa /= fmtl->bw;
+ tile_y_sa /= fmtl->bh;
+
+ isl_surf = &tmp_surf;
+
+ if (device->info.gen <= 8) {
+ assert(surface->isl.tiling == ISL_TILING_LINEAR);
+ assert(tile_x_sa == 0);
+ assert(tile_y_sa == 0);
+ }
+ }
+
+ isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
+ .surf = isl_surf,
+ .view = &view,
+ .address = address + offset_B,
+ .clear_color = *clear_color,
+ .aux_surf = &aux_surface->isl,
+ .aux_usage = aux_usage,
+ .aux_address = aux_address,
+ .mocs = device->default_mocs,
+ .x_offset_sa = tile_x_sa,
+ .y_offset_sa = tile_y_sa);
+ state_inout->address = address + offset_B;
+ if (device->info.gen >= 8) {
+ state_inout->aux_address = aux_address;
+ } else {
+ /* 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.
+ */
+ uint32_t *aux_addr_dw = state_inout->state.map +
+ device->isl_dev.ss.aux_addr_offset;
+ assert((aux_address & 0xfff) == 0);
+ assert(aux_address == (*aux_addr_dw & 0xfffff000));
+ state_inout->aux_address = *aux_addr_dw;
+ }
+ }
+
+ anv_state_flush(device, state_inout->state);
+
+ if (image_param_out) {
+ assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
+ isl_surf_fill_image_param(&device->isl_dev, image_param_out,
+ &surface->isl, &view);
+ }
+}
+
+static VkImageAspectFlags
+remap_aspect_flags(VkImageAspectFlags view_aspects)
+{
+ if (view_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) {
+ 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,
+ const VkAllocationCallbacks *pAllocator,
+ VkImageView *pView)