• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ALIAS_BIT) ||
320           !(image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT));
321    return image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT;
322 }
323 
324 static void
panvk_image_init(struct panvk_device * dev,struct panvk_image * image,const VkImageCreateInfo * pCreateInfo)325 panvk_image_init(struct panvk_device *dev, struct panvk_image *image,
326                  const VkImageCreateInfo *pCreateInfo)
327 {
328    /* Add any create/usage flags that might be needed for meta operations.
329     * This is run before the modifier selection because some
330     * usage/create_flags influence the modifier selection logic. */
331    panvk_image_pre_mod_select_meta_adjustments(image);
332 
333    /* Now that we've patched the create/usage flags, we can proceed with the
334     * modifier selection. */
335    image->vk.drm_format_mod = panvk_image_get_mod(image, pCreateInfo);
336    panvk_image_init_layouts(image, pCreateInfo);
337 }
338 
339 VKAPI_ATTR VkResult VKAPI_CALL
panvk_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)340 panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
341                   const VkAllocationCallbacks *pAllocator, VkImage *pImage)
342 {
343    VK_FROM_HANDLE(panvk_device, dev, device);
344    struct panvk_physical_device *phys_dev =
345       to_panvk_physical_device(dev->vk.physical);
346 
347    const VkImageSwapchainCreateInfoKHR *swapchain_info =
348       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
349    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
350       return wsi_common_create_swapchain_image(&phys_dev->wsi_device,
351                                                pCreateInfo,
352                                                swapchain_info->swapchain,
353                                                pImage);
354    }
355 
356    struct panvk_image *image =
357       vk_image_create(&dev->vk, pCreateInfo, pAllocator, sizeof(*image));
358    if (!image)
359       return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
360 
361    panvk_image_init(dev, image, pCreateInfo);
362 
363    /*
364     * From the Vulkan spec:
365     *
366     *    If the size of the resultant image would exceed maxResourceSize, then
367     *    vkCreateImage must fail and return VK_ERROR_OUT_OF_DEVICE_MEMORY.
368     */
369    if (panvk_image_get_total_size(image) > UINT32_MAX) {
370       vk_image_destroy(&dev->vk, pAllocator, &image->vk);
371       return panvk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
372    }
373 
374    *pImage = panvk_image_to_handle(image);
375    return VK_SUCCESS;
376 }
377 
378 VKAPI_ATTR void VKAPI_CALL
panvk_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)379 panvk_DestroyImage(VkDevice _device, VkImage _image,
380                    const VkAllocationCallbacks *pAllocator)
381 {
382    VK_FROM_HANDLE(panvk_device, device, _device);
383    VK_FROM_HANDLE(panvk_image, image, _image);
384 
385    if (!image)
386       return;
387 
388    if (image->bo)
389       pan_kmod_bo_put(image->bo);
390 
391    vk_image_destroy(&device->vk, pAllocator, &image->vk);
392 }
393 
394 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * pSubresource,VkSubresourceLayout * pLayout)395 panvk_GetImageSubresourceLayout(VkDevice _device, VkImage _image,
396                                 const VkImageSubresource *pSubresource,
397                                 VkSubresourceLayout *pLayout)
398 {
399    VK_FROM_HANDLE(panvk_image, image, _image);
400 
401    unsigned plane =
402       panvk_plane_index(image->vk.format, pSubresource->aspectMask);
403    assert(plane < PANVK_MAX_PLANES);
404 
405    const struct pan_image_slice_layout *slice_layout =
406       &image->planes[plane].layout.slices[pSubresource->mipLevel];
407 
408    uint64_t base_offset = 0;
409    if (!is_disjoint(image)) {
410       for (uint8_t plane_idx = 0; plane_idx < plane; plane_idx++)
411          base_offset += image->planes[plane_idx].layout.data_size;
412    }
413 
414    pLayout->offset = base_offset +
415       slice_layout->offset + (pSubresource->arrayLayer *
416                               image->planes[plane].layout.array_stride);
417    pLayout->size = slice_layout->size;
418    pLayout->rowPitch = slice_layout->row_stride;
419    pLayout->arrayPitch = image->planes[plane].layout.array_stride;
420    pLayout->depthPitch = slice_layout->surface_stride;
421 }
422 
423 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)424 panvk_GetImageMemoryRequirements2(VkDevice device,
425                                   const VkImageMemoryRequirementsInfo2 *pInfo,
426                                   VkMemoryRequirements2 *pMemoryRequirements)
427 {
428    VK_FROM_HANDLE(panvk_image, image, pInfo->image);
429 
430    const uint64_t alignment = 4096;
431    const VkImagePlaneMemoryRequirementsInfo *plane_info =
432       vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
433    const bool disjoint = is_disjoint(image);
434    const VkImageAspectFlags aspects =
435       disjoint ? plane_info->planeAspect : image->vk.aspects;
436    uint8_t plane = panvk_plane_index(image->vk.format, aspects);
437    const uint64_t size =
438       disjoint ? image->planes[plane].layout.data_size :
439       panvk_image_get_total_size(image);
440 
441    pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
442    pMemoryRequirements->memoryRequirements.alignment = alignment;
443    pMemoryRequirements->memoryRequirements.size = size;
444 
445    vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
446       switch (ext->sType) {
447       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
448          VkMemoryDedicatedRequirements *dedicated = (void *)ext;
449          dedicated->requiresDedicatedAllocation = false;
450          dedicated->prefersDedicatedAllocation = dedicated->requiresDedicatedAllocation;
451          break;
452       }
453       default:
454          vk_debug_ignored_stype(ext->sType);
455          break;
456       }
457    }
458 }
459 
460 VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceImageMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)461 panvk_GetDeviceImageMemoryRequirements(VkDevice device,
462                                        const VkDeviceImageMemoryRequirements *pInfo,
463                                        VkMemoryRequirements2 *pMemoryRequirements)
464 {
465    VK_FROM_HANDLE(panvk_device, dev, device);
466 
467    struct panvk_image image;
468    vk_image_init(&dev->vk, &image.vk, pInfo->pCreateInfo);
469    panvk_image_init(dev, &image, pInfo->pCreateInfo);
470 
471    VkImageMemoryRequirementsInfo2 info2 = {
472       .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
473       .image = panvk_image_to_handle(&image),
474    };
475    panvk_GetImageMemoryRequirements2(device, &info2, pMemoryRequirements);
476 }
477 
478 VKAPI_ATTR void VKAPI_CALL
panvk_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)479 panvk_GetImageSparseMemoryRequirements2(
480    VkDevice device, const VkImageSparseMemoryRequirementsInfo2 *pInfo,
481    uint32_t *pSparseMemoryRequirementCount,
482    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
483 {
484    /* Sparse images are not yet supported. */
485    *pSparseMemoryRequirementCount = 0;
486 }
487 
488 VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)489 panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
490                                              const VkDeviceImageMemoryRequirements *pInfo,
491                                              uint32_t *pSparseMemoryRequirementCount,
492                                              VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
493 {
494    /* Sparse images are not yet supported. */
495    *pSparseMemoryRequirementCount = 0;
496 }
497 
498 static void
panvk_image_plane_bind(struct pan_image * plane,struct pan_kmod_bo * bo,uint64_t base,uint64_t offset)499 panvk_image_plane_bind(struct pan_image *plane, struct pan_kmod_bo *bo,
500                        uint64_t base, uint64_t offset)
501 {
502    plane->data.base = base;
503    plane->data.offset = offset;
504    /* Reset the AFBC headers */
505    if (drm_is_afbc(plane->layout.modifier)) {
506       /* Transient CPU mapping */
507       void *bo_base = pan_kmod_bo_mmap(bo, 0, pan_kmod_bo_size(bo),
508                                        PROT_WRITE, MAP_SHARED, NULL);
509 
510       assert(bo_base != MAP_FAILED);
511 
512       for (unsigned layer = 0; layer < plane->layout.array_size;
513            layer++) {
514          for (unsigned level = 0; level < plane->layout.nr_slices;
515               level++) {
516             void *header = bo_base + plane->data.offset +
517                            (layer * plane->layout.array_stride) +
518                            plane->layout.slices[level].offset;
519             memset(header, 0,
520                    plane->layout.slices[level].afbc.header_size);
521          }
522       }
523 
524       ASSERTED int ret = os_munmap(bo_base, pan_kmod_bo_size(bo));
525       assert(!ret);
526    }
527 }
528 
529 VKAPI_ATTR VkResult VKAPI_CALL
panvk_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)530 panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
531                        const VkBindImageMemoryInfo *pBindInfos)
532 {
533    const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
534       vk_find_struct_const(pBindInfos->pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
535 
536    for (uint32_t i = 0; i < bindInfoCount; ++i) {
537       VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);
538       struct pan_kmod_bo *old_bo = image->bo;
539 
540       if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
541          VkImage wsi_vk_image = wsi_common_get_image(swapchain_info->swapchain,
542                                                    swapchain_info->imageIndex);
543          VK_FROM_HANDLE(panvk_image, wsi_image, wsi_vk_image);
544 
545          assert(image->plane_count == 1);
546          assert(wsi_image->plane_count == 1);
547 
548          image->bo = pan_kmod_bo_get(wsi_image->bo);
549          panvk_image_plane_bind(&image->planes[0], image->bo,
550                                 wsi_image->planes[0].data.base,
551                                 wsi_image->planes[0].data.offset);
552       } else {
553          VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
554          assert(mem);
555          image->bo = pan_kmod_bo_get(mem->bo);
556          uint64_t offset = pBindInfos[i].memoryOffset;
557          if (is_disjoint(image)) {
558             const VkBindImagePlaneMemoryInfo *plane_info =
559                vk_find_struct_const(pBindInfos[i].pNext,
560                                     BIND_IMAGE_PLANE_MEMORY_INFO);
561             uint8_t plane =
562                panvk_plane_index(image->vk.format, plane_info->planeAspect);
563             panvk_image_plane_bind(&image->planes[plane], image->bo,
564                                    mem->addr.dev, offset);
565          } else {
566             for (unsigned plane = 0; plane < image->plane_count; plane++) {
567                panvk_image_plane_bind(&image->planes[plane], image->bo,
568                                       mem->addr.dev, offset);
569                offset += image->planes[plane].layout.data_size;
570             }
571          }
572       }
573 
574       pan_kmod_bo_put(old_bo);
575    }
576 
577    return VK_SUCCESS;
578 }
579