1 /*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from tu_image.c which is:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 * Copyright © 2015 Intel Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29 #include "pan_props.h"
30
31 #include "panvk_device.h"
32 #include "panvk_device_memory.h"
33 #include "panvk_entrypoints.h"
34 #include "panvk_image.h"
35 #include "panvk_instance.h"
36 #include "panvk_physical_device.h"
37
38 #include "drm-uapi/drm_fourcc.h"
39 #include "util/u_atomic.h"
40 #include "util/u_debug.h"
41 #include "util/u_drm.h"
42
43 #include "vk_format.h"
44 #include "vk_log.h"
45 #include "vk_object.h"
46 #include "vk_util.h"
47
48 static bool
panvk_image_can_use_mod(struct panvk_image * image,uint64_t mod)49 panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
50 {
51 struct panvk_physical_device *phys_dev =
52 to_panvk_physical_device(image->vk.base.device->physical);
53 unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
54 struct panvk_instance *instance =
55 to_panvk_instance(image->vk.base.device->physical->instance);
56 enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
57 bool forced_linear = (instance->debug_flags & PANVK_DEBUG_LINEAR) ||
58 image->vk.tiling == VK_IMAGE_TILING_LINEAR ||
59 image->vk.image_type == VK_IMAGE_TYPE_1D;
60
61 /* If the image is meant to be linear, don't bother testing the
62 * other cases. */
63 if (forced_linear)
64 return mod == DRM_FORMAT_MOD_LINEAR;
65
66 if (drm_is_afbc(mod)) {
67 /* Disallow AFBC if either of these is true
68 * - PANVK_DEBUG does not have the 'afbc' flag set
69 * - storage image views are requested
70 * - this is a multisample image
71 * - the GPU doesn't support AFBC
72 * - the format is not AFBC-able
73 * - tiling is set to linear
74 * - this is a 1D image
75 * - this is a 3D image on a pre-v7 GPU
76 * - this is a mutable format image on v7
77 */
78 if (!(instance->debug_flags & PANVK_DEBUG_AFBC) ||
79 ((image->vk.usage | image->vk.stencil_usage) &
80 VK_IMAGE_USAGE_STORAGE_BIT) ||
81 image->vk.samples > 1 ||
82 !panfrost_query_afbc(&phys_dev->kmod.props) ||
83 !panfrost_format_supports_afbc(arch, pfmt) ||
84 image->vk.tiling == VK_IMAGE_TILING_LINEAR ||
85 image->vk.image_type == VK_IMAGE_TYPE_1D ||
86 (image->vk.image_type == VK_IMAGE_TYPE_3D && arch < 7) ||
87 ((image->vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
88 arch == 7))
89 return false;
90
91 const struct util_format_description *fdesc =
92 util_format_description(pfmt);
93 bool is_rgb = fdesc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
94 fdesc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB;
95
96 if ((mod & AFBC_FORMAT_MOD_YTR) && (!is_rgb || fdesc->nr_channels >= 3))
97 return false;
98
99 /* We assume all other unsupported AFBC modes have been filtered out
100 * through pan_best_modifiers[]. */
101 return true;
102 }
103
104 if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
105 /* If we're dealing with a compressed format that requires non-compressed
106 * views we can't use U_INTERLEAVED tiling because the tiling is different
107 * between compressed and non-compressed formats. If we wanted to support
108 * format re-interpretation we would have to specialize the shaders
109 * accessing non-compressed image views (coordinate patching for
110 * sampled/storage image, frag_coord patching for color attachments). Let's
111 * keep things simple for now and make all compressed images that
112 * have VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT set linear. */
113 return !(image->vk.create_flags &
114 VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT);
115 }
116
117 /* If we get there, it must be linear to be supported. */
118 return mod == DRM_FORMAT_MOD_LINEAR;
119 }
120
121 static uint64_t
panvk_image_get_explicit_mod(struct panvk_image * image,const VkImageDrmFormatModifierExplicitCreateInfoEXT * explicit)122 panvk_image_get_explicit_mod(
123 struct panvk_image *image,
124 const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit)
125 {
126 uint64_t mod = explicit->drmFormatModifier;
127
128 assert(!vk_format_is_depth_or_stencil(image->vk.format));
129 assert(image->vk.samples == 1);
130 assert(image->vk.array_layers == 1);
131 assert(image->vk.image_type != VK_IMAGE_TYPE_3D);
132 assert(explicit->drmFormatModifierPlaneCount == 1);
133 assert(panvk_image_can_use_mod(image, mod));
134
135 return mod;
136 }
137
138 static uint64_t
panvk_image_get_mod_from_list(struct panvk_image * image,const uint64_t * mods,uint32_t mod_count)139 panvk_image_get_mod_from_list(struct panvk_image *image,
140 const uint64_t *mods, uint32_t mod_count)
141 {
142 for (unsigned i = 0; i < PAN_MODIFIER_COUNT; ++i) {
143 if (!panvk_image_can_use_mod(image, pan_best_modifiers[i]))
144 continue;
145
146 if (!mod_count ||
147 drm_find_modifier(pan_best_modifiers[i], mods, mod_count))
148 return pan_best_modifiers[i];
149 }
150
151 /* If we reached that point without finding a proper modifier, there's
152 * a serious issue. */
153 assert(!"Invalid modifier");
154 return DRM_FORMAT_MOD_INVALID;
155 }
156
157 static uint64_t
panvk_image_get_mod(struct panvk_image * image,const VkImageCreateInfo * pCreateInfo)158 panvk_image_get_mod(struct panvk_image *image,
159 const VkImageCreateInfo *pCreateInfo)
160 {
161 if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
162 const VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
163 vk_find_struct_const(pCreateInfo->pNext,
164 IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
165 const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =
166 vk_find_struct_const(
167 pCreateInfo->pNext,
168 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
169
170 if (explicit_mod)
171 return panvk_image_get_explicit_mod(image, explicit_mod);
172
173 if (mod_list)
174 return panvk_image_get_mod_from_list(image,
175 mod_list->pDrmFormatModifiers,
176 mod_list->drmFormatModifierCount);
177
178 assert(!"Missing modifier info");
179 }
180
181 return panvk_image_get_mod_from_list(image, NULL, 0);
182 }
183
184 static enum mali_texture_dimension
panvk_image_type_to_mali_tex_dim(VkImageType type)185 panvk_image_type_to_mali_tex_dim(VkImageType type)
186 {
187 switch (type) {
188 case VK_IMAGE_TYPE_1D:
189 return MALI_TEXTURE_DIMENSION_1D;
190 case VK_IMAGE_TYPE_2D:
191 return MALI_TEXTURE_DIMENSION_2D;
192 case VK_IMAGE_TYPE_3D:
193 return MALI_TEXTURE_DIMENSION_3D;
194 default:
195 unreachable("Invalid image type");
196 }
197 }
198
199 static void
panvk_image_init_layouts(struct panvk_image * image,const VkImageCreateInfo * pCreateInfo)200 panvk_image_init_layouts(struct panvk_image *image,
201 const VkImageCreateInfo *pCreateInfo)
202 {
203 struct panvk_physical_device *phys_dev =
204 to_panvk_physical_device(image->vk.base.device->physical);
205 unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
206 const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_info =
207 vk_find_struct_const(
208 pCreateInfo->pNext,
209 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
210
211 image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
212
213 /* Z32_S8X24 is not supported on v9+, and we don't want to use it
214 * on v7- anyway, because it's less efficient than the multiplanar
215 * alternative.
216 */
217 if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
218 image->plane_count = 2;
219
220 for (uint8_t plane = 0; plane < image->plane_count; plane++) {
221 VkFormat format =
222 (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) ?
223 ((plane == 0) ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT) :
224 image->vk.format;
225
226 struct pan_image_explicit_layout plane_layout;
227 if (explicit_info)
228 plane_layout = (struct pan_image_explicit_layout){
229 .offset = explicit_info->pPlaneLayouts[plane].offset,
230 .row_stride = explicit_info->pPlaneLayouts[plane].rowPitch,
231 };
232
233 image->planes[plane].layout = (struct pan_image_layout){
234 .format = vk_format_to_pipe_format(format),
235 .dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
236 .width = image->vk.extent.width,
237 .height = image->vk.extent.height,
238 .depth = image->vk.extent.depth,
239 .array_size = image->vk.array_layers,
240 .nr_samples = image->vk.samples,
241 .nr_slices = image->vk.mip_levels,
242 };
243
244 image->planes[plane].layout.modifier = image->vk.drm_format_mod;
245 pan_image_layout_init(arch, &image->planes[plane].layout,
246 explicit_info ? &plane_layout : NULL);
247 }
248 }
249
250 static void
panvk_image_pre_mod_select_meta_adjustments(struct panvk_image * image)251 panvk_image_pre_mod_select_meta_adjustments(struct panvk_image *image)
252 {
253 const VkImageAspectFlags aspects = vk_format_aspects(image->vk.format);
254
255 /* We do image blit/resolve with vk_meta, so when an image is flagged as
256 * being a potential transfer source, we also need to add the sampled usage.
257 */
258 if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
259 image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
260 if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
261 image->vk.stencil_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
262 }
263
264 if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
265 /* Similarly, image that can be a transfer destination can be attached
266 * as a color or depth-stencil attachment by vk_meta. */
267 if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
268 image->vk.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
269
270 if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
271 image->vk.stencil_usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
272
273 if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
274 image->vk.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
275 image->vk.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
276 }
277
278 /* vk_meta creates 2D array views of 3D images. */
279 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
280 image->vk.create_flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
281 }
282
283 /* Needed for resolve operations. */
284 if (image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
285 image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
286
287 if (image->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
288 if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
289 image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
290
291 if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
292 image->vk.stencil_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
293 }
294
295 if ((image->vk.usage &
296 (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) &&
297 vk_format_is_compressed(image->vk.format)) {
298 /* We need to be able to create RGBA views of compressed formats for
299 * vk_meta copies. */
300 image->vk.create_flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
301 VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
302 }
303 }
304
305 static uint64_t
panvk_image_get_total_size(const struct panvk_image * image)306 panvk_image_get_total_size(const struct panvk_image *image)
307 {
308 uint64_t size = 0;
309 for (uint8_t plane = 0; plane < image->plane_count; plane++)
310 size += image->planes[plane].layout.data_size;
311 return size;
312 }
313
314 static bool
is_disjoint(struct panvk_image * image)315 is_disjoint(struct panvk_image *image)
316 {
317 assert((image->plane_count > 1 &&
318 image->vk.format != VK_FORMAT_D32_SFLOAT_S8_UINT) ||
319 !(image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT));
320 return image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT;
321 }
322
323 static void
panvk_image_init(struct panvk_device * dev,struct panvk_image * image,const VkImageCreateInfo * pCreateInfo)324 panvk_image_init(struct panvk_device *dev, struct panvk_image *image,
325 const VkImageCreateInfo *pCreateInfo)
326 {
327 /* Add any create/usage flags that might be needed for meta operations.
328 * This is run before the modifier selection because some
329 * usage/create_flags influence the modifier selection logic. */
330 panvk_image_pre_mod_select_meta_adjustments(image);
331
332 /* Now that we've patched the create/usage flags, we can proceed with the
333 * modifier selection. */
334 image->vk.drm_format_mod = panvk_image_get_mod(image, pCreateInfo);
335 panvk_image_init_layouts(image, pCreateInfo);
336 }
337
338 VKAPI_ATTR VkResult VKAPI_CALL
panvk_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)339 panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
340 const VkAllocationCallbacks *pAllocator, VkImage *pImage)
341 {
342 VK_FROM_HANDLE(panvk_device, dev, device);
343 struct panvk_physical_device *phys_dev =
344 to_panvk_physical_device(dev->vk.physical);
345
346 const VkImageSwapchainCreateInfoKHR *swapchain_info =
347 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
348 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
349 return wsi_common_create_swapchain_image(&phys_dev->wsi_device,
350 pCreateInfo,
351 swapchain_info->swapchain,
352 pImage);
353 }
354
355 struct panvk_image *image =
356 vk_image_create(&dev->vk, pCreateInfo, pAllocator, sizeof(*image));
357 if (!image)
358 return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
359
360 panvk_image_init(dev, image, pCreateInfo);
361
362 /*
363 * From the Vulkan spec:
364 *
365 * If the size of the resultant image would exceed maxResourceSize, then
366 * vkCreateImage must fail and return VK_ERROR_OUT_OF_DEVICE_MEMORY.
367 */
368 if (panvk_image_get_total_size(image) > UINT32_MAX) {
369 vk_image_destroy(&dev->vk, pAllocator, &image->vk);
370 return panvk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
371 }
372
373 *pImage = panvk_image_to_handle(image);
374 return VK_SUCCESS;
375 }
376
377 VKAPI_ATTR void VKAPI_CALL
panvk_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)378 panvk_DestroyImage(VkDevice _device, VkImage _image,
379 const VkAllocationCallbacks *pAllocator)
380 {
381 VK_FROM_HANDLE(panvk_device, device, _device);
382 VK_FROM_HANDLE(panvk_image, image, _image);
383
384 if (!image)
385 return;
386
387 if (image->bo)
388 pan_kmod_bo_put(image->bo);
389
390 vk_image_destroy(&device->vk, pAllocator, &image->vk);
391 }
392
393 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * pSubresource,VkSubresourceLayout * pLayout)394 panvk_GetImageSubresourceLayout(VkDevice _device, VkImage _image,
395 const VkImageSubresource *pSubresource,
396 VkSubresourceLayout *pLayout)
397 {
398 VK_FROM_HANDLE(panvk_image, image, _image);
399
400 unsigned plane =
401 panvk_plane_index(image->vk.format, pSubresource->aspectMask);
402 assert(plane < PANVK_MAX_PLANES);
403
404 const struct pan_image_slice_layout *slice_layout =
405 &image->planes[plane].layout.slices[pSubresource->mipLevel];
406
407 uint64_t base_offset = 0;
408 if (!is_disjoint(image)) {
409 for (uint8_t plane_idx = 0; plane_idx < plane; plane_idx++)
410 base_offset += image->planes[plane_idx].layout.data_size;
411 }
412
413 pLayout->offset = base_offset +
414 slice_layout->offset + (pSubresource->arrayLayer *
415 image->planes[plane].layout.array_stride);
416 pLayout->size = slice_layout->size;
417 pLayout->rowPitch = slice_layout->row_stride;
418 pLayout->arrayPitch = image->planes[plane].layout.array_stride;
419 pLayout->depthPitch = slice_layout->surface_stride;
420 }
421
422 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)423 panvk_GetImageMemoryRequirements2(VkDevice device,
424 const VkImageMemoryRequirementsInfo2 *pInfo,
425 VkMemoryRequirements2 *pMemoryRequirements)
426 {
427 VK_FROM_HANDLE(panvk_image, image, pInfo->image);
428
429 const uint64_t alignment = 4096;
430 const VkImagePlaneMemoryRequirementsInfo *plane_info =
431 vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
432 const bool disjoint = is_disjoint(image);
433 const VkImageAspectFlags aspects =
434 disjoint ? plane_info->planeAspect : image->vk.aspects;
435 uint8_t plane = panvk_plane_index(image->vk.format, aspects);
436 const uint64_t size =
437 disjoint ? image->planes[plane].layout.data_size :
438 panvk_image_get_total_size(image);
439
440 pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
441 pMemoryRequirements->memoryRequirements.alignment = alignment;
442 pMemoryRequirements->memoryRequirements.size = size;
443
444 vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
445 switch (ext->sType) {
446 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
447 VkMemoryDedicatedRequirements *dedicated = (void *)ext;
448 dedicated->requiresDedicatedAllocation = false;
449 dedicated->prefersDedicatedAllocation = dedicated->requiresDedicatedAllocation;
450 break;
451 }
452 default:
453 vk_debug_ignored_stype(ext->sType);
454 break;
455 }
456 }
457 }
458
459 VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceImageMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)460 panvk_GetDeviceImageMemoryRequirements(VkDevice device,
461 const VkDeviceImageMemoryRequirements *pInfo,
462 VkMemoryRequirements2 *pMemoryRequirements)
463 {
464 VK_FROM_HANDLE(panvk_device, dev, device);
465
466 struct panvk_image image;
467 vk_image_init(&dev->vk, &image.vk, pInfo->pCreateInfo);
468 panvk_image_init(dev, &image, pInfo->pCreateInfo);
469
470 VkImageMemoryRequirementsInfo2 info2 = {
471 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
472 .image = panvk_image_to_handle(&image),
473 };
474 panvk_GetImageMemoryRequirements2(device, &info2, pMemoryRequirements);
475 }
476
477 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)478 panvk_GetImageSparseMemoryRequirements2(
479 VkDevice device, const VkImageSparseMemoryRequirementsInfo2 *pInfo,
480 uint32_t *pSparseMemoryRequirementCount,
481 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
482 {
483 /* Sparse images are not yet supported. */
484 *pSparseMemoryRequirementCount = 0;
485 }
486
487 VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)488 panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
489 const VkDeviceImageMemoryRequirements *pInfo,
490 uint32_t *pSparseMemoryRequirementCount,
491 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
492 {
493 /* Sparse images are not yet supported. */
494 *pSparseMemoryRequirementCount = 0;
495 }
496
497 static void
panvk_image_plane_bind(struct pan_image * plane,struct pan_kmod_bo * bo,uint64_t base,uint64_t offset)498 panvk_image_plane_bind(struct pan_image *plane, struct pan_kmod_bo *bo,
499 uint64_t base, uint64_t offset)
500 {
501 plane->data.base = base;
502 plane->data.offset = offset;
503 /* Reset the AFBC headers */
504 if (drm_is_afbc(plane->layout.modifier)) {
505 /* Transient CPU mapping */
506 void *bo_base = pan_kmod_bo_mmap(bo, 0, pan_kmod_bo_size(bo),
507 PROT_WRITE, MAP_SHARED, NULL);
508
509 assert(bo_base != MAP_FAILED);
510
511 for (unsigned layer = 0; layer < plane->layout.array_size;
512 layer++) {
513 for (unsigned level = 0; level < plane->layout.nr_slices;
514 level++) {
515 void *header = bo_base + plane->data.offset +
516 (layer * plane->layout.array_stride) +
517 plane->layout.slices[level].offset;
518 memset(header, 0,
519 plane->layout.slices[level].afbc.header_size);
520 }
521 }
522
523 ASSERTED int ret = os_munmap(bo_base, pan_kmod_bo_size(bo));
524 assert(!ret);
525 }
526 }
527
528 VKAPI_ATTR VkResult VKAPI_CALL
panvk_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)529 panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
530 const VkBindImageMemoryInfo *pBindInfos)
531 {
532 const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
533 vk_find_struct_const(pBindInfos->pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
534
535 for (uint32_t i = 0; i < bindInfoCount; ++i) {
536 VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);
537 struct pan_kmod_bo *old_bo = image->bo;
538
539 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
540 VkImage wsi_vk_image = wsi_common_get_image(swapchain_info->swapchain,
541 swapchain_info->imageIndex);
542 VK_FROM_HANDLE(panvk_image, wsi_image, wsi_vk_image);
543
544 assert(image->plane_count == 1);
545 assert(wsi_image->plane_count == 1);
546
547 image->bo = pan_kmod_bo_get(wsi_image->bo);
548 panvk_image_plane_bind(&image->planes[0], image->bo,
549 wsi_image->planes[0].data.base,
550 wsi_image->planes[0].data.offset);
551 } else {
552 VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
553 assert(mem);
554 image->bo = pan_kmod_bo_get(mem->bo);
555 uint64_t offset = pBindInfos[i].memoryOffset;
556 if (is_disjoint(image)) {
557 const VkBindImagePlaneMemoryInfo *plane_info =
558 vk_find_struct_const(pBindInfos[i].pNext,
559 BIND_IMAGE_PLANE_MEMORY_INFO);
560 uint8_t plane =
561 panvk_plane_index(image->vk.format, plane_info->planeAspect);
562 panvk_image_plane_bind(&image->planes[plane], image->bo,
563 mem->addr.dev, offset);
564 } else {
565 for (unsigned plane = 0; plane < image->plane_count; plane++) {
566 panvk_image_plane_bind(&image->planes[plane], image->bo,
567 mem->addr.dev, offset);
568 offset += image->planes[plane].layout.data_size;
569 }
570 }
571 }
572
573 pan_kmod_bo_put(old_bo);
574 }
575
576 return VK_SUCCESS;
577 }
578