17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2021 Collabora Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Derived from tu_image.c which is: 57ec681f3Smrg * Copyright © 2016 Red Hat. 67ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen 77ec681f3Smrg * Copyright © 2015 Intel Corporation 87ec681f3Smrg * 97ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 107ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 117ec681f3Smrg * to deal in the Software without restriction, including without limitation 127ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 137ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 147ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 157ec681f3Smrg * 167ec681f3Smrg * The above copyright notice and this permission notice (including the next 177ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 187ec681f3Smrg * Software. 197ec681f3Smrg * 207ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 217ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 227ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 237ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 247ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 257ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 267ec681f3Smrg * DEALINGS IN THE SOFTWARE. 277ec681f3Smrg */ 287ec681f3Smrg 297ec681f3Smrg#include "panvk_private.h" 307ec681f3Smrg#include "panfrost-quirks.h" 317ec681f3Smrg 327ec681f3Smrg#include "util/debug.h" 337ec681f3Smrg#include "util/u_atomic.h" 347ec681f3Smrg#include "vk_format.h" 357ec681f3Smrg#include "vk_object.h" 367ec681f3Smrg#include "vk_util.h" 377ec681f3Smrg#include "drm-uapi/drm_fourcc.h" 387ec681f3Smrg 397ec681f3Smrgunsigned 407ec681f3Smrgpanvk_image_get_plane_size(const struct panvk_image *image, unsigned plane) 417ec681f3Smrg{ 427ec681f3Smrg assert(!plane); 437ec681f3Smrg return image->pimage.layout.data_size; 447ec681f3Smrg} 457ec681f3Smrg 467ec681f3Smrgunsigned 477ec681f3Smrgpanvk_image_get_total_size(const struct panvk_image *image) 487ec681f3Smrg{ 497ec681f3Smrg assert(util_format_get_num_planes(image->pimage.layout.format) == 1); 507ec681f3Smrg return image->pimage.layout.data_size; 517ec681f3Smrg} 527ec681f3Smrg 537ec681f3Smrgstatic enum mali_texture_dimension 547ec681f3Smrgpanvk_image_type_to_mali_tex_dim(VkImageType type) 557ec681f3Smrg{ 567ec681f3Smrg switch (type) { 577ec681f3Smrg case VK_IMAGE_TYPE_1D: return MALI_TEXTURE_DIMENSION_1D; 587ec681f3Smrg case VK_IMAGE_TYPE_2D: return MALI_TEXTURE_DIMENSION_2D; 597ec681f3Smrg case VK_IMAGE_TYPE_3D: return MALI_TEXTURE_DIMENSION_3D; 607ec681f3Smrg default: unreachable("Invalid image type"); 617ec681f3Smrg } 627ec681f3Smrg} 637ec681f3Smrg 647ec681f3Smrgstatic VkResult 657ec681f3Smrgpanvk_image_create(VkDevice _device, 667ec681f3Smrg const VkImageCreateInfo *pCreateInfo, 677ec681f3Smrg const VkAllocationCallbacks *alloc, 687ec681f3Smrg VkImage *pImage, 697ec681f3Smrg uint64_t modifier, 707ec681f3Smrg const VkSubresourceLayout *plane_layouts) 717ec681f3Smrg{ 727ec681f3Smrg VK_FROM_HANDLE(panvk_device, device, _device); 737ec681f3Smrg const struct panfrost_device *pdev = &device->physical_device->pdev; 747ec681f3Smrg struct panvk_image *image = NULL; 757ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); 767ec681f3Smrg 777ec681f3Smrg assert(pCreateInfo->mipLevels > 0); 787ec681f3Smrg assert(pCreateInfo->arrayLayers > 0); 797ec681f3Smrg assert(pCreateInfo->samples > 0); 807ec681f3Smrg assert(pCreateInfo->extent.width > 0); 817ec681f3Smrg assert(pCreateInfo->extent.height > 0); 827ec681f3Smrg assert(pCreateInfo->extent.depth > 0); 837ec681f3Smrg 847ec681f3Smrg image = vk_object_zalloc(&device->vk, alloc, sizeof(*image), 857ec681f3Smrg VK_OBJECT_TYPE_IMAGE); 867ec681f3Smrg if (!image) 877ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 887ec681f3Smrg 897ec681f3Smrg image->type = pCreateInfo->imageType; 907ec681f3Smrg 917ec681f3Smrg image->vk_format = pCreateInfo->format; 927ec681f3Smrg image->tiling = pCreateInfo->tiling; 937ec681f3Smrg image->usage = pCreateInfo->usage; 947ec681f3Smrg image->flags = pCreateInfo->flags; 957ec681f3Smrg image->extent = pCreateInfo->extent; 967ec681f3Smrg pan_image_layout_init(pdev, &image->pimage.layout, modifier, 977ec681f3Smrg vk_format_to_pipe_format(pCreateInfo->format), 987ec681f3Smrg panvk_image_type_to_mali_tex_dim(pCreateInfo->imageType), 997ec681f3Smrg pCreateInfo->extent.width, pCreateInfo->extent.height, 1007ec681f3Smrg pCreateInfo->extent.depth, pCreateInfo->arrayLayers, 1017ec681f3Smrg pCreateInfo->samples, pCreateInfo->mipLevels, 1027ec681f3Smrg PAN_IMAGE_CRC_NONE, NULL); 1037ec681f3Smrg 1047ec681f3Smrg image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE; 1057ec681f3Smrg if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) { 1067ec681f3Smrg for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i) { 1077ec681f3Smrg if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL) 1087ec681f3Smrg image->queue_family_mask |= (1u << PANVK_MAX_QUEUE_FAMILIES) - 1u; 1097ec681f3Smrg else 1107ec681f3Smrg image->queue_family_mask |= 1u << pCreateInfo->pQueueFamilyIndices[i]; 1117ec681f3Smrg } 1127ec681f3Smrg } 1137ec681f3Smrg 1147ec681f3Smrg if (vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO)) 1157ec681f3Smrg image->shareable = true; 1167ec681f3Smrg 1177ec681f3Smrg *pImage = panvk_image_to_handle(image); 1187ec681f3Smrg return VK_SUCCESS; 1197ec681f3Smrg} 1207ec681f3Smrg 1217ec681f3Smrgstatic uint64_t 1227ec681f3Smrgpanvk_image_select_mod(VkDevice _device, 1237ec681f3Smrg const VkImageCreateInfo *pCreateInfo, 1247ec681f3Smrg const VkSubresourceLayout **plane_layouts) 1257ec681f3Smrg{ 1267ec681f3Smrg VK_FROM_HANDLE(panvk_device, device, _device); 1277ec681f3Smrg const struct panfrost_device *pdev = &device->physical_device->pdev; 1287ec681f3Smrg enum pipe_format fmt = vk_format_to_pipe_format(pCreateInfo->format); 1297ec681f3Smrg bool noafbc = !(device->physical_device->instance->debug_flags & PANVK_DEBUG_AFBC); 1307ec681f3Smrg bool linear = device->physical_device->instance->debug_flags & PANVK_DEBUG_LINEAR; 1317ec681f3Smrg 1327ec681f3Smrg *plane_layouts = NULL; 1337ec681f3Smrg 1347ec681f3Smrg if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) 1357ec681f3Smrg return DRM_FORMAT_MOD_LINEAR; 1367ec681f3Smrg 1377ec681f3Smrg if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { 1387ec681f3Smrg const VkImageDrmFormatModifierListCreateInfoEXT *mod_info = 1397ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 1407ec681f3Smrg IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); 1417ec681f3Smrg const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info = 1427ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 1437ec681f3Smrg IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); 1447ec681f3Smrg 1457ec681f3Smrg assert(mod_info || drm_explicit_info); 1467ec681f3Smrg 1477ec681f3Smrg uint64_t modifier; 1487ec681f3Smrg 1497ec681f3Smrg if (mod_info) { 1507ec681f3Smrg modifier = DRM_FORMAT_MOD_LINEAR; 1517ec681f3Smrg for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) { 1527ec681f3Smrg if (drm_is_afbc(mod_info->pDrmFormatModifiers[i]) && !noafbc) { 1537ec681f3Smrg modifier = mod_info->pDrmFormatModifiers[i]; 1547ec681f3Smrg break; 1557ec681f3Smrg } 1567ec681f3Smrg } 1577ec681f3Smrg } else { 1587ec681f3Smrg modifier = drm_explicit_info->drmFormatModifier; 1597ec681f3Smrg assert(modifier == DRM_FORMAT_MOD_LINEAR || 1607ec681f3Smrg modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || 1617ec681f3Smrg (drm_is_afbc(modifier) && !noafbc)); 1627ec681f3Smrg *plane_layouts = drm_explicit_info->pPlaneLayouts; 1637ec681f3Smrg } 1647ec681f3Smrg 1657ec681f3Smrg return modifier; 1667ec681f3Smrg } 1677ec681f3Smrg 1687ec681f3Smrg const struct wsi_image_create_info *wsi_info = 1697ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA); 1707ec681f3Smrg if (wsi_info && wsi_info->scanout) 1717ec681f3Smrg return DRM_FORMAT_MOD_LINEAR; 1727ec681f3Smrg 1737ec681f3Smrg assert(pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL); 1747ec681f3Smrg 1757ec681f3Smrg if (linear) 1767ec681f3Smrg return DRM_FORMAT_MOD_LINEAR; 1777ec681f3Smrg 1787ec681f3Smrg /* Image store don't work on AFBC images */ 1797ec681f3Smrg if (pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT) 1807ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 1817ec681f3Smrg 1827ec681f3Smrg /* AFBC does not support layered multisampling */ 1837ec681f3Smrg if (pCreateInfo->samples > 1) 1847ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 1857ec681f3Smrg 1867ec681f3Smrg if (!pdev->has_afbc) 1877ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 1887ec681f3Smrg 1897ec681f3Smrg /* Only a small selection of formats are AFBC'able */ 1907ec681f3Smrg if (!panfrost_format_supports_afbc(pdev, fmt)) 1917ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 1927ec681f3Smrg 1937ec681f3Smrg /* 3D AFBC is only supported on Bifrost v7+. It's supposed to 1947ec681f3Smrg * be supported on Midgard but it doesn't seem to work. 1957ec681f3Smrg */ 1967ec681f3Smrg if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D && pdev->arch < 7) 1977ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 1987ec681f3Smrg 1997ec681f3Smrg /* For one tile, AFBC is a loss compared to u-interleaved */ 2007ec681f3Smrg if (pCreateInfo->extent.width <= 16 && pCreateInfo->extent.height <= 16) 2017ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 2027ec681f3Smrg 2037ec681f3Smrg if (noafbc) 2047ec681f3Smrg return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 2057ec681f3Smrg 2067ec681f3Smrg uint64_t afbc_type = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | 2077ec681f3Smrg AFBC_FORMAT_MOD_SPARSE; 2087ec681f3Smrg 2097ec681f3Smrg if (panfrost_afbc_can_ytr(fmt)) 2107ec681f3Smrg afbc_type |= AFBC_FORMAT_MOD_YTR; 2117ec681f3Smrg 2127ec681f3Smrg return DRM_FORMAT_MOD_ARM_AFBC(afbc_type); 2137ec681f3Smrg} 2147ec681f3Smrg 2157ec681f3SmrgVkResult 2167ec681f3Smrgpanvk_CreateImage(VkDevice device, 2177ec681f3Smrg const VkImageCreateInfo *pCreateInfo, 2187ec681f3Smrg const VkAllocationCallbacks *pAllocator, 2197ec681f3Smrg VkImage *pImage) 2207ec681f3Smrg{ 2217ec681f3Smrg const VkSubresourceLayout *plane_layouts; 2227ec681f3Smrg uint64_t modifier = panvk_image_select_mod(device, pCreateInfo, &plane_layouts); 2237ec681f3Smrg 2247ec681f3Smrg return panvk_image_create(device, pCreateInfo, pAllocator, pImage, modifier, plane_layouts); 2257ec681f3Smrg} 2267ec681f3Smrg 2277ec681f3Smrgvoid 2287ec681f3Smrgpanvk_DestroyImage(VkDevice _device, 2297ec681f3Smrg VkImage _image, 2307ec681f3Smrg const VkAllocationCallbacks *pAllocator) 2317ec681f3Smrg{ 2327ec681f3Smrg VK_FROM_HANDLE(panvk_device, device, _device); 2337ec681f3Smrg VK_FROM_HANDLE(panvk_image, image, _image); 2347ec681f3Smrg 2357ec681f3Smrg if (!image) 2367ec681f3Smrg return; 2377ec681f3Smrg 2387ec681f3Smrg vk_object_free(&device->vk, pAllocator, image); 2397ec681f3Smrg} 2407ec681f3Smrg 2417ec681f3Smrgstatic unsigned 2427ec681f3Smrgpanvk_plane_index(VkFormat format, VkImageAspectFlags aspect_mask) 2437ec681f3Smrg{ 2447ec681f3Smrg switch (aspect_mask) { 2457ec681f3Smrg default: 2467ec681f3Smrg return 0; 2477ec681f3Smrg case VK_IMAGE_ASPECT_PLANE_1_BIT: 2487ec681f3Smrg return 1; 2497ec681f3Smrg case VK_IMAGE_ASPECT_PLANE_2_BIT: 2507ec681f3Smrg return 2; 2517ec681f3Smrg case VK_IMAGE_ASPECT_STENCIL_BIT: 2527ec681f3Smrg return format == VK_FORMAT_D32_SFLOAT_S8_UINT; 2537ec681f3Smrg } 2547ec681f3Smrg} 2557ec681f3Smrg 2567ec681f3Smrgvoid 2577ec681f3Smrgpanvk_GetImageSubresourceLayout(VkDevice _device, 2587ec681f3Smrg VkImage _image, 2597ec681f3Smrg const VkImageSubresource *pSubresource, 2607ec681f3Smrg VkSubresourceLayout *pLayout) 2617ec681f3Smrg{ 2627ec681f3Smrg VK_FROM_HANDLE(panvk_image, image, _image); 2637ec681f3Smrg 2647ec681f3Smrg unsigned plane = panvk_plane_index(image->vk_format, pSubresource->aspectMask); 2657ec681f3Smrg assert(plane < PANVK_MAX_PLANES); 2667ec681f3Smrg 2677ec681f3Smrg const struct pan_image_slice_layout *slice_layout = 2687ec681f3Smrg &image->pimage.layout.slices[pSubresource->mipLevel]; 2697ec681f3Smrg 2707ec681f3Smrg pLayout->offset = slice_layout->offset + 2717ec681f3Smrg (pSubresource->arrayLayer * 2727ec681f3Smrg image->pimage.layout.array_stride); 2737ec681f3Smrg pLayout->size = slice_layout->size; 2747ec681f3Smrg pLayout->rowPitch = slice_layout->line_stride; 2757ec681f3Smrg pLayout->arrayPitch = image->pimage.layout.array_stride; 2767ec681f3Smrg pLayout->depthPitch = slice_layout->surface_stride; 2777ec681f3Smrg} 2787ec681f3Smrg 2797ec681f3Smrgvoid 2807ec681f3Smrgpanvk_DestroyImageView(VkDevice _device, 2817ec681f3Smrg VkImageView _view, 2827ec681f3Smrg const VkAllocationCallbacks *pAllocator) 2837ec681f3Smrg{ 2847ec681f3Smrg VK_FROM_HANDLE(panvk_device, device, _device); 2857ec681f3Smrg VK_FROM_HANDLE(panvk_image_view, view, _view); 2867ec681f3Smrg 2877ec681f3Smrg if (!view) 2887ec681f3Smrg return; 2897ec681f3Smrg 2907ec681f3Smrg panfrost_bo_unreference(view->bo); 2917ec681f3Smrg vk_object_free(&device->vk, pAllocator, view); 2927ec681f3Smrg} 2937ec681f3Smrg 2947ec681f3SmrgVkResult 2957ec681f3Smrgpanvk_CreateBufferView(VkDevice _device, 2967ec681f3Smrg const VkBufferViewCreateInfo *pCreateInfo, 2977ec681f3Smrg const VkAllocationCallbacks *pAllocator, 2987ec681f3Smrg VkBufferView *pView) 2997ec681f3Smrg{ 3007ec681f3Smrg panvk_stub(); 3017ec681f3Smrg return VK_SUCCESS; 3027ec681f3Smrg} 3037ec681f3Smrg 3047ec681f3Smrgvoid 3057ec681f3Smrgpanvk_DestroyBufferView(VkDevice _device, 3067ec681f3Smrg VkBufferView bufferView, 3077ec681f3Smrg const VkAllocationCallbacks *pAllocator) 3087ec681f3Smrg{ 3097ec681f3Smrg panvk_stub(); 3107ec681f3Smrg} 3117ec681f3Smrg 3127ec681f3SmrgVkResult 3137ec681f3Smrgpanvk_GetImageDrmFormatModifierPropertiesEXT(VkDevice device, 3147ec681f3Smrg VkImage _image, 3157ec681f3Smrg VkImageDrmFormatModifierPropertiesEXT *pProperties) 3167ec681f3Smrg{ 3177ec681f3Smrg VK_FROM_HANDLE(panvk_image, image, _image); 3187ec681f3Smrg 3197ec681f3Smrg assert(pProperties->sType == VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT); 3207ec681f3Smrg 3217ec681f3Smrg pProperties->drmFormatModifier = image->pimage.layout.modifier; 3227ec681f3Smrg return VK_SUCCESS; 3237ec681f3Smrg} 324