• 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_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