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 "radv_image.h"
12 #include "util/u_atomic.h"
13 #include "util/u_debug.h"
14 #include "ac_drm_fourcc.h"
15 #include "ac_formats.h"
16 #include "radv_android.h"
17 #include "radv_buffer.h"
18 #include "radv_buffer_view.h"
19 #include "radv_debug.h"
20 #include "radv_device_memory.h"
21 #include "radv_entrypoints.h"
22 #include "radv_formats.h"
23 #include "radv_image_view.h"
24 #include "radv_radeon_winsys.h"
25 #include "radv_rmv.h"
26 #include "radv_video.h"
27 #include "radv_wsi.h"
28 #include "sid.h"
29 #include "vk_debug_utils.h"
30 #include "vk_format.h"
31 #include "vk_log.h"
32 #include "vk_render_pass.h"
33 #include "vk_util.h"
34
35 #include "gfx10_format_table.h"
36
37 static unsigned
radv_choose_tiling(struct radv_device * device,const VkImageCreateInfo * pCreateInfo,VkFormat format)38 radv_choose_tiling(struct radv_device *device, const VkImageCreateInfo *pCreateInfo, VkFormat format)
39 {
40 const struct radv_physical_device *pdev = radv_device_physical(device);
41
42 if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) {
43 assert(pCreateInfo->samples <= 1);
44 return RADEON_SURF_MODE_LINEAR_ALIGNED;
45 }
46
47 if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR))
48 return RADEON_SURF_MODE_LINEAR_ALIGNED;
49
50 if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR))
51 return RADEON_SURF_MODE_LINEAR_ALIGNED;
52
53 /* MSAA resources must be 2D tiled. */
54 if (pCreateInfo->samples > 1)
55 return RADEON_SURF_MODE_2D;
56
57 if (!vk_format_is_compressed(format) && !vk_format_is_depth_or_stencil(format) && pdev->info.gfx_level <= GFX8) {
58 /* this causes hangs in some VK CTS tests on GFX9. */
59 /* Textures with a very small height are recommended to be linear. */
60 if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D ||
61 /* Only very thin and long 2D textures should benefit from
62 * linear_aligned. */
63 (pCreateInfo->extent.width > 8 && pCreateInfo->extent.height <= 2))
64 return RADEON_SURF_MODE_LINEAR_ALIGNED;
65 }
66
67 return RADEON_SURF_MODE_2D;
68 }
69
70 static bool
radv_use_tc_compat_htile_for_image(struct radv_device * device,const VkImageCreateInfo * pCreateInfo,VkFormat format)71 radv_use_tc_compat_htile_for_image(struct radv_device *device, const VkImageCreateInfo *pCreateInfo, VkFormat format)
72 {
73 const struct radv_physical_device *pdev = radv_device_physical(device);
74
75 if (!pdev->info.has_tc_compatible_htile)
76 return false;
77
78 if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
79 return false;
80
81 /* Do not enable TC-compatible HTILE if the image isn't readable by a
82 * shader because no texture fetches will happen.
83 */
84 if (!(pCreateInfo->usage &
85 (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))
86 return false;
87
88 if (pdev->info.gfx_level < GFX9) {
89 /* TC-compat HTILE for MSAA depth/stencil images is broken
90 * on GFX8 because the tiling doesn't match.
91 */
92 if (pCreateInfo->samples >= 2 && format == VK_FORMAT_D32_SFLOAT_S8_UINT)
93 return false;
94
95 /* GFX9+ supports compression for both 32-bit and 16-bit depth
96 * surfaces, while GFX8 only supports 32-bit natively. Though,
97 * the driver allows TC-compat HTILE for 16-bit depth surfaces
98 * with no Z planes compression.
99 */
100 if (format != VK_FORMAT_D32_SFLOAT_S8_UINT && format != VK_FORMAT_D32_SFLOAT && format != VK_FORMAT_D16_UNORM)
101 return false;
102
103 /* TC-compat HTILE for layered images can have interleaved slices (see sliceInterleaved flag
104 * in addrlib). radv_clear_htile does not work.
105 */
106 if (pCreateInfo->arrayLayers > 1)
107 return false;
108 }
109
110 /* GFX9 has issues when the sample count is 4 and the format is D16 */
111 if (pdev->info.gfx_level == GFX9 && pCreateInfo->samples == 4 && format == VK_FORMAT_D16_UNORM)
112 return false;
113
114 return true;
115 }
116
117 static bool
radv_surface_has_scanout(struct radv_device * device,const struct radv_image_create_info * info)118 radv_surface_has_scanout(struct radv_device *device, const struct radv_image_create_info *info)
119 {
120 const struct radv_physical_device *pdev = radv_device_physical(device);
121
122 if (info->bo_metadata) {
123 if (pdev->info.gfx_level >= GFX12) {
124 return info->bo_metadata->u.gfx12.scanout;
125 } else if (pdev->info.gfx_level >= GFX9)
126 return info->bo_metadata->u.gfx9.scanout;
127 else
128 return info->bo_metadata->u.legacy.scanout;
129 }
130
131 return info->scanout;
132 }
133
134 static bool
radv_image_use_fast_clear_for_image_early(const struct radv_device * device,const struct radv_image * image)135 radv_image_use_fast_clear_for_image_early(const struct radv_device *device, const struct radv_image *image)
136 {
137 const struct radv_physical_device *pdev = radv_device_physical(device);
138 const struct radv_instance *instance = radv_physical_device_instance(pdev);
139
140 if (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)
141 return true;
142
143 if (image->vk.samples <= 1 && image->vk.extent.width * image->vk.extent.height <= 512 * 512) {
144 /* Do not enable CMASK or DCC for small surfaces where the cost
145 * of the eliminate pass can be higher than the benefit of fast
146 * clear. RadeonSI does this, but the image threshold is
147 * different.
148 */
149 return false;
150 }
151
152 return !!(image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
153 }
154
155 static bool
radv_image_use_fast_clear_for_image(const struct radv_device * device,const struct radv_image * image)156 radv_image_use_fast_clear_for_image(const struct radv_device *device, const struct radv_image *image)
157 {
158 const struct radv_physical_device *pdev = radv_device_physical(device);
159 const struct radv_instance *instance = radv_physical_device_instance(pdev);
160
161 if (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)
162 return true;
163
164 return radv_image_use_fast_clear_for_image_early(device, image) && (image->exclusive ||
165 /* Enable DCC for concurrent images if stores are
166 * supported because that means we can keep DCC
167 * compressed on all layouts/queues.
168 */
169 radv_image_use_dcc_image_stores(device, image));
170 }
171
172 bool
radv_are_formats_dcc_compatible(const struct radv_physical_device * pdev,const void * pNext,VkFormat format,VkImageCreateFlags flags,bool * sign_reinterpret)173 radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const void *pNext, VkFormat format,
174 VkImageCreateFlags flags, bool *sign_reinterpret)
175 {
176 if (!radv_is_colorbuffer_format_supported(pdev, format))
177 return false;
178
179 if (sign_reinterpret != NULL)
180 *sign_reinterpret = false;
181
182 /* All formats are compatible on GFX11. */
183 if ((flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && pdev->info.gfx_level < GFX11) {
184 const struct VkImageFormatListCreateInfo *format_list =
185 (const struct VkImageFormatListCreateInfo *)vk_find_struct_const(pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
186
187 /* We have to ignore the existence of the list if viewFormatCount = 0 */
188 if (format_list && format_list->viewFormatCount) {
189 /* compatibility is transitive, so we only need to check
190 * one format with everything else. */
191 for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {
192 if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
193 continue;
194
195 if (!radv_dcc_formats_compatible(pdev->info.gfx_level, format, format_list->pViewFormats[i],
196 sign_reinterpret))
197 return false;
198 }
199 } else {
200 return false;
201 }
202 }
203
204 return true;
205 }
206
207 static bool
radv_format_is_atomic_allowed(struct radv_device * device,VkFormat format)208 radv_format_is_atomic_allowed(struct radv_device *device, VkFormat format)
209 {
210 if (format == VK_FORMAT_R32_SFLOAT && !radv_uses_image_float32_atomics(device))
211 return false;
212
213 return radv_is_atomic_format_supported(format);
214 }
215
216 static bool
radv_formats_is_atomic_allowed(struct radv_device * device,const void * pNext,VkFormat format,VkImageCreateFlags flags)217 radv_formats_is_atomic_allowed(struct radv_device *device, const void *pNext, VkFormat format, VkImageCreateFlags flags)
218 {
219 if (radv_format_is_atomic_allowed(device, format))
220 return true;
221
222 if (flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
223 const struct VkImageFormatListCreateInfo *format_list =
224 (const struct VkImageFormatListCreateInfo *)vk_find_struct_const(pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
225
226 /* We have to ignore the existence of the list if viewFormatCount = 0 */
227 if (format_list && format_list->viewFormatCount) {
228 for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {
229 if (radv_format_is_atomic_allowed(device, format_list->pViewFormats[i]))
230 return true;
231 }
232 }
233 }
234
235 return false;
236 }
237
238 static bool
radv_use_dcc_for_image_early(struct radv_device * device,struct radv_image * image,const VkImageCreateInfo * pCreateInfo,VkFormat format,bool * sign_reinterpret)239 radv_use_dcc_for_image_early(struct radv_device *device, struct radv_image *image, const VkImageCreateInfo *pCreateInfo,
240 VkFormat format, bool *sign_reinterpret)
241 {
242 const struct radv_physical_device *pdev = radv_device_physical(device);
243 const struct radv_instance *instance = radv_physical_device_instance(pdev);
244
245 /* DCC (Delta Color Compression) is only available for GFX8+. */
246 if (pdev->info.gfx_level < GFX8)
247 return false;
248
249 const VkImageCompressionControlEXT *compression =
250 vk_find_struct_const(pCreateInfo->pNext, IMAGE_COMPRESSION_CONTROL_EXT);
251
252 if (instance->debug_flags & RADV_DEBUG_NO_DCC ||
253 (compression && compression->flags == VK_IMAGE_COMPRESSION_DISABLED_EXT)) {
254 return false;
255 }
256
257 if (image->shareable && image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
258 return false;
259
260 /*
261 * TODO: Enable DCC for storage images on GFX9 and earlier.
262 *
263 * Also disable DCC with atomics because even when DCC stores are
264 * supported atomics will always decompress. So if we are
265 * decompressing a lot anyway we might as well not have DCC.
266 */
267 if ((pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
268 (pdev->info.gfx_level < GFX10 ||
269 radv_formats_is_atomic_allowed(device, pCreateInfo->pNext, format, pCreateInfo->flags)))
270 return false;
271
272 if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
273 return false;
274
275 if (vk_format_is_subsampled(format) || vk_format_get_plane_count(format) > 1)
276 return false;
277
278 if (!radv_image_use_fast_clear_for_image_early(device, image) &&
279 image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
280 return false;
281
282 /* Do not enable DCC for mipmapped arrays because performance is worse. */
283 if (pCreateInfo->arrayLayers > 1 && pCreateInfo->mipLevels > 1)
284 return false;
285
286 if (pdev->info.gfx_level < GFX10) {
287 /* TODO: Add support for DCC MSAA on GFX8-9. */
288 if (pCreateInfo->samples > 1 && !pdev->dcc_msaa_allowed)
289 return false;
290
291 /* TODO: Add support for DCC layers/mipmaps on GFX9. */
292 if ((pCreateInfo->arrayLayers > 1 || pCreateInfo->mipLevels > 1) && pdev->info.gfx_level == GFX9)
293 return false;
294 }
295
296 /* Force disable DCC for mips to workaround game bugs. */
297 if (instance->drirc.disable_dcc_mips && pCreateInfo->mipLevels > 1)
298 return false;
299
300 /* Force disable DCC for stores to workaround game bugs. */
301 if (instance->drirc.disable_dcc_stores && (pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT))
302 return false;
303
304 /* DCC MSAA can't work on GFX10.3 and earlier without FMASK. */
305 if (pCreateInfo->samples > 1 && pdev->info.gfx_level < GFX11 && (instance->debug_flags & RADV_DEBUG_NO_FMASK))
306 return false;
307
308 return radv_are_formats_dcc_compatible(pdev, pCreateInfo->pNext, format, pCreateInfo->flags, sign_reinterpret);
309 }
310
311 static bool
radv_use_dcc_for_image_late(struct radv_device * device,struct radv_image * image)312 radv_use_dcc_for_image_late(struct radv_device *device, struct radv_image *image)
313 {
314 if (!radv_image_has_dcc(image))
315 return false;
316
317 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
318 return true;
319
320 if (!radv_image_use_fast_clear_for_image(device, image))
321 return false;
322
323 /* TODO: Fix storage images with DCC without DCC image stores.
324 * Disabling it for now. */
325 if ((image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) && !radv_image_use_dcc_image_stores(device, image))
326 return false;
327
328 return true;
329 }
330
331 /*
332 * Whether to enable image stores with DCC compression for this image. If
333 * this function returns false the image subresource should be decompressed
334 * before using it with image stores.
335 *
336 * Note that this can have mixed performance implications, see
337 * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6796#note_643299
338 *
339 * This function assumes the image uses DCC compression.
340 */
341 bool
radv_image_use_dcc_image_stores(const struct radv_device * device,const struct radv_image * image)342 radv_image_use_dcc_image_stores(const struct radv_device *device, const struct radv_image *image)
343 {
344 const struct radv_physical_device *pdev = radv_device_physical(device);
345
346 return ac_surface_supports_dcc_image_stores(pdev->info.gfx_level, &image->planes[0].surface);
347 }
348
349 /*
350 * Whether to use a predicate to determine whether DCC is in a compressed
351 * state. This can be used to avoid decompressing an image multiple times.
352 */
353 bool
radv_image_use_dcc_predication(const struct radv_device * device,const struct radv_image * image)354 radv_image_use_dcc_predication(const struct radv_device *device, const struct radv_image *image)
355 {
356 return radv_image_has_dcc(image) && !radv_image_use_dcc_image_stores(device, image);
357 }
358
359 static inline bool
radv_use_fmask_for_image(const struct radv_device * device,const struct radv_image * image)360 radv_use_fmask_for_image(const struct radv_device *device, const struct radv_image *image)
361 {
362 const struct radv_physical_device *pdev = radv_device_physical(device);
363 const struct radv_instance *instance = radv_physical_device_instance(pdev);
364
365 if (pdev->info.gfx_level == GFX9 && image->vk.array_layers > 1) {
366 /* On GFX9, FMASK can be interleaved with layers and this isn't properly supported. */
367 return false;
368 }
369
370 return pdev->use_fmask && image->vk.samples > 1 &&
371 ((image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ||
372 (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS));
373 }
374
375 static inline bool
radv_use_htile_for_image(const struct radv_device * device,const struct radv_image * image,const VkImageCreateInfo * pCreateInfo)376 radv_use_htile_for_image(const struct radv_device *device, const struct radv_image *image,
377 const VkImageCreateInfo *pCreateInfo)
378 {
379 const struct radv_physical_device *pdev = radv_device_physical(device);
380 const struct radv_instance *instance = radv_physical_device_instance(pdev);
381 const enum amd_gfx_level gfx_level = pdev->info.gfx_level;
382
383 const VkImageCompressionControlEXT *compression =
384 vk_find_struct_const(pCreateInfo->pNext, IMAGE_COMPRESSION_CONTROL_EXT);
385
386 if (instance->debug_flags & RADV_DEBUG_NO_HIZ ||
387 (compression && compression->flags == VK_IMAGE_COMPRESSION_DISABLED_EXT))
388 return false;
389
390 if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
391 return false;
392
393 /* TODO:
394 * - Investigate about mips+layers.
395 * - Enable on other gens.
396 */
397 bool use_htile_for_mips = image->vk.array_layers == 1 && pdev->info.gfx_level >= GFX10;
398
399 /* Stencil texturing with HTILE doesn't work with mipmapping on Navi10-14. */
400 if (pdev->info.gfx_level == GFX10 && image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT && image->vk.mip_levels > 1)
401 return false;
402
403 /* Do not enable HTILE for very small images because it seems less performant but make sure it's
404 * allowed with VRS attachments because we need HTILE on GFX10.3.
405 */
406 if (image->vk.extent.width * image->vk.extent.height < 8 * 8 &&
407 !(instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS) &&
408 !(gfx_level == GFX10_3 && device->vk.enabled_features.attachmentFragmentShadingRate))
409 return false;
410
411 return (image->vk.mip_levels == 1 || use_htile_for_mips) && !image->shareable;
412 }
413
414 static bool
radv_use_tc_compat_cmask_for_image(struct radv_device * device,struct radv_image * image)415 radv_use_tc_compat_cmask_for_image(struct radv_device *device, struct radv_image *image)
416 {
417 const struct radv_physical_device *pdev = radv_device_physical(device);
418 const struct radv_instance *instance = radv_physical_device_instance(pdev);
419
420 /* TC-compat CMASK is only available for GFX8+. */
421 if (pdev->info.gfx_level < GFX8)
422 return false;
423
424 /* GFX9 has issues when sample count is greater than 2 */
425 if (pdev->info.gfx_level == GFX9 && image->vk.samples > 2)
426 return false;
427
428 if (instance->debug_flags & RADV_DEBUG_NO_TC_COMPAT_CMASK)
429 return false;
430
431 /* TC-compat CMASK with storage images is supported on GFX10+. */
432 if ((image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) && pdev->info.gfx_level < GFX10)
433 return false;
434
435 /* Do not enable TC-compatible if the image isn't readable by a shader
436 * because no texture fetches will happen.
437 */
438 if (!(image->vk.usage &
439 (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))
440 return false;
441
442 /* If the image doesn't have FMASK, it can't be fetchable. */
443 if (!radv_image_has_fmask(image))
444 return false;
445
446 return true;
447 }
448
449 static uint32_t
radv_get_bo_metadata_word1(const struct radv_device * device)450 radv_get_bo_metadata_word1(const struct radv_device *device)
451 {
452 const struct radv_physical_device *pdev = radv_device_physical(device);
453
454 return (ATI_VENDOR_ID << 16) | pdev->info.pci_id;
455 }
456
457 static bool
radv_is_valid_opaque_metadata(const struct radv_device * device,const struct radeon_bo_metadata * md)458 radv_is_valid_opaque_metadata(const struct radv_device *device, const struct radeon_bo_metadata *md)
459 {
460 if (md->metadata[0] != 1 || md->metadata[1] != radv_get_bo_metadata_word1(device))
461 return false;
462
463 if (md->size_metadata < 40)
464 return false;
465
466 return true;
467 }
468
469 static void
radv_patch_surface_from_metadata(struct radv_device * device,struct radeon_surf * surface,const struct radeon_bo_metadata * md)470 radv_patch_surface_from_metadata(struct radv_device *device, struct radeon_surf *surface,
471 const struct radeon_bo_metadata *md)
472 {
473 const struct radv_physical_device *pdev = radv_device_physical(device);
474
475 surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
476
477 if (pdev->info.gfx_level >= GFX12) {
478 surface->u.gfx9.swizzle_mode = md->u.gfx12.swizzle_mode;
479 surface->u.gfx9.color.dcc.max_compressed_block_size = md->u.gfx12.dcc_max_compressed_block;
480 surface->u.gfx9.color.dcc_data_format = md->u.gfx12.dcc_data_format;
481 surface->u.gfx9.color.dcc_number_type = md->u.gfx12.dcc_number_type;
482 surface->u.gfx9.color.dcc_write_compress_disable = md->u.gfx12.dcc_write_compress_disable;
483 } else if (pdev->info.gfx_level >= GFX9) {
484 if (md->u.gfx9.swizzle_mode > 0)
485 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
486 else
487 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
488
489 surface->u.gfx9.swizzle_mode = md->u.gfx9.swizzle_mode;
490 } else {
491 surface->u.legacy.pipe_config = md->u.legacy.pipe_config;
492 surface->u.legacy.bankw = md->u.legacy.bankw;
493 surface->u.legacy.bankh = md->u.legacy.bankh;
494 surface->u.legacy.tile_split = md->u.legacy.tile_split;
495 surface->u.legacy.mtilea = md->u.legacy.mtilea;
496 surface->u.legacy.num_banks = md->u.legacy.num_banks;
497
498 if (md->u.legacy.macrotile == RADEON_LAYOUT_TILED)
499 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
500 else if (md->u.legacy.microtile == RADEON_LAYOUT_TILED)
501 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
502 else
503 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
504 }
505 }
506
507 static VkResult
radv_patch_image_dimensions(struct radv_device * device,struct radv_image * image,const struct radv_image_create_info * create_info,struct ac_surf_info * image_info)508 radv_patch_image_dimensions(struct radv_device *device, struct radv_image *image,
509 const struct radv_image_create_info *create_info, struct ac_surf_info *image_info)
510 {
511 const struct radv_physical_device *pdev = radv_device_physical(device);
512 unsigned width = image->vk.extent.width;
513 unsigned height = image->vk.extent.height;
514
515 /*
516 * minigbm sometimes allocates bigger images which is going to result in
517 * weird strides and other properties. Lets be lenient where possible and
518 * fail it on GFX10 (as we cannot cope there).
519 *
520 * Example hack: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/1457777/
521 */
522 if (create_info->bo_metadata && radv_is_valid_opaque_metadata(device, create_info->bo_metadata)) {
523 const struct radeon_bo_metadata *md = create_info->bo_metadata;
524
525 if (pdev->info.gfx_level >= GFX10) {
526 width = G_00A004_WIDTH_LO(md->metadata[3]) + (G_00A008_WIDTH_HI(md->metadata[4]) << 2) + 1;
527 height = G_00A008_HEIGHT(md->metadata[4]) + 1;
528 } else {
529 width = G_008F18_WIDTH(md->metadata[4]) + 1;
530 height = G_008F18_HEIGHT(md->metadata[4]) + 1;
531 }
532 }
533
534 if (image->vk.extent.width == width && image->vk.extent.height == height)
535 return VK_SUCCESS;
536
537 if (width < image->vk.extent.width || height < image->vk.extent.height) {
538 fprintf(stderr,
539 "The imported image has smaller dimensions than the internal\n"
540 "dimensions. Using it is going to fail badly, so we reject\n"
541 "this import.\n"
542 "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
543 image->vk.extent.width, image->vk.extent.height, width, height);
544 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
545 } else if (pdev->info.gfx_level >= GFX10) {
546 fprintf(stderr,
547 "Tried to import an image with inconsistent width on GFX10.\n"
548 "As GFX10 has no separate stride fields we cannot cope with\n"
549 "an inconsistency in width and will fail this import.\n"
550 "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
551 image->vk.extent.width, image->vk.extent.height, width, height);
552 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
553 } else {
554 fprintf(stderr,
555 "Tried to import an image with inconsistent width on pre-GFX10.\n"
556 "As GFX10 has no separate stride fields we cannot cope with\n"
557 "an inconsistency and would fail on GFX10.\n"
558 "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
559 image->vk.extent.width, image->vk.extent.height, width, height);
560 }
561 image_info->width = width;
562 image_info->height = height;
563
564 return VK_SUCCESS;
565 }
566
567 static VkResult
radv_patch_image_from_extra_info(struct radv_device * device,struct radv_image * image,const struct radv_image_create_info * create_info,struct ac_surf_info * image_info)568 radv_patch_image_from_extra_info(struct radv_device *device, struct radv_image *image,
569 const struct radv_image_create_info *create_info, struct ac_surf_info *image_info)
570 {
571 const struct radv_physical_device *pdev = radv_device_physical(device);
572 const struct radv_instance *instance = radv_physical_device_instance(pdev);
573
574 VkResult result = radv_patch_image_dimensions(device, image, create_info, image_info);
575 if (result != VK_SUCCESS)
576 return result;
577
578 for (unsigned plane = 0; plane < image->plane_count; ++plane) {
579 if (create_info->bo_metadata) {
580 radv_patch_surface_from_metadata(device, &image->planes[plane].surface, create_info->bo_metadata);
581 }
582
583 if (radv_surface_has_scanout(device, create_info)) {
584 image->planes[plane].surface.flags |= RADEON_SURF_SCANOUT;
585 if (instance->debug_flags & RADV_DEBUG_NO_DISPLAY_DCC)
586 image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC;
587
588 image_info->surf_index = NULL;
589 }
590
591 if (create_info->prime_blit_src && !pdev->info.sdma_supports_compression) {
592 /* Older SDMA hw can't handle DCC */
593 image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC;
594 }
595 }
596 return VK_SUCCESS;
597 }
598
599 static VkFormat
radv_image_get_plane_format(const struct radv_physical_device * pdev,const struct radv_image * image,unsigned plane)600 radv_image_get_plane_format(const struct radv_physical_device *pdev, const struct radv_image *image, unsigned plane)
601 {
602 if (radv_is_format_emulated(pdev, image->vk.format)) {
603 if (plane == 0)
604 return image->vk.format;
605 if (vk_format_description(image->vk.format)->layout == UTIL_FORMAT_LAYOUT_ASTC)
606 return vk_texcompress_astc_emulation_format(image->vk.format);
607 else
608 return vk_texcompress_etc2_emulation_format(image->vk.format);
609 }
610
611 return vk_format_get_plane_format(image->vk.format, plane);
612 }
613
614 static uint64_t
radv_get_surface_flags(struct radv_device * device,struct radv_image * image,unsigned plane_id,const VkImageCreateInfo * pCreateInfo,VkFormat image_format)615 radv_get_surface_flags(struct radv_device *device, struct radv_image *image, unsigned plane_id,
616 const VkImageCreateInfo *pCreateInfo, VkFormat image_format)
617 {
618 const struct radv_physical_device *pdev = radv_device_physical(device);
619 const struct radv_instance *instance = radv_physical_device_instance(pdev);
620 uint64_t flags;
621 unsigned array_mode = radv_choose_tiling(device, pCreateInfo, image_format);
622 VkFormat format = radv_image_get_plane_format(pdev, image, plane_id);
623 const struct util_format_description *desc = vk_format_description(format);
624 const VkImageAlignmentControlCreateInfoMESA *alignment =
625 vk_find_struct_const(pCreateInfo->pNext, IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA);
626 bool is_depth, is_stencil;
627
628 is_depth = util_format_has_depth(desc);
629 is_stencil = util_format_has_stencil(desc);
630
631 flags = RADEON_SURF_SET(array_mode, MODE);
632
633 switch (pCreateInfo->imageType) {
634 case VK_IMAGE_TYPE_1D:
635 if (pCreateInfo->arrayLayers > 1)
636 flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
637 else
638 flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
639 break;
640 case VK_IMAGE_TYPE_2D:
641 if (pCreateInfo->arrayLayers > 1)
642 flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
643 else
644 flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
645 break;
646 case VK_IMAGE_TYPE_3D:
647 flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
648 break;
649 default:
650 unreachable("unhandled image type");
651 }
652
653 /* Required for clearing/initializing a specific layer on GFX8. */
654 flags |= RADEON_SURF_CONTIGUOUS_DCC_LAYERS;
655
656 if (is_depth) {
657 flags |= RADEON_SURF_ZBUFFER;
658
659 if (is_depth && is_stencil && pdev->info.gfx_level <= GFX8) {
660 if (!(pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
661 flags |= RADEON_SURF_NO_RENDER_TARGET;
662
663 /* RADV doesn't support stencil pitch adjustment. As a result there are some spec gaps that
664 * are not covered by CTS.
665 *
666 * For D+S images with pitch constraints due to rendertarget usage it can happen that
667 * sampling from mipmaps beyond the base level of the descriptor is broken as the pitch
668 * adjustment can't be applied to anything beyond the first level.
669 */
670 flags |= RADEON_SURF_NO_STENCIL_ADJUST;
671 }
672
673 if (radv_use_htile_for_image(device, image, pCreateInfo) && !(flags & RADEON_SURF_NO_RENDER_TARGET)) {
674 if (radv_use_tc_compat_htile_for_image(device, pCreateInfo, image_format))
675 flags |= RADEON_SURF_TC_COMPATIBLE_HTILE;
676 } else {
677 flags |= RADEON_SURF_NO_HTILE;
678 }
679 }
680
681 if (is_stencil)
682 flags |= RADEON_SURF_SBUFFER;
683
684 if (pdev->info.gfx_level >= GFX9 && pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&
685 vk_format_get_blocksizebits(image_format) == 128 && vk_format_is_compressed(image_format))
686 flags |= RADEON_SURF_NO_RENDER_TARGET;
687
688 if (!radv_use_dcc_for_image_early(device, image, pCreateInfo, image_format, &image->dcc_sign_reinterpret))
689 flags |= RADEON_SURF_DISABLE_DCC;
690
691 if (!radv_use_fmask_for_image(device, image))
692 flags |= RADEON_SURF_NO_FMASK;
693
694 if (pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
695 flags |= RADEON_SURF_PRT | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE | RADEON_SURF_DISABLE_DCC;
696 }
697
698 if (image->queue_family_mask & BITFIELD_BIT(RADV_QUEUE_TRANSFER)) {
699 if (!pdev->info.sdma_supports_compression)
700 flags |= RADEON_SURF_DISABLE_DCC | RADEON_SURF_NO_HTILE;
701 }
702
703 /* Disable DCC for VRS rate images because the hw can't handle compression. */
704 if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)
705 flags |= RADEON_SURF_VRS_RATE | RADEON_SURF_DISABLE_DCC;
706 if (!(pCreateInfo->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)))
707 flags |= RADEON_SURF_NO_TEXTURE;
708
709 if (alignment && alignment->maximumRequestedAlignment && !(instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)) {
710 bool is_4k_capable;
711
712 if (!vk_format_is_depth_or_stencil(image_format)) {
713 is_4k_capable =
714 !(pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && (flags & RADEON_SURF_DISABLE_DCC) &&
715 (flags & RADEON_SURF_NO_FMASK);
716 } else {
717 /* Depth-stencil format without DEPTH_STENCIL usage does not work either. */
718 is_4k_capable = false;
719 }
720
721 if (is_4k_capable && alignment->maximumRequestedAlignment <= 4096)
722 flags |= RADEON_SURF_PREFER_4K_ALIGNMENT;
723 if (alignment->maximumRequestedAlignment <= 64 * 1024)
724 flags |= RADEON_SURF_PREFER_64K_ALIGNMENT;
725 }
726
727 return flags;
728 }
729
730 void
radv_compose_swizzle(const struct util_format_description * desc,const VkComponentMapping * mapping,enum pipe_swizzle swizzle[4])731 radv_compose_swizzle(const struct util_format_description *desc, const VkComponentMapping *mapping,
732 enum pipe_swizzle swizzle[4])
733 {
734 if (desc->format == PIPE_FORMAT_R64_UINT || desc->format == PIPE_FORMAT_R64_SINT) {
735 /* 64-bit formats only support storage images and storage images
736 * require identity component mappings. We use 32-bit
737 * instructions to access 64-bit images, so we need a special
738 * case here.
739 *
740 * The zw components are 1,0 so that they can be easily be used
741 * by loads to create the w component, which has to be 0 for
742 * NULL descriptors.
743 */
744 swizzle[0] = PIPE_SWIZZLE_X;
745 swizzle[1] = PIPE_SWIZZLE_Y;
746 swizzle[2] = PIPE_SWIZZLE_1;
747 swizzle[3] = PIPE_SWIZZLE_0;
748 } else if (!mapping) {
749 for (unsigned i = 0; i < 4; i++)
750 swizzle[i] = desc->swizzle[i];
751 } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
752 const unsigned char swizzle_xxxx[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_0, PIPE_SWIZZLE_0, PIPE_SWIZZLE_1};
753 vk_format_compose_swizzles(mapping, swizzle_xxxx, swizzle);
754 } else {
755 vk_format_compose_swizzles(mapping, desc->swizzle, swizzle);
756 }
757 }
758
759 void
radv_image_bo_set_metadata(struct radv_device * device,struct radv_image * image,struct radeon_winsys_bo * bo)760 radv_image_bo_set_metadata(struct radv_device *device, struct radv_image *image, struct radeon_winsys_bo *bo)
761 {
762 const struct radv_physical_device *pdev = radv_device_physical(device);
763 const struct radv_instance *instance = radv_physical_device_instance(pdev);
764 static const VkComponentMapping fixedmapping;
765 const uint32_t plane_id = 0; /* Always plane 0 to follow RadeonSI. */
766 const VkFormat plane_format = radv_image_get_plane_format(pdev, image, plane_id);
767 const unsigned plane_width = vk_format_get_plane_width(image->vk.format, plane_id, image->vk.extent.width);
768 const unsigned plane_height = vk_format_get_plane_height(image->vk.format, plane_id, image->vk.extent.height);
769 struct radeon_surf *surface = &image->planes[plane_id].surface;
770 const struct legacy_surf_level *base_level_info = pdev->info.gfx_level <= GFX8 ? &surface->u.legacy.level[0] : NULL;
771 struct radeon_bo_metadata md;
772 uint32_t desc[8];
773
774 memset(&md, 0, sizeof(md));
775
776 if (pdev->info.gfx_level >= GFX12) {
777 md.u.gfx12.swizzle_mode = surface->u.gfx9.swizzle_mode;
778 md.u.gfx12.dcc_max_compressed_block = surface->u.gfx9.color.dcc.max_compressed_block_size;
779 md.u.gfx12.dcc_number_type = surface->u.gfx9.color.dcc_number_type;
780 md.u.gfx12.dcc_data_format = surface->u.gfx9.color.dcc_data_format;
781 md.u.gfx12.dcc_write_compress_disable = surface->u.gfx9.color.dcc_write_compress_disable;
782 md.u.gfx12.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
783 } else if (pdev->info.gfx_level >= GFX9) {
784 uint64_t dcc_offset =
785 image->bindings[0].offset + (surface->display_dcc_offset ? surface->display_dcc_offset : surface->meta_offset);
786 md.u.gfx9.swizzle_mode = surface->u.gfx9.swizzle_mode;
787 md.u.gfx9.dcc_offset_256b = dcc_offset >> 8;
788 md.u.gfx9.dcc_pitch_max = surface->u.gfx9.color.display_dcc_pitch_max;
789 md.u.gfx9.dcc_independent_64b_blocks = surface->u.gfx9.color.dcc.independent_64B_blocks;
790 md.u.gfx9.dcc_independent_128b_blocks = surface->u.gfx9.color.dcc.independent_128B_blocks;
791 md.u.gfx9.dcc_max_compressed_block_size = surface->u.gfx9.color.dcc.max_compressed_block_size;
792 md.u.gfx9.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
793 } else {
794 md.u.legacy.microtile =
795 surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_1D ? RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR;
796 md.u.legacy.macrotile =
797 surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_2D ? RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR;
798 md.u.legacy.pipe_config = surface->u.legacy.pipe_config;
799 md.u.legacy.bankw = surface->u.legacy.bankw;
800 md.u.legacy.bankh = surface->u.legacy.bankh;
801 md.u.legacy.tile_split = surface->u.legacy.tile_split;
802 md.u.legacy.mtilea = surface->u.legacy.mtilea;
803 md.u.legacy.num_banks = surface->u.legacy.num_banks;
804 md.u.legacy.stride = surface->u.legacy.level[0].nblk_x * surface->bpe;
805 md.u.legacy.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
806 }
807
808 radv_make_texture_descriptor(device, image, false, (VkImageViewType)image->vk.image_type, plane_format,
809 &fixedmapping, 0, image->vk.mip_levels - 1, 0, image->vk.array_layers - 1, plane_width,
810 plane_height, image->vk.extent.depth, 0.0f, desc, NULL, NULL, NULL);
811
812 radv_set_mutable_tex_desc_fields(device, image, base_level_info, plane_id, 0, 0, surface->blk_w, false, false, false,
813 false, desc, NULL, 0);
814
815 ac_surface_compute_umd_metadata(&pdev->info, surface, image->vk.mip_levels, desc, &md.size_metadata, md.metadata,
816 instance->debug_flags & RADV_DEBUG_EXTRA_MD);
817
818 device->ws->buffer_set_metadata(device->ws, bo, &md);
819 }
820
821 void
radv_image_override_offset_stride(struct radv_device * device,struct radv_image * image,uint64_t offset,uint32_t stride)822 radv_image_override_offset_stride(struct radv_device *device, struct radv_image *image, uint64_t offset,
823 uint32_t stride)
824 {
825 const struct radv_physical_device *pdev = radv_device_physical(device);
826 ac_surface_override_offset_stride(&pdev->info, &image->planes[0].surface, image->vk.array_layers,
827 image->vk.mip_levels, offset, stride);
828 }
829
830 static void
radv_image_alloc_single_sample_cmask(const struct radv_device * device,const struct radv_image * image,struct radeon_surf * surf)831 radv_image_alloc_single_sample_cmask(const struct radv_device *device, const struct radv_image *image,
832 struct radeon_surf *surf)
833 {
834 if (!surf->cmask_size || surf->cmask_offset || surf->bpe > 8 || image->vk.mip_levels > 1 ||
835 image->vk.extent.depth > 1 || radv_image_has_dcc(image) || !radv_image_use_fast_clear_for_image(device, image) ||
836 (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT))
837 return;
838
839 assert(image->vk.samples == 1);
840
841 surf->cmask_offset = align64(surf->total_size, 1ull << surf->cmask_alignment_log2);
842 surf->total_size = surf->cmask_offset + surf->cmask_size;
843 surf->alignment_log2 = MAX2(surf->alignment_log2, surf->cmask_alignment_log2);
844 }
845
846 static void
radv_image_alloc_values(const struct radv_device * device,struct radv_image * image)847 radv_image_alloc_values(const struct radv_device *device, struct radv_image *image)
848 {
849 const struct radv_physical_device *pdev = radv_device_physical(device);
850
851 /* images with modifiers can be potentially imported */
852 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
853 return;
854
855 if (radv_image_has_cmask(image) || (radv_image_has_dcc(image) && !image->support_comp_to_single)) {
856 image->fce_pred_offset = image->size;
857 image->size += 8 * image->vk.mip_levels;
858 }
859
860 if (radv_image_use_dcc_predication(device, image)) {
861 image->dcc_pred_offset = image->size;
862 image->size += 8 * image->vk.mip_levels;
863 }
864
865 if ((radv_image_has_dcc(image) && !image->support_comp_to_single) || radv_image_has_cmask(image) ||
866 radv_image_has_htile(image)) {
867 image->clear_value_offset = image->size;
868 image->size += 8 * image->vk.mip_levels;
869 }
870
871 if (radv_image_is_tc_compat_htile(image) && pdev->info.has_tc_compat_zrange_bug) {
872 /* Metadata for the TC-compatible HTILE hardware bug which
873 * have to be fixed by updating ZRANGE_PRECISION when doing
874 * fast depth clears to 0.0f.
875 */
876 image->tc_compat_zrange_offset = image->size;
877 image->size += image->vk.mip_levels * 4;
878 }
879 }
880
881 /* Determine if the image is affected by the pipe misaligned metadata issue
882 * which requires to invalidate L2.
883 */
884 static bool
radv_image_is_pipe_misaligned(const struct radv_image * image,const VkImageSubresourceRange * range)885 radv_image_is_pipe_misaligned(const struct radv_image *image, const VkImageSubresourceRange *range)
886 {
887 for (unsigned i = 0; i < image->plane_count; ++i) {
888 const uint32_t first_mip_pipe_misaligned = image->planes[i].first_mip_pipe_misaligned;
889
890 if (range) {
891 if (range->baseMipLevel + range->levelCount - 1 >= first_mip_pipe_misaligned)
892 return true;
893 } else {
894 /* Be conservative when the range is unknown because it's not possible to know which mips
895 * are used.
896 */
897 if (first_mip_pipe_misaligned != UINT32_MAX)
898 return true;
899 }
900 }
901
902 return false;
903 }
904
905 bool
radv_image_is_l2_coherent(const struct radv_device * device,const struct radv_image * image,const VkImageSubresourceRange * range)906 radv_image_is_l2_coherent(const struct radv_device *device, const struct radv_image *image,
907 const VkImageSubresourceRange *range)
908 {
909 const struct radv_physical_device *pdev = radv_device_physical(device);
910
911 if (pdev->info.gfx_level >= GFX12) {
912 return true; /* Everything is coherent with TC L2. */
913 } else if (pdev->info.gfx_level >= GFX10) {
914 return !radv_image_is_pipe_misaligned(image, range);
915 } else if (pdev->info.gfx_level == GFX9) {
916 if (image->vk.samples == 1 &&
917 (image->vk.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
918 !vk_format_has_stencil(image->vk.format)) {
919 /* Single-sample color and single-sample depth
920 * (not stencil) are coherent with shaders on
921 * GFX9.
922 */
923 return true;
924 }
925 }
926
927 return false;
928 }
929
930 /**
931 * Determine if the given image can be fast cleared.
932 */
933 bool
radv_image_can_fast_clear(const struct radv_device * device,const struct radv_image * image)934 radv_image_can_fast_clear(const struct radv_device *device, const struct radv_image *image)
935 {
936 const struct radv_physical_device *pdev = radv_device_physical(device);
937 const struct radv_instance *instance = radv_physical_device_instance(pdev);
938
939 if (instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS)
940 return false;
941
942 if (vk_format_is_color(image->vk.format)) {
943 if (!radv_image_has_cmask(image) && !radv_image_has_dcc(image))
944 return false;
945
946 /* RB+ doesn't work with CMASK fast clear on Stoney. */
947 if (!radv_image_has_dcc(image) && pdev->info.family == CHIP_STONEY)
948 return false;
949
950 /* Fast-clears with CMASK aren't supported for 128-bit formats. */
951 if (radv_image_has_cmask(image) && vk_format_get_blocksizebits(image->vk.format) > 64)
952 return false;
953 } else {
954 if (!radv_image_has_htile(image))
955 return false;
956 }
957
958 /* Do not fast clears 3D images. */
959 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
960 return false;
961
962 return true;
963 }
964
965 /**
966 * Determine if the given image can be fast cleared using comp-to-single.
967 */
968 static bool
radv_image_use_comp_to_single(const struct radv_device * device,const struct radv_image * image)969 radv_image_use_comp_to_single(const struct radv_device *device, const struct radv_image *image)
970 {
971 const struct radv_physical_device *pdev = radv_device_physical(device);
972
973 /* comp-to-single is only available for GFX10+. */
974 if (pdev->info.gfx_level < GFX10)
975 return false;
976
977 /* If the image can't be fast cleared, comp-to-single can't be used. */
978 if (!radv_image_can_fast_clear(device, image))
979 return false;
980
981 /* If the image doesn't have DCC, it can't be fast cleared using comp-to-single */
982 if (!radv_image_has_dcc(image))
983 return false;
984
985 /* It seems 8bpp and 16bpp require RB+ to work. */
986 unsigned bytes_per_pixel = vk_format_get_blocksize(image->vk.format);
987 if (bytes_per_pixel <= 2 && !pdev->info.rbplus_allowed)
988 return false;
989
990 return true;
991 }
992
993 static unsigned
radv_get_internal_plane_count(const struct radv_physical_device * pdev,VkFormat fmt)994 radv_get_internal_plane_count(const struct radv_physical_device *pdev, VkFormat fmt)
995 {
996 if (radv_is_format_emulated(pdev, fmt))
997 return 2;
998 return vk_format_get_plane_count(fmt);
999 }
1000
1001 static void
radv_image_reset_layout(const struct radv_physical_device * pdev,struct radv_image * image)1002 radv_image_reset_layout(const struct radv_physical_device *pdev, struct radv_image *image)
1003 {
1004 image->size = 0;
1005 image->alignment = 1;
1006
1007 image->tc_compatible_cmask = 0;
1008 image->fce_pred_offset = image->dcc_pred_offset = 0;
1009 image->clear_value_offset = image->tc_compat_zrange_offset = 0;
1010
1011 unsigned plane_count = radv_get_internal_plane_count(pdev, image->vk.format);
1012 for (unsigned i = 0; i < plane_count; ++i) {
1013 VkFormat format = radv_image_get_plane_format(pdev, image, i);
1014 if (vk_format_has_depth(format))
1015 format = vk_format_depth_only(format);
1016
1017 uint64_t flags = image->planes[i].surface.flags;
1018 uint64_t modifier = image->planes[i].surface.modifier;
1019 memset(image->planes + i, 0, sizeof(image->planes[i]));
1020
1021 image->planes[i].surface.flags = flags;
1022 image->planes[i].surface.modifier = modifier;
1023 image->planes[i].surface.blk_w = vk_format_get_blockwidth(format);
1024 image->planes[i].surface.blk_h = vk_format_get_blockheight(format);
1025 image->planes[i].surface.bpe = vk_format_get_blocksize(format);
1026
1027 /* align byte per element on dword */
1028 if (image->planes[i].surface.bpe == 3) {
1029 image->planes[i].surface.bpe = 4;
1030 }
1031 }
1032 }
1033
1034 struct ac_surf_info
radv_get_ac_surf_info(struct radv_device * device,const struct radv_image * image)1035 radv_get_ac_surf_info(struct radv_device *device, const struct radv_image *image)
1036 {
1037 struct ac_surf_info info;
1038
1039 memset(&info, 0, sizeof(info));
1040
1041 info.width = image->vk.extent.width;
1042 info.height = image->vk.extent.height;
1043 info.depth = image->vk.extent.depth;
1044 info.samples = image->vk.samples;
1045 info.storage_samples = image->vk.samples;
1046 info.array_size = image->vk.array_layers;
1047 info.levels = image->vk.mip_levels;
1048 info.num_channels = vk_format_get_nr_components(image->vk.format);
1049
1050 if (!vk_format_is_depth_or_stencil(image->vk.format) && !image->shareable &&
1051 !(image->vk.create_flags & (VK_IMAGE_CREATE_SPARSE_ALIASED_BIT | VK_IMAGE_CREATE_ALIAS_BIT |
1052 VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT)) &&
1053 image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1054 info.surf_index = &device->image_mrt_offset_counter;
1055 info.fmask_surf_index = &device->fmask_mrt_offset_counter;
1056 }
1057
1058 return info;
1059 }
1060
1061 static void
radv_surface_init(struct radv_physical_device * pdev,const struct ac_surf_info * surf_info,struct radeon_surf * surf)1062 radv_surface_init(struct radv_physical_device *pdev, const struct ac_surf_info *surf_info, struct radeon_surf *surf)
1063 {
1064 uint32_t type = RADEON_SURF_GET(surf->flags, TYPE);
1065 uint32_t mode = RADEON_SURF_GET(surf->flags, MODE);
1066
1067 struct ac_surf_config config;
1068
1069 memcpy(&config.info, surf_info, sizeof(config.info));
1070 config.is_1d = type == RADEON_SURF_TYPE_1D || type == RADEON_SURF_TYPE_1D_ARRAY;
1071 config.is_3d = type == RADEON_SURF_TYPE_3D;
1072 config.is_cube = type == RADEON_SURF_TYPE_CUBEMAP;
1073 config.is_array = type == RADEON_SURF_TYPE_1D_ARRAY || type == RADEON_SURF_TYPE_2D_ARRAY;
1074
1075 ac_compute_surface(pdev->addrlib, &pdev->info, &config, mode, surf);
1076 }
1077
1078 /* Return the first mip level which is pipe-misaligned with metadata, UINT32_MAX means no mips are
1079 * affected and zero means all mips.
1080 */
1081 static uint32_t
radv_image_get_first_mip_pipe_misaligned(const struct radv_device * device,const struct radv_image * image,uint32_t plane_id)1082 radv_image_get_first_mip_pipe_misaligned(const struct radv_device *device, const struct radv_image *image,
1083 uint32_t plane_id)
1084 {
1085 const struct radv_physical_device *pdev = radv_device_physical(device);
1086 const int log2_samples = util_logbase2(image->vk.samples);
1087 uint32_t first_mip = UINT32_MAX;
1088
1089 /* Add a special case for mips in the metadata mip-tail for GFX11. */
1090 if (pdev->info.gfx_level >= GFX11) {
1091 if (image->vk.mip_levels > 1 && (radv_image_has_dcc(image) || radv_image_has_htile(image))) {
1092 first_mip = image->planes[plane_id].surface.num_meta_levels;
1093 }
1094 }
1095
1096 VkFormat fmt = radv_image_get_plane_format(pdev, image, plane_id);
1097 int log2_bpp = util_logbase2(vk_format_get_blocksize(fmt));
1098 int log2_bpp_and_samples;
1099
1100 if (pdev->info.gfx_level >= GFX10_3) {
1101 log2_bpp_and_samples = log2_bpp + log2_samples;
1102 } else {
1103 if (vk_format_has_depth(image->vk.format) && image->vk.array_layers >= 8) {
1104 log2_bpp = 2;
1105 }
1106
1107 log2_bpp_and_samples = MIN2(6, log2_bpp + log2_samples);
1108 }
1109
1110 int num_pipes = G_0098F8_NUM_PIPES(pdev->info.gb_addr_config);
1111 int overlap = MAX2(0, log2_bpp_and_samples + num_pipes - 8);
1112
1113 if (vk_format_has_depth(image->vk.format)) {
1114 if (radv_image_is_tc_compat_htile(image) && (pdev->info.tcc_rb_non_coherent || overlap)) {
1115 first_mip = 0;
1116 }
1117 } else {
1118 int max_compressed_frags = G_0098F8_MAX_COMPRESSED_FRAGS(pdev->info.gb_addr_config);
1119 int log2_samples_frag_diff = MAX2(0, log2_samples - max_compressed_frags);
1120 int samples_overlap = MIN2(log2_samples, overlap);
1121
1122 /* TODO: It shouldn't be necessary if the image has DCC but
1123 * not readable by shader.
1124 */
1125 if ((radv_image_has_dcc(image) || radv_image_is_tc_compat_cmask(image)) &&
1126 (pdev->info.tcc_rb_non_coherent || (samples_overlap > log2_samples_frag_diff))) {
1127 first_mip = 0;
1128 }
1129 }
1130
1131 return first_mip;
1132 }
1133
1134 static void
radv_image_init_first_mip_pipe_misaligned(const struct radv_device * device,struct radv_image * image)1135 radv_image_init_first_mip_pipe_misaligned(const struct radv_device *device, struct radv_image *image)
1136 {
1137 for (uint32_t i = 0; i < image->plane_count; i++) {
1138 image->planes[i].first_mip_pipe_misaligned = radv_image_get_first_mip_pipe_misaligned(device, image, i);
1139 }
1140 }
1141
1142 VkResult
radv_image_create_layout(struct radv_device * device,struct radv_image_create_info create_info,const struct VkImageDrmFormatModifierExplicitCreateInfoEXT * mod_info,const struct VkVideoProfileListInfoKHR * profile_list,struct radv_image * image)1143 radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info,
1144 const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info,
1145 const struct VkVideoProfileListInfoKHR *profile_list, struct radv_image *image)
1146 {
1147 struct radv_physical_device *pdev = radv_device_physical(device);
1148
1149 /* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the
1150 * common internal case. */
1151 create_info.vk_info = NULL;
1152
1153 struct ac_surf_info image_info = radv_get_ac_surf_info(device, image);
1154 VkResult result = radv_patch_image_from_extra_info(device, image, &create_info, &image_info);
1155 if (result != VK_SUCCESS)
1156 return result;
1157
1158 assert(!mod_info || mod_info->drmFormatModifierPlaneCount >= image->plane_count);
1159
1160 radv_image_reset_layout(pdev, image);
1161
1162 /*
1163 * Due to how the decoder works, the user can't supply an oversized image, because if it attempts
1164 * to sample it later with a linear filter, it will get garbage after the height it wants,
1165 * so we let the user specify the width/height unaligned, and align them preallocation.
1166 */
1167 if (image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
1168 VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1169 VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)) {
1170 if (!device->vk.enabled_features.videoMaintenance1)
1171 assert(profile_list);
1172 uint32_t width_align, height_align;
1173 radv_video_get_profile_alignments(pdev, profile_list, &width_align, &height_align);
1174 image_info.width = align(image_info.width, width_align);
1175 image_info.height = align(image_info.height, height_align);
1176
1177 if (radv_has_uvd(pdev) && image->vk.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) {
1178 /* UVD and kernel demand a full DPB allocation. */
1179 image_info.array_size = MIN2(16, image_info.array_size);
1180 }
1181 }
1182
1183 unsigned plane_count = radv_get_internal_plane_count(pdev, image->vk.format);
1184 for (unsigned plane = 0; plane < plane_count; ++plane) {
1185 struct ac_surf_info info = image_info;
1186 uint64_t offset;
1187 unsigned stride;
1188
1189 info.width = vk_format_get_plane_width(image->vk.format, plane, info.width);
1190 info.height = vk_format_get_plane_height(image->vk.format, plane, info.height);
1191
1192 if (create_info.no_metadata_planes || plane_count > 1) {
1193 image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE;
1194 }
1195
1196 radv_surface_init(pdev, &info, &image->planes[plane].surface);
1197
1198 if (plane == 0) {
1199 if (!radv_use_dcc_for_image_late(device, image))
1200 ac_surface_zero_dcc_fields(&image->planes[0].surface);
1201 }
1202
1203 if (pdev->info.gfx_level >= GFX12 &&
1204 (!radv_surface_has_scanout(device, &create_info) || pdev->info.gfx12_supports_display_dcc)) {
1205 const enum pipe_format format = vk_format_to_pipe_format(image->vk.format);
1206
1207 /* Set DCC tilings for both color and depth/stencil. */
1208 image->planes[plane].surface.u.gfx9.color.dcc_number_type = ac_get_cb_number_type(format);
1209 image->planes[plane].surface.u.gfx9.color.dcc_data_format = ac_get_cb_format(pdev->info.gfx_level, format);
1210 image->planes[plane].surface.u.gfx9.color.dcc_write_compress_disable = false;
1211 }
1212
1213 if (create_info.bo_metadata && !mod_info &&
1214 !ac_surface_apply_umd_metadata(&pdev->info, &image->planes[plane].surface, image->vk.samples,
1215 image->vk.mip_levels, create_info.bo_metadata->size_metadata,
1216 create_info.bo_metadata->metadata))
1217 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1218
1219 if (!create_info.no_metadata_planes && !create_info.bo_metadata && plane_count == 1 && !mod_info)
1220 radv_image_alloc_single_sample_cmask(device, image, &image->planes[plane].surface);
1221
1222 if (mod_info) {
1223 if (mod_info->pPlaneLayouts[plane].rowPitch % image->planes[plane].surface.bpe ||
1224 !mod_info->pPlaneLayouts[plane].rowPitch)
1225 return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1226
1227 offset = mod_info->pPlaneLayouts[plane].offset;
1228 stride = mod_info->pPlaneLayouts[plane].rowPitch / image->planes[plane].surface.bpe;
1229 } else {
1230 offset = image->disjoint ? 0 : align64(image->size, 1ull << image->planes[plane].surface.alignment_log2);
1231 stride = 0; /* 0 means no override */
1232 }
1233
1234 if (!ac_surface_override_offset_stride(&pdev->info, &image->planes[plane].surface, image->vk.array_layers,
1235 image->vk.mip_levels, offset, stride))
1236 return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1237
1238 /* Validate DCC offsets in modifier layout. */
1239 if (plane_count == 1 && mod_info) {
1240 unsigned mem_planes = ac_surface_get_nplanes(&image->planes[plane].surface);
1241 if (mod_info->drmFormatModifierPlaneCount != mem_planes)
1242 return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1243
1244 for (unsigned i = 1; i < mem_planes; ++i) {
1245 if (ac_surface_get_plane_offset(pdev->info.gfx_level, &image->planes[plane].surface, i, 0) !=
1246 mod_info->pPlaneLayouts[i].offset)
1247 return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1248 }
1249 }
1250
1251 image->size = MAX2(image->size, offset + image->planes[plane].surface.total_size);
1252 image->alignment = MAX2(image->alignment, 1 << image->planes[plane].surface.alignment_log2);
1253
1254 image->planes[plane].format = radv_image_get_plane_format(pdev, image, plane);
1255 }
1256
1257 image->tc_compatible_cmask = radv_image_has_cmask(image) && radv_use_tc_compat_cmask_for_image(device, image);
1258
1259 if (pdev->info.gfx_level >= GFX10 && pdev->info.gfx_level < GFX12)
1260 radv_image_init_first_mip_pipe_misaligned(device, image);
1261
1262 image->support_comp_to_single = radv_image_use_comp_to_single(device, image);
1263
1264 radv_image_alloc_values(device, image);
1265
1266 assert(image->planes[0].surface.surf_size);
1267 assert(image->planes[0].surface.modifier == DRM_FORMAT_MOD_INVALID ||
1268 ac_modifier_has_dcc(image->planes[0].surface.modifier) ==
1269 (pdev->info.gfx_level >= GFX12 ? image->planes[0].surface.u.gfx9.gfx12_enable_dcc
1270 : radv_image_has_dcc(image)));
1271 return VK_SUCCESS;
1272 }
1273
1274 static void
radv_destroy_image(struct radv_device * device,const VkAllocationCallbacks * pAllocator,struct radv_image * image)1275 radv_destroy_image(struct radv_device *device, const VkAllocationCallbacks *pAllocator, struct radv_image *image)
1276 {
1277 struct radv_physical_device *pdev = radv_device_physical(device);
1278 struct radv_instance *instance = radv_physical_device_instance(pdev);
1279
1280 if ((image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && image->bindings[0].bo)
1281 radv_bo_destroy(device, &image->vk.base, image->bindings[0].bo);
1282
1283 if (image->owned_memory != VK_NULL_HANDLE) {
1284 VK_FROM_HANDLE(radv_device_memory, mem, image->owned_memory);
1285 radv_free_memory(device, pAllocator, mem);
1286 }
1287
1288 for (uint32_t i = 0; i < ARRAY_SIZE(image->bindings); i++) {
1289 if (!image->bindings[i].bo_va)
1290 continue;
1291
1292 vk_address_binding_report(&instance->vk, &image->vk.base, image->bindings[i].bo_va + image->bindings[i].offset,
1293 image->bindings[i].range, VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
1294 }
1295
1296 radv_rmv_log_resource_destroy(device, (uint64_t)radv_image_to_handle(image));
1297 vk_image_finish(&image->vk);
1298 vk_free2(&device->vk.alloc, pAllocator, image);
1299 }
1300
1301 static void
radv_image_print_info(struct radv_device * device,struct radv_image * image)1302 radv_image_print_info(struct radv_device *device, struct radv_image *image)
1303 {
1304 const struct radv_physical_device *pdev = radv_device_physical(device);
1305
1306 fprintf(stderr, "Image:\n");
1307 fprintf(stderr,
1308 " Info: size=%" PRIu64 ", alignment=%" PRIu32 ", "
1309 "width=%" PRIu32 ", height=%" PRIu32 ", depth=%" PRIu32 ", "
1310 "array_size=%" PRIu32 ", levels=%" PRIu32 "\n",
1311 image->size, image->alignment, image->vk.extent.width, image->vk.extent.height, image->vk.extent.depth,
1312 image->vk.array_layers, image->vk.mip_levels);
1313 for (unsigned i = 0; i < image->plane_count; ++i) {
1314 const struct radv_image_plane *plane = &image->planes[i];
1315 const struct radeon_surf *surf = &plane->surface;
1316 const struct util_format_description *desc = vk_format_description(plane->format);
1317 uint64_t offset = ac_surface_get_plane_offset(pdev->info.gfx_level, &plane->surface, 0, 0);
1318
1319 fprintf(stderr, " Plane[%u]: vkformat=%s, offset=%" PRIu64 "\n", i, desc->name, offset);
1320
1321 ac_surface_print_info(stderr, &pdev->info, surf);
1322 }
1323 }
1324
1325 static uint64_t
radv_select_modifier(const struct radv_device * dev,VkFormat format,const struct VkImageDrmFormatModifierListCreateInfoEXT * mod_list)1326 radv_select_modifier(const struct radv_device *dev, VkFormat format,
1327 const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list)
1328 {
1329 const struct radv_physical_device *pdev = radv_device_physical(dev);
1330 unsigned mod_count;
1331
1332 assert(mod_list->drmFormatModifierCount);
1333
1334 /* We can allow everything here as it does not affect order and the application
1335 * is only allowed to specify modifiers that we support. */
1336 const struct ac_modifier_options modifier_options = {
1337 .dcc = true,
1338 .dcc_retile = true,
1339 };
1340
1341 ac_get_supported_modifiers(&pdev->info, &modifier_options, radv_format_to_pipe_format(format), &mod_count, NULL);
1342
1343 uint64_t *mods = calloc(mod_count, sizeof(*mods));
1344
1345 /* If allocations fail, fall back to a dumber solution. */
1346 if (!mods)
1347 return mod_list->pDrmFormatModifiers[0];
1348
1349 ac_get_supported_modifiers(&pdev->info, &modifier_options, radv_format_to_pipe_format(format), &mod_count, mods);
1350
1351 for (unsigned i = 0; i < mod_count; ++i) {
1352 for (uint32_t j = 0; j < mod_list->drmFormatModifierCount; ++j) {
1353 if (mods[i] == mod_list->pDrmFormatModifiers[j]) {
1354 free(mods);
1355 return mod_list->pDrmFormatModifiers[j];
1356 }
1357 }
1358 }
1359 unreachable("App specified an invalid modifier");
1360 }
1361
1362 VkResult
radv_image_create(VkDevice _device,const struct radv_image_create_info * create_info,const VkAllocationCallbacks * alloc,VkImage * pImage,bool is_internal)1363 radv_image_create(VkDevice _device, const struct radv_image_create_info *create_info,
1364 const VkAllocationCallbacks *alloc, VkImage *pImage, bool is_internal)
1365 {
1366 VK_FROM_HANDLE(radv_device, device, _device);
1367 const struct radv_physical_device *pdev = radv_device_physical(device);
1368 const struct radv_instance *instance = radv_physical_device_instance(pdev);
1369 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1370 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
1371 struct radv_image *image = NULL;
1372 VkFormat format = radv_select_android_external_format(pCreateInfo->pNext, pCreateInfo->format);
1373 const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
1374 vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1375 const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =
1376 vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1377 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
1378 const struct VkVideoProfileListInfoKHR *profile_list =
1379 vk_find_struct_const(pCreateInfo->pNext, VIDEO_PROFILE_LIST_INFO_KHR);
1380
1381 unsigned plane_count = radv_get_internal_plane_count(pdev, format);
1382
1383 const size_t image_struct_size = sizeof(*image) + sizeof(struct radv_image_plane) * plane_count;
1384
1385 image = vk_zalloc2(&device->vk.alloc, alloc, image_struct_size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1386 if (!image)
1387 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1388
1389 vk_image_init(&device->vk, &image->vk, pCreateInfo);
1390
1391 image->plane_count = vk_format_get_plane_count(format);
1392 image->disjoint = image->plane_count > 1 && pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT;
1393
1394 image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
1395 if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
1396 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)
1397 if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL ||
1398 pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_FOREIGN_EXT)
1399 image->queue_family_mask |= (1u << RADV_MAX_QUEUE_FAMILIES) - 1u;
1400 else
1401 image->queue_family_mask |= 1u << vk_queue_to_radv(pdev, pCreateInfo->pQueueFamilyIndices[i]);
1402
1403 /* This queue never really accesses the image. */
1404 image->queue_family_mask &= ~(1u << RADV_QUEUE_SPARSE);
1405 }
1406
1407 const VkExternalMemoryImageCreateInfo *external_info =
1408 vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
1409
1410 image->shareable = external_info;
1411
1412 if (mod_list)
1413 modifier = radv_select_modifier(device, format, mod_list);
1414 else if (explicit_mod)
1415 modifier = explicit_mod->drmFormatModifier;
1416
1417 for (unsigned plane = 0; plane < plane_count; ++plane) {
1418 image->planes[plane].surface.flags = radv_get_surface_flags(device, image, plane, pCreateInfo, format);
1419 image->planes[plane].surface.modifier = modifier;
1420 }
1421
1422 if (image->vk.external_handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1423 #if DETECT_OS_ANDROID
1424 image->vk.ahb_format = radv_ahb_format_for_vk_format(image->vk.format);
1425 #endif
1426
1427 *pImage = radv_image_to_handle(image);
1428 assert(!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT));
1429 return VK_SUCCESS;
1430 }
1431
1432 VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, profile_list, image);
1433 if (result != VK_SUCCESS) {
1434 radv_destroy_image(device, alloc, image);
1435 return result;
1436 }
1437
1438 if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
1439 image->alignment = MAX2(image->alignment, 4096);
1440 image->size = align64(image->size, image->alignment);
1441 image->bindings[0].offset = 0;
1442
1443 result = radv_bo_create(device, &image->vk.base, image->size, image->alignment, 0, RADEON_FLAG_VIRTUAL,
1444 RADV_BO_PRIORITY_VIRTUAL, 0, true, &image->bindings[0].bo);
1445 if (result != VK_SUCCESS) {
1446 radv_destroy_image(device, alloc, image);
1447 return vk_error(device, result);
1448 }
1449 }
1450
1451 if (instance->debug_flags & RADV_DEBUG_IMG) {
1452 radv_image_print_info(device, image);
1453 }
1454
1455 *pImage = radv_image_to_handle(image);
1456
1457 radv_rmv_log_image_create(device, pCreateInfo, is_internal, *pImage);
1458 if (image->bindings[0].bo)
1459 radv_rmv_log_image_bind(device, 0, *pImage);
1460 return VK_SUCCESS;
1461 }
1462
1463 unsigned
radv_plane_from_aspect(VkImageAspectFlags mask)1464 radv_plane_from_aspect(VkImageAspectFlags mask)
1465 {
1466 switch (mask) {
1467 case VK_IMAGE_ASPECT_PLANE_1_BIT:
1468 case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
1469 return 1;
1470 case VK_IMAGE_ASPECT_PLANE_2_BIT:
1471 case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
1472 return 2;
1473 case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT:
1474 return 3;
1475 default:
1476 return 0;
1477 }
1478 }
1479
1480 VkFormat
radv_get_aspect_format(struct radv_image * image,VkImageAspectFlags mask)1481 radv_get_aspect_format(struct radv_image *image, VkImageAspectFlags mask)
1482 {
1483 switch (mask) {
1484 case VK_IMAGE_ASPECT_PLANE_0_BIT:
1485 return image->planes[0].format;
1486 case VK_IMAGE_ASPECT_PLANE_1_BIT:
1487 return image->planes[1].format;
1488 case VK_IMAGE_ASPECT_PLANE_2_BIT:
1489 return image->planes[2].format;
1490 case VK_IMAGE_ASPECT_STENCIL_BIT:
1491 return vk_format_stencil_only(image->vk.format);
1492 case VK_IMAGE_ASPECT_DEPTH_BIT:
1493 return vk_format_depth_only(image->vk.format);
1494 case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
1495 return vk_format_depth_only(image->vk.format);
1496 default:
1497 return image->vk.format;
1498 }
1499 }
1500
1501 bool
radv_layout_is_htile_compressed(const struct radv_device * device,const struct radv_image * image,VkImageLayout layout,unsigned queue_mask)1502 radv_layout_is_htile_compressed(const struct radv_device *device, const struct radv_image *image, VkImageLayout layout,
1503 unsigned queue_mask)
1504 {
1505 const struct radv_physical_device *pdev = radv_device_physical(device);
1506 const struct radv_instance *instance = radv_physical_device_instance(pdev);
1507
1508 /* Don't compress exclusive images used on transfer queues when SDMA doesn't support HTILE.
1509 * Note that HTILE is already disabled on concurrent images when not supported.
1510 */
1511 if (queue_mask == BITFIELD_BIT(RADV_QUEUE_TRANSFER) && !pdev->info.sdma_supports_compression)
1512 return false;
1513
1514 switch (layout) {
1515 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
1516 case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
1517 case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
1518 case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL:
1519 return radv_image_has_htile(image);
1520 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
1521 return radv_image_is_tc_compat_htile(image) ||
1522 (radv_image_has_htile(image) && queue_mask == (1u << RADV_QUEUE_GENERAL));
1523 case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
1524 case VK_IMAGE_LAYOUT_GENERAL:
1525 /* It should be safe to enable TC-compat HTILE with
1526 * VK_IMAGE_LAYOUT_GENERAL if we are not in a render loop and
1527 * if the image doesn't have the storage bit set. This
1528 * improves performance for apps that use GENERAL for the main
1529 * depth pass because this allows compression and this reduces
1530 * the number of decompressions from/to GENERAL.
1531 */
1532 if (radv_image_is_tc_compat_htile(image) && queue_mask & (1u << RADV_QUEUE_GENERAL) &&
1533 !instance->drirc.disable_tc_compat_htile_in_general) {
1534 return true;
1535 } else {
1536 return false;
1537 }
1538 case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
1539 /* Do not compress HTILE with feedback loops because we can't read&write it without
1540 * introducing corruption.
1541 */
1542 return false;
1543 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1544 case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL:
1545 if (radv_image_is_tc_compat_htile(image) ||
1546 (radv_image_has_htile(image) &&
1547 !(image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)))) {
1548 /* Keep HTILE compressed if the image is only going to
1549 * be used as a depth/stencil read-only attachment.
1550 */
1551 return true;
1552 } else {
1553 return false;
1554 }
1555 break;
1556 default:
1557 return radv_image_is_tc_compat_htile(image);
1558 }
1559 }
1560
1561 bool
radv_layout_can_fast_clear(const struct radv_device * device,const struct radv_image * image,unsigned level,VkImageLayout layout,unsigned queue_mask)1562 radv_layout_can_fast_clear(const struct radv_device *device, const struct radv_image *image, unsigned level,
1563 VkImageLayout layout, unsigned queue_mask)
1564 {
1565 if (radv_dcc_enabled(image, level) && !radv_layout_dcc_compressed(device, image, level, layout, queue_mask))
1566 return false;
1567
1568 if (!(image->vk.usage & RADV_IMAGE_USAGE_WRITE_BITS))
1569 return false;
1570
1571 if (layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && layout != VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL)
1572 return false;
1573
1574 /* Exclusive images with CMASK or DCC can always be fast-cleared on the gfx queue. Concurrent
1575 * images can only be fast-cleared if comp-to-single is supported because we don't yet support
1576 * FCE on the compute queue.
1577 */
1578 return queue_mask == (1u << RADV_QUEUE_GENERAL) || radv_image_use_comp_to_single(device, image);
1579 }
1580
1581 bool
radv_layout_dcc_compressed(const struct radv_device * device,const struct radv_image * image,unsigned level,VkImageLayout layout,unsigned queue_mask)1582 radv_layout_dcc_compressed(const struct radv_device *device, const struct radv_image *image, unsigned level,
1583 VkImageLayout layout, unsigned queue_mask)
1584 {
1585 const struct radv_physical_device *pdev = radv_device_physical(device);
1586
1587 if (!radv_dcc_enabled(image, level))
1588 return false;
1589
1590 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && queue_mask & (1u << RADV_QUEUE_FOREIGN))
1591 return true;
1592
1593 /* If the image is read-only, we can always just keep it compressed */
1594 if (!(image->vk.usage & RADV_IMAGE_USAGE_WRITE_BITS))
1595 return true;
1596
1597 /* Don't compress compute transfer dst when image stores are not supported. */
1598 if ((layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || layout == VK_IMAGE_LAYOUT_GENERAL) &&
1599 (queue_mask & (1u << RADV_QUEUE_COMPUTE)) && !radv_image_use_dcc_image_stores(device, image))
1600 return false;
1601
1602 /* Don't compress exclusive images used on transfer queues when SDMA doesn't support DCC.
1603 * Note that DCC is already disabled on concurrent images when not supported.
1604 */
1605 if (queue_mask == BITFIELD_BIT(RADV_QUEUE_TRANSFER) && !pdev->info.sdma_supports_compression)
1606 return false;
1607
1608 if (layout == VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT) {
1609 /* Do not compress DCC with feedback loops because we can't read&write it without introducing
1610 * corruption.
1611 */
1612 return false;
1613 }
1614
1615 return pdev->info.gfx_level >= GFX10 || layout != VK_IMAGE_LAYOUT_GENERAL;
1616 }
1617
1618 enum radv_fmask_compression
radv_layout_fmask_compression(const struct radv_device * device,const struct radv_image * image,VkImageLayout layout,unsigned queue_mask)1619 radv_layout_fmask_compression(const struct radv_device *device, const struct radv_image *image, VkImageLayout layout,
1620 unsigned queue_mask)
1621 {
1622 if (!radv_image_has_fmask(image))
1623 return RADV_FMASK_COMPRESSION_NONE;
1624
1625 if (layout == VK_IMAGE_LAYOUT_GENERAL)
1626 return RADV_FMASK_COMPRESSION_NONE;
1627
1628 /* Don't compress compute transfer dst because image stores ignore FMASK and it needs to be
1629 * expanded before.
1630 */
1631 if (layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && (queue_mask & (1u << RADV_QUEUE_COMPUTE)))
1632 return RADV_FMASK_COMPRESSION_NONE;
1633
1634 /* Compress images if TC-compat CMASK is enabled. */
1635 if (radv_image_is_tc_compat_cmask(image))
1636 return RADV_FMASK_COMPRESSION_FULL;
1637
1638 switch (layout) {
1639 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
1640 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
1641 /* Don't compress images but no need to expand FMASK. */
1642 return RADV_FMASK_COMPRESSION_PARTIAL;
1643 case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
1644 /* Don't compress images that are in feedback loops. */
1645 return RADV_FMASK_COMPRESSION_NONE;
1646 default:
1647 /* Don't compress images that are concurrent. */
1648 return queue_mask == (1u << RADV_QUEUE_GENERAL) ? RADV_FMASK_COMPRESSION_FULL : RADV_FMASK_COMPRESSION_NONE;
1649 }
1650 }
1651
1652 unsigned
radv_image_queue_family_mask(const struct radv_image * image,enum radv_queue_family family,enum radv_queue_family queue_family)1653 radv_image_queue_family_mask(const struct radv_image *image, enum radv_queue_family family,
1654 enum radv_queue_family queue_family)
1655 {
1656 if (!image->exclusive)
1657 return image->queue_family_mask;
1658 if (family == RADV_QUEUE_FOREIGN)
1659 return ((1u << RADV_MAX_QUEUE_FAMILIES) - 1u) | (1u << RADV_QUEUE_FOREIGN);
1660 if (family == RADV_QUEUE_IGNORED)
1661 return 1u << queue_family;
1662 return 1u << family;
1663 }
1664
1665 bool
radv_image_is_renderable(const struct radv_device * device,const struct radv_image * image)1666 radv_image_is_renderable(const struct radv_device *device, const struct radv_image *image)
1667 {
1668 const struct radv_physical_device *pdev = radv_device_physical(device);
1669
1670 if (image->vk.format == VK_FORMAT_R32G32B32_UINT || image->vk.format == VK_FORMAT_R32G32B32_SINT ||
1671 image->vk.format == VK_FORMAT_R32G32B32_SFLOAT)
1672 return false;
1673
1674 if (pdev->info.gfx_level >= GFX9 && image->vk.image_type == VK_IMAGE_TYPE_3D &&
1675 vk_format_get_blocksizebits(image->vk.format) == 128 && vk_format_is_compressed(image->vk.format))
1676 return false;
1677
1678 if (image->planes[0].surface.flags & RADEON_SURF_NO_RENDER_TARGET)
1679 return false;
1680
1681 return true;
1682 }
1683
1684 VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1685 radv_CreateImage(VkDevice _device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1686 VkImage *pImage)
1687 {
1688 #if DETECT_OS_ANDROID
1689 const VkNativeBufferANDROID *gralloc_info = vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1690
1691 if (gralloc_info)
1692 return radv_image_from_gralloc(_device, pCreateInfo, gralloc_info, pAllocator, pImage);
1693 #endif
1694
1695 #ifdef RADV_USE_WSI_PLATFORM
1696 /* Ignore swapchain creation info on Android. Since we don't have an implementation in Mesa,
1697 * we're guaranteed to access an Android object incorrectly.
1698 */
1699 VK_FROM_HANDLE(radv_device, device, _device);
1700 const struct radv_physical_device *pdev = radv_device_physical(device);
1701 const VkImageSwapchainCreateInfoKHR *swapchain_info =
1702 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1703 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1704 return wsi_common_create_swapchain_image(pdev->vk.wsi_device, pCreateInfo, swapchain_info->swapchain, pImage);
1705 }
1706 #endif
1707
1708 const struct wsi_image_create_info *wsi_info = vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
1709 bool scanout = wsi_info && wsi_info->scanout;
1710 bool prime_blit_src = wsi_info && wsi_info->blit_src;
1711
1712 return radv_image_create(_device,
1713 &(struct radv_image_create_info){
1714 .vk_info = pCreateInfo,
1715 .scanout = scanout,
1716 .prime_blit_src = prime_blit_src,
1717 },
1718 pAllocator, pImage, false);
1719 }
1720
1721 VKAPI_ATTR void VKAPI_CALL
radv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1722 radv_DestroyImage(VkDevice _device, VkImage _image, const VkAllocationCallbacks *pAllocator)
1723 {
1724 VK_FROM_HANDLE(radv_device, device, _device);
1725 VK_FROM_HANDLE(radv_image, image, _image);
1726
1727 if (!image)
1728 return;
1729
1730 radv_destroy_image(device, pAllocator, image);
1731 }
1732
1733 static void
radv_bind_image_memory(struct radv_device * device,struct radv_image * image,uint32_t bind_idx,struct radeon_winsys_bo * bo,uint64_t offset,uint64_t range)1734 radv_bind_image_memory(struct radv_device *device, struct radv_image *image, uint32_t bind_idx,
1735 struct radeon_winsys_bo *bo, uint64_t offset, uint64_t range)
1736 {
1737 struct radv_physical_device *pdev = radv_device_physical(device);
1738 struct radv_instance *instance = radv_physical_device_instance(pdev);
1739
1740 assert(bind_idx < 3);
1741
1742 image->bindings[bind_idx].bo = bo;
1743 image->bindings[bind_idx].offset = offset;
1744 image->bindings[bind_idx].bo_va = radv_buffer_get_va(bo);
1745 image->bindings[bind_idx].range = range;
1746
1747 radv_rmv_log_image_bind(device, bind_idx, radv_image_to_handle(image));
1748
1749 vk_address_binding_report(&instance->vk, &image->vk.base,
1750 image->bindings[bind_idx].bo_va + image->bindings[bind_idx].offset,
1751 image->bindings[bind_idx].range, VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
1752 }
1753
1754 VKAPI_ATTR VkResult VKAPI_CALL
radv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1755 radv_BindImageMemory2(VkDevice _device, uint32_t bindInfoCount, const VkBindImageMemoryInfo *pBindInfos)
1756 {
1757 VK_FROM_HANDLE(radv_device, device, _device);
1758
1759 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1760 VK_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory);
1761 VK_FROM_HANDLE(radv_image, image, pBindInfos[i].image);
1762 VkBindMemoryStatus *status = (void *)vk_find_struct_const(&pBindInfos[i], BIND_MEMORY_STATUS);
1763
1764 if (status)
1765 *status->pResult = VK_SUCCESS;
1766
1767 /* Ignore this struct on Android, we cannot access swapchain structures there. */
1768 #ifdef RADV_USE_WSI_PLATFORM
1769 const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1770 vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
1771
1772 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1773 struct radv_image *swapchain_img =
1774 radv_image_from_handle(wsi_common_get_image(swapchain_info->swapchain, swapchain_info->imageIndex));
1775
1776 radv_bind_image_memory(device, image, 0,
1777 swapchain_img->bindings[0].bo, swapchain_img->bindings[0].offset,
1778 swapchain_img->bindings[0].range);
1779 continue;
1780 }
1781 #endif
1782
1783 const VkBindImagePlaneMemoryInfo *plane_info = NULL;
1784 uint32_t bind_idx = 0;
1785
1786 if (image->disjoint) {
1787 plane_info = vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
1788 bind_idx = radv_plane_from_aspect(plane_info->planeAspect);
1789 }
1790
1791 VkImagePlaneMemoryRequirementsInfo plane = {
1792 .sType = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
1793 .planeAspect = plane_info ? plane_info->planeAspect : 0,
1794 };
1795 VkImageMemoryRequirementsInfo2 info = {
1796 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
1797 .pNext = image->disjoint ? &plane : NULL,
1798 .image = pBindInfos[i].image,
1799 };
1800 VkMemoryRequirements2 reqs = {
1801 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1802 };
1803
1804 radv_GetImageMemoryRequirements2(_device, &info, &reqs);
1805
1806 if (mem->alloc_size) {
1807 if (pBindInfos[i].memoryOffset + reqs.memoryRequirements.size > mem->alloc_size) {
1808 if (status)
1809 *status->pResult = VK_ERROR_UNKNOWN;
1810 return vk_errorf(device, VK_ERROR_UNKNOWN, "Device memory object too small for the image.\n");
1811 }
1812 }
1813
1814 radv_bind_image_memory(device, image, bind_idx, mem->bo, pBindInfos[i].memoryOffset,
1815 reqs.memoryRequirements.size);
1816 }
1817 return VK_SUCCESS;
1818 }
1819
1820 VKAPI_ATTR void VKAPI_CALL
radv_GetImageSubresourceLayout2(VkDevice _device,VkImage _image,const VkImageSubresource2 * pSubresource,VkSubresourceLayout2 * pLayout)1821 radv_GetImageSubresourceLayout2(VkDevice _device, VkImage _image, const VkImageSubresource2 *pSubresource,
1822 VkSubresourceLayout2 *pLayout)
1823 {
1824 VK_FROM_HANDLE(radv_image, image, _image);
1825 VK_FROM_HANDLE(radv_device, device, _device);
1826 const struct radv_physical_device *pdev = radv_device_physical(device);
1827 int level = pSubresource->imageSubresource.mipLevel;
1828 int layer = pSubresource->imageSubresource.arrayLayer;
1829
1830 const unsigned plane_count = vk_format_get_plane_count(image->vk.format);
1831 unsigned plane_id = 0;
1832 if (plane_count > 1)
1833 plane_id = radv_plane_from_aspect(pSubresource->imageSubresource.aspectMask);
1834
1835 struct radv_image_plane *plane = &image->planes[plane_id];
1836 struct radeon_surf *surface = &plane->surface;
1837
1838 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && plane_count == 1) {
1839 unsigned mem_plane_id = radv_plane_from_aspect(pSubresource->imageSubresource.aspectMask);
1840
1841 assert(level == 0);
1842 assert(layer == 0);
1843
1844 pLayout->subresourceLayout.offset = ac_surface_get_plane_offset(pdev->info.gfx_level, surface, mem_plane_id, 0);
1845 pLayout->subresourceLayout.rowPitch =
1846 ac_surface_get_plane_stride(pdev->info.gfx_level, surface, mem_plane_id, level);
1847 pLayout->subresourceLayout.arrayPitch = 0;
1848 pLayout->subresourceLayout.depthPitch = 0;
1849 pLayout->subresourceLayout.size = ac_surface_get_plane_size(surface, mem_plane_id);
1850 } else if (pdev->info.gfx_level >= GFX9) {
1851 uint64_t level_offset = surface->is_linear ? surface->u.gfx9.offset[level] : 0;
1852
1853 pLayout->subresourceLayout.offset =
1854 ac_surface_get_plane_offset(pdev->info.gfx_level, &plane->surface, 0, layer) + level_offset;
1855 if (image->vk.format == VK_FORMAT_R32G32B32_UINT || image->vk.format == VK_FORMAT_R32G32B32_SINT ||
1856 image->vk.format == VK_FORMAT_R32G32B32_SFLOAT) {
1857 /* Adjust the number of bytes between each row because
1858 * the pitch is actually the number of components per
1859 * row.
1860 */
1861 pLayout->subresourceLayout.rowPitch = surface->u.gfx9.surf_pitch * surface->bpe / 3;
1862 } else {
1863 uint32_t pitch = surface->is_linear ? surface->u.gfx9.pitch[level] : surface->u.gfx9.surf_pitch;
1864
1865 assert(util_is_power_of_two_nonzero(surface->bpe));
1866 pLayout->subresourceLayout.rowPitch = pitch * surface->bpe;
1867 }
1868
1869 pLayout->subresourceLayout.arrayPitch = surface->u.gfx9.surf_slice_size;
1870 pLayout->subresourceLayout.depthPitch = surface->u.gfx9.surf_slice_size;
1871 pLayout->subresourceLayout.size = surface->u.gfx9.surf_slice_size;
1872 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
1873 pLayout->subresourceLayout.size *= u_minify(image->vk.extent.depth, level);
1874 } else {
1875 pLayout->subresourceLayout.offset = (uint64_t)surface->u.legacy.level[level].offset_256B * 256 +
1876 (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4 * layer;
1877 pLayout->subresourceLayout.rowPitch = surface->u.legacy.level[level].nblk_x * surface->bpe;
1878 pLayout->subresourceLayout.arrayPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1879 pLayout->subresourceLayout.depthPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1880 pLayout->subresourceLayout.size = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1881 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
1882 pLayout->subresourceLayout.size *= u_minify(image->vk.extent.depth, level);
1883 }
1884
1885 VkImageCompressionPropertiesEXT *image_compression_props =
1886 vk_find_struct(pLayout->pNext, IMAGE_COMPRESSION_PROPERTIES_EXT);
1887 if (image_compression_props) {
1888 image_compression_props->imageCompressionFixedRateFlags = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
1889
1890 if (image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
1891 image_compression_props->imageCompressionFlags =
1892 radv_image_has_htile(image) ? VK_IMAGE_COMPRESSION_DEFAULT_EXT : VK_IMAGE_COMPRESSION_DISABLED_EXT;
1893 } else {
1894 image_compression_props->imageCompressionFlags =
1895 radv_image_has_dcc(image) ? VK_IMAGE_COMPRESSION_DEFAULT_EXT : VK_IMAGE_COMPRESSION_DISABLED_EXT;
1896 }
1897 }
1898 }
1899
1900 VKAPI_ATTR VkResult VKAPI_CALL
radv_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device,VkImage _image,VkImageDrmFormatModifierPropertiesEXT * pProperties)1901 radv_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device, VkImage _image,
1902 VkImageDrmFormatModifierPropertiesEXT *pProperties)
1903 {
1904 VK_FROM_HANDLE(radv_image, image, _image);
1905
1906 pProperties->drmFormatModifier = image->planes[0].surface.modifier;
1907 return VK_SUCCESS;
1908 }
1909