• 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  * SPDX-License-Identifier: MIT
9  */
10 
11 #include "vk_log.h"
12 
13 #include "radv_image_view.h"
14 #include "radv_buffer_view.h"
15 #include "radv_entrypoints.h"
16 #include "radv_formats.h"
17 #include "radv_image.h"
18 
19 #include "ac_descriptors.h"
20 #include "ac_formats.h"
21 #include "gfx10_format_table.h"
22 
23 static unsigned
radv_tex_dim(VkImageType image_type,VkImageViewType view_type,unsigned nr_layers,unsigned nr_samples,bool is_storage_image,bool gfx9)24 radv_tex_dim(VkImageType image_type, VkImageViewType view_type, unsigned nr_layers, unsigned nr_samples,
25              bool is_storage_image, bool gfx9)
26 {
27    if (view_type == VK_IMAGE_VIEW_TYPE_CUBE || view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
28       return is_storage_image ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_CUBE;
29 
30    /* GFX9 allocates 1D textures as 2D. */
31    if (gfx9 && image_type == VK_IMAGE_TYPE_1D)
32       image_type = VK_IMAGE_TYPE_2D;
33    switch (image_type) {
34    case VK_IMAGE_TYPE_1D:
35       return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_1D_ARRAY : V_008F1C_SQ_RSRC_IMG_1D;
36    case VK_IMAGE_TYPE_2D:
37       if (nr_samples > 1)
38          return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY : V_008F1C_SQ_RSRC_IMG_2D_MSAA;
39       else
40          return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_2D;
41    case VK_IMAGE_TYPE_3D:
42       if (view_type == VK_IMAGE_VIEW_TYPE_3D)
43          return V_008F1C_SQ_RSRC_IMG_3D;
44       else
45          return V_008F1C_SQ_RSRC_IMG_2D_ARRAY;
46    default:
47       unreachable("illegal image type");
48    }
49 }
50 
51 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,uint64_t offset)52 radv_set_mutable_tex_desc_fields(struct radv_device *device, struct radv_image *image,
53                                  const struct legacy_surf_level *base_level_info, unsigned plane_id,
54                                  unsigned base_level, unsigned first_level, unsigned block_width, bool is_stencil,
55                                  bool is_storage_image, bool disable_compression, bool enable_write_compression,
56                                  uint32_t *state, const struct ac_surf_nbc_view *nbc_view, uint64_t offset)
57 {
58    const struct radv_physical_device *pdev = radv_device_physical(device);
59    struct radv_image_plane *plane = &image->planes[plane_id];
60    const uint32_t bind_idx = image->disjoint ? plane_id : 0;
61    struct radv_image_binding *binding = &image->bindings[bind_idx];
62    uint64_t gpu_address = binding->bo ? radv_image_get_va(image, bind_idx) + offset : 0;
63    const bool dcc_enabled = pdev->info.gfx_level >= GFX12 || radv_dcc_enabled(image, first_level);
64 
65    const struct ac_mutable_tex_state ac_state = {
66       .surf = &plane->surface,
67       .va = gpu_address,
68       .gfx10 =
69          {
70             .write_compress_enable = dcc_enabled && is_storage_image && enable_write_compression,
71             .iterate_256 = radv_image_get_iterate256(device, image),
72          },
73       .gfx9 =
74          {
75             .nbc_view = nbc_view,
76          },
77       .gfx6 =
78          {
79             .base_level_info = base_level_info,
80             .base_level = base_level,
81             .block_width = block_width,
82          },
83       .is_stencil = is_stencil,
84       .dcc_enabled = !disable_compression && dcc_enabled,
85       .tc_compat_htile_enabled = !disable_compression && radv_image_is_tc_compat_htile(image),
86    };
87 
88    ac_set_mutable_tex_desc_fields(&pdev->info, &ac_state, state);
89 }
90 
91 /**
92  * Build the sampler view descriptor for a texture (GFX10).
93  */
94 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,const struct ac_surf_nbc_view * nbc_view,const VkImageViewSlicedCreateInfoEXT * sliced_3d)95 gfx10_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
96                               VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
97                               unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
98                               unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
99                               uint32_t *fmask_state, const struct ac_surf_nbc_view *nbc_view,
100                               const VkImageViewSlicedCreateInfoEXT *sliced_3d)
101 {
102    const struct radv_physical_device *pdev = radv_device_physical(device);
103    const bool create_2d_view_of_3d =
104       (image->vk.create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) && view_type == VK_IMAGE_VIEW_TYPE_2D;
105    enum pipe_format format = radv_format_to_pipe_format(vk_format);
106    const struct util_format_description *desc;
107    enum pipe_swizzle swizzle[4];
108    unsigned array_pitch = 0;
109    unsigned type;
110 
111    /* For emulated ETC2 without alpha we need to override the format to a 3-componenent format, so
112     * that border colors work correctly (alpha forced to 1). Since Vulkan has no such format,
113     * this uses the Gallium formats to set the description. */
114    if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK && format == PIPE_FORMAT_R8G8B8A8_UNORM) {
115       format = PIPE_FORMAT_R8G8B8X8_UNORM;
116    } else if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK && format == PIPE_FORMAT_R8G8B8A8_SRGB) {
117       format = PIPE_FORMAT_R8G8B8X8_SRGB;
118    }
119 
120    desc = util_format_description(format);
121 
122    radv_compose_swizzle(desc, mapping, swizzle);
123 
124    if (create_2d_view_of_3d) {
125       assert(image->vk.image_type == VK_IMAGE_TYPE_3D);
126       type = V_008F1C_SQ_RSRC_IMG_3D;
127    } else {
128       type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, image->vk.samples, is_storage_image,
129                           pdev->info.gfx_level == GFX9);
130    }
131 
132    if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
133       height = 1;
134       depth = image->vk.array_layers;
135    } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
136       if (view_type != VK_IMAGE_VIEW_TYPE_3D)
137          depth = image->vk.array_layers;
138    } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
139       depth = image->vk.array_layers / 6;
140 
141    if (create_2d_view_of_3d) {
142       assert(type == V_008F1C_SQ_RSRC_IMG_3D);
143 
144       depth = !is_storage_image ? depth : u_minify(depth, first_level);
145       array_pitch = is_storage_image;
146    } else if (sliced_3d) {
147       assert(type == V_008F1C_SQ_RSRC_IMG_3D && is_storage_image);
148 
149       const unsigned total = u_minify(depth, first_level);
150       const unsigned slice_count = sliced_3d->sliceCount == VK_REMAINING_3D_SLICES_EXT
151                                       ? MAX2(1, total - sliced_3d->sliceOffset)
152                                       : sliced_3d->sliceCount;
153 
154       first_layer = sliced_3d->sliceOffset;
155       depth = sliced_3d->sliceOffset + slice_count;
156       array_pitch = 1;
157    }
158 
159    const struct ac_texture_state tex_state = {
160       .surf = &image->planes[0].surface,
161       .format = format,
162       .img_format = radv_format_to_pipe_format(image->vk.format),
163       .width = width,
164       .height = height,
165       .depth = type == V_008F1C_SQ_RSRC_IMG_3D ? depth - 1 : last_layer,
166       .type = type,
167       .swizzle =
168          {
169             swizzle[0],
170             swizzle[1],
171             swizzle[2],
172             swizzle[3],
173          },
174       .num_samples = image->vk.samples,
175       .num_storage_samples = image->vk.samples,
176       .first_level = first_level,
177       .last_level = last_level,
178       .num_levels = image->vk.mip_levels,
179       .first_layer = first_layer,
180       .last_layer = last_layer,
181       .min_lod = min_lod,
182       .gfx10 =
183          {
184             .uav3d = array_pitch,
185          },
186       .gfx9 =
187          {
188             .nbc_view = nbc_view,
189          },
190       .dcc_enabled = radv_dcc_enabled(image, first_level),
191       .tc_compat_htile_enabled = radv_image_is_tc_compat_htile(image),
192    };
193 
194    ac_build_texture_descriptor(&pdev->info, &tex_state, &state[0]);
195 
196    /* Initialize the sampler view for FMASK. */
197    if (fmask_state) {
198       if (radv_image_has_fmask(image)) {
199          assert(image->plane_count == 1);
200 
201          const struct ac_fmask_state ac_state = {
202             .surf = &image->planes[0].surface,
203             .va = radv_image_get_va(image, 0),
204             .width = width,
205             .height = height,
206             .depth = depth,
207             .type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, 0, false, false),
208             .first_layer = first_layer,
209             .last_layer = last_layer,
210             .num_samples = image->vk.samples,
211             .num_storage_samples = image->vk.samples,
212             .tc_compat_cmask = radv_image_is_tc_compat_cmask(image),
213          };
214 
215          ac_build_fmask_descriptor(pdev->info.gfx_level, &ac_state, &fmask_state[0]);
216       } else
217          memset(fmask_state, 0, 8 * 4);
218    }
219 }
220 
221 /**
222  * Build the sampler view descriptor for a texture (SI-GFX9)
223  */
224 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)225 gfx6_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
226                              VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
227                              unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
228                              unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
229                              uint32_t *fmask_state)
230 {
231    const struct radv_physical_device *pdev = radv_device_physical(device);
232    const struct radv_instance *instance = radv_physical_device_instance(pdev);
233    enum pipe_format format = radv_format_to_pipe_format(vk_format);
234    const bool create_2d_view_of_3d =
235       (image->vk.create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) && view_type == VK_IMAGE_VIEW_TYPE_2D;
236    const struct util_format_description *desc;
237    enum pipe_swizzle swizzle[4];
238    unsigned type;
239 
240    /* For emulated ETC2 without alpha we need to override the format to a 3-componenent format, so
241     * that border colors work correctly (alpha forced to 1). Since Vulkan has no such format,
242     * this uses the Gallium formats to set the description. */
243    if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK && format == PIPE_FORMAT_R8G8B8A8_UNORM) {
244       format = PIPE_FORMAT_R8G8B8X8_UNORM;
245    } else if (image->vk.format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK && format == PIPE_FORMAT_R8G8B8A8_SRGB) {
246       format = PIPE_FORMAT_R8G8B8X8_SRGB;
247    }
248 
249    desc = util_format_description(format);
250 
251    radv_compose_swizzle(desc, mapping, swizzle);
252 
253    if (pdev->info.gfx_level == GFX9 && create_2d_view_of_3d) {
254       assert(image->vk.image_type == VK_IMAGE_TYPE_3D);
255       type = V_008F1C_SQ_RSRC_IMG_3D;
256    } else {
257       type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, image->vk.samples, is_storage_image,
258                           pdev->info.gfx_level == GFX9);
259    }
260 
261    if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
262       height = 1;
263       depth = image->vk.array_layers;
264    } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
265       if (view_type != VK_IMAGE_VIEW_TYPE_3D)
266          depth = image->vk.array_layers;
267    } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
268       depth = image->vk.array_layers / 6;
269 
270    const struct ac_texture_state tex_state = {
271       .surf = &image->planes[0].surface,
272       .format = format,
273       .img_format = radv_format_to_pipe_format(image->vk.format),
274       .width = width,
275       .height = height,
276       .depth = depth,
277       .type = type,
278       .swizzle =
279          {
280             swizzle[0],
281             swizzle[1],
282             swizzle[2],
283             swizzle[3],
284          },
285       .num_samples = image->vk.samples,
286       .num_storage_samples = image->vk.samples,
287       .first_level = first_level,
288       .last_level = last_level,
289       .num_levels = image->vk.mip_levels,
290       .first_layer = first_layer,
291       .last_layer = last_layer,
292       .min_lod = min_lod,
293       .dcc_enabled = radv_dcc_enabled(image, first_level),
294       .tc_compat_htile_enabled = radv_image_is_tc_compat_htile(image),
295       .aniso_single_level = !instance->drirc.disable_aniso_single_level,
296    };
297 
298    ac_build_texture_descriptor(&pdev->info, &tex_state, &state[0]);
299 
300    /* Initialize the sampler view for FMASK. */
301    if (fmask_state) {
302       if (radv_image_has_fmask(image)) {
303          assert(image->plane_count == 1);
304 
305          const struct ac_fmask_state ac_fmask_state = {
306             .surf = &image->planes[0].surface,
307             .va = radv_image_get_va(image, 0),
308             .width = width,
309             .height = height,
310             .depth = depth,
311             .type = radv_tex_dim(image->vk.image_type, view_type, image->vk.array_layers, 0, false, false),
312             .first_layer = first_layer,
313             .last_layer = last_layer,
314             .num_samples = image->vk.samples,
315             .num_storage_samples = image->vk.samples,
316             .tc_compat_cmask = radv_image_is_tc_compat_cmask(image),
317          };
318 
319          ac_build_fmask_descriptor(pdev->info.gfx_level, &ac_fmask_state, &fmask_state[0]);
320       } else
321          memset(fmask_state, 0, 8 * 4);
322    }
323 }
324 
325 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,const struct ac_surf_nbc_view * nbc_view,const VkImageViewSlicedCreateInfoEXT * sliced_3d)326 radv_make_texture_descriptor(struct radv_device *device, struct radv_image *image, bool is_storage_image,
327                              VkImageViewType view_type, VkFormat vk_format, const VkComponentMapping *mapping,
328                              unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer,
329                              unsigned width, unsigned height, unsigned depth, float min_lod, uint32_t *state,
330                              uint32_t *fmask_state, const struct ac_surf_nbc_view *nbc_view,
331                              const VkImageViewSlicedCreateInfoEXT *sliced_3d)
332 {
333    const struct radv_physical_device *pdev = radv_device_physical(device);
334 
335    if (pdev->info.gfx_level >= GFX10) {
336       gfx10_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping, first_level,
337                                     last_level, first_layer, last_layer, width, height, depth, min_lod, state,
338                                     fmask_state, nbc_view, sliced_3d);
339    } else {
340       gfx6_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping, first_level,
341                                    last_level, first_layer, last_layer, width, height, depth, min_lod, state,
342                                    fmask_state);
343    }
344 }
345 
346 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)347 compute_non_block_compressed_view(struct radv_device *device, const struct radv_image_view *iview,
348                                   struct ac_surf_nbc_view *nbc_view)
349 {
350    const struct radv_physical_device *pdev = radv_device_physical(device);
351    const struct radv_image *image = iview->image;
352    const struct radeon_surf *surf = &image->planes[0].surface;
353    struct ac_surf_info surf_info = radv_get_ac_surf_info(device, image);
354 
355    ac_surface_compute_nbc_view(pdev->addrlib, &pdev->info, surf, &surf_info, iview->vk.base_mip_level,
356                                iview->vk.base_array_layer, nbc_view);
357 }
358 
359 static void
radv_image_view_make_descriptor(struct radv_image_view * iview,struct radv_device * device,VkFormat vk_format,const VkComponentMapping * components,bool is_storage_image,bool disable_compression,bool enable_compression,unsigned plane_id,unsigned descriptor_plane_id,const VkImageViewSlicedCreateInfoEXT * sliced_3d)360 radv_image_view_make_descriptor(struct radv_image_view *iview, struct radv_device *device, VkFormat vk_format,
361                                 const VkComponentMapping *components, bool is_storage_image, bool disable_compression,
362                                 bool enable_compression, unsigned plane_id, unsigned descriptor_plane_id,
363                                 const VkImageViewSlicedCreateInfoEXT *sliced_3d)
364 {
365    const struct radv_physical_device *pdev = radv_device_physical(device);
366    struct radv_image *image = iview->image;
367    struct radv_image_plane *plane = &image->planes[plane_id];
368    bool is_stencil = iview->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT;
369    unsigned first_layer = iview->vk.base_array_layer;
370    uint32_t blk_w;
371    union radv_descriptor *descriptor;
372    uint32_t hw_level = iview->vk.base_mip_level;
373    bool force_zero_base_mip = false;
374    uint64_t offset = 0;
375 
376    if (is_storage_image) {
377       descriptor = &iview->storage_descriptor;
378    } else {
379       descriptor = &iview->descriptor;
380    }
381 
382    assert(vk_format_get_plane_count(vk_format) == 1);
383    assert(plane->surface.blk_w % vk_format_get_blockwidth(plane->format) == 0);
384    blk_w = plane->surface.blk_w / vk_format_get_blockwidth(plane->format) * vk_format_get_blockwidth(vk_format);
385 
386    VkExtent3D extent = {
387       .width = iview->extent.width,
388       .height = iview->extent.height,
389       .depth = iview->extent.depth,
390    };
391 
392    if (pdev->info.gfx_level >= GFX9) {
393       if (iview->nbc_view.valid) {
394          hw_level = iview->nbc_view.level;
395 
396          /* Clear the base array layer because addrlib adds it as part of the base addr offset. */
397          first_layer = 0;
398       } else {
399          /* Video decode target uses custom height alignment. */
400          if (image->vk.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) {
401             assert(image->planes[plane_id].surface.u.gfx9.swizzle_mode == 0);
402             offset += first_layer * image->planes[plane_id].surface.u.gfx9.surf_slice_size;
403             first_layer = 0;
404          }
405       }
406    } else {
407       /* On GFX6-8, there are some cases where the view must use mip0 and minified image sizes:
408        * - storage descriptors
409        * - block compressed images
410        * - depth view of a depth/stencil image (ie. depth/stencil pitch adjustments)
411        * - 2d view of a 3d image
412        */
413       if (is_storage_image) {
414          force_zero_base_mip = true;
415       } else if (vk_format_is_block_compressed(image->planes[plane_id].format)) {
416          force_zero_base_mip = true;
417       } else if (iview->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT &&
418                  (iview->image->vk.aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
419          force_zero_base_mip = true;
420       } else if (iview->image->vk.create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT &&
421                  iview->vk.view_type == VK_IMAGE_VIEW_TYPE_2D) {
422          force_zero_base_mip = true;
423       }
424 
425       if (force_zero_base_mip) {
426          hw_level = 0;
427       } else {
428          extent.width = image->vk.extent.width;
429          extent.height = image->vk.extent.height;
430          extent.depth = image->vk.extent.depth;
431       }
432 
433       /* Video decode target uses custom height alignment. */
434       if (image->vk.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) {
435          offset += first_layer * image->planes[plane_id].surface.u.legacy.level[0].slice_size_dw * 4;
436          first_layer = 0;
437       }
438    }
439 
440    radv_make_texture_descriptor(
441       device, image, is_storage_image, iview->vk.view_type, vk_format, components, hw_level,
442       hw_level + iview->vk.level_count - 1, first_layer, iview->vk.base_array_layer + iview->vk.layer_count - 1,
443       vk_format_get_plane_width(image->vk.format, plane_id, extent.width),
444       vk_format_get_plane_height(image->vk.format, plane_id, extent.height), extent.depth, iview->vk.min_lod,
445       descriptor->plane_descriptors[descriptor_plane_id],
446       descriptor_plane_id || is_storage_image ? NULL : descriptor->fmask_descriptor, &iview->nbc_view, sliced_3d);
447 
448    const struct legacy_surf_level *base_level_info = NULL;
449    if (pdev->info.gfx_level <= GFX8) {
450       if (is_stencil)
451          base_level_info =
452             &plane->surface.u.legacy.zs.stencil_level[force_zero_base_mip ? iview->vk.base_mip_level : 0];
453       else
454          base_level_info = &plane->surface.u.legacy.level[force_zero_base_mip ? iview->vk.base_mip_level : 0];
455    }
456 
457    bool enable_write_compression = radv_image_use_dcc_image_stores(device, image);
458    if (is_storage_image && !(enable_write_compression || enable_compression))
459       disable_compression = true;
460 
461    radv_set_mutable_tex_desc_fields(device, image, base_level_info, plane_id,
462                                     force_zero_base_mip ? iview->vk.base_mip_level : 0, iview->vk.base_mip_level, blk_w,
463                                     is_stencil, is_storage_image, disable_compression, enable_write_compression,
464                                     descriptor->plane_descriptors[descriptor_plane_id], &iview->nbc_view, offset);
465 }
466 
467 /**
468  * Determine if the given image view can be fast cleared.
469  */
470 static bool
radv_image_view_can_fast_clear(const struct radv_device * device,const struct radv_image_view * iview)471 radv_image_view_can_fast_clear(const struct radv_device *device, const struct radv_image_view *iview)
472 {
473    struct radv_image *image;
474 
475    if (!iview)
476       return false;
477    image = iview->image;
478 
479    /* Only fast clear if the image itself can be fast cleared. */
480    if (!radv_image_can_fast_clear(device, image))
481       return false;
482 
483    /* Only fast clear if all layers are bound. */
484    if (iview->vk.base_array_layer > 0 || iview->vk.layer_count != image->vk.array_layers)
485       return false;
486 
487    /* Only fast clear if the view covers the whole image. */
488    if (!radv_image_extent_compare(image, &iview->extent))
489       return false;
490 
491    return true;
492 }
493 
494 void
radv_image_view_init(struct radv_image_view * iview,struct radv_device * device,const VkImageViewCreateInfo * pCreateInfo,const struct radv_image_view_extra_create_info * extra_create_info)495 radv_image_view_init(struct radv_image_view *iview, struct radv_device *device,
496                      const VkImageViewCreateInfo *pCreateInfo,
497                      const struct radv_image_view_extra_create_info *extra_create_info)
498 {
499    VK_FROM_HANDLE(radv_image, image, pCreateInfo->image);
500    const struct radv_physical_device *pdev = radv_device_physical(device);
501    uint32_t plane_count = 1;
502 
503    const struct VkImageViewSlicedCreateInfoEXT *sliced_3d =
504       vk_find_struct_const(pCreateInfo->pNext, IMAGE_VIEW_SLICED_CREATE_INFO_EXT);
505 
506    bool from_client = extra_create_info && extra_create_info->from_client;
507    vk_image_view_init(&device->vk, &iview->vk, !from_client, pCreateInfo);
508 
509    iview->image = image;
510    iview->plane_id = radv_plane_from_aspect(pCreateInfo->subresourceRange.aspectMask);
511    iview->nbc_view.valid = false;
512 
513    /* If the image has an Android external format, pCreateInfo->format will be
514     * VK_FORMAT_UNDEFINED. */
515    if (iview->vk.format == VK_FORMAT_UNDEFINED) {
516       iview->vk.format = image->vk.format;
517       iview->vk.view_format = image->vk.format;
518    }
519 
520    /* Split out the right aspect. Note that for internal meta code we sometimes
521     * use an equivalent color format for the aspect so we first have to check
522     * if we actually got depth/stencil formats. */
523    if (iview->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
524       if (vk_format_has_stencil(iview->vk.view_format))
525          iview->vk.view_format = vk_format_stencil_only(iview->vk.view_format);
526    } else if (iview->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
527       if (vk_format_has_depth(iview->vk.view_format))
528          iview->vk.view_format = vk_format_depth_only(iview->vk.view_format);
529    }
530 
531    if (vk_format_get_plane_count(image->vk.format) > 1 &&
532        pCreateInfo->subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
533       plane_count = vk_format_get_plane_count(iview->vk.format);
534    }
535 
536    /* when the view format is emulated, redirect the view to the hidden plane 1 */
537    if (radv_is_format_emulated(pdev, iview->vk.format)) {
538       assert(radv_is_format_emulated(pdev, image->vk.format));
539       iview->plane_id = 1;
540       iview->vk.view_format = image->planes[iview->plane_id].format;
541       iview->vk.format = image->planes[iview->plane_id].format;
542       plane_count = 1;
543    }
544 
545    if (pdev->info.gfx_level >= GFX9) {
546       iview->extent = (VkExtent3D){
547          .width = image->vk.extent.width,
548          .height = image->vk.extent.height,
549          .depth = image->vk.extent.depth,
550       };
551    } else {
552       /* On GFX6-8, CB/DS surfaces use minified images sizes because the mip level can't be
553        * specified in registers.
554        */
555       iview->extent = vk_image_mip_level_extent(&image->vk, iview->vk.base_mip_level);
556    }
557 
558    if (iview->vk.format != image->planes[iview->plane_id].format) {
559       const struct radv_image_plane *plane = &image->planes[iview->plane_id];
560       unsigned view_bw = vk_format_get_blockwidth(iview->vk.format);
561       unsigned view_bh = vk_format_get_blockheight(iview->vk.format);
562       unsigned plane_bw = vk_format_get_blockwidth(plane->format);
563       unsigned plane_bh = vk_format_get_blockheight(plane->format);
564 
565       iview->extent.width = DIV_ROUND_UP(iview->extent.width * view_bw, plane_bw);
566       iview->extent.height = DIV_ROUND_UP(iview->extent.height * view_bh, plane_bh);
567 
568       /* Comment ported from amdvlk -
569        * If we have the following image:
570        *              Uncompressed pixels   Compressed block sizes (4x4)
571        *      mip0:       22 x 22                   6 x 6
572        *      mip1:       11 x 11                   3 x 3
573        *      mip2:        5 x  5                   2 x 2
574        *      mip3:        2 x  2                   1 x 1
575        *      mip4:        1 x  1                   1 x 1
576        *
577        * On GFX9 the descriptor is always programmed with the WIDTH and HEIGHT of the base level and
578        * the HW is calculating the degradation of the block sizes down the mip-chain as follows
579        * (straight-up divide-by-two integer math): mip0:  6x6 mip1:  3x3 mip2:  1x1 mip3:  1x1
580        *
581        * This means that mip2 will be missing texels.
582        *
583        * Fix this by calculating the base mip's width and height, then convert
584        * that, and round it back up to get the level 0 size. Clamp the
585        * converted size between the original values, and the physical extent
586        * of the base mipmap.
587        *
588        * On GFX10 we have to take care to not go over the physical extent
589        * of the base mipmap as otherwise the GPU computes a different layout.
590        * Note that the GPU does use the same base-mip dimensions for both a
591        * block compatible format and the compressed format, so even if we take
592        * the plain converted dimensions the physical layout is correct.
593        */
594       if (pdev->info.gfx_level >= GFX9 && vk_format_is_block_compressed(plane->format) &&
595           !vk_format_is_block_compressed(iview->vk.format)) {
596          /* If we have multiple levels in the view we should ideally take the last level,
597           * but the mip calculation has a max(..., 1) so walking back to the base mip in an
598           * useful way is hard. */
599          if (iview->vk.level_count > 1) {
600             iview->extent.width = plane->surface.u.gfx9.base_mip_width;
601             iview->extent.height = plane->surface.u.gfx9.base_mip_height;
602          } else {
603             unsigned lvl_width = u_minify(image->vk.extent.width, iview->vk.base_mip_level);
604             unsigned lvl_height = u_minify(image->vk.extent.height, iview->vk.base_mip_level);
605 
606             lvl_width = DIV_ROUND_UP(lvl_width * view_bw, plane_bw);
607             lvl_height = DIV_ROUND_UP(lvl_height * view_bh, plane_bh);
608 
609             iview->extent.width =
610                CLAMP(lvl_width << iview->vk.base_mip_level, iview->extent.width, plane->surface.u.gfx9.base_mip_width);
611             iview->extent.height = CLAMP(lvl_height << iview->vk.base_mip_level, iview->extent.height,
612                                          plane->surface.u.gfx9.base_mip_height);
613 
614             /* If the hardware-computed extent is still be too small, on GFX10
615              * we can attempt another workaround provided by addrlib that
616              * changes the descriptor's base level, and adjusts the address and
617              * extents accordingly.
618              */
619             if (pdev->info.gfx_level >= GFX10 &&
620                 (u_minify(iview->extent.width, iview->vk.base_mip_level) < lvl_width ||
621                  u_minify(iview->extent.height, iview->vk.base_mip_level) < lvl_height) &&
622                 iview->vk.layer_count == 1) {
623                compute_non_block_compressed_view(device, iview, &iview->nbc_view);
624 
625                if (iview->nbc_view.valid) {
626                   iview->extent.width = iview->nbc_view.width;
627                   iview->extent.height = iview->nbc_view.height;
628                }
629             }
630          }
631       }
632    }
633 
634    iview->support_fast_clear = radv_image_view_can_fast_clear(device, iview);
635    iview->disable_dcc_mrt = extra_create_info ? extra_create_info->disable_dcc_mrt : false;
636 
637    bool disable_compression = extra_create_info ? extra_create_info->disable_compression : false;
638    bool enable_compression = extra_create_info ? extra_create_info->enable_compression : false;
639    for (unsigned i = 0; i < plane_count; ++i) {
640       VkFormat format = vk_format_get_plane_format(iview->vk.view_format, i);
641       radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, false, disable_compression,
642                                       enable_compression, iview->plane_id + i, i, NULL);
643       radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, true, disable_compression,
644                                       enable_compression, iview->plane_id + i, i, sliced_3d);
645    }
646 }
647 
648 void
radv_image_view_finish(struct radv_image_view * iview)649 radv_image_view_finish(struct radv_image_view *iview)
650 {
651    vk_image_view_finish(&iview->vk);
652 }
653 
654 VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)655 radv_CreateImageView(VkDevice _device, const VkImageViewCreateInfo *pCreateInfo,
656                      const VkAllocationCallbacks *pAllocator, VkImageView *pView)
657 {
658    VK_FROM_HANDLE(radv_device, device, _device);
659    struct radv_image_view *view;
660 
661    view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
662    if (view == NULL)
663       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
664 
665    radv_image_view_init(view, device, pCreateInfo, &(struct radv_image_view_extra_create_info){.from_client = true});
666 
667    *pView = radv_image_view_to_handle(view);
668 
669    return VK_SUCCESS;
670 }
671 
672 VKAPI_ATTR void VKAPI_CALL
radv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)673 radv_DestroyImageView(VkDevice _device, VkImageView _iview, const VkAllocationCallbacks *pAllocator)
674 {
675    VK_FROM_HANDLE(radv_device, device, _device);
676    VK_FROM_HANDLE(radv_image_view, iview, _iview);
677 
678    if (!iview)
679       return;
680 
681    radv_image_view_finish(iview);
682    vk_free2(&device->vk.alloc, pAllocator, iview);
683 }
684