Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_formats.c
4560 views
/*1* Copyright © 2021 Collabora Ltd.2*3* Derived from tu_formats.c which is:4* Copyright © 2016 Red Hat.5* Copyright © 2016 Bas Nieuwenhuizen6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice (including the next15* paragraph) shall be included in all copies or substantial portions of the16* Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR19* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,20* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL21* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER22* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING23* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER24* DEALINGS IN THE SOFTWARE.25*/2627#include "panvk_private.h"2829#include "util/format_r11g11b10f.h"30#include "util/format_srgb.h"31#include "util/half_float.h"32#include "vulkan/util/vk_format.h"33#include "vk_format.h"34#include "vk_util.h"35#include "panfrost/lib/pan_texture.h"3637static void38get_format_properties(struct panvk_physical_device *physical_device,39VkFormat format,40VkFormatProperties *out_properties)41{42struct panfrost_device *pdev = &physical_device->pdev;43VkFormatFeatureFlags tex = 0, buffer = 0;44enum pipe_format pfmt = vk_format_to_pipe_format(format);45const struct panfrost_format fmt = pdev->formats[pfmt];4647if (!pfmt || !fmt.hw)48goto end;4950/* 3byte formats are not supported by the buffer <-> image copy helpers. */51if (util_format_get_blocksize(pfmt) == 3)52goto end;5354/* We don't support compressed formats yet: this is causing trouble when55* doing a vkCmdCopyImage() between a compressed and a non-compressed format56* on a tiled/AFBC resource.57*/58if (util_format_is_compressed(pfmt))59goto end;6061buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |62VK_FORMAT_FEATURE_TRANSFER_DST_BIT;6364if (fmt.bind & PIPE_BIND_VERTEX_BUFFER)65buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;6667if (fmt.bind & PIPE_BIND_SAMPLER_VIEW) {68tex |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |69VK_FORMAT_FEATURE_TRANSFER_DST_BIT |70VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |71VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |72VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT |73VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |74VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;7576buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;7778tex |= VK_FORMAT_FEATURE_BLIT_SRC_BIT;79}8081if (fmt.bind & PIPE_BIND_RENDER_TARGET) {82tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |83VK_FORMAT_FEATURE_BLIT_DST_BIT;8485tex |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;86buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;8788/* Can always blend via blend shaders */89tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;90}9192if (fmt.bind & PIPE_BIND_DEPTH_STENCIL)93tex |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;9495end:96out_properties->linearTilingFeatures = tex;97out_properties->optimalTilingFeatures = tex;98out_properties->bufferFeatures = buffer;99}100101void102panvk_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,103VkFormat format,104VkFormatProperties *pFormatProperties)105{106VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);107108get_format_properties(physical_device, format, pFormatProperties);109}110111void112panvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,113VkFormat format,114VkFormatProperties2 *pFormatProperties)115{116VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);117118get_format_properties(physical_device, format,119&pFormatProperties->formatProperties);120121VkDrmFormatModifierPropertiesListEXT *list =122vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);123if (list) {124VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,125&list->drmFormatModifierCount);126127vk_outarray_append(&out, mod_props) {128mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;129mod_props->drmFormatModifierPlaneCount = 1;130}131}132}133134static VkResult135get_image_format_properties(struct panvk_physical_device *physical_device,136const VkPhysicalDeviceImageFormatInfo2 *info,137VkImageFormatProperties *pImageFormatProperties,138VkFormatFeatureFlags *p_feature_flags)139{140VkFormatProperties format_props;141VkFormatFeatureFlags format_feature_flags;142VkExtent3D maxExtent;143uint32_t maxMipLevels;144uint32_t maxArraySize;145VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;146enum pipe_format format = vk_format_to_pipe_format(info->format);147148get_format_properties(physical_device, info->format, &format_props);149150switch (info->tiling) {151case VK_IMAGE_TILING_LINEAR:152format_feature_flags = format_props.linearTilingFeatures;153break;154155case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:156/* The only difference between optimal and linear is currently whether157* depth/stencil attachments are allowed on depth/stencil formats.158* There's no reason to allow importing depth/stencil textures, so just159* disallow it and then this annoying edge case goes away.160*161* TODO: If anyone cares, we could enable this by looking at the162* modifier and checking if it's LINEAR or not.163*/164if (util_format_is_depth_or_stencil(format))165goto unsupported;166167assert(format_props.optimalTilingFeatures == format_props.linearTilingFeatures);168/* fallthrough */169case VK_IMAGE_TILING_OPTIMAL:170format_feature_flags = format_props.optimalTilingFeatures;171break;172default:173unreachable("bad VkPhysicalDeviceImageFormatInfo2");174}175176if (format_feature_flags == 0)177goto unsupported;178179if (info->type != VK_IMAGE_TYPE_2D &&180util_format_is_depth_or_stencil(format))181goto unsupported;182183switch (info->type) {184default:185unreachable("bad vkimage type");186case VK_IMAGE_TYPE_1D:187maxExtent.width = 16384;188maxExtent.height = 1;189maxExtent.depth = 1;190maxMipLevels = 15; /* log2(maxWidth) + 1 */191maxArraySize = 2048;192break;193case VK_IMAGE_TYPE_2D:194maxExtent.width = 16384;195maxExtent.height = 16384;196maxExtent.depth = 1;197maxMipLevels = 15; /* log2(maxWidth) + 1 */198maxArraySize = 2048;199break;200case VK_IMAGE_TYPE_3D:201maxExtent.width = 2048;202maxExtent.height = 2048;203maxExtent.depth = 2048;204maxMipLevels = 12; /* log2(maxWidth) + 1 */205maxArraySize = 1;206break;207}208209if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&210info->type == VK_IMAGE_TYPE_2D &&211(format_feature_flags &212(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |213VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&214!(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&215!(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {216sampleCounts |= VK_SAMPLE_COUNT_4_BIT;217}218219if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {220if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {221goto unsupported;222}223}224225if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {226if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {227goto unsupported;228}229}230231if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {232if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {233goto unsupported;234}235}236237if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {238if (!(format_feature_flags &239VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {240goto unsupported;241}242}243244*pImageFormatProperties = (VkImageFormatProperties) {245.maxExtent = maxExtent,246.maxMipLevels = maxMipLevels,247.maxArrayLayers = maxArraySize,248.sampleCounts = sampleCounts,249250/* FINISHME: Accurately calculate251* VkImageFormatProperties::maxResourceSize.252*/253.maxResourceSize = UINT32_MAX,254};255256if (p_feature_flags)257*p_feature_flags = format_feature_flags;258259return VK_SUCCESS;260unsupported:261*pImageFormatProperties = (VkImageFormatProperties) {262.maxExtent = { 0, 0, 0 },263.maxMipLevels = 0,264.maxArrayLayers = 0,265.sampleCounts = 0,266.maxResourceSize = 0,267};268269return VK_ERROR_FORMAT_NOT_SUPPORTED;270}271272273VkResult274panvk_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,275VkFormat format,276VkImageType type,277VkImageTiling tiling,278VkImageUsageFlags usage,279VkImageCreateFlags createFlags,280VkImageFormatProperties *pImageFormatProperties)281{282VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);283284const VkPhysicalDeviceImageFormatInfo2 info = {285.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,286.pNext = NULL,287.format = format,288.type = type,289.tiling = tiling,290.usage = usage,291.flags = createFlags,292};293294return get_image_format_properties(physical_device, &info,295pImageFormatProperties, NULL);296}297298static VkResult299panvk_get_external_image_format_properties(const struct panvk_physical_device *physical_device,300const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,301VkExternalMemoryHandleTypeFlagBits handleType,302VkExternalMemoryProperties *external_properties)303{304VkExternalMemoryFeatureFlagBits flags = 0;305VkExternalMemoryHandleTypeFlags export_flags = 0;306VkExternalMemoryHandleTypeFlags compat_flags = 0;307308/* From the Vulkan 1.1.98 spec:309*310* If handleType is not compatible with the format, type, tiling,311* usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,312* then vkGetPhysicalDeviceImageFormatProperties2 returns313* VK_ERROR_FORMAT_NOT_SUPPORTED.314*/315switch (handleType) {316case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:317case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:318switch (pImageFormatInfo->type) {319case VK_IMAGE_TYPE_2D:320flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |321VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |322VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;323compat_flags = export_flags =324VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |325VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;326break;327default:328return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,329"VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",330handleType, pImageFormatInfo->type);331}332break;333case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:334flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;335compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;336break;337default:338return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,339"VkExternalMemoryTypeFlagBits(0x%x) unsupported",340handleType);341}342343*external_properties = (VkExternalMemoryProperties) {344.externalMemoryFeatures = flags,345.exportFromImportedHandleTypes = export_flags,346.compatibleHandleTypes = compat_flags,347};348349return VK_SUCCESS;350}351352VkResult353panvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,354const VkPhysicalDeviceImageFormatInfo2 *base_info,355VkImageFormatProperties2 *base_props)356{357VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);358const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;359const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;360VkExternalImageFormatProperties *external_props = NULL;361VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;362VkFormatFeatureFlags format_feature_flags;363VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;364VkResult result;365366result = get_image_format_properties(physical_device, base_info,367&base_props->imageFormatProperties,368&format_feature_flags);369if (result != VK_SUCCESS)370return result;371372/* Extract input structs */373vk_foreach_struct_const(s, base_info->pNext)374{375switch (s->sType) {376case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:377external_info = (const void *) s;378break;379case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:380image_view_info = (const void *) s;381break;382default:383break;384}385}386387/* Extract output structs */388vk_foreach_struct(s, base_props->pNext)389{390switch (s->sType) {391case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:392external_props = (void *) s;393break;394case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:395cubic_props = (void *) s;396break;397case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:398ycbcr_props = (void *) s;399break;400default:401break;402}403}404405/* From the Vulkan 1.0.42 spec:406*407* If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will408* behave as if VkPhysicalDeviceExternalImageFormatInfo was not409* present and VkExternalImageFormatProperties will be ignored.410*/411if (external_info && external_info->handleType != 0) {412result = panvk_get_external_image_format_properties(physical_device,413base_info,414external_info->handleType,415&external_props->externalMemoryProperties);416if (result != VK_SUCCESS)417goto fail;418}419420if (cubic_props) {421/* note: blob only allows cubic filtering for 2D and 2D array views422* its likely we can enable it for 1D and CUBE, needs testing however423*/424if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||425image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&426(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {427cubic_props->filterCubic = true;428cubic_props->filterCubicMinmax = true;429} else {430cubic_props->filterCubic = false;431cubic_props->filterCubicMinmax = false;432}433}434435if (ycbcr_props)436ycbcr_props->combinedImageSamplerDescriptorCount = 1;437438return VK_SUCCESS;439440fail:441if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {442/* From the Vulkan 1.0.42 spec:443*444* If the combination of parameters to445* vkGetPhysicalDeviceImageFormatProperties2 is not supported by446* the implementation for use in vkCreateImage, then all members of447* imageFormatProperties will be filled with zero.448*/449base_props->imageFormatProperties = (VkImageFormatProperties) {};450}451452return result;453}454455void456panvk_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,457VkFormat format,458VkImageType type,459uint32_t samples,460VkImageUsageFlags usage,461VkImageTiling tiling,462uint32_t *pNumProperties,463VkSparseImageFormatProperties *pProperties)464{465panvk_stub();466}467468void469panvk_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,470const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,471uint32_t *pPropertyCount,472VkSparseImageFormatProperties2 *pProperties)473{474panvk_stub();475}476477void478panvk_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,479const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,480VkExternalBufferProperties *pExternalBufferProperties)481{482panvk_stub();483}484485486