Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_image.c
4560 views
/*1* Copyright © 2021 Collabora Ltd.2*3* Derived from tu_image.c which is:4* Copyright © 2016 Red Hat.5* Copyright © 2016 Bas Nieuwenhuizen6* Copyright © 2015 Intel Corporation7*8* Permission is hereby granted, free of charge, to any person obtaining a9* copy of this software and associated documentation files (the "Software"),10* to deal in the Software without restriction, including without limitation11* the rights to use, copy, modify, merge, publish, distribute, sublicense,12* and/or sell copies of the Software, and to permit persons to whom the13* Software is furnished to do so, subject to the following conditions:14*15* The above copyright notice and this permission notice (including the next16* paragraph) shall be included in all copies or substantial portions of the17* Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING24* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER25* DEALINGS IN THE SOFTWARE.26*/2728#include "panvk_private.h"29#include "panfrost-quirks.h"3031#include "util/debug.h"32#include "util/u_atomic.h"33#include "vk_format.h"34#include "vk_object.h"35#include "vk_util.h"36#include "drm-uapi/drm_fourcc.h"3738unsigned39panvk_image_get_plane_size(const struct panvk_image *image, unsigned plane)40{41assert(!plane);42return image->pimage.layout.data_size;43}4445unsigned46panvk_image_get_total_size(const struct panvk_image *image)47{48assert(util_format_get_num_planes(image->pimage.layout.format) == 1);49return image->pimage.layout.data_size;50}5152static enum mali_texture_dimension53panvk_image_type_to_mali_tex_dim(VkImageType type)54{55switch (type) {56case VK_IMAGE_TYPE_1D: return MALI_TEXTURE_DIMENSION_1D;57case VK_IMAGE_TYPE_2D: return MALI_TEXTURE_DIMENSION_2D;58case VK_IMAGE_TYPE_3D: return MALI_TEXTURE_DIMENSION_3D;59default: unreachable("Invalid image type");60}61}6263static VkResult64panvk_image_create(VkDevice _device,65const VkImageCreateInfo *pCreateInfo,66const VkAllocationCallbacks *alloc,67VkImage *pImage,68uint64_t modifier,69const VkSubresourceLayout *plane_layouts)70{71VK_FROM_HANDLE(panvk_device, device, _device);72const struct panfrost_device *pdev = &device->physical_device->pdev;73struct panvk_image *image = NULL;74assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);7576assert(pCreateInfo->mipLevels > 0);77assert(pCreateInfo->arrayLayers > 0);78assert(pCreateInfo->samples > 0);79assert(pCreateInfo->extent.width > 0);80assert(pCreateInfo->extent.height > 0);81assert(pCreateInfo->extent.depth > 0);8283image = vk_object_zalloc(&device->vk, alloc, sizeof(*image),84VK_OBJECT_TYPE_IMAGE);85if (!image)86return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);8788image->type = pCreateInfo->imageType;8990image->vk_format = pCreateInfo->format;91image->tiling = pCreateInfo->tiling;92image->usage = pCreateInfo->usage;93image->flags = pCreateInfo->flags;94image->extent = pCreateInfo->extent;95pan_image_layout_init(pdev, &image->pimage.layout, modifier,96vk_format_to_pipe_format(pCreateInfo->format),97panvk_image_type_to_mali_tex_dim(pCreateInfo->imageType),98pCreateInfo->extent.width, pCreateInfo->extent.height,99pCreateInfo->extent.depth, pCreateInfo->arrayLayers,100pCreateInfo->samples, pCreateInfo->mipLevels,101PAN_IMAGE_CRC_NONE, NULL);102103image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;104if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {105for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i) {106if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL)107image->queue_family_mask |= (1u << PANVK_MAX_QUEUE_FAMILIES) - 1u;108else109image->queue_family_mask |= 1u << pCreateInfo->pQueueFamilyIndices[i];110}111}112113if (vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO))114image->shareable = true;115116*pImage = panvk_image_to_handle(image);117return VK_SUCCESS;118}119120static uint64_t121panvk_image_select_mod(VkDevice _device,122const VkImageCreateInfo *pCreateInfo,123const VkSubresourceLayout **plane_layouts)124{125VK_FROM_HANDLE(panvk_device, device, _device);126const struct panfrost_device *pdev = &device->physical_device->pdev;127enum pipe_format fmt = vk_format_to_pipe_format(pCreateInfo->format);128bool noafbc = !(device->physical_device->instance->debug_flags & PANVK_DEBUG_AFBC);129bool linear = device->physical_device->instance->debug_flags & PANVK_DEBUG_LINEAR;130131*plane_layouts = NULL;132133if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)134return DRM_FORMAT_MOD_LINEAR;135136if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {137const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =138vk_find_struct_const(pCreateInfo->pNext,139IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);140const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info =141vk_find_struct_const(pCreateInfo->pNext,142IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);143144assert(mod_info || drm_explicit_info);145146uint64_t modifier;147148if (mod_info) {149modifier = DRM_FORMAT_MOD_LINEAR;150for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {151if (drm_is_afbc(mod_info->pDrmFormatModifiers[i]) && !noafbc) {152modifier = mod_info->pDrmFormatModifiers[i];153break;154}155}156} else {157modifier = drm_explicit_info->drmFormatModifier;158assert(modifier == DRM_FORMAT_MOD_LINEAR ||159modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||160(drm_is_afbc(modifier) && !noafbc));161*plane_layouts = drm_explicit_info->pPlaneLayouts;162}163164return modifier;165}166167const struct wsi_image_create_info *wsi_info =168vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);169if (wsi_info && wsi_info->scanout)170return DRM_FORMAT_MOD_LINEAR;171172assert(pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL);173174if (linear)175return DRM_FORMAT_MOD_LINEAR;176177/* Image store don't work on AFBC images */178if (pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT)179return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;180181/* AFBC does not support layered multisampling */182if (pCreateInfo->samples > 1)183return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;184185if (pdev->quirks & MIDGARD_NO_AFBC)186return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;187188/* Only a small selection of formats are AFBC'able */189if (!panfrost_format_supports_afbc(pdev, fmt))190return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;191192/* 3D AFBC is only supported on Bifrost v7+. It's supposed to193* be supported on Midgard but it doesn't seem to work.194*/195if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D && pdev->arch < 7)196return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;197198/* For one tile, AFBC is a loss compared to u-interleaved */199if (pCreateInfo->extent.width <= 16 && pCreateInfo->extent.height <= 16)200return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;201202if (noafbc)203return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;204205uint64_t afbc_type = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |206AFBC_FORMAT_MOD_SPARSE;207208if (panfrost_afbc_can_ytr(fmt))209afbc_type |= AFBC_FORMAT_MOD_YTR;210211return DRM_FORMAT_MOD_ARM_AFBC(afbc_type);212}213214VkResult215panvk_CreateImage(VkDevice device,216const VkImageCreateInfo *pCreateInfo,217const VkAllocationCallbacks *pAllocator,218VkImage *pImage)219{220const VkSubresourceLayout *plane_layouts;221uint64_t modifier = panvk_image_select_mod(device, pCreateInfo, &plane_layouts);222223return panvk_image_create(device, pCreateInfo, pAllocator, pImage, modifier, plane_layouts);224}225226void227panvk_DestroyImage(VkDevice _device,228VkImage _image,229const VkAllocationCallbacks *pAllocator)230{231VK_FROM_HANDLE(panvk_device, device, _device);232VK_FROM_HANDLE(panvk_image, image, _image);233234if (!image)235return;236237vk_object_free(&device->vk, pAllocator, image);238}239240static unsigned241panvk_plane_index(VkFormat format, VkImageAspectFlags aspect_mask)242{243switch (aspect_mask) {244default:245return 0;246case VK_IMAGE_ASPECT_PLANE_1_BIT:247return 1;248case VK_IMAGE_ASPECT_PLANE_2_BIT:249return 2;250case VK_IMAGE_ASPECT_STENCIL_BIT:251return format == VK_FORMAT_D32_SFLOAT_S8_UINT;252}253}254255void256panvk_GetImageSubresourceLayout(VkDevice _device,257VkImage _image,258const VkImageSubresource *pSubresource,259VkSubresourceLayout *pLayout)260{261VK_FROM_HANDLE(panvk_image, image, _image);262263unsigned plane = panvk_plane_index(image->vk_format, pSubresource->aspectMask);264assert(plane < PANVK_MAX_PLANES);265266const struct pan_image_slice_layout *slice_layout =267&image->pimage.layout.slices[pSubresource->mipLevel];268269pLayout->offset = slice_layout->offset +270(pSubresource->arrayLayer *271image->pimage.layout.array_stride);272pLayout->size = slice_layout->size;273pLayout->rowPitch = slice_layout->line_stride;274pLayout->arrayPitch = image->pimage.layout.array_stride;275pLayout->depthPitch = slice_layout->surface_stride;276}277278static enum mali_texture_dimension279panvk_view_type_to_mali_tex_dim(VkImageViewType type)280{281switch (type) {282case VK_IMAGE_VIEW_TYPE_1D:283case VK_IMAGE_VIEW_TYPE_1D_ARRAY:284return MALI_TEXTURE_DIMENSION_1D;285case VK_IMAGE_VIEW_TYPE_2D:286case VK_IMAGE_VIEW_TYPE_2D_ARRAY:287return MALI_TEXTURE_DIMENSION_2D;288case VK_IMAGE_VIEW_TYPE_3D:289return MALI_TEXTURE_DIMENSION_3D;290case VK_IMAGE_VIEW_TYPE_CUBE:291case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:292return MALI_TEXTURE_DIMENSION_CUBE;293default:294unreachable("Invalid view type");295}296}297298static void299panvk_convert_swizzle(const VkComponentMapping *in,300unsigned char *out)301{302const VkComponentSwizzle *comp = &in->r;303for (unsigned i = 0; i < 4; i++) {304switch (comp[i]) {305case VK_COMPONENT_SWIZZLE_IDENTITY:306out[i] = PIPE_SWIZZLE_X + i;307break;308case VK_COMPONENT_SWIZZLE_ZERO:309out[i] = PIPE_SWIZZLE_0;310break;311case VK_COMPONENT_SWIZZLE_ONE:312out[i] = PIPE_SWIZZLE_1;313break;314case VK_COMPONENT_SWIZZLE_R:315out[i] = PIPE_SWIZZLE_X;316break;317case VK_COMPONENT_SWIZZLE_G:318out[i] = PIPE_SWIZZLE_Y;319break;320case VK_COMPONENT_SWIZZLE_B:321out[i] = PIPE_SWIZZLE_Z;322break;323case VK_COMPONENT_SWIZZLE_A:324out[i] = PIPE_SWIZZLE_W;325break;326default:327unreachable("Invalid swizzle");328}329}330}331332333334VkResult335panvk_CreateImageView(VkDevice _device,336const VkImageViewCreateInfo *pCreateInfo,337const VkAllocationCallbacks *pAllocator,338VkImageView *pView)339{340VK_FROM_HANDLE(panvk_device, device, _device);341VK_FROM_HANDLE(panvk_image, image, pCreateInfo->image);342struct panvk_image_view *view;343344view = vk_object_zalloc(&device->vk, pAllocator, sizeof(*view),345VK_OBJECT_TYPE_IMAGE_VIEW);346if (view == NULL)347return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);348349view->pview.format = vk_format_to_pipe_format(pCreateInfo->format);350351if (pCreateInfo->subresourceRange.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)352view->pview.format = util_format_get_depth_only(view->pview.format);353else if (pCreateInfo->subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)354view->pview.format = util_format_stencil_only(view->pview.format);355356view->pview.dim = panvk_view_type_to_mali_tex_dim(pCreateInfo->viewType);357view->pview.first_level = pCreateInfo->subresourceRange.baseMipLevel;358view->pview.last_level = pCreateInfo->subresourceRange.baseMipLevel +359pCreateInfo->subresourceRange.levelCount - 1;360view->pview.first_layer = pCreateInfo->subresourceRange.baseArrayLayer;361view->pview.last_layer = pCreateInfo->subresourceRange.baseArrayLayer +362pCreateInfo->subresourceRange.layerCount - 1;363panvk_convert_swizzle(&pCreateInfo->components, view->pview.swizzle);364view->pview.image = &image->pimage;365view->pview.nr_samples = image->pimage.layout.nr_samples;366view->vk_format = pCreateInfo->format;367368struct panfrost_device *pdev = &device->physical_device->pdev;369unsigned bo_size =370panfrost_estimate_texture_payload_size(pdev, &view->pview);371372unsigned surf_descs_offset = 0;373if (!pan_is_bifrost(pdev)) {374bo_size += MALI_MIDGARD_TEXTURE_LENGTH;375surf_descs_offset = MALI_MIDGARD_TEXTURE_LENGTH;376}377378view->bo = panfrost_bo_create(pdev, bo_size, 0, "Texture descriptor");379380struct panfrost_ptr surf_descs = {381.cpu = view->bo->ptr.cpu + surf_descs_offset,382.gpu = view->bo->ptr.gpu + surf_descs_offset,383};384void *tex_desc = pan_is_bifrost(pdev) ?385&view->bifrost.tex_desc : view->bo->ptr.cpu;386387panfrost_new_texture(pdev, &view->pview, tex_desc, &surf_descs);388389*pView = panvk_image_view_to_handle(view);390return VK_SUCCESS;391}392393void394panvk_DestroyImageView(VkDevice _device,395VkImageView _view,396const VkAllocationCallbacks *pAllocator)397{398VK_FROM_HANDLE(panvk_device, device, _device);399VK_FROM_HANDLE(panvk_image_view, view, _view);400401if (!view)402return;403404panfrost_bo_unreference(view->bo);405vk_object_free(&device->vk, pAllocator, view);406}407408VkResult409panvk_CreateBufferView(VkDevice _device,410const VkBufferViewCreateInfo *pCreateInfo,411const VkAllocationCallbacks *pAllocator,412VkBufferView *pView)413{414panvk_stub();415return VK_SUCCESS;416}417418void419panvk_DestroyBufferView(VkDevice _device,420VkBufferView bufferView,421const VkAllocationCallbacks *pAllocator)422{423panvk_stub();424}425426VkResult427panvk_GetImageDrmFormatModifierPropertiesEXT(VkDevice device,428VkImage _image,429VkImageDrmFormatModifierPropertiesEXT *pProperties)430{431VK_FROM_HANDLE(panvk_image, image, _image);432433assert(pProperties->sType == VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT);434435pProperties->drmFormatModifier = image->pimage.layout.modifier;436return VK_SUCCESS;437}438439440