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