1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include <stdbool.h> 25 26#include "pvr_formats.h" 27#include "pvr_private.h" 28#include "vk_enum_to_str.h" 29#include "vk_format.h" 30#include "vk_log.h" 31#include "vk_util.h" 32 33#define FORMAT(vk, tex_fmt, pack_mode) \ 34 [VK_FORMAT_##vk] = { \ 35 .vk_format = VK_FORMAT_##vk, \ 36 .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt, \ 37 .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \ 38 .supported = true, \ 39 } 40 41struct pvr_format { 42 VkFormat vk_format; 43 uint32_t tex_format; 44 uint32_t pbe_packmode; 45 bool supported; 46}; 47 48/* TODO: add all supported core formats */ 49static const struct pvr_format pvr_format_table[] = { 50 /* VK_FORMAT_R8_UINT = 13. */ 51 FORMAT(R8_UINT, U8, U8), 52 /* VK_FORMAT_B8G8R8A8_UNORM = 44. */ 53 FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8), 54 /* VK_FORMAT_R32_UINT = 98. */ 55 FORMAT(R32_UINT, U32, U32), 56 /* VK_FORMAT_R32G32B32A32_UINT = 107. */ 57 FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32), 58 /* VK_FORMAT_R32G32B32A32_SFLOAT = 109. */ 59 FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32), 60 /* VK_FORMAT_D32_SFLOAT = 126. */ 61 FORMAT(D32_SFLOAT, F32, F32), 62}; 63 64#undef FORMAT 65 66static inline const struct pvr_format *pvr_get_format(VkFormat vk_format) 67{ 68 if (vk_format < ARRAY_SIZE(pvr_format_table) && 69 pvr_format_table[vk_format].supported) { 70 return &pvr_format_table[vk_format]; 71 } 72 73 mesa_logd("Format %s(%d) not supported\n", 74 vk_Format_to_str(vk_format), 75 vk_format); 76 77 return NULL; 78} 79 80uint32_t pvr_get_tex_format(VkFormat vk_format) 81{ 82 const struct pvr_format *pvr_format = pvr_get_format(vk_format); 83 if (pvr_format) { 84 return pvr_format->tex_format; 85 } 86 87 return ROGUE_TEXSTATE_FORMAT_INVALID; 88} 89 90uint32_t pvr_get_pbe_packmode(VkFormat vk_format) 91{ 92 const struct pvr_format *pvr_format = pvr_get_format(vk_format); 93 if (pvr_format) 94 return pvr_format->pbe_packmode; 95 96 return ROGUE_PBESTATE_PACKMODE_INVALID; 97} 98 99static VkFormatFeatureFlags 100pvr_get_image_format_features(const struct pvr_format *pvr_format, 101 VkImageTiling vk_tiling) 102{ 103 VkFormatFeatureFlags flags = 0; 104 VkImageAspectFlags aspects; 105 106 if (!pvr_format) 107 return 0; 108 109 aspects = vk_format_aspects(pvr_format->vk_format); 110 if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { 111 flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | 112 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | 113 VK_FORMAT_FEATURE_BLIT_SRC_BIT; 114 } 115 116 return flags; 117} 118 119const uint8_t *pvr_get_format_swizzle(VkFormat vk_format) 120{ 121 const struct util_format_description *vf = vk_format_description(vk_format); 122 123 return vf->swizzle; 124} 125 126static VkFormatFeatureFlags 127pvr_get_buffer_format_features(const struct pvr_format *pvr_format) 128{ 129 VkFormatFeatureFlags flags = 0; 130 131 if (!pvr_format) 132 return 0; 133 134 return flags; 135} 136 137void pvr_GetPhysicalDeviceFormatProperties2( 138 VkPhysicalDevice physicalDevice, 139 VkFormat format, 140 VkFormatProperties2 *pFormatProperties) 141{ 142 const struct pvr_format *pvr_format = pvr_get_format(format); 143 144 pFormatProperties->formatProperties = (VkFormatProperties){ 145 .linearTilingFeatures = 146 pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_LINEAR), 147 .optimalTilingFeatures = 148 pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_OPTIMAL), 149 .bufferFeatures = pvr_get_buffer_format_features(pvr_format), 150 }; 151 152 vk_foreach_struct (ext, pFormatProperties->pNext) { 153 pvr_debug_ignored_stype(ext->sType); 154 } 155} 156 157static VkResult 158pvr_get_image_format_properties(struct pvr_physical_device *pdevice, 159 const VkPhysicalDeviceImageFormatInfo2 *info, 160 VkImageFormatProperties *pImageFormatProperties) 161{ 162 assert(!"Unimplemented"); 163 return VK_SUCCESS; 164} 165 166VkResult pvr_GetPhysicalDeviceImageFormatProperties2( 167 VkPhysicalDevice physicalDevice, 168 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, 169 VkImageFormatProperties2 *pImageFormatProperties) 170{ 171 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; 172 PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); 173 VkExternalImageFormatProperties *external_props = NULL; 174 VkResult result; 175 176 result = pvr_get_image_format_properties( 177 pdevice, 178 pImageFormatInfo, 179 &pImageFormatProperties->imageFormatProperties); 180 if (result != VK_SUCCESS) 181 return result; 182 183 /* Extract input structs */ 184 vk_foreach_struct_const (ext, pImageFormatInfo->pNext) { 185 switch (ext->sType) { 186 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: 187 external_info = (const void *)ext; 188 break; 189 default: 190 pvr_debug_ignored_stype(ext->sType); 191 break; 192 } 193 } 194 195 /* Extract output structs */ 196 vk_foreach_struct (ext, pImageFormatProperties->pNext) { 197 switch (ext->sType) { 198 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: 199 external_props = (void *)ext; 200 break; 201 default: 202 pvr_debug_ignored_stype(ext->sType); 203 break; 204 } 205 } 206 207 /* From the Vulkan 1.0.42 spec: 208 * 209 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will 210 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not 211 * present and VkExternalImageFormatProperties will be ignored. 212 */ 213 if (external_info && external_info->handleType != 0) { 214 switch (external_info->handleType) { 215 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 216 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 217 if (!external_props) 218 break; 219 220 external_props->externalMemoryProperties.externalMemoryFeatures = 221 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | 222 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 223 external_props->externalMemoryProperties.compatibleHandleTypes = 224 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 225 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 226 external_props->externalMemoryProperties.exportFromImportedHandleTypes = 227 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 228 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 229 break; 230 default: 231 return vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); 232 } 233 } 234 235 return VK_SUCCESS; 236} 237 238void pvr_GetPhysicalDeviceSparseImageFormatProperties( 239 VkPhysicalDevice physicalDevice, 240 VkFormat format, 241 VkImageType type, 242 uint32_t samples, 243 VkImageUsageFlags usage, 244 VkImageTiling tiling, 245 uint32_t *pNumProperties, 246 VkSparseImageFormatProperties *pProperties) 247{ 248 /* Sparse images are not yet supported. */ 249 *pNumProperties = 0; 250} 251 252void pvr_GetPhysicalDeviceSparseImageFormatProperties2( 253 VkPhysicalDevice physicalDevice, 254 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, 255 uint32_t *pPropertyCount, 256 VkSparseImageFormatProperties2 *pProperties) 257{ 258 /* Sparse images are not yet supported. */ 259 *pPropertyCount = 0; 260} 261 262void pvr_GetPhysicalDeviceExternalBufferProperties( 263 VkPhysicalDevice physicalDevice, 264 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, 265 VkExternalBufferProperties *pExternalBufferProperties) 266{ 267 /* The Vulkan 1.0.42 spec says "handleType must be a valid 268 * VkExternalMemoryHandleTypeFlagBits value" in 269 * VkPhysicalDeviceExternalBufferInfo. This differs from 270 * VkPhysicalDeviceExternalImageFormatInfo, which surprisingly permits 271 * handleType == 0. 272 */ 273 assert(pExternalBufferInfo->handleType != 0); 274 275 /* All of the current flags are for sparse which we don't support. */ 276 if (pExternalBufferInfo->flags) 277 goto unsupported; 278 279 switch (pExternalBufferInfo->handleType) { 280 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 281 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 282 /* clang-format off */ 283 pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 284 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | 285 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 286 pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = 287 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 288 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 289 pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = 290 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 291 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 292 /* clang-format on */ 293 return; 294 default: 295 break; 296 } 297 298unsupported: 299 /* From the Vulkan 1.1.113 spec: 300 * 301 * compatibleHandleTypes must include at least handleType. 302 */ 303 pExternalBufferProperties->externalMemoryProperties = 304 (VkExternalMemoryProperties){ 305 .compatibleHandleTypes = pExternalBufferInfo->handleType, 306 }; 307} 308 309bool pvr_format_is_pbe_downscalable(VkFormat vk_format) 310{ 311 if (vk_format_is_int(vk_format)) { 312 /* PBE downscale behavior for integer formats does not match Vulkan 313 * spec. Vulkan requires a single sample to be chosen instead of 314 * taking the average sample color. 315 */ 316 return false; 317 } 318 319 switch (pvr_get_pbe_packmode(vk_format)) { 320 default: 321 return true; 322 323 case ROGUE_PBESTATE_PACKMODE_U16U16U16U16: 324 case ROGUE_PBESTATE_PACKMODE_S16S16S16S16: 325 case ROGUE_PBESTATE_PACKMODE_U32U32U32U32: 326 case ROGUE_PBESTATE_PACKMODE_S32S32S32S32: 327 case ROGUE_PBESTATE_PACKMODE_F32F32F32F32: 328 case ROGUE_PBESTATE_PACKMODE_U16U16U16: 329 case ROGUE_PBESTATE_PACKMODE_S16S16S16: 330 case ROGUE_PBESTATE_PACKMODE_U32U32U32: 331 case ROGUE_PBESTATE_PACKMODE_S32S32S32: 332 case ROGUE_PBESTATE_PACKMODE_F32F32F32: 333 case ROGUE_PBESTATE_PACKMODE_U16U16: 334 case ROGUE_PBESTATE_PACKMODE_S16S16: 335 case ROGUE_PBESTATE_PACKMODE_U32U32: 336 case ROGUE_PBESTATE_PACKMODE_S32S32: 337 case ROGUE_PBESTATE_PACKMODE_F32F32: 338 case ROGUE_PBESTATE_PACKMODE_U24ST8: 339 case ROGUE_PBESTATE_PACKMODE_ST8U24: 340 case ROGUE_PBESTATE_PACKMODE_U16: 341 case ROGUE_PBESTATE_PACKMODE_S16: 342 case ROGUE_PBESTATE_PACKMODE_U32: 343 case ROGUE_PBESTATE_PACKMODE_S32: 344 case ROGUE_PBESTATE_PACKMODE_F32: 345 case ROGUE_PBESTATE_PACKMODE_X24U8F32: 346 case ROGUE_PBESTATE_PACKMODE_X24X8F32: 347 case ROGUE_PBESTATE_PACKMODE_X24G8X32: 348 case ROGUE_PBESTATE_PACKMODE_X8U24: 349 case ROGUE_PBESTATE_PACKMODE_U8X24: 350 case ROGUE_PBESTATE_PACKMODE_PBYTE: 351 case ROGUE_PBESTATE_PACKMODE_PWORD: 352 case ROGUE_PBESTATE_PACKMODE_INVALID: 353 return false; 354 } 355} 356