xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan/anv_image_view.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* Copyright © 2024 Intel Corporation
2  * SPDX-License-Identifier: MIT
3  */
4 
5 #include "anv_private.h"
6 
7 static enum isl_channel_select
remap_swizzle(VkComponentSwizzle swizzle,struct isl_swizzle format_swizzle)8 remap_swizzle(VkComponentSwizzle swizzle,
9               struct isl_swizzle format_swizzle)
10 {
11    switch (swizzle) {
12    case VK_COMPONENT_SWIZZLE_ZERO:  return ISL_CHANNEL_SELECT_ZERO;
13    case VK_COMPONENT_SWIZZLE_ONE:   return ISL_CHANNEL_SELECT_ONE;
14    case VK_COMPONENT_SWIZZLE_R:     return format_swizzle.r;
15    case VK_COMPONENT_SWIZZLE_G:     return format_swizzle.g;
16    case VK_COMPONENT_SWIZZLE_B:     return format_swizzle.b;
17    case VK_COMPONENT_SWIZZLE_A:     return format_swizzle.a;
18    default:
19       unreachable("Invalid swizzle");
20    }
21 }
22 
23 void
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)24 anv_image_fill_surface_state(struct anv_device *device,
25                              const struct anv_image *image,
26                              VkImageAspectFlagBits aspect,
27                              const struct isl_view *view_in,
28                              isl_surf_usage_flags_t view_usage,
29                              enum isl_aux_usage aux_usage,
30                              const union isl_color_value *clear_color,
31                              enum anv_image_view_state_flags flags,
32                              struct anv_surface_state *state_inout)
33 {
34    uint32_t plane = anv_image_aspect_to_plane(image, aspect);
35    if (image->emu_plane_format != VK_FORMAT_UNDEFINED) {
36       const uint16_t view_bpb = isl_format_get_layout(view_in->format)->bpb;
37       const uint16_t plane_bpb = isl_format_get_layout(
38             image->planes[plane].primary_surface.isl.format)->bpb;
39 
40       /* We should redirect to the hidden plane when the original view format
41        * is compressed or when the view usage is storage.  But we don't always
42        * have visibility to the original view format so we also check for size
43        * compatibility.
44        */
45       if (isl_format_is_compressed(view_in->format) ||
46           (view_usage & ISL_SURF_USAGE_STORAGE_BIT) ||
47           view_bpb != plane_bpb) {
48          plane = image->n_planes;
49          assert(isl_format_get_layout(
50                   image->planes[plane].primary_surface.isl.format)->bpb ==
51                 view_bpb);
52       }
53    }
54 
55    const struct anv_surface *surface = &image->planes[plane].primary_surface,
56       *aux_surface = &image->planes[plane].aux_surface;
57 
58    struct isl_view view = *view_in;
59    view.usage |= view_usage;
60 
61    /* Propagate the protection flag of the image to the view. */
62    view_usage |= surface->isl.usage & ISL_SURF_USAGE_PROTECTED_BIT;
63 
64    if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
65       view.swizzle = anv_swizzle_for_render(view.swizzle);
66 
67    /* If this is a HiZ buffer we can sample from with a programmable clear
68     * value (SKL+), define the clear value to the optimal constant.
69     */
70    union isl_color_value default_clear_color = { .u32 = { 0, } };
71    if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
72       default_clear_color = anv_image_hiz_clear_value(image);
73 
74    if (!clear_color)
75       clear_color = &default_clear_color;
76 
77    const struct anv_address address =
78       anv_image_address(image, &surface->memory_range);
79 
80    void *surface_state_map = state_inout->state_data.data;
81 
82    const struct isl_surf *isl_surf = &surface->isl;
83 
84    struct isl_surf tmp_surf;
85    uint64_t offset_B = 0;
86    uint32_t tile_x_sa = 0, tile_y_sa = 0;
87    if (isl_format_is_compressed(surface->isl.format) &&
88        !isl_format_is_compressed(view.format)) {
89       /* We're creating an uncompressed view of a compressed surface. This is
90        * allowed but only for a single level/layer.
91        */
92       assert(surface->isl.samples == 1);
93       assert(view.levels == 1);
94 
95       ASSERTED bool ok =
96          isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
97                                         &tmp_surf, &view,
98                                         &offset_B, &tile_x_sa, &tile_y_sa);
99       assert(ok);
100       isl_surf = &tmp_surf;
101    }
102 
103    state_inout->address = anv_address_add(address, offset_B);
104 
105    struct anv_address aux_address = ANV_NULL_ADDRESS;
106    if (aux_usage != ISL_AUX_USAGE_NONE)
107       aux_address = anv_image_address(image, &aux_surface->memory_range);
108    state_inout->aux_address = aux_address;
109 
110    struct anv_address clear_address = ANV_NULL_ADDRESS;
111    if (device->info->ver >= 10 && isl_aux_usage_has_fast_clears(aux_usage)) {
112       clear_address = anv_image_get_clear_color_addr(device, image, aspect);
113    }
114    state_inout->clear_address = clear_address;
115 
116    if (image->vk.create_flags & VK_IMAGE_CREATE_PROTECTED_BIT)
117       view_usage |= ISL_SURF_USAGE_PROTECTED_BIT;
118 
119    isl_surf_fill_state(&device->isl_dev, surface_state_map,
120                        .surf = isl_surf,
121                        .view = &view,
122                        .address = anv_address_physical(state_inout->address),
123                        .clear_color = *clear_color,
124                        .aux_surf = &aux_surface->isl,
125                        .aux_usage = aux_usage,
126                        .aux_address = anv_address_physical(aux_address),
127                        .clear_address = anv_address_physical(clear_address),
128                        .use_clear_address = !anv_address_is_null(clear_address),
129                        .mocs = anv_mocs(device, state_inout->address.bo,
130                                         view_usage),
131                        .x_offset_sa = tile_x_sa,
132                        .y_offset_sa = tile_y_sa,
133                        /* Assume robustness with EXT_pipeline_robustness
134                         * because this can be turned on/off per pipeline and
135                         * we have no visibility on this here.
136                         */
137                        .robust_image_access =
138                           device->vk.enabled_features.robustImageAccess ||
139                           device->vk.enabled_features.robustImageAccess2 ||
140                           device->vk.enabled_extensions.EXT_pipeline_robustness);
141 
142    /* With the exception of gfx8, the bottom 12 bits of the MCS base address
143     * are used to store other information. This should be ok, however, because
144     * the surface buffer addresses are always 4K page aligned.
145     */
146    if (!anv_address_is_null(aux_address)) {
147       uint32_t *aux_addr_dw = surface_state_map +
148          device->isl_dev.ss.aux_addr_offset;
149       assert((aux_address.offset & 0xfff) == 0);
150       state_inout->aux_address.offset |= *aux_addr_dw & 0xfff;
151    }
152 
153    if (device->info->ver >= 10 && clear_address.bo) {
154       uint32_t *clear_addr_dw = surface_state_map +
155          device->isl_dev.ss.clear_color_state_offset;
156       assert((clear_address.offset & 0x3f) == 0);
157       state_inout->clear_address.offset |= *clear_addr_dw & 0x3f;
158    }
159 
160    if (state_inout->state.map)
161       memcpy(state_inout->state.map, surface_state_map, ANV_SURFACE_STATE_SIZE);
162 }
163 
164 static uint32_t
anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)165 anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
166 {
167    anv_assert_valid_aspect_set(aspect_mask);
168    return util_bitcount(aspect_mask);
169 }
170 
171 bool
anv_can_hiz_clear_ds_view(struct anv_device * device,const struct anv_image_view * iview,VkImageLayout layout,VkImageAspectFlags clear_aspects,float depth_clear_value,VkRect2D render_area,const VkQueueFlagBits queue_flags)172 anv_can_hiz_clear_ds_view(struct anv_device *device,
173                           const struct anv_image_view *iview,
174                           VkImageLayout layout,
175                           VkImageAspectFlags clear_aspects,
176                           float depth_clear_value,
177                           VkRect2D render_area,
178                           const VkQueueFlagBits queue_flags)
179 {
180    if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
181       return false;
182 
183    /* If we're just clearing stencil, we can always HiZ clear */
184    if (!(clear_aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
185       return true;
186 
187    /* We must have depth in order to have HiZ */
188    if (!(iview->image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
189       return false;
190 
191    const enum isl_aux_usage clear_aux_usage =
192       anv_layout_to_aux_usage(device->info, iview->image,
193                               VK_IMAGE_ASPECT_DEPTH_BIT,
194                               VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
195                               layout, queue_flags);
196 
197    if (!isl_aux_usage_has_fast_clears(clear_aux_usage))
198       return false;
199 
200    if (isl_aux_usage_has_ccs(clear_aux_usage)) {
201       /* From the TGL PRM, Vol 9, "Compressed Depth Buffers" (under the
202        * "Texture performant" and "ZCS" columns):
203        *
204        *    Update with clear at either 16x8 or 8x4 granularity, based on
205        *    fs_clr or otherwise.
206        *
207        * Although alignment requirements are only listed for the texture
208        * performant mode, test results indicate that requirements exist for
209        * the non-texture performant mode as well. Disable partial clears.
210        */
211       if (render_area.offset.x > 0 ||
212           render_area.offset.y > 0 ||
213           render_area.extent.width !=
214           u_minify(iview->vk.extent.width, iview->vk.base_mip_level) ||
215           render_area.extent.height !=
216           u_minify(iview->vk.extent.height, iview->vk.base_mip_level)) {
217          return false;
218       }
219 
220       /* When fast-clearing, hardware behaves in unexpected ways if the clear
221        * rectangle, aligned to 16x8, could cover neighboring LODs.
222        * Fortunately, ISL guarantees that LOD0 will be 8-row aligned and
223        * LOD0's height seems to not matter. Also, few applications ever clear
224        * LOD1+. Only allow fast-clearing upper LODs if no overlap can occur.
225        */
226       const struct isl_surf *surf =
227          &iview->image->planes[0].primary_surface.isl;
228       assert(isl_surf_usage_is_depth(surf->usage));
229       assert(surf->dim_layout == ISL_DIM_LAYOUT_GFX4_2D);
230       assert(surf->array_pitch_el_rows % 8 == 0);
231       if (clear_aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT &&
232           iview->vk.base_mip_level >= 1 &&
233           (iview->vk.extent.width % 32 != 0 ||
234            surf->image_alignment_el.h % 8 != 0)) {
235          return false;
236       }
237    }
238 
239    if (device->info->ver <= 12 &&
240        depth_clear_value != anv_image_hiz_clear_value(iview->image).f32[0])
241       return false;
242 
243    /* If we got here, then we can fast clear */
244    return true;
245 }
246 
247 static bool
isl_color_value_requires_conversion(union isl_color_value color,const struct isl_surf * surf,const struct isl_view * view)248 isl_color_value_requires_conversion(union isl_color_value color,
249                                     const struct isl_surf *surf,
250                                     const struct isl_view *view)
251 {
252    if (surf->format == view->format && isl_swizzle_is_identity(view->swizzle))
253       return false;
254 
255    uint32_t surf_pack[4] = { 0, 0, 0, 0 };
256    isl_color_value_pack(&color, surf->format, surf_pack);
257 
258    uint32_t view_pack[4] = { 0, 0, 0, 0 };
259    union isl_color_value swiz_color =
260       isl_color_value_swizzle_inv(color, view->swizzle);
261    isl_color_value_pack(&swiz_color, view->format, view_pack);
262 
263    return memcmp(surf_pack, view_pack, sizeof(surf_pack)) != 0;
264 }
265 
266 bool
anv_can_fast_clear_color_view(struct anv_device * device,struct anv_image_view * iview,VkImageLayout layout,union isl_color_value clear_color,uint32_t num_layers,VkRect2D render_area,const VkQueueFlagBits queue_flags)267 anv_can_fast_clear_color_view(struct anv_device *device,
268                               struct anv_image_view *iview,
269                               VkImageLayout layout,
270                               union isl_color_value clear_color,
271                               uint32_t num_layers,
272                               VkRect2D render_area,
273                               const VkQueueFlagBits queue_flags)
274 {
275    if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
276       return false;
277 
278    if (iview->planes[0].isl.base_array_layer >=
279        anv_image_aux_layers(iview->image, VK_IMAGE_ASPECT_COLOR_BIT,
280                             iview->planes[0].isl.base_level))
281       return false;
282 
283    /* Start by getting the fast clear type.  We use the first subpass
284     * layout here because we don't want to fast-clear if the first subpass
285     * to use the attachment can't handle fast-clears.
286     */
287    enum anv_fast_clear_type fast_clear_type =
288       anv_layout_to_fast_clear_type(device->info, iview->image,
289                                     VK_IMAGE_ASPECT_COLOR_BIT,
290                                     layout, queue_flags);
291    switch (fast_clear_type) {
292    case ANV_FAST_CLEAR_NONE:
293       return false;
294    case ANV_FAST_CLEAR_DEFAULT_VALUE:
295       if (!isl_color_value_is_zero(clear_color, iview->planes[0].isl.format))
296          return false;
297       break;
298    case ANV_FAST_CLEAR_ANY:
299       break;
300    }
301 
302    /* Potentially, we could do partial fast-clears but doing so has crazy
303     * alignment restrictions.  It's easier to just restrict to full size
304     * fast clears for now.
305     */
306    if (render_area.offset.x != 0 ||
307        render_area.offset.y != 0 ||
308        render_area.extent.width != iview->vk.extent.width ||
309        render_area.extent.height != iview->vk.extent.height)
310       return false;
311 
312    /* If the clear color is one that would require non-trivial format
313     * conversion on resolve, we don't bother with the fast clear.  This
314     * shouldn't be common as most clear colors are 0/1 and the most common
315     * format re-interpretation is for sRGB.
316     */
317    if (isl_color_value_requires_conversion(clear_color,
318                                            &iview->image->planes[0].primary_surface.isl,
319                                            &iview->planes[0].isl)) {
320       anv_perf_warn(VK_LOG_OBJS(&iview->vk.base),
321                     "Cannot fast-clear to colors which would require "
322                     "format conversion on resolve");
323       return false;
324    }
325 
326    /* We only allow fast clears to the first slice of an image (level 0,
327     * layer 0) and only for the entire slice.  This guarantees us that, at
328     * any given time, there is only one clear color on any given image at
329     * any given time.  At the time of our testing (Jan 17, 2018), there
330     * were no known applications which would benefit from fast-clearing
331     * more than just the first slice.
332     */
333    if (iview->planes[0].isl.base_level > 0 ||
334        iview->planes[0].isl.base_array_layer > 0) {
335       anv_perf_warn(VK_LOG_OBJS(&iview->image->vk.base),
336                     "Rendering with multi-lod or multi-layer framebuffer "
337                     "with LOAD_OP_LOAD and baseMipLevel > 0 or "
338                     "baseArrayLayer > 0.  Not fast clearing.");
339       return false;
340    }
341 
342    if (num_layers > 1) {
343       anv_perf_warn(VK_LOG_OBJS(&iview->image->vk.base),
344                     "Rendering to a multi-layer framebuffer with "
345                     "LOAD_OP_CLEAR.  Only fast-clearing the first slice");
346    }
347 
348    /* Wa_18020603990 - slow clear surfaces up to 256x256, 32bpp. */
349    if (intel_needs_workaround(device->info, 18020603990)) {
350       const struct anv_surface *anv_surf =
351          &iview->image->planes->primary_surface;
352       if (isl_format_get_layout(anv_surf->isl.format)->bpb <= 32 &&
353           anv_surf->isl.logical_level0_px.w <= 256 &&
354           anv_surf->isl.logical_level0_px.h <= 256)
355          return false;
356    }
357 
358    /* On gfx12.0, CCS fast clears don't seem to cover the correct portion of
359     * the aux buffer when the pitch is not 512B-aligned.
360     */
361    if (device->info->verx10 == 120 &&
362        iview->image->planes->primary_surface.isl.samples == 1 &&
363        iview->image->planes->primary_surface.isl.row_pitch_B % 512) {
364       anv_perf_warn(VK_LOG_OBJS(&iview->image->vk.base),
365                     "Pitch not 512B-aligned. Slow clearing surface.");
366       return false;
367    }
368 
369    /* Disable sRGB fast-clears for non-0/1 color values on Gfx9. For texturing
370     * and draw calls, HW expects the clear color to be in two different color
371     * spaces after sRGB fast-clears - sRGB in the former and linear in the
372     * latter. By limiting the allowable values to 0/1, both color space
373     * requirements are satisfied.
374     *
375     * Gfx11+ is fine as the fast clear generate 2 colors at the clear color
376     * address, raw & converted such that all fixed functions can find the
377     * value they need.
378     */
379    if (device->info->ver == 9 &&
380        isl_format_is_srgb(iview->planes[0].isl.format) &&
381        !isl_color_value_is_zero_one(clear_color,
382                                     iview->planes[0].isl.format))
383       return false;
384 
385    /* Wa_16021232440: Disable fast clear when height is 16k */
386    if (intel_needs_workaround(device->info, 16021232440) &&
387        iview->vk.extent.height == 16 * 1024) {
388       return false;
389    }
390 
391    return true;
392 }
393 
394 void
anv_image_view_init(struct anv_device * device,struct anv_image_view * iview,const VkImageViewCreateInfo * pCreateInfo,struct anv_state_stream * surface_state_stream)395 anv_image_view_init(struct anv_device *device,
396                     struct anv_image_view *iview,
397                     const VkImageViewCreateInfo *pCreateInfo,
398                     struct anv_state_stream *surface_state_stream)
399 {
400    ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
401 
402    vk_image_view_init(&device->vk, &iview->vk, false, pCreateInfo);
403    iview->image = image;
404    iview->n_planes = anv_image_aspect_get_planes(iview->vk.aspects);
405    iview->use_surface_state_stream = surface_state_stream != NULL;
406 
407    /* Now go through the underlying image selected planes and map them to
408     * planes in the image view.
409     */
410    anv_foreach_image_aspect_bit(iaspect_bit, image, iview->vk.aspects) {
411       const uint32_t vplane =
412          anv_aspect_to_plane(iview->vk.aspects, 1UL << iaspect_bit);
413 
414       VkFormat view_format = iview->vk.view_format;
415       if (anv_is_format_emulated(device->physical, view_format)) {
416          assert(image->emu_plane_format != VK_FORMAT_UNDEFINED);
417          view_format =
418             anv_get_emulation_format(device->physical, view_format);
419       }
420       const struct anv_format_plane format = anv_get_format_plane(
421             device->info, view_format, vplane, image->vk.tiling);
422 
423       iview->planes[vplane].isl = (struct isl_view) {
424          .format = format.isl_format,
425          .base_level = iview->vk.base_mip_level,
426          .levels = iview->vk.level_count,
427          .base_array_layer = iview->vk.base_array_layer,
428          .array_len = iview->vk.layer_count,
429          .min_lod_clamp = iview->vk.min_lod,
430          .swizzle = {
431             .r = remap_swizzle(iview->vk.swizzle.r, format.swizzle),
432             .g = remap_swizzle(iview->vk.swizzle.g, format.swizzle),
433             .b = remap_swizzle(iview->vk.swizzle.b, format.swizzle),
434             .a = remap_swizzle(iview->vk.swizzle.a, format.swizzle),
435          },
436       };
437 
438       if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
439          iview->planes[vplane].isl.base_array_layer = 0;
440          iview->planes[vplane].isl.array_len = iview->vk.extent.depth;
441       }
442 
443       if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
444           pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
445          iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
446       } else {
447          iview->planes[vplane].isl.usage = 0;
448       }
449 
450       if (iview->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
451                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
452          iview->planes[vplane].optimal_sampler.state =
453             anv_device_maybe_alloc_surface_state(device, surface_state_stream);
454          iview->planes[vplane].general_sampler.state =
455             anv_device_maybe_alloc_surface_state(device, surface_state_stream);
456 
457          enum isl_aux_usage general_aux_usage =
458             anv_layout_to_aux_usage(device->info, image, 1UL << iaspect_bit,
459                                     VK_IMAGE_USAGE_SAMPLED_BIT,
460                                     VK_IMAGE_LAYOUT_GENERAL,
461                                     VK_QUEUE_GRAPHICS_BIT |
462                                     VK_QUEUE_COMPUTE_BIT |
463                                     VK_QUEUE_TRANSFER_BIT);
464          enum isl_aux_usage optimal_aux_usage =
465             anv_layout_to_aux_usage(device->info, image, 1UL << iaspect_bit,
466                                     VK_IMAGE_USAGE_SAMPLED_BIT,
467                                     VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
468                                     VK_QUEUE_GRAPHICS_BIT |
469                                     VK_QUEUE_COMPUTE_BIT |
470                                     VK_QUEUE_TRANSFER_BIT);
471 
472          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
473                                       &iview->planes[vplane].isl,
474                                       ISL_SURF_USAGE_TEXTURE_BIT,
475                                       optimal_aux_usage, NULL,
476                                       ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
477                                       &iview->planes[vplane].optimal_sampler);
478 
479          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
480                                       &iview->planes[vplane].isl,
481                                       ISL_SURF_USAGE_TEXTURE_BIT,
482                                       general_aux_usage, NULL,
483                                       0,
484                                       &iview->planes[vplane].general_sampler);
485       }
486 
487       /* NOTE: This one needs to go last since it may stomp isl_view.format */
488       if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
489          struct isl_view storage_view = iview->planes[vplane].isl;
490          if (iview->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) {
491             storage_view.base_array_layer = iview->vk.storage.z_slice_offset;
492             storage_view.array_len = iview->vk.storage.z_slice_count;
493          }
494 
495          enum isl_aux_usage general_aux_usage =
496             anv_layout_to_aux_usage(device->info, image, 1UL << iaspect_bit,
497                                     VK_IMAGE_USAGE_STORAGE_BIT,
498                                     VK_IMAGE_LAYOUT_GENERAL,
499                                     VK_QUEUE_GRAPHICS_BIT |
500                                     VK_QUEUE_COMPUTE_BIT |
501                                     VK_QUEUE_TRANSFER_BIT);
502          iview->planes[vplane].storage.state =
503             anv_device_maybe_alloc_surface_state(device, surface_state_stream);
504 
505          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
506                                       &storage_view,
507                                       ISL_SURF_USAGE_STORAGE_BIT,
508                                       general_aux_usage, NULL,
509                                       0,
510                                       &iview->planes[vplane].storage);
511       }
512    }
513 }
514 
515 void
anv_image_view_finish(struct anv_image_view * iview)516 anv_image_view_finish(struct anv_image_view *iview)
517 {
518    struct anv_device *device =
519       container_of(iview->vk.base.device, struct anv_device, vk);
520 
521    if (!iview->use_surface_state_stream) {
522       for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
523          if (iview->planes[plane].optimal_sampler.state.alloc_size) {
524             anv_state_pool_free(&device->bindless_surface_state_pool,
525                   iview->planes[plane].optimal_sampler.state);
526          }
527 
528          if (iview->planes[plane].general_sampler.state.alloc_size) {
529             anv_state_pool_free(&device->bindless_surface_state_pool,
530                   iview->planes[plane].general_sampler.state);
531          }
532 
533          if (iview->planes[plane].storage.state.alloc_size) {
534             anv_state_pool_free(&device->bindless_surface_state_pool,
535                   iview->planes[plane].storage.state);
536          }
537       }
538    }
539 
540    vk_image_view_finish(&iview->vk);
541 }
542 
543 VkResult
anv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)544 anv_CreateImageView(VkDevice _device,
545                     const VkImageViewCreateInfo *pCreateInfo,
546                     const VkAllocationCallbacks *pAllocator,
547                     VkImageView *pView)
548 {
549    ANV_FROM_HANDLE(anv_device, device, _device);
550    struct anv_image_view *iview;
551 
552    iview = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*iview), 8,
553                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
554    if (iview == NULL)
555       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
556 
557    anv_image_view_init(device, iview, pCreateInfo, NULL);
558 
559    *pView = anv_image_view_to_handle(iview);
560 
561    return VK_SUCCESS;
562 }
563 
564 void
anv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)565 anv_DestroyImageView(VkDevice _device, VkImageView _iview,
566                      const VkAllocationCallbacks *pAllocator)
567 {
568    ANV_FROM_HANDLE(anv_image_view, iview, _iview);
569 
570    if (!iview)
571       return;
572 
573    anv_image_view_finish(iview);
574    vk_free2(&iview->vk.base.device->alloc, pAllocator, iview);
575 }
576