• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Red Hat.
3  * Copyright © 2016 Bas Nieuwenhuizen
4  *
5  * based in part on anv driver which is:
6  * Copyright © 2015 Intel Corporation
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25  * IN THE SOFTWARE.
26  */
27 
28 #include "radv_private.h"
29 
30 #include "gfx10_format_table.h"
31 
32 static unsigned
gfx9_border_color_swizzle(const struct util_format_description * desc)33 gfx9_border_color_swizzle(const struct util_format_description *desc)
34 {
35    unsigned bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;
36 
37    if (desc->format == PIPE_FORMAT_S8_UINT) {
38       /* Swizzle of 8-bit stencil format is defined as _x__ but the hw expects XYZW. */
39       assert(desc->swizzle[1] == PIPE_SWIZZLE_X);
40       return bc_swizzle;
41    }
42 
43    if (desc->swizzle[3] == PIPE_SWIZZLE_X) {
44       /* For the pre-defined border color values (white, opaque
45        * black, transparent black), the only thing that matters is
46        * that the alpha channel winds up in the correct place
47        * (because the RGB channels are all the same) so either of
48        * these enumerations will work.
49        */
50       if (desc->swizzle[2] == PIPE_SWIZZLE_Y)
51          bc_swizzle = V_008F20_BC_SWIZZLE_WZYX;
52       else
53          bc_swizzle = V_008F20_BC_SWIZZLE_WXYZ;
54    } else if (desc->swizzle[0] == PIPE_SWIZZLE_X) {
55       if (desc->swizzle[1] == PIPE_SWIZZLE_Y)
56          bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;
57       else
58          bc_swizzle = V_008F20_BC_SWIZZLE_XWYZ;
59    } else if (desc->swizzle[1] == PIPE_SWIZZLE_X) {
60       bc_swizzle = V_008F20_BC_SWIZZLE_YXWZ;
61    } else if (desc->swizzle[2] == PIPE_SWIZZLE_X) {
62       bc_swizzle = V_008F20_BC_SWIZZLE_ZYXW;
63    }
64 
65    return bc_swizzle;
66 }
67 
68 static unsigned
radv_tex_dim(VkImageType image_type,VkImageViewType view_type,unsigned nr_layers,unsigned nr_samples,bool is_storage_image,bool gfx9)69 radv_tex_dim(VkImageType image_type, VkImageViewType view_type, unsigned nr_layers, unsigned nr_samples,
70              bool is_storage_image, bool gfx9)
71 {
72    if (view_type == VK_IMAGE_VIEW_TYPE_CUBE || view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
73       return is_storage_image ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_CUBE;
74 
75    /* GFX9 allocates 1D textures as 2D. */
76    if (gfx9 && image_type == VK_IMAGE_TYPE_1D)
77       image_type = VK_IMAGE_TYPE_2D;
78    switch (image_type) {
79    case VK_IMAGE_TYPE_1D:
80       return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_1D_ARRAY : V_008F1C_SQ_RSRC_IMG_1D;
81    case VK_IMAGE_TYPE_2D:
82       if (nr_samples > 1)
83          return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY : V_008F1C_SQ_RSRC_IMG_2D_MSAA;
84       else
85          return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_2D;
86    case VK_IMAGE_TYPE_3D:
87       if (view_type == VK_IMAGE_VIEW_TYPE_3D)
88          return V_008F1C_SQ_RSRC_IMG_3D;
89       else
90          return V_008F1C_SQ_RSRC_IMG_2D_ARRAY;
91    default:
92       unreachable("illegal image type");
93    }
94 }
95 
96 void
radv_set_mutable_tex_desc_fields(struct radv_device * device,struct radv_image * image,const struct legacy_surf_level * base_level_info,unsigned plane_id,unsigned base_level,unsigned first_level,unsigned block_width,bool is_stencil,bool is_storage_image,bool disable_compression,bool enable_write_compression,uint32_t * state,const struct ac_surf_nbc_view * nbc_view)97 radv_set_mutable_tex_desc_fields(struct radv_device *device, struct radv_image *image,
98                                  const struct legacy_surf_level *base_level_info, unsigned plane_id,
99                                  unsigned base_level, unsigned first_level, unsigned block_width, bool is_stencil,
100                                  bool is_storage_image, bool disable_compression, bool enable_write_compression,
101                                  uint32_t *state, const struct ac_surf_nbc_view *nbc_view)
102 {
103    struct radv_image_plane *plane = &image->planes[plane_id];
104    struct radv_image_binding *binding = image->disjoint ? &image->bindings[plane_id] : &image->bindings[0];
105    uint64_t gpu_address = binding->bo ? radv_buffer_get_va(binding->bo) + binding->offset : 0;
106    uint64_t va = gpu_address;
107    uint8_t swizzle = plane->surface.tile_swizzle;
108    enum amd_gfx_level gfx_level = device->physical_device->rad_info.gfx_level;
109    uint64_t meta_va = 0;
110    if (gfx_level >= GFX9) {
111       if (is_stencil)
112          va += plane->surface.u.gfx9.zs.stencil_offset;
113       else
114          va += plane->surface.u.gfx9.surf_offset;
115       if (nbc_view && nbc_view->valid) {
116          va += nbc_view->base_address_offset;
117          swizzle = nbc_view->tile_swizzle;
118       }
119    } else
120       va += (uint64_t)base_level_info->offset_256B * 256;
121 
122    state[0] = va >> 8;
123    if (gfx_level >= GFX9 || base_level_info->mode == RADEON_SURF_MODE_2D)
124       state[0] |= swizzle;
125    state[1] &= C_008F14_BASE_ADDRESS_HI;
126    state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);
127 
128    if (gfx_level >= GFX8) {
129       state[6] &= C_008F28_COMPRESSION_EN;
130       state[7] = 0;
131       if (!disable_compression && radv_dcc_enabled(image, first_level)) {
132          meta_va = gpu_address + plane->surface.meta_offset;
133          if (gfx_level <= GFX8)
134             meta_va += plane->surface.u.legacy.color.dcc_level[base_level].dcc_offset;
135 
136          unsigned dcc_tile_swizzle = swizzle << 8;
137          dcc_tile_swizzle &= (1 << plane->surface.meta_alignment_log2) - 1;
138          meta_va |= dcc_tile_swizzle;
139       } else if (!disable_compression && radv_image_is_tc_compat_htile(image)) {
140          meta_va = gpu_address + plane->surface.meta_offset;
141       }
142 
143       if (meta_va) {
144          state[6] |= S_008F28_COMPRESSION_EN(1);
145          if (gfx_level <= GFX9)
146             state[7] = meta_va >> 8;
147       }
148    }
149 
150    /* GFX10.3+ can set a custom pitch for 1D and 2D non-array, but it must be a multiple
151     * of 256B.
152     *
153     * If an imported image is used with VK_IMAGE_VIEW_TYPE_2D_ARRAY, it may hang due to VM faults
154     * because DEPTH means pitch with 2D, but it means depth with 2D array.
155     */
156    if (device->physical_device->rad_info.gfx_level >= GFX10_3 && plane->surface.u.gfx9.uses_custom_pitch) {
157       assert((plane->surface.u.gfx9.surf_pitch * plane->surface.bpe) % 256 == 0);
158       assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
159       assert(plane->surface.is_linear);
160       assert(G_00A00C_TYPE(state[3]) == V_008F1C_SQ_RSRC_IMG_2D);
161       unsigned pitch = plane->surface.u.gfx9.surf_pitch;
162 
163       /* Subsampled images have the pitch in the units of blocks. */
164       if (plane->surface.blk_w == 2)
165          pitch *= 2;
166 
167       state[4] &= C_00A010_DEPTH & C_00A010_PITCH_MSB;
168       state[4] |= S_00A010_DEPTH(pitch - 1) | /* DEPTH contains low bits of PITCH. */
169                   S_00A010_PITCH_MSB((pitch - 1) >> 13);
170    }
171 
172    if (gfx_level >= GFX10) {
173       state[3] &= C_00A00C_SW_MODE;
174 
175       if (is_stencil) {
176          state[3] |= S_00A00C_SW_MODE(plane->surface.u.gfx9.zs.stencil_swizzle_mode);
177       } else {
178          state[3] |= S_00A00C_SW_MODE(plane->surface.u.gfx9.swizzle_mode);
179       }
180 
181       state[6] &= C_00A018_META_DATA_ADDRESS_LO & C_00A018_META_PIPE_ALIGNED;
182 
183       if (meta_va) {
184          struct gfx9_surf_meta_flags meta = {
185             .rb_aligned = 1,
186             .pipe_aligned = 1,
187          };
188 
189          if (!(plane->surface.flags & RADEON_SURF_Z_OR_SBUFFER))
190             meta = plane->surface.u.gfx9.color.dcc;
191 
192          if (radv_dcc_enabled(image, first_level) && is_storage_image && enable_write_compression)
193             state[6] |= S_00A018_WRITE_COMPRESS_ENABLE(1);
194 
195          state[6] |= S_00A018_META_PIPE_ALIGNED(meta.pipe_aligned) | S_00A018_META_DATA_ADDRESS_LO(meta_va >> 8);
196       }
197 
198       state[7] = meta_va >> 16;
199    } else if (gfx_level == GFX9) {
200       state[3] &= C_008F1C_SW_MODE;
201       state[4] &= C_008F20_PITCH;
202 
203       if (is_stencil) {
204          state[3] |= S_008F1C_SW_MODE(plane->surface.u.gfx9.zs.stencil_swizzle_mode);
205          state[4] |= S_008F20_PITCH(plane->surface.u.gfx9.zs.stencil_epitch);
206       } else {
207          state[3] |= S_008F1C_SW_MODE(plane->surface.u.gfx9.swizzle_mode);
208          state[4] |= S_008F20_PITCH(plane->surface.u.gfx9.epitch);
209       }
210 
211       state[5] &= C_008F24_META_DATA_ADDRESS & C_008F24_META_PIPE_ALIGNED & C_008F24_META_RB_ALIGNED;
212       if (meta_va) {
213          struct gfx9_surf_meta_flags meta = {
214             .rb_aligned = 1,
215             .pipe_aligned = 1,
216          };
217 
218          if (!(plane->surface.flags & RADEON_SURF_Z_OR_SBUFFER))
219             meta = plane->surface.u.gfx9.color.dcc;
220 
221          state[5] |= S_008F24_META_DATA_ADDRESS(meta_va >> 40) | S_008F24_META_PIPE_ALIGNED(meta.pipe_aligned) |
222                      S_008F24_META_RB_ALIGNED(meta.rb_aligned);
223       }
224    } else {
225       /* GFX6-GFX8 */
226       unsigned pitch = base_level_info->nblk_x * block_width;
227       unsigned index = radv_tile_mode_index(plane, base_level, is_stencil);
228 
229       state[3] &= C_008F1C_TILING_INDEX;
230       state[3] |= S_008F1C_TILING_INDEX(index);
231       state[4] &= C_008F20_PITCH;
232       state[4] |= S_008F20_PITCH(pitch - 1);
233    }
234 }
235 
236 /**
237  * Build the sampler view descriptor for a texture (GFX10).
238  */
239 static void
gfx10_make_texture_descriptor(struct radv_device * device,struct radv_image * image,bool is_storage_image,VkImageViewType view_type,VkFormat vk_format,const VkComponentMapping * mapping,unsigned first_level,unsigned last_level,unsigned first_layer,unsigned last_layer,unsigned width,unsigned height,unsigned depth,float min_lod,uint32_t * state,uint32_t * fmask_state,VkImageCreateFlags img_create_flags,const struct ac_surf_nbc_view * nbc_view,const VkImageViewSlicedCreateInfoEXT * sliced_3d)240 gfx10_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
241                               VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
242                               unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
243                               unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
244                               uint32_t *fmask_state, VkImageCreateFlags img_create_flags,
245                               const struct ac_surf_nbc_view *nbc_view, const VkImageViewSlicedCreateInfoEXT *sliced_3d)
246 {
247    const struct util_format_description *desc;
248    enum pipe_swizzle swizzle[4];
249    unsigned img_format;
250    unsigned type;
251 
252    desc = vk_format_description(vk_format);
253 
254    /* For emulated ETC2 without alpha we need to override the format to a 3-componenent format, so
255     * that border colors work correctly (alpha forced to 1). Since Vulkan has no such format,
256     * this uses the Gallium formats to set the description. */
257    if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK && vk_format == VK_FORMAT_R8G8B8A8_UNORM) {
258       desc = util_format_description(PIPE_FORMAT_R8G8B8X8_UNORM);
259    } else if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK && vk_format == VK_FORMAT_R8G8B8A8_SRGB) {
260       desc = util_format_description(PIPE_FORMAT_R8G8B8X8_SRGB);
261    }
262 
263    img_format =
264       ac_get_gfx10_format_table(&device->physical_device->rad_info)[vk_format_to_pipe_format(vk_format)].img_format;
265 
266    radv_compose_swizzle(desc, mapping, swizzle);
267 
268    if (img_create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) {
269       assert(image->vk.image_type == VK_IMAGE_TYPE_3D);
270       type = V_008F1C_SQ_RSRC_IMG_3D;
271    } else {
272       type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, image->vk.samples, is_storage_image,
273                           device->physical_device->rad_info.gfx_level == GFX9);
274    }
275 
276    if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
277       height = 1;
278       depth = image->vk.array_layers;
279    } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
280       if (view_type != VK_IMAGE_VIEW_TYPE_3D)
281          depth = image->vk.array_layers;
282    } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
283       depth = image->vk.array_layers / 6;
284 
285    state[0] = 0;
286    state[1] = S_00A004_FORMAT(img_format) | S_00A004_WIDTH_LO(width - 1);
287    state[2] = S_00A008_WIDTH_HI((width - 1) >> 2) | S_00A008_HEIGHT(height - 1) |
288               S_00A008_RESOURCE_LEVEL(device->physical_device->rad_info.gfx_level < GFX11);
289    state[3] = S_00A00C_DST_SEL_X(radv_map_swizzle(swizzle[0])) | S_00A00C_DST_SEL_Y(radv_map_swizzle(swizzle[1])) |
290               S_00A00C_DST_SEL_Z(radv_map_swizzle(swizzle[2])) | S_00A00C_DST_SEL_W(radv_map_swizzle(swizzle[3])) |
291               S_00A00C_BASE_LEVEL(image->vk.samples > 1 ? 0 : first_level) |
292               S_00A00C_LAST_LEVEL(image->vk.samples > 1 ? util_logbase2(image->vk.samples) : last_level) |
293               S_00A00C_BC_SWIZZLE(gfx9_border_color_swizzle(desc)) | S_00A00C_TYPE(type);
294    /* Depth is the the last accessible layer on gfx9+. The hw doesn't need
295     * to know the total number of layers.
296     */
297    state[4] =
298       S_00A010_DEPTH(type == V_008F1C_SQ_RSRC_IMG_3D ? depth - 1 : last_layer) | S_00A010_BASE_ARRAY(first_layer);
299    state[5] = S_00A014_ARRAY_PITCH(0) | S_00A014_PERF_MOD(4);
300    state[6] = 0;
301    state[7] = 0;
302 
303    if (img_create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) {
304       assert(type == V_008F1C_SQ_RSRC_IMG_3D);
305 
306       /* ARRAY_PITCH is only meaningful for 3D images, 0 means SRV, 1 means UAV.
307        * In SRV mode, BASE_ARRAY is ignored and DEPTH is the last slice of mipmap level 0.
308        * In UAV mode, BASE_ARRAY is the first slice and DEPTH is the last slice of the bound level.
309        */
310       state[4] &= C_00A010_DEPTH;
311       state[4] |= S_00A010_DEPTH(!is_storage_image ? depth - 1 : u_minify(depth, first_level) - 1);
312       state[5] |= S_00A014_ARRAY_PITCH(is_storage_image);
313    } else if (sliced_3d) {
314       unsigned total = u_minify(depth, first_level);
315 
316       assert(type == V_008F1C_SQ_RSRC_IMG_3D && is_storage_image);
317 
318       unsigned first_slice = sliced_3d->sliceOffset;
319       unsigned slice_count = sliced_3d->sliceCount == VK_REMAINING_3D_SLICES_EXT
320                                 ? MAX2(1, total - sliced_3d->sliceOffset)
321                                 : sliced_3d->sliceCount;
322       unsigned last_slice = first_slice + slice_count - 1;
323 
324       state[4] = 0;
325       state[4] |= S_00A010_DEPTH(last_slice) | S_00A010_BASE_ARRAY(first_slice);
326       state[5] |= S_00A014_ARRAY_PITCH(1);
327    }
328 
329    unsigned max_mip = image->vk.samples > 1 ? util_logbase2(image->vk.samples) : image->vk.mip_levels - 1;
330    if (nbc_view && nbc_view->valid)
331       max_mip = nbc_view->num_levels - 1;
332 
333    unsigned min_lod_clamped = radv_float_to_ufixed(CLAMP(min_lod, 0, 15), 8);
334    if (device->physical_device->rad_info.gfx_level >= GFX11) {
335       state[1] |= S_00A004_MAX_MIP(max_mip);
336       state[5] |= S_00A014_MIN_LOD_LO(min_lod_clamped);
337       state[6] |= S_00A018_MIN_LOD_HI(min_lod_clamped >> 5);
338    } else {
339       state[1] |= S_00A004_MIN_LOD(min_lod_clamped);
340       state[5] |= S_00A014_MAX_MIP(max_mip);
341    }
342 
343    if (radv_dcc_enabled(image, first_level)) {
344       state[6] |=
345          S_00A018_MAX_UNCOMPRESSED_BLOCK_SIZE(V_028C78_MAX_BLOCK_SIZE_256B) |
346          S_00A018_MAX_COMPRESSED_BLOCK_SIZE(image->planes[0].surface.u.gfx9.color.dcc.max_compressed_block_size) |
347          S_00A018_ALPHA_IS_ON_MSB(vi_alpha_is_on_msb(device, vk_format));
348    }
349 
350    if (radv_image_get_iterate256(device, image)) {
351       state[6] |= S_00A018_ITERATE_256(1);
352    }
353 
354    /* Initialize the sampler view for FMASK. */
355    if (fmask_state) {
356       if (radv_image_has_fmask(image)) {
357          uint64_t gpu_address = radv_buffer_get_va(image->bindings[0].bo);
358          uint32_t format;
359          uint64_t va;
360 
361          assert(image->plane_count == 1);
362 
363          va = gpu_address + image->bindings[0].offset + image->planes[0].surface.fmask_offset;
364 
365          switch (image->vk.samples) {
366          case 2:
367             format = V_008F0C_GFX10_FORMAT_FMASK8_S2_F2;
368             break;
369          case 4:
370             format = V_008F0C_GFX10_FORMAT_FMASK8_S4_F4;
371             break;
372          case 8:
373             format = V_008F0C_GFX10_FORMAT_FMASK32_S8_F8;
374             break;
375          default:
376             unreachable("invalid nr_samples");
377          }
378 
379          fmask_state[0] = (va >> 8) | image->planes[0].surface.fmask_tile_swizzle;
380          fmask_state[1] = S_00A004_BASE_ADDRESS_HI(va >> 40) | S_00A004_FORMAT(format) | S_00A004_WIDTH_LO(width - 1);
381          fmask_state[2] =
382             S_00A008_WIDTH_HI((width - 1) >> 2) | S_00A008_HEIGHT(height - 1) | S_00A008_RESOURCE_LEVEL(1);
383          fmask_state[3] =
384             S_00A00C_DST_SEL_X(V_008F1C_SQ_SEL_X) | S_00A00C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
385             S_00A00C_DST_SEL_Z(V_008F1C_SQ_SEL_X) | S_00A00C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
386             S_00A00C_SW_MODE(image->planes[0].surface.u.gfx9.color.fmask_swizzle_mode) |
387             S_00A00C_TYPE(radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, 0, false, false));
388          fmask_state[4] = S_00A010_DEPTH(last_layer) | S_00A010_BASE_ARRAY(first_layer);
389          fmask_state[5] = 0;
390          fmask_state[6] = S_00A018_META_PIPE_ALIGNED(1);
391          fmask_state[7] = 0;
392 
393          if (radv_image_is_tc_compat_cmask(image)) {
394             va = gpu_address + image->bindings[0].offset + image->planes[0].surface.cmask_offset;
395 
396             fmask_state[6] |= S_00A018_COMPRESSION_EN(1);
397             fmask_state[6] |= S_00A018_META_DATA_ADDRESS_LO(va >> 8);
398             fmask_state[7] |= va >> 16;
399          }
400       } else
401          memset(fmask_state, 0, 8 * 4);
402    }
403 }
404 
405 /**
406  * Build the sampler view descriptor for a texture (SI-GFX9)
407  */
408 static void
gfx6_make_texture_descriptor(struct radv_device * device,struct radv_image * image,bool is_storage_image,VkImageViewType view_type,VkFormat vk_format,const VkComponentMapping * mapping,unsigned first_level,unsigned last_level,unsigned first_layer,unsigned last_layer,unsigned width,unsigned height,unsigned depth,float min_lod,uint32_t * state,uint32_t * fmask_state,VkImageCreateFlags img_create_flags)409 gfx6_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
410                              VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
411                              unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
412                              unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
413                              uint32_t *fmask_state, VkImageCreateFlags img_create_flags)
414 {
415    const struct util_format_description *desc;
416    enum pipe_swizzle swizzle[4];
417    int first_non_void;
418    unsigned num_format, data_format, type;
419 
420    desc = vk_format_description(vk_format);
421 
422    /* For emulated ETC2 without alpha we need to override the format to a 3-componenent format, so
423     * that border colors work correctly (alpha forced to 1). Since Vulkan has no such format,
424     * this uses the Gallium formats to set the description. */
425    if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK && vk_format == VK_FORMAT_R8G8B8A8_UNORM) {
426       desc = util_format_description(PIPE_FORMAT_R8G8B8X8_UNORM);
427    } else if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK && vk_format == VK_FORMAT_R8G8B8A8_SRGB) {
428       desc = util_format_description(PIPE_FORMAT_R8G8B8X8_SRGB);
429    }
430 
431    radv_compose_swizzle(desc, mapping, swizzle);
432 
433    first_non_void = vk_format_get_first_non_void_channel(vk_format);
434 
435    num_format = radv_translate_tex_numformat(vk_format, desc, first_non_void);
436    if (num_format == ~0) {
437       num_format = 0;
438    }
439 
440    data_format = radv_translate_tex_dataformat(vk_format, desc, first_non_void);
441    if (data_format == ~0) {
442       data_format = 0;
443    }
444 
445    /* S8 with either Z16 or Z32 HTILE need a special format. */
446    if (device->physical_device->rad_info.gfx_level == GFX9 && vk_format == VK_FORMAT_S8_UINT &&
447        radv_image_is_tc_compat_htile(image)) {
448       if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
449          data_format = V_008F14_IMG_DATA_FORMAT_S8_32;
450       else if (image->vk.format == VK_FORMAT_D16_UNORM_S8_UINT)
451          data_format = V_008F14_IMG_DATA_FORMAT_S8_16;
452    }
453 
454    if (device->physical_device->rad_info.gfx_level == GFX9 &&
455        img_create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) {
456       assert(image->vk.image_type == VK_IMAGE_TYPE_3D);
457       type = V_008F1C_SQ_RSRC_IMG_3D;
458    } else {
459       type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, image->vk.samples, is_storage_image,
460                           device->physical_device->rad_info.gfx_level == GFX9);
461    }
462 
463    if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
464       height = 1;
465       depth = image->vk.array_layers;
466    } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
467       if (view_type != VK_IMAGE_VIEW_TYPE_3D)
468          depth = image->vk.array_layers;
469    } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
470       depth = image->vk.array_layers / 6;
471 
472    state[0] = 0;
473    state[1] = (S_008F14_MIN_LOD(radv_float_to_ufixed(CLAMP(min_lod, 0, 15), 8)) | S_008F14_DATA_FORMAT(data_format) |
474                S_008F14_NUM_FORMAT(num_format));
475    state[2] = (S_008F18_WIDTH(width - 1) | S_008F18_HEIGHT(height - 1) | S_008F18_PERF_MOD(4));
476    state[3] = (S_008F1C_DST_SEL_X(radv_map_swizzle(swizzle[0])) | S_008F1C_DST_SEL_Y(radv_map_swizzle(swizzle[1])) |
477                S_008F1C_DST_SEL_Z(radv_map_swizzle(swizzle[2])) | S_008F1C_DST_SEL_W(radv_map_swizzle(swizzle[3])) |
478                S_008F1C_BASE_LEVEL(image->vk.samples > 1 ? 0 : first_level) |
479                S_008F1C_LAST_LEVEL(image->vk.samples > 1 ? util_logbase2(image->vk.samples) : last_level) |
480                S_008F1C_TYPE(type));
481    state[4] = 0;
482    state[5] = S_008F24_BASE_ARRAY(first_layer);
483    state[6] = 0;
484    state[7] = 0;
485 
486    if (device->physical_device->rad_info.gfx_level == GFX9) {
487       unsigned bc_swizzle = gfx9_border_color_swizzle(desc);
488 
489       /* Depth is the last accessible layer on Gfx9.
490        * The hw doesn't need to know the total number of layers.
491        */
492       if (type == V_008F1C_SQ_RSRC_IMG_3D)
493          state[4] |= S_008F20_DEPTH(depth - 1);
494       else
495          state[4] |= S_008F20_DEPTH(last_layer);
496 
497       state[4] |= S_008F20_BC_SWIZZLE(bc_swizzle);
498       state[5] |= S_008F24_MAX_MIP(image->vk.samples > 1 ? util_logbase2(image->vk.samples) : image->vk.mip_levels - 1);
499    } else {
500       state[3] |= S_008F1C_POW2_PAD(image->vk.mip_levels > 1);
501       state[4] |= S_008F20_DEPTH(depth - 1);
502       state[5] |= S_008F24_LAST_ARRAY(last_layer);
503    }
504    if (!(image->planes[0].surface.flags & RADEON_SURF_Z_OR_SBUFFER) && image->planes[0].surface.meta_offset) {
505       state[6] = S_008F28_ALPHA_IS_ON_MSB(vi_alpha_is_on_msb(device, vk_format));
506    } else {
507       if (device->instance->drirc.disable_aniso_single_level) {
508          /* The last dword is unused by hw. The shader uses it to clear
509           * bits in the first dword of sampler state.
510           */
511          if (device->physical_device->rad_info.gfx_level <= GFX7 && image->vk.samples <= 1) {
512             if (first_level == last_level)
513                state[7] = C_008F30_MAX_ANISO_RATIO;
514             else
515                state[7] = 0xffffffff;
516          }
517       }
518    }
519 
520    /* Initialize the sampler view for FMASK. */
521    if (fmask_state) {
522       if (radv_image_has_fmask(image)) {
523          uint32_t fmask_format;
524          uint64_t gpu_address = radv_buffer_get_va(image->bindings[0].bo);
525          uint64_t va;
526 
527          assert(image->plane_count == 1);
528 
529          va = gpu_address + image->bindings[0].offset + image->planes[0].surface.fmask_offset;
530 
531          if (device->physical_device->rad_info.gfx_level == GFX9) {
532             fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK;
533             switch (image->vk.samples) {
534             case 2:
535                num_format = V_008F14_IMG_NUM_FORMAT_FMASK_8_2_2;
536                break;
537             case 4:
538                num_format = V_008F14_IMG_NUM_FORMAT_FMASK_8_4_4;
539                break;
540             case 8:
541                num_format = V_008F14_IMG_NUM_FORMAT_FMASK_32_8_8;
542                break;
543             default:
544                unreachable("invalid nr_samples");
545             }
546          } else {
547             switch (image->vk.samples) {
548             case 2:
549                fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
550                break;
551             case 4:
552                fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S4_F4;
553                break;
554             case 8:
555                fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
556                break;
557             default:
558                assert(0);
559                fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
560             }
561             num_format = V_008F14_IMG_NUM_FORMAT_UINT;
562          }
563 
564          fmask_state[0] = va >> 8;
565          fmask_state[0] |= image->planes[0].surface.fmask_tile_swizzle;
566          fmask_state[1] =
567             S_008F14_BASE_ADDRESS_HI(va >> 40) | S_008F14_DATA_FORMAT(fmask_format) | S_008F14_NUM_FORMAT(num_format);
568          fmask_state[2] = S_008F18_WIDTH(width - 1) | S_008F18_HEIGHT(height - 1);
569          fmask_state[3] =
570             S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
571             S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
572             S_008F1C_TYPE(radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, 0, false, false));
573          fmask_state[4] = 0;
574          fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);
575          fmask_state[6] = 0;
576          fmask_state[7] = 0;
577 
578          if (device->physical_device->rad_info.gfx_level == GFX9) {
579             fmask_state[3] |= S_008F1C_SW_MODE(image->planes[0].surface.u.gfx9.color.fmask_swizzle_mode);
580             fmask_state[4] |=
581                S_008F20_DEPTH(last_layer) | S_008F20_PITCH(image->planes[0].surface.u.gfx9.color.fmask_epitch);
582             fmask_state[5] |= S_008F24_META_PIPE_ALIGNED(1) | S_008F24_META_RB_ALIGNED(1);
583 
584             if (radv_image_is_tc_compat_cmask(image)) {
585                va = gpu_address + image->bindings[0].offset + image->planes[0].surface.cmask_offset;
586 
587                fmask_state[5] |= S_008F24_META_DATA_ADDRESS(va >> 40);
588                fmask_state[6] |= S_008F28_COMPRESSION_EN(1);
589                fmask_state[7] |= va >> 8;
590             }
591          } else {
592             fmask_state[3] |= S_008F1C_TILING_INDEX(image->planes[0].surface.u.legacy.color.fmask.tiling_index);
593             fmask_state[4] |= S_008F20_DEPTH(depth - 1) |
594                               S_008F20_PITCH(image->planes[0].surface.u.legacy.color.fmask.pitch_in_pixels - 1);
595             fmask_state[5] |= S_008F24_LAST_ARRAY(last_layer);
596 
597             if (radv_image_is_tc_compat_cmask(image)) {
598                va = gpu_address + image->bindings[0].offset + image->planes[0].surface.cmask_offset;
599 
600                fmask_state[6] |= S_008F28_COMPRESSION_EN(1);
601                fmask_state[7] |= va >> 8;
602             }
603          }
604       } else
605          memset(fmask_state, 0, 8 * 4);
606    }
607 }
608 
609 void
radv_make_texture_descriptor(struct radv_device * device,struct radv_image * image,bool is_storage_image,VkImageViewType view_type,VkFormat vk_format,const VkComponentMapping * mapping,unsigned first_level,unsigned last_level,unsigned first_layer,unsigned last_layer,unsigned width,unsigned height,unsigned depth,float min_lod,uint32_t * state,uint32_t * fmask_state,VkImageCreateFlags img_create_flags,const struct ac_surf_nbc_view * nbc_view,const VkImageViewSlicedCreateInfoEXT * sliced_3d)610 radv_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
611                              VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
612                              unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
613                              unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
614                              uint32_t *fmask_state, VkImageCreateFlags img_create_flags,
615                              const struct ac_surf_nbc_view *nbc_view, const VkImageViewSlicedCreateInfoEXT *sliced_3d)
616 {
617    if (device->physical_device->rad_info.gfx_level >= GFX10) {
618       gfx10_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping, first_level,
619                                     last_level, first_layer, last_layer, width, height, depth, min_lod, state,
620                                     fmask_state, img_create_flags, nbc_view, sliced_3d);
621    } else {
622       gfx6_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping, first_level,
623                                    last_level, first_layer, last_layer, width, height, depth, min_lod, state,
624                                    fmask_state, img_create_flags);
625    }
626 }
627 
628 static inline void
compute_non_block_compressed_view(struct radv_device * device,const struct radv_image_view * iview,struct ac_surf_nbc_view * nbc_view)629 compute_non_block_compressed_view(struct radv_device *device, const struct radv_image_view *iview,
630                                   struct ac_surf_nbc_view *nbc_view)
631 {
632    const struct radv_image *image = iview->image;
633    const struct radeon_surf *surf = &image->planes[0].surface;
634    struct ac_addrlib *addrlib = device->ws->get_addrlib(device->ws);
635    struct ac_surf_info surf_info = radv_get_ac_surf_info(device, image);
636 
637    ac_surface_compute_nbc_view(addrlib, &device->physical_device->rad_info, surf, &surf_info, iview->vk.base_mip_level,
638                                iview->vk.base_array_layer, nbc_view);
639 }
640 
641 static void
radv_image_view_make_descriptor(struct radv_image_view * iview,struct radv_device * device,VkFormat vk_format,const VkComponentMapping * components,float min_lod,bool is_storage_image,bool disable_compression,bool enable_compression,unsigned plane_id,unsigned descriptor_plane_id,VkImageCreateFlags img_create_flags,const struct ac_surf_nbc_view * nbc_view,const VkImageViewSlicedCreateInfoEXT * sliced_3d,bool force_zero_base_mip)642 radv_image_view_make_descriptor(struct radv_image_view *iview, struct radv_device *device, VkFormat vk_format,
643                                 const VkComponentMapping *components, float min_lod, bool is_storage_image,
644                                 bool disable_compression, bool enable_compression, unsigned plane_id,
645                                 unsigned descriptor_plane_id, VkImageCreateFlags img_create_flags,
646                                 const struct ac_surf_nbc_view *nbc_view,
647                                 const VkImageViewSlicedCreateInfoEXT *sliced_3d, bool force_zero_base_mip)
648 {
649    struct radv_image *image = iview->image;
650    struct radv_image_plane *plane = &image->planes[plane_id];
651    bool is_stencil = iview->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT;
652    unsigned first_layer = iview->vk.base_array_layer;
653    uint32_t blk_w;
654    union radv_descriptor *descriptor;
655    uint32_t hw_level = iview->vk.base_mip_level;
656 
657    if (is_storage_image) {
658       descriptor = &iview->storage_descriptor;
659    } else {
660       descriptor = &iview->descriptor;
661    }
662 
663    assert(vk_format_get_plane_count(vk_format) == 1);
664    assert(plane->surface.blk_w % vk_format_get_blockwidth(plane->format) == 0);
665    blk_w = plane->surface.blk_w / vk_format_get_blockwidth(plane->format) * vk_format_get_blockwidth(vk_format);
666 
667    if (device->physical_device->rad_info.gfx_level >= GFX9) {
668       if (nbc_view->valid) {
669          hw_level = nbc_view->level;
670          iview->extent.width = nbc_view->width;
671          iview->extent.height = nbc_view->height;
672 
673          /* Clear the base array layer because addrlib adds it as part of the base addr offset. */
674          first_layer = 0;
675       }
676    } else {
677       if (force_zero_base_mip)
678          hw_level = 0;
679    }
680 
681    radv_make_texture_descriptor(device, image, is_storage_image, iview->vk.view_type, vk_format, components, hw_level,
682                                 hw_level + iview->vk.level_count - 1, first_layer,
683                                 iview->vk.base_array_layer + iview->vk.layer_count - 1,
684                                 vk_format_get_plane_width(image->vk.format, plane_id, iview->extent.width),
685                                 vk_format_get_plane_height(image->vk.format, plane_id, iview->extent.height),
686                                 iview->extent.depth, min_lod, descriptor->plane_descriptors[descriptor_plane_id],
687                                 descriptor_plane_id || is_storage_image ? NULL : descriptor->fmask_descriptor,
688                                 img_create_flags, nbc_view, sliced_3d);
689 
690    const struct legacy_surf_level *base_level_info = NULL;
691    if (device->physical_device->rad_info.gfx_level <= GFX8) {
692       if (is_stencil)
693          base_level_info = &plane->surface.u.legacy.zs.stencil_level[iview->vk.base_mip_level];
694       else
695          base_level_info = &plane->surface.u.legacy.level[force_zero_base_mip ? iview->vk.base_mip_level : 0];
696    }
697 
698    bool enable_write_compression = radv_image_use_dcc_image_stores(device, image);
699    if (is_storage_image && !(enable_write_compression || enable_compression))
700       disable_compression = true;
701    radv_set_mutable_tex_desc_fields(device, image, base_level_info, plane_id, iview->vk.base_mip_level,
702                                     iview->vk.base_mip_level, blk_w, is_stencil, is_storage_image, disable_compression,
703                                     enable_write_compression, descriptor->plane_descriptors[descriptor_plane_id],
704                                     nbc_view);
705 }
706 
707 /**
708  * Determine if the given image view can be fast cleared.
709  */
710 static bool
radv_image_view_can_fast_clear(const struct radv_device * device,const struct radv_image_view * iview)711 radv_image_view_can_fast_clear(const struct radv_device *device, const struct radv_image_view *iview)
712 {
713    struct radv_image *image;
714 
715    if (!iview)
716       return false;
717    image = iview->image;
718 
719    /* Only fast clear if the image itself can be fast cleared. */
720    if (!radv_image_can_fast_clear(device, image))
721       return false;
722 
723    /* Only fast clear if all layers are bound. */
724    if (iview->vk.base_array_layer > 0 || iview->vk.layer_count != image->vk.array_layers)
725       return false;
726 
727    /* Only fast clear if the view covers the whole image. */
728    if (!radv_image_extent_compare(image, &iview->extent))
729       return false;
730 
731    return true;
732 }
733 
734 void
radv_image_view_init(struct radv_image_view * iview,struct radv_device * device,const VkImageViewCreateInfo * pCreateInfo,VkImageCreateFlags img_create_flags,const struct radv_image_view_extra_create_info * extra_create_info)735 radv_image_view_init(struct radv_image_view *iview, struct radv_device *device,
736                      const VkImageViewCreateInfo *pCreateInfo, VkImageCreateFlags img_create_flags,
737                      const struct radv_image_view_extra_create_info *extra_create_info)
738 {
739    RADV_FROM_HANDLE(radv_image, image, pCreateInfo->image);
740    const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
741    uint32_t plane_count = 1;
742    float min_lod = 0.0f;
743 
744    const struct VkImageViewMinLodCreateInfoEXT *min_lod_info =
745       vk_find_struct_const(pCreateInfo->pNext, IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT);
746 
747    if (min_lod_info)
748       min_lod = min_lod_info->minLod;
749 
750    const struct VkImageViewSlicedCreateInfoEXT *sliced_3d =
751       vk_find_struct_const(pCreateInfo->pNext, IMAGE_VIEW_SLICED_CREATE_INFO_EXT);
752 
753    bool from_client = extra_create_info && extra_create_info->from_client;
754    vk_image_view_init(&device->vk, &iview->vk, !from_client, pCreateInfo);
755 
756    bool force_zero_base_mip = true;
757    if (device->physical_device->rad_info.gfx_level <= GFX8 && min_lod) {
758       /* Do not force the base level to zero to workaround a spurious bug with mipmaps and min LOD. */
759       force_zero_base_mip = false;
760    }
761 
762    switch (image->vk.image_type) {
763    case VK_IMAGE_TYPE_1D:
764    case VK_IMAGE_TYPE_2D:
765       assert(range->baseArrayLayer + vk_image_subresource_layer_count(&image->vk, range) - 1 <= image->vk.array_layers);
766       break;
767    case VK_IMAGE_TYPE_3D:
768       assert(range->baseArrayLayer + vk_image_subresource_layer_count(&image->vk, range) - 1 <=
769              radv_minify(image->vk.extent.depth, range->baseMipLevel));
770       break;
771    default:
772       unreachable("bad VkImageType");
773    }
774    iview->image = image;
775    iview->plane_id = radv_plane_from_aspect(pCreateInfo->subresourceRange.aspectMask);
776    iview->nbc_view.valid = false;
777 
778    /* If the image has an Android external format, pCreateInfo->format will be
779     * VK_FORMAT_UNDEFINED. */
780    if (iview->vk.format == VK_FORMAT_UNDEFINED) {
781       iview->vk.format = image->vk.format;
782       iview->vk.view_format = image->vk.format;
783    }
784 
785    /* Split out the right aspect. Note that for internal meta code we sometimes
786     * use an equivalent color format for the aspect so we first have to check
787     * if we actually got depth/stencil formats. */
788    if (iview->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
789       if (vk_format_has_stencil(iview->vk.view_format))
790          iview->vk.view_format = vk_format_stencil_only(iview->vk.view_format);
791    } else if (iview->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
792       if (vk_format_has_depth(iview->vk.view_format))
793          iview->vk.view_format = vk_format_depth_only(iview->vk.view_format);
794    }
795 
796    if (vk_format_get_plane_count(image->vk.format) > 1 &&
797        pCreateInfo->subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
798       plane_count = vk_format_get_plane_count(iview->vk.format);
799    }
800 
801    /* when the view format is emulated, redirect the view to the hidden plane 1 */
802    if (radv_is_format_emulated(device->physical_device, iview->vk.format)) {
803       assert(radv_is_format_emulated(device->physical_device, image->vk.format));
804       iview->plane_id = 1;
805       iview->vk.view_format = image->planes[iview->plane_id].format;
806       iview->vk.format = image->planes[iview->plane_id].format;
807       plane_count = 1;
808    }
809 
810    if (!force_zero_base_mip || device->physical_device->rad_info.gfx_level >= GFX9) {
811       iview->extent = (VkExtent3D){
812          .width = image->vk.extent.width,
813          .height = image->vk.extent.height,
814          .depth = image->vk.extent.depth,
815       };
816    } else {
817       iview->extent = iview->vk.extent;
818    }
819 
820    if (iview->vk.format != image->planes[iview->plane_id].format) {
821       const struct radv_image_plane *plane = &image->planes[iview->plane_id];
822       unsigned view_bw = vk_format_get_blockwidth(iview->vk.format);
823       unsigned view_bh = vk_format_get_blockheight(iview->vk.format);
824       unsigned plane_bw = vk_format_get_blockwidth(plane->format);
825       unsigned plane_bh = vk_format_get_blockheight(plane->format);
826 
827       iview->extent.width = DIV_ROUND_UP(iview->extent.width * view_bw, plane_bw);
828       iview->extent.height = DIV_ROUND_UP(iview->extent.height * view_bh, plane_bh);
829 
830       /* Comment ported from amdvlk -
831        * If we have the following image:
832        *              Uncompressed pixels   Compressed block sizes (4x4)
833        *      mip0:       22 x 22                   6 x 6
834        *      mip1:       11 x 11                   3 x 3
835        *      mip2:        5 x  5                   2 x 2
836        *      mip3:        2 x  2                   1 x 1
837        *      mip4:        1 x  1                   1 x 1
838        *
839        * On GFX9 the descriptor is always programmed with the WIDTH and HEIGHT of the base level and
840        * the HW is calculating the degradation of the block sizes down the mip-chain as follows
841        * (straight-up divide-by-two integer math): mip0:  6x6 mip1:  3x3 mip2:  1x1 mip3:  1x1
842        *
843        * This means that mip2 will be missing texels.
844        *
845        * Fix this by calculating the base mip's width and height, then convert
846        * that, and round it back up to get the level 0 size. Clamp the
847        * converted size between the original values, and the physical extent
848        * of the base mipmap.
849        *
850        * On GFX10 we have to take care to not go over the physical extent
851        * of the base mipmap as otherwise the GPU computes a different layout.
852        * Note that the GPU does use the same base-mip dimensions for both a
853        * block compatible format and the compressed format, so even if we take
854        * the plain converted dimensions the physical layout is correct.
855        */
856       if (device->physical_device->rad_info.gfx_level >= GFX9 && vk_format_is_block_compressed(plane->format) &&
857           !vk_format_is_block_compressed(iview->vk.format)) {
858          /* If we have multiple levels in the view we should ideally take the last level,
859           * but the mip calculation has a max(..., 1) so walking back to the base mip in an
860           * useful way is hard. */
861          if (iview->vk.level_count > 1) {
862             iview->extent.width = plane->surface.u.gfx9.base_mip_width;
863             iview->extent.height = plane->surface.u.gfx9.base_mip_height;
864          } else {
865             unsigned lvl_width = radv_minify(image->vk.extent.width, range->baseMipLevel);
866             unsigned lvl_height = radv_minify(image->vk.extent.height, range->baseMipLevel);
867 
868             lvl_width = DIV_ROUND_UP(lvl_width * view_bw, plane_bw);
869             lvl_height = DIV_ROUND_UP(lvl_height * view_bh, plane_bh);
870 
871             iview->extent.width =
872                CLAMP(lvl_width << range->baseMipLevel, iview->extent.width, plane->surface.u.gfx9.base_mip_width);
873             iview->extent.height =
874                CLAMP(lvl_height << range->baseMipLevel, iview->extent.height, plane->surface.u.gfx9.base_mip_height);
875 
876             /* If the hardware-computed extent is still be too small, on GFX10
877              * we can attempt another workaround provided by addrlib that
878              * changes the descriptor's base level, and adjusts the address and
879              * extents accordingly.
880              */
881             if (device->physical_device->rad_info.gfx_level >= GFX10 &&
882                 (radv_minify(iview->extent.width, range->baseMipLevel) < lvl_width ||
883                  radv_minify(iview->extent.height, range->baseMipLevel) < lvl_height) &&
884                 iview->vk.layer_count == 1) {
885                compute_non_block_compressed_view(device, iview, &iview->nbc_view);
886             }
887          }
888       }
889    }
890 
891    iview->support_fast_clear = radv_image_view_can_fast_clear(device, iview);
892    iview->disable_dcc_mrt = extra_create_info ? extra_create_info->disable_dcc_mrt : false;
893 
894    bool disable_compression = extra_create_info ? extra_create_info->disable_compression : false;
895    bool enable_compression = extra_create_info ? extra_create_info->enable_compression : false;
896    for (unsigned i = 0; i < plane_count; ++i) {
897       VkFormat format = vk_format_get_plane_format(iview->vk.view_format, i);
898       radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, min_lod, false,
899                                       disable_compression, enable_compression, iview->plane_id + i, i, img_create_flags,
900                                       &iview->nbc_view, NULL, force_zero_base_mip);
901       radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, min_lod, true,
902                                       disable_compression, enable_compression, iview->plane_id + i, i, img_create_flags,
903                                       &iview->nbc_view, sliced_3d, force_zero_base_mip);
904    }
905 }
906 
907 void
radv_image_view_finish(struct radv_image_view * iview)908 radv_image_view_finish(struct radv_image_view *iview)
909 {
910    vk_image_view_finish(&iview->vk);
911 }
912 
913 VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)914 radv_CreateImageView(VkDevice _device, const VkImageViewCreateInfo *pCreateInfo,
915                      const VkAllocationCallbacks *pAllocator, VkImageView *pView)
916 {
917    RADV_FROM_HANDLE(radv_image, image, pCreateInfo->image);
918    RADV_FROM_HANDLE(radv_device, device, _device);
919    struct radv_image_view *view;
920 
921    view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
922    if (view == NULL)
923       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
924 
925    radv_image_view_init(view, device, pCreateInfo, image->vk.create_flags,
926                         &(struct radv_image_view_extra_create_info){.from_client = true});
927 
928    *pView = radv_image_view_to_handle(view);
929 
930    return VK_SUCCESS;
931 }
932 
933 VKAPI_ATTR void VKAPI_CALL
radv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)934 radv_DestroyImageView(VkDevice _device, VkImageView _iview, const VkAllocationCallbacks *pAllocator)
935 {
936    RADV_FROM_HANDLE(radv_device, device, _device);
937    RADV_FROM_HANDLE(radv_image_view, iview, _iview);
938 
939    if (!iview)
940       return;
941 
942    radv_image_view_finish(iview);
943    vk_free2(&device->vk.alloc, pAllocator, iview);
944 }
945