Path: blob/21.2-virgl/src/broadcom/vulkan/v3dv_formats.c
4560 views
/*1* Copyright © 2019 Raspberry Pi2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "v3dv_private.h"24#include "vk_util.h"25#include "vk_format_info.h"2627#include "drm-uapi/drm_fourcc.h"28#include "util/format/u_format.h"29#include "vulkan/wsi/wsi_common.h"3031const uint8_t *32v3dv_get_format_swizzle(struct v3dv_device *device, VkFormat f)33{34const struct v3dv_format *vf = v3dv_X(device, get_format)(f);35static const uint8_t fallback[] = {0, 1, 2, 3};3637if (!vf)38return fallback;3940return vf->swizzle;41}4243uint8_t44v3dv_get_tex_return_size(const struct v3dv_format *vf,45bool compare_enable)46{47if (compare_enable)48return 16;4950return vf->return_size;51}5253/* Some cases of transfer operations are raw data copies that don't depend54* on the semantics of the pixel format (no pixel format conversions are55* involved). In these cases, it is safe to choose any format supported by56* the TFU so long as it has the same texel size, which allows us to use the57* TFU paths with formats that are not TFU supported otherwise.58*/59const struct v3dv_format *60v3dv_get_compatible_tfu_format(struct v3dv_device *device,61uint32_t bpp,62VkFormat *out_vk_format)63{64VkFormat vk_format;65switch (bpp) {66case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break;67case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break;68case 4: vk_format = VK_FORMAT_R32_SFLOAT; break;69case 2: vk_format = VK_FORMAT_R16_SFLOAT; break;70case 1: vk_format = VK_FORMAT_R8_UNORM; break;71default: unreachable("unsupported format bit-size"); break;72};7374if (out_vk_format)75*out_vk_format = vk_format;7677const struct v3dv_format *format = v3dv_X(device, get_format)(vk_format);78assert(v3dv_X(device, tfu_supports_tex_format)(format->tex_type));7980return format;81}8283static VkFormatFeatureFlags84image_format_features(struct v3dv_physical_device *pdevice,85VkFormat vk_format,86const struct v3dv_format *v3dv_format,87VkImageTiling tiling)88{89if (!v3dv_format || !v3dv_format->supported)90return 0;9192const VkImageAspectFlags aspects = vk_format_aspects(vk_format);9394const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |95VK_IMAGE_ASPECT_STENCIL_BIT;96const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |97zs_aspects;98if ((aspects & supported_aspects) != aspects)99return 0;100101/* FIXME: We don't support separate stencil yet */102if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)103return 0;104105if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&106v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {107return 0;108}109110VkFormatFeatureFlags flags = 0;111112/* Raster format is only supported for 1D textures, so let's just113* always require optimal tiling for anything that requires sampling.114* Note: even if the user requests optimal for a 1D image, we will still115* use raster format since that is what the HW requires.116*/117if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&118tiling == VK_IMAGE_TILING_OPTIMAL) {119flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |120VK_FORMAT_FEATURE_BLIT_SRC_BIT;121122if (v3dv_format->supports_filtering)123flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;124}125126if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {127if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {128flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |129VK_FORMAT_FEATURE_BLIT_DST_BIT;130if (v3dv_X(pdevice, format_supports_blending)(v3dv_format))131flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;132} else if (aspects & zs_aspects) {133flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |134VK_FORMAT_FEATURE_BLIT_DST_BIT;135}136}137138const struct util_format_description *desc =139vk_format_description(vk_format);140assert(desc);141142if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {143flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;144if (desc->nr_channels == 1 && vk_format_is_int(vk_format))145flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;146} else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||147vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||148vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {149/* To comply with shaderStorageImageExtendedFormats */150flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;151}152153if (flags) {154flags |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |155VK_FORMAT_FEATURE_TRANSFER_DST_BIT;156}157158return flags;159}160161static VkFormatFeatureFlags162buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)163{164if (!v3dv_format || !v3dv_format->supported)165return 0;166167if (!v3dv_format->supported)168return 0;169170/* We probably only want to support buffer formats that have a171* color format specification.172*/173if (!vk_format_is_color(vk_format))174return 0;175176const struct util_format_description *desc =177vk_format_description(vk_format);178assert(desc);179180VkFormatFeatureFlags flags = 0;181if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&182desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&183desc->is_array) {184flags |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;185if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO) {186flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |187VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;188}189} else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) {190flags |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |191VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |192VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;193} else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||194vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {195flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |196VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;197}198199if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&200desc->is_array &&201desc->nr_channels == 1 &&202vk_format_is_int(vk_format)) {203flags |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;204}205206return flags;207}208209bool210v3dv_buffer_format_supports_features(struct v3dv_device *device,211VkFormat vk_format,212VkFormatFeatureFlags features)213{214const struct v3dv_format *v3dv_format = v3dv_X(device, get_format)(vk_format);215const VkFormatFeatureFlags supported =216buffer_format_features(vk_format, v3dv_format);217return (supported & features) == features;218}219220VKAPI_ATTR void VKAPI_CALL221v3dv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,222VkFormat format,223VkFormatProperties* pFormatProperties)224{225V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);226const struct v3dv_format *v3dv_format = v3dv_X(pdevice, get_format)(format);227228*pFormatProperties = (VkFormatProperties) {229.linearTilingFeatures =230image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_LINEAR),231.optimalTilingFeatures =232image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_OPTIMAL),233.bufferFeatures =234buffer_format_features(format, v3dv_format),235};236}237238VKAPI_ATTR void VKAPI_CALL239v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,240VkFormat format,241VkFormatProperties2 *pFormatProperties)242{243v3dv_GetPhysicalDeviceFormatProperties(physicalDevice, format,244&pFormatProperties->formatProperties);245246vk_foreach_struct(ext, pFormatProperties->pNext) {247switch ((unsigned)ext->sType) {248case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {249struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;250VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,251&list->drmFormatModifierCount);252if (pFormatProperties->formatProperties.linearTilingFeatures) {253vk_outarray_append(&out, mod_props) {254mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;255mod_props->drmFormatModifierPlaneCount = 1;256}257}258if (pFormatProperties->formatProperties.optimalTilingFeatures) {259vk_outarray_append(&out, mod_props) {260mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;261mod_props->drmFormatModifierPlaneCount = 1;262}263}264break;265}266default:267v3dv_debug_ignored_stype(ext->sType);268break;269}270}271}272273static VkResult274get_image_format_properties(275struct v3dv_physical_device *physical_device,276const VkPhysicalDeviceImageFormatInfo2 *info,277VkImageTiling tiling,278VkImageFormatProperties *pImageFormatProperties,279VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)280{281const struct v3dv_format *v3dv_format = v3dv_X(physical_device, get_format)(info->format);282VkFormatFeatureFlags format_feature_flags =283image_format_features(physical_device, info->format, v3dv_format, tiling);284if (!format_feature_flags)285goto unsupported;286287/* This allows users to create uncompressed views of compressed images,288* however this is not something the hardware supports naturally and requires289* the driver to lie when programming the texture state to make the hardware290* sample with the uncompressed view correctly, and even then, there are291* issues when running on real hardware.292*293* See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336294* for details.295*/296if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)297goto unsupported;298299if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {300if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) {301goto unsupported;302}303304/* Sampling of raster depth/stencil images is not supported. Since 1D305* images are always raster, even if the user requested optimal tiling,306* we can't have them be used as transfer sources, since that includes307* using them for blit sources, which might require sampling.308*/309if (info->type == VK_IMAGE_TYPE_1D &&310vk_format_is_depth_or_stencil(info->format)) {311goto unsupported;312}313}314315if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {316if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {317goto unsupported;318}319}320321if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {322if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {323goto unsupported;324}325326/* Sampling of raster depth/stencil images is not supported. Since 1D327* images are always raster, even if the user requested optimal tiling,328* we can't allow sampling if the format is depth/stencil.329*/330if (info->type == VK_IMAGE_TYPE_1D &&331vk_format_is_depth_or_stencil(info->format)) {332goto unsupported;333}334}335336if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {337if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {338goto unsupported;339}340}341342if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {343if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {344goto unsupported;345}346}347348if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {349if (!(format_feature_flags &350VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {351goto unsupported;352}353}354355/* FIXME: these are taken from VkPhysicalDeviceLimits, we should just put356* these limits available in the physical device and read them from there357* wherever we need them.358*/359switch (info->type) {360case VK_IMAGE_TYPE_1D:361pImageFormatProperties->maxExtent.width = 4096;362pImageFormatProperties->maxExtent.height = 1;363pImageFormatProperties->maxExtent.depth = 1;364pImageFormatProperties->maxArrayLayers = 2048;365pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */366break;367case VK_IMAGE_TYPE_2D:368pImageFormatProperties->maxExtent.width = 4096;369pImageFormatProperties->maxExtent.height = 4096;370pImageFormatProperties->maxExtent.depth = 1;371pImageFormatProperties->maxArrayLayers = 2048;372pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */373break;374case VK_IMAGE_TYPE_3D:375pImageFormatProperties->maxExtent.width = 4096;376pImageFormatProperties->maxExtent.height = 4096;377pImageFormatProperties->maxExtent.depth = 4096;378pImageFormatProperties->maxArrayLayers = 1;379pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */380break;381default:382unreachable("bad VkImageType");383}384385/* Our hw doesn't support 1D compressed textures. */386if (info->type == VK_IMAGE_TYPE_1D &&387vk_format_is_compressed(info->format)) {388goto unsupported;389}390391/* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:392*393* sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the394* following conditions is true:395*396* - tiling is VK_IMAGE_TILING_LINEAR397* - type is not VK_IMAGE_TYPE_2D398* - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT399* - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the400* VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in401* VkFormatProperties::optimalTilingFeatures returned by402* vkGetPhysicalDeviceFormatProperties is set.403*/404pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;405if (tiling != VK_IMAGE_TILING_LINEAR &&406info->type == VK_IMAGE_TYPE_2D &&407!(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&408(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||409format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {410pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;411}412413if (tiling == VK_IMAGE_TILING_LINEAR)414pImageFormatProperties->maxMipLevels = 1;415416pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */417418return VK_SUCCESS;419420unsupported:421*pImageFormatProperties = (VkImageFormatProperties) {422.maxExtent = { 0, 0, 0 },423.maxMipLevels = 0,424.maxArrayLayers = 0,425.sampleCounts = 0,426.maxResourceSize = 0,427};428429return VK_ERROR_FORMAT_NOT_SUPPORTED;430}431432static const VkExternalMemoryProperties prime_fd_props = {433.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |434VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,435.exportFromImportedHandleTypes =436VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |437VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,438.compatibleHandleTypes =439VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |440VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,441};442443VKAPI_ATTR VkResult VKAPI_CALL444v3dv_GetPhysicalDeviceImageFormatProperties(445VkPhysicalDevice physicalDevice,446VkFormat format,447VkImageType type,448VkImageTiling tiling,449VkImageUsageFlags usage,450VkImageCreateFlags createFlags,451VkImageFormatProperties *pImageFormatProperties)452{453V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);454455const VkPhysicalDeviceImageFormatInfo2 info = {456.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,457.pNext = NULL,458.format = format,459.type = type,460.tiling = tiling,461.usage = usage,462.flags = createFlags,463};464465return get_image_format_properties(physical_device, &info, tiling,466pImageFormatProperties, NULL);467}468469VKAPI_ATTR VkResult VKAPI_CALL470v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,471const VkPhysicalDeviceImageFormatInfo2 *base_info,472VkImageFormatProperties2 *base_props)473{474V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);475const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;476const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;477VkExternalImageFormatProperties *external_props = NULL;478VkImageTiling tiling = base_info->tiling;479480/* Extract input structs */481vk_foreach_struct_const(s, base_info->pNext) {482switch (s->sType) {483case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:484external_info = (const void *) s;485break;486case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:487drm_format_mod_info = (const void *) s;488switch (drm_format_mod_info->drmFormatModifier) {489case DRM_FORMAT_MOD_LINEAR:490tiling = VK_IMAGE_TILING_LINEAR;491break;492case DRM_FORMAT_MOD_BROADCOM_UIF:493tiling = VK_IMAGE_TILING_OPTIMAL;494break;495default:496assert("Unknown DRM format modifier");497}498break;499default:500v3dv_debug_ignored_stype(s->sType);501break;502}503}504505assert(tiling == VK_IMAGE_TILING_OPTIMAL ||506tiling == VK_IMAGE_TILING_LINEAR);507508/* Extract output structs */509vk_foreach_struct(s, base_props->pNext) {510switch (s->sType) {511case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:512external_props = (void *) s;513break;514default:515v3dv_debug_ignored_stype(s->sType);516break;517}518}519520VkResult result =521get_image_format_properties(physical_device, base_info, tiling,522&base_props->imageFormatProperties, NULL);523if (result != VK_SUCCESS)524goto done;525526if (external_info && external_info->handleType != 0) {527switch (external_info->handleType) {528case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:529case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:530if (external_props)531external_props->externalMemoryProperties = prime_fd_props;532break;533default:534result = VK_ERROR_FORMAT_NOT_SUPPORTED;535break;536}537}538539done:540return result;541}542543VKAPI_ATTR void VKAPI_CALL544v3dv_GetPhysicalDeviceSparseImageFormatProperties(545VkPhysicalDevice physicalDevice,546VkFormat format,547VkImageType type,548VkSampleCountFlagBits samples,549VkImageUsageFlags usage,550VkImageTiling tiling,551uint32_t *pPropertyCount,552VkSparseImageFormatProperties *pProperties)553{554*pPropertyCount = 0;555}556557VKAPI_ATTR void VKAPI_CALL558v3dv_GetPhysicalDeviceSparseImageFormatProperties2(559VkPhysicalDevice physicalDevice,560const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,561uint32_t *pPropertyCount,562VkSparseImageFormatProperties2 *pProperties)563{564*pPropertyCount = 0;565}566567VKAPI_ATTR void VKAPI_CALL568v3dv_GetPhysicalDeviceExternalBufferProperties(569VkPhysicalDevice physicalDevice,570const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,571VkExternalBufferProperties *pExternalBufferProperties)572{573switch (pExternalBufferInfo->handleType) {574case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:575case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:576pExternalBufferProperties->externalMemoryProperties = prime_fd_props;577return;578default: /* Unsupported */579pExternalBufferProperties->externalMemoryProperties =580(VkExternalMemoryProperties) {581.compatibleHandleTypes = pExternalBufferInfo->handleType,582};583break;584}585}586587588