/* * Copyright © 2022 Imagination Technologies Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include "hwdef/rogue_hw_utils.h" #include "pvr_common.h" #include "pvr_formats.h" #include "pvr_private.h" #include "util/bitpack_helpers.h" #include "util/compiler.h" #include "util/format/format_utils.h" #include "util/half_float.h" #include "util/log.h" #include "util/macros.h" #include "util/u_math.h" #include "vk_enum_defines.h" #include "vk_enum_to_str.h" #include "vk_format.h" #include "vk_log.h" #include "vk_util.h" #define FORMAT(vk, tex_fmt, pack_mode, accum_format) \ [VK_FORMAT_##vk] = { \ .vk_format = VK_FORMAT_##vk, \ .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt, \ .depth_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \ .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_##accum_format, \ .supported = true, \ } #define FORMAT_COMPRESSED(vk, tex_fmt) \ [VK_FORMAT_##vk] = { \ .vk_format = VK_FORMAT_##vk, \ .tex_format = ROGUE_TEXSTATE_FORMAT_COMPRESSED_##tex_fmt, \ .depth_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .pbe_packmode = ROGUE_PBESTATE_PACKMODE_INVALID, \ .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_INVALID, \ .supported = true, \ } #define FORMAT_DEPTH_STENCIL(vk, combined_fmt, d_fmt, s_fmt) \ [VK_FORMAT_##vk] = { \ .vk_format = VK_FORMAT_##vk, \ .tex_format = ROGUE_TEXSTATE_FORMAT_##combined_fmt, \ .depth_tex_format = ROGUE_TEXSTATE_FORMAT_##d_fmt, \ .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_##s_fmt, \ .pbe_packmode = ROGUE_PBESTATE_PACKMODE_INVALID, \ .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_INVALID, \ .supported = true, \ } struct pvr_format { VkFormat vk_format; uint32_t tex_format; uint32_t depth_tex_format; uint32_t stencil_tex_format; uint32_t pbe_packmode; enum pvr_pbe_accum_format pbe_accum_format; bool supported; }; static const struct pvr_format pvr_format_table[] = { /* VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3. */ FORMAT(B4G4R4A4_UNORM_PACK16, A4R4G4B4, A4R4G4B4, U8), /* VK_FORMAT_R5G6B5_UNORM_PACK16 = 4. */ FORMAT(R5G6B5_UNORM_PACK16, R5G6B5, R5G6B5, U8), /* VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8. */ FORMAT(A1R5G5B5_UNORM_PACK16, A1R5G5B5, A1R5G5B5, U8), /* VK_FORMAT_R8_UNORM = 9. */ FORMAT(R8_UNORM, U8, U8, U8), /* VK_FORMAT_R8_SNORM = 10. */ FORMAT(R8_SNORM, S8, S8, S8), /* VK_FORMAT_R8_UINT = 13. */ FORMAT(R8_UINT, U8, U8, UINT8), /* VK_FORMAT_R8_SINT = 14. */ FORMAT(R8_SINT, S8, S8, SINT8), /* VK_FORMAT_R8G8_UNORM = 16. */ FORMAT(R8G8_UNORM, U8U8, U8U8, U8), /* VK_FORMAT_R8G8_SNORM = 17. */ FORMAT(R8G8_SNORM, S8S8, S8S8, S8), /* VK_FORMAT_R8G8_UINT = 20. */ FORMAT(R8G8_UINT, U8U8, U8U8, UINT8), /* VK_FORMAT_R8G8_SINT = 21. */ FORMAT(R8G8_SINT, S8S8, S8S8, SINT8), /* VK_FORMAT_R8G8B8A8_UNORM = 37. */ FORMAT(R8G8B8A8_UNORM, U8U8U8U8, U8U8U8U8, U8), /* VK_FORMAT_R8G8B8A8_SNORM = 38. */ FORMAT(R8G8B8A8_SNORM, S8S8S8S8, S8S8S8S8, S8), /* VK_FORMAT_R8G8B8A8_UINT = 41. */ FORMAT(R8G8B8A8_UINT, U8U8U8U8, U8U8U8U8, UINT8), /* VK_FORMAT_R8G8B8A8_SINT = 42. */ FORMAT(R8G8B8A8_SINT, S8S8S8S8, S8S8S8S8, SINT8), /* VK_FORMAT_R8G8B8A8_SRGB = 43. */ FORMAT(R8G8B8A8_SRGB, U8U8U8U8, U8U8U8U8, F16), /* VK_FORMAT_B8G8R8A8_UNORM = 44. */ FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8, U8), /* VK_FORMAT_B8G8R8A8_SRGB = 50. */ FORMAT(B8G8R8A8_SRGB, U8U8U8U8, U8U8U8U8, F16), /* VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51. */ FORMAT(A8B8G8R8_UNORM_PACK32, U8U8U8U8, U8U8U8U8, U8), /* VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52. */ FORMAT(A8B8G8R8_SNORM_PACK32, S8S8S8S8, S8S8S8S8, S8), /* VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55. */ FORMAT(A8B8G8R8_UINT_PACK32, U8U8U8U8, U8U8U8U8, UINT8), /* VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56. */ FORMAT(A8B8G8R8_SINT_PACK32, S8S8S8S8, S8S8S8S8, SINT8), /* VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57. */ FORMAT(A8B8G8R8_SRGB_PACK32, U8U8U8U8, U8U8U8U8, F16), /* VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64. */ FORMAT(A2B10G10R10_UNORM_PACK32, A2R10B10G10, A2R10B10G10, F16), /* VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68. */ FORMAT(A2B10G10R10_UINT_PACK32, A2R10B10G10, U32, UINT32), /* VK_FORMAT_R16_UNORM = 70. */ FORMAT(R16_UNORM, U16, U16, U16), /* VK_FORMAT_R16_SNORM = 71. */ FORMAT(R16_SNORM, S16, S16, S16), /* VK_FORMAT_R16_UINT = 74. */ FORMAT(R16_UINT, U16, U16, UINT16), /* VK_FORMAT_R16_SINT = 75. */ FORMAT(R16_SINT, S16, S16, SINT16), /* VK_FORMAT_R16_SFLOAT = 76. */ FORMAT(R16_SFLOAT, F16, F16, F16), /* VK_FORMAT_R16G16_UNORM = 77. */ FORMAT(R16G16_UNORM, U16U16, U16U16, U16), /* VK_FORMAT_R16G16_SNORM = 78. */ FORMAT(R16G16_SNORM, S16S16, S16S16, S16), /* VK_FORMAT_R16G16_UINT = 81. */ FORMAT(R16G16_UINT, U16U16, U16U16, UINT16), /* VK_FORMAT_R16G16_SINT = 82. */ FORMAT(R16G16_SINT, S16S16, S16S16, SINT16), /* VK_FORMAT_R16G16_SFLOAT = 83. */ FORMAT(R16G16_SFLOAT, F16F16, F16F16, F16), /* VK_FORMAT_R16G16B16A16_UNORM = 91. */ FORMAT(R16G16B16A16_UNORM, U16U16U16U16, U16U16U16U16, U16), /* VK_FORMAT_R16G16B16A16_SNORM = 92. */ FORMAT(R16G16B16A16_SNORM, S16S16S16S16, S16S16S16S16, S16), /* VK_FORMAT_R16G16B16A16_UINT = 95. */ FORMAT(R16G16B16A16_UINT, U16U16U16U16, U16U16U16U16, UINT16), /* VK_FORMAT_R16G16B16A16_SINT = 96 */ FORMAT(R16G16B16A16_SINT, S16S16S16S16, S16S16S16S16, SINT16), /* VK_FORMAT_R16G16B16A16_SFLOAT = 97. */ FORMAT(R16G16B16A16_SFLOAT, F16F16F16F16, F16F16F16F16, F16), /* VK_FORMAT_R32_UINT = 98. */ FORMAT(R32_UINT, U32, U32, UINT32), /* VK_FORMAT_R32_SINT = 99. */ FORMAT(R32_SINT, S32, S32, SINT32), /* VK_FORMAT_R32_SFLOAT = 100. */ FORMAT(R32_SFLOAT, F32, F32, F32), /* VK_FORMAT_R32G32_UINT = 101. */ FORMAT(R32G32_UINT, U32U32, U32U32, UINT32), /* VK_FORMAT_R32G32_SINT = 102. */ FORMAT(R32G32_SINT, S32S32, S32S32, SINT32), /* VK_FORMAT_R32G32_SFLOAT = 103. */ FORMAT(R32G32_SFLOAT, F32F32, F32F32, F32), /* VK_FORMAT_R32G32B32_UINT = 104. */ FORMAT(R32G32B32_UINT, U32U32U32, U32U32U32, UINT32), /* VK_FORMAT_R32G32B32_SINT = 105. */ FORMAT(R32G32B32_SINT, S32S32S32, S32S32S32, SINT32), /* VK_FORMAT_R32G32B32_SFLOAT = 106. */ FORMAT(R32G32B32_SFLOAT, F32F32F32, F32F32F32, F32), /* VK_FORMAT_R32G32B32A32_UINT = 107. */ FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32, UINT32), /* VK_FORMAT_R32G32B32A32_SINT = 108. */ FORMAT(R32G32B32A32_SINT, S32S32S32S32, S32S32S32S32, SINT32), /* VK_FORMAT_R32G32B32A32_SFLOAT = 109. */ FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32, F32), /* VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122. */ FORMAT(B10G11R11_UFLOAT_PACK32, F10F11F11, F10F11F11, F16), /* VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123. */ FORMAT(E5B9G9R9_UFLOAT_PACK32, SE9995, SE9995, INVALID), /* VK_FORMAT_D16_UNORM = 124. */ FORMAT_DEPTH_STENCIL(D16_UNORM, U16, U16, INVALID), /* VK_FORMAT_D32_SFLOAT = 126. */ FORMAT_DEPTH_STENCIL(D32_SFLOAT, F32, F32, INVALID), /* VK_FORMAT_D24_UNORM_S8_UINT = 129. */ FORMAT_DEPTH_STENCIL(D24_UNORM_S8_UINT, ST8U24, X8U24, U8X24), /* VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147. */ FORMAT_COMPRESSED(ETC2_R8G8B8_UNORM_BLOCK, ETC2_RGB), /* VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148. */ FORMAT_COMPRESSED(ETC2_R8G8B8_SRGB_BLOCK, ETC2_RGB), /* VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149. */ FORMAT_COMPRESSED(ETC2_R8G8B8A1_UNORM_BLOCK, ETC2_PUNCHTHROUGHA), /* VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150. */ FORMAT_COMPRESSED(ETC2_R8G8B8A1_SRGB_BLOCK, ETC2_PUNCHTHROUGHA), /* VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 150. */ FORMAT_COMPRESSED(ETC2_R8G8B8A8_UNORM_BLOCK, ETC2A_RGBA), /* VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152. */ FORMAT_COMPRESSED(ETC2_R8G8B8A8_SRGB_BLOCK, ETC2A_RGBA), /* VK_FORMAT_EAC_R11_UNORM_BLOCK = 153. */ FORMAT_COMPRESSED(EAC_R11_UNORM_BLOCK, EAC_R11_UNSIGNED), /* VK_FORMAT_EAC_R11_SNORM_BLOCK = 154. */ FORMAT_COMPRESSED(EAC_R11_SNORM_BLOCK, EAC_R11_SIGNED), /* VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155. */ FORMAT_COMPRESSED(EAC_R11G11_UNORM_BLOCK, EAC_RG11_UNSIGNED), /* VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156. */ FORMAT_COMPRESSED(EAC_R11G11_SNORM_BLOCK, EAC_RG11_SIGNED), }; #undef FORMAT static inline const struct pvr_format *pvr_get_format(VkFormat vk_format) { if (vk_format < ARRAY_SIZE(pvr_format_table) && pvr_format_table[vk_format].supported) { return &pvr_format_table[vk_format]; } mesa_logd("Format %s(%d) not supported\n", vk_Format_to_str(vk_format), vk_format); return NULL; } uint32_t pvr_get_tex_format(VkFormat vk_format) { const struct pvr_format *pvr_format = pvr_get_format(vk_format); if (pvr_format) { return pvr_format->tex_format; } return ROGUE_TEXSTATE_FORMAT_INVALID; } uint32_t pvr_get_tex_format_aspect(VkFormat vk_format, VkImageAspectFlags aspect_mask) { const struct pvr_format *pvr_format = pvr_get_format(vk_format); if (pvr_format) { if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) return pvr_format->depth_tex_format; else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) return pvr_format->stencil_tex_format; return pvr_format->tex_format; } return PVRX(TEXSTATE_FORMAT_INVALID); } uint32_t pvr_get_pbe_packmode(VkFormat vk_format) { const struct pvr_format *pvr_format = pvr_get_format(vk_format); if (pvr_format) return pvr_format->pbe_packmode; return ROGUE_PBESTATE_PACKMODE_INVALID; } uint32_t pvr_get_pbe_accum_format(VkFormat vk_format) { const struct pvr_format *pvr_format = pvr_get_format(vk_format); if (pvr_format) return pvr_format->pbe_accum_format; return PVR_PBE_ACCUM_FORMAT_INVALID; } uint32_t pvr_get_pbe_accum_format_size_in_bytes(VkFormat vk_format) { enum pvr_pbe_accum_format pbe_accum_format; uint32_t nr_components; pbe_accum_format = pvr_get_pbe_accum_format(vk_format); nr_components = vk_format_get_nr_components(vk_format); switch (pbe_accum_format) { case PVR_PBE_ACCUM_FORMAT_U8: case PVR_PBE_ACCUM_FORMAT_S8: case PVR_PBE_ACCUM_FORMAT_UINT8: case PVR_PBE_ACCUM_FORMAT_SINT8: return nr_components * 1; case PVR_PBE_ACCUM_FORMAT_U16: case PVR_PBE_ACCUM_FORMAT_S16: case PVR_PBE_ACCUM_FORMAT_F16: case PVR_PBE_ACCUM_FORMAT_UINT16: case PVR_PBE_ACCUM_FORMAT_SINT16: return nr_components * 2; case PVR_PBE_ACCUM_FORMAT_F32: case PVR_PBE_ACCUM_FORMAT_UINT32: case PVR_PBE_ACCUM_FORMAT_SINT32: case PVR_PBE_ACCUM_FORMAT_UINT32_MEDP: case PVR_PBE_ACCUM_FORMAT_SINT32_MEDP: case PVR_PBE_ACCUM_FORMAT_U1010102: case PVR_PBE_ACCUM_FORMAT_U24: return nr_components * 4; default: unreachable("Unknown pbe accum format. Implementation error"); } } /** * \brief Packs VK_FORMAT_A2B10G10R10_UINT_PACK32 or A2R10G10B10. * * \param[in] values RGBA ordered values to pack. * \param[in] swap_rb If true pack A2B10G10R10 else pack A2R10G10B10. */ static inline uint32_t pvr_pack_a2x10y10z10_uint( const uint32_t values[static const PVR_CLEAR_COLOR_ARRAY_SIZE], bool swap_rb) { const uint32_t blue = swap_rb ? values[0] : values[2]; const uint32_t red = swap_rb ? values[2] : values[0]; uint32_t packed_val; /* The user is allowed to specify a value which is over the range * representable for a component so we need to AND before packing. */ packed_val = util_bitpack_uint(values[3] & BITSET_MASK(2), 30, 31); packed_val |= util_bitpack_uint(red & BITSET_MASK(10), 20, 29); packed_val |= util_bitpack_uint(values[1] & BITSET_MASK(10), 10, 19); packed_val |= util_bitpack_uint(blue & BITSET_MASK(10), 0, 9); return packed_val; } #define APPLY_FUNC_4V(DST, FUNC, ARG) \ ASSIGN_4V(DST, FUNC(ARG[0]), FUNC(ARG[1]), FUNC(ARG[2]), FUNC(ARG[3])) #define f32_to_unorm8(val) _mesa_float_to_unorm(val, 8) #define f32_to_unorm16(val) _mesa_float_to_unorm(val, 16) #define f32_to_snorm8(val) _mesa_float_to_snorm(val, 8) #define f32_to_snorm16(val) _mesa_float_to_snorm(val, 16) #define f32_to_f16(val) _mesa_float_to_half(val) /** * \brief Packs clear color input values into the appropriate accum format. * * The input value array must have zeroed out elements for components not * present in the format. E.g. R8G8B8 has no A component so [3] must be 0. * * Note: the output is not swizzled so it's packed in RGBA order no matter the * component order specified by the vk_format. * * \param[in] vk_format Vulkan format of the input color value. * \param[in] value Unpacked RGBA input color values. * \param[out] packed_out Accum format packed values. */ void pvr_get_hw_clear_color( VkFormat vk_format, VkClearColorValue value, uint32_t packed_out[static const PVR_CLEAR_COLOR_ARRAY_SIZE]) { union { uint32_t u32[PVR_CLEAR_COLOR_ARRAY_SIZE]; int32_t i32[PVR_CLEAR_COLOR_ARRAY_SIZE]; uint16_t u16[PVR_CLEAR_COLOR_ARRAY_SIZE * 2]; int16_t i16[PVR_CLEAR_COLOR_ARRAY_SIZE * 2]; uint8_t u8[PVR_CLEAR_COLOR_ARRAY_SIZE * 4]; int8_t i8[PVR_CLEAR_COLOR_ARRAY_SIZE * 4]; } packed_val = { 0 }; const enum pvr_pbe_accum_format pbe_accum_format = pvr_get_pbe_accum_format(vk_format); static_assert(ARRAY_SIZE(value.uint32) == PVR_CLEAR_COLOR_ARRAY_SIZE, "Size mismatch. Unknown/unhandled extra values."); /* TODO: Right now we pack all RGBA values. Would we get any benefit in * packing just the components required by the format? */ switch (pbe_accum_format) { case PVR_PBE_ACCUM_FORMAT_U8: APPLY_FUNC_4V(packed_val.u8, f32_to_unorm8, value.float32); break; case PVR_PBE_ACCUM_FORMAT_S8: APPLY_FUNC_4V(packed_val.i8, f32_to_snorm8, value.float32); break; case PVR_PBE_ACCUM_FORMAT_UINT8: COPY_4V(packed_val.u8, value.uint32); break; case PVR_PBE_ACCUM_FORMAT_SINT8: COPY_4V(packed_val.i8, value.int32); break; case PVR_PBE_ACCUM_FORMAT_U16: APPLY_FUNC_4V(packed_val.u16, f32_to_unorm16, value.float32); break; case PVR_PBE_ACCUM_FORMAT_S16: APPLY_FUNC_4V(packed_val.i16, f32_to_snorm16, value.float32); break; case PVR_PBE_ACCUM_FORMAT_F16: APPLY_FUNC_4V(packed_val.u16, f32_to_f16, value.float32); break; case PVR_PBE_ACCUM_FORMAT_UINT16: COPY_4V(packed_val.u16, value.uint32); break; case PVR_PBE_ACCUM_FORMAT_SINT16: COPY_4V(packed_val.i16, value.int32); break; case PVR_PBE_ACCUM_FORMAT_F32: COPY_4V(packed_val.u32, value.uint32); break; case PVR_PBE_ACCUM_FORMAT_UINT32: /* The PBE can't pack 1010102 UINT. */ if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32) { packed_val.u32[0] = pvr_pack_a2x10y10z10_uint(value.uint32, true); break; } else if (vk_format == VK_FORMAT_A2R10G10B10_UINT_PACK32) { packed_val.u32[0] = pvr_pack_a2x10y10z10_uint(value.uint32, false); break; } COPY_4V(packed_val.u32, value.uint32); break; case PVR_PBE_ACCUM_FORMAT_SINT32: COPY_4V(packed_val.i32, value.int32); break; default: unreachable("Packing not supported for the accum format."); break; } COPY_4V(packed_out, packed_val.u32); } #undef APPLY_FUNC_4V #undef f32_to_unorm8 #undef f32_to_unorm16 #undef f32_to_snorm8 #undef f32_to_snorm16 #undef f32_to_f16 /* TODO: This currently only sets up Vulkan 1.0 flags. */ static VkFormatFeatureFlags2 pvr_get_image_format_features2(const struct pvr_format *pvr_format, VkImageTiling vk_tiling) { VkFormatFeatureFlags flags = 0; VkFormat vk_format; if (!pvr_format) return 0; assert(pvr_format->supported); vk_format = pvr_format->vk_format; if (pvr_get_tex_format(vk_format) != ROGUE_TEXSTATE_FORMAT_INVALID) { if (vk_tiling == VK_IMAGE_TILING_OPTIMAL) { const uint32_t first_component_size = vk_format_get_component_bits(vk_format, UTIL_FORMAT_COLORSPACE_RGB, 0); flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_BLIT_SRC_BIT; if (!vk_format_is_int(vk_format) && !vk_format_is_depth_or_stencil(vk_format) && (first_component_size < 32 || vk_format_is_block_compressed(vk_format))) { flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT; } } else if (!vk_format_is_block_compressed(vk_format)) { flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_BLIT_SRC_BIT; } } if (pvr_get_pbe_accum_format(vk_format) != PVR_PBE_ACCUM_FORMAT_INVALID) { if (vk_format_is_color(vk_format)) { flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT; if (!vk_format_is_int(vk_format)) { flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT; } } } else if (vk_format_is_depth_or_stencil(vk_format)) { flags |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT; } if (vk_tiling == VK_IMAGE_TILING_OPTIMAL) { if (vk_format_is_color(vk_format) && vk_format_get_nr_components(vk_format) == 1 && vk_format_get_blocksizebits(vk_format) == 32 && vk_format_is_int(vk_format)) { flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT; } switch (vk_format) { case VK_FORMAT_R8_UNORM: case VK_FORMAT_R8_SNORM: case VK_FORMAT_R8_UINT: case VK_FORMAT_R8_SINT: case VK_FORMAT_R8G8_UNORM: case VK_FORMAT_R8G8_SNORM: case VK_FORMAT_R8G8_UINT: case VK_FORMAT_R8G8_SINT: case VK_FORMAT_R8G8B8A8_UNORM: case VK_FORMAT_R8G8B8A8_SNORM: case VK_FORMAT_R8G8B8A8_UINT: case VK_FORMAT_R8G8B8A8_SINT: case VK_FORMAT_A2B10G10R10_UNORM_PACK32: case VK_FORMAT_A2B10G10R10_UINT_PACK32: case VK_FORMAT_R16_UNORM: case VK_FORMAT_R16_SNORM: case VK_FORMAT_R16_UINT: case VK_FORMAT_R16_SINT: case VK_FORMAT_R16_SFLOAT: case VK_FORMAT_R16G16_UNORM: case VK_FORMAT_R16G16_SNORM: case VK_FORMAT_R16G16_UINT: case VK_FORMAT_R16G16_SINT: case VK_FORMAT_R16G16_SFLOAT: case VK_FORMAT_R16G16B16A16_UNORM: case VK_FORMAT_R16G16B16A16_SNORM: case VK_FORMAT_R16G16B16A16_UINT: case VK_FORMAT_R16G16B16A16_SINT: case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32G32_UINT: case VK_FORMAT_R32G32_SINT: case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_B10G11R11_UFLOAT_PACK32: flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT; break; default: break; } } return flags; } const uint8_t *pvr_get_format_swizzle(VkFormat vk_format) { const struct util_format_description *vf = vk_format_description(vk_format); return vf->swizzle; } /* TODO: This currently only sets up Vulkan 1.0 flags. */ static VkFormatFeatureFlags2 pvr_get_buffer_format_features2(const struct pvr_format *pvr_format) { const struct util_format_description *desc; VkFormatFeatureFlags2 flags = 0; VkFormat vk_format; if (!pvr_format) return 0; assert(pvr_format->supported); vk_format = pvr_format->vk_format; if (!vk_format_is_color(vk_format)) return 0; desc = vk_format_description(vk_format); if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB) { flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT; if (desc->is_array && vk_format != VK_FORMAT_R32G32B32_UINT && vk_format != VK_FORMAT_R32G32B32_SINT && vk_format != VK_FORMAT_R32G32B32_SFLOAT) { flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT; } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32) { flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT; } } else if (vk_format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) { flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT; } if (vk_format_is_color(vk_format) && vk_format_get_nr_components(vk_format) == 1 && vk_format_get_blocksizebits(vk_format) == 32 && vk_format_is_int(vk_format)) { flags |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT; } switch (vk_format) { case VK_FORMAT_R8G8B8A8_UNORM: case VK_FORMAT_R8G8B8A8_SNORM: case VK_FORMAT_R8G8B8A8_UINT: case VK_FORMAT_R8G8B8A8_SINT: case VK_FORMAT_A8B8G8R8_UNORM_PACK32: case VK_FORMAT_A8B8G8R8_SNORM_PACK32: case VK_FORMAT_A8B8G8R8_UINT_PACK32: case VK_FORMAT_A8B8G8R8_SINT_PACK32: case VK_FORMAT_R16G16B16A16_UINT: case VK_FORMAT_R16G16B16A16_SINT: case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32G32_UINT: case VK_FORMAT_R32G32_SINT: case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32B32A32_UINT: case VK_FORMAT_R32G32B32A32_SINT: case VK_FORMAT_R32G32B32A32_SFLOAT: flags |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT; break; case VK_FORMAT_B10G11R11_UFLOAT_PACK32: flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT; break; default: break; } return flags; } void pvr_GetPhysicalDeviceFormatProperties2( VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2 *pFormatProperties) { const struct pvr_format *pvr_format = pvr_get_format(format); VkFormatFeatureFlags2 linear2, optimal2, buffer2; linear2 = pvr_get_image_format_features2(pvr_format, VK_IMAGE_TILING_LINEAR); optimal2 = pvr_get_image_format_features2(pvr_format, VK_IMAGE_TILING_OPTIMAL); buffer2 = pvr_get_buffer_format_features2(pvr_format); pFormatProperties->formatProperties = (VkFormatProperties){ .linearTilingFeatures = vk_format_features2_to_features(linear2), .optimalTilingFeatures = vk_format_features2_to_features(optimal2), .bufferFeatures = vk_format_features2_to_features(buffer2), }; vk_foreach_struct (ext, pFormatProperties->pNext) { pvr_debug_ignored_stype(ext->sType); } } static VkResult pvr_get_image_format_properties(struct pvr_physical_device *pdevice, const VkPhysicalDeviceImageFormatInfo2 *info, VkImageFormatProperties *pImageFormatProperties) { /* Input attachments aren't rendered but they must have the same size * restrictions as any framebuffer attachment. */ const VkImageUsageFlags render_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; const struct pvr_format *pvr_format = pvr_get_format(info->format); VkFormatFeatureFlags2 tiling_features2; VkResult result; if (!pvr_format) { result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); goto err_unsupported_format; } tiling_features2 = pvr_get_image_format_features2(pvr_format, info->tiling); if (tiling_features2 == 0) { result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); goto err_unsupported_format; } /* If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set, the driver can't decide if a * specific format isn't supported based on the usage. */ if ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) == 0 && info->usage & (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && pvr_format->pbe_accum_format == PVR_PBE_ACCUM_FORMAT_INVALID) { result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); goto err_unsupported_format; } if (info->type == VK_IMAGE_TYPE_3D) { const VkImageUsageFlags transfer_usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; /* We don't support 3D depth/stencil images. */ if (tiling_features2 & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT) { result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); goto err_unsupported_format; } /* Linear tiled 3D images may only be used for transfer or blit * operations. */ if (info->tiling == VK_IMAGE_TILING_LINEAR && info->usage & ~transfer_usage) { result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); goto err_unsupported_format; } } if (info->usage & render_usage) { const uint32_t max_render_size = rogue_get_render_size_max(&pdevice->dev_info); pImageFormatProperties->maxExtent.width = max_render_size; pImageFormatProperties->maxExtent.height = max_render_size; pImageFormatProperties->maxExtent.depth = PVR_MAX_TEXTURE_EXTENT_Z; } else { const uint32_t max_texture_extent_xy = PVRX(TEXSTATE_IMAGE_WORD0_WIDTH_MAX_SIZE) + 1U; pImageFormatProperties->maxExtent.width = max_texture_extent_xy; pImageFormatProperties->maxExtent.height = max_texture_extent_xy; pImageFormatProperties->maxExtent.depth = PVR_MAX_TEXTURE_EXTENT_Z; } if (info->tiling == VK_IMAGE_TILING_LINEAR) { pImageFormatProperties->maxExtent.depth = 1; pImageFormatProperties->maxArrayLayers = 1; pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; } else { /* Default value is the minimum value found in all existing cores. */ const uint32_t max_multisample = PVR_GET_FEATURE_VALUE(&pdevice->dev_info, max_multisample, 4); const uint32_t max_sample_bits = ((max_multisample << 1) - 1); pImageFormatProperties->maxArrayLayers = PVR_MAX_ARRAY_LAYERS; pImageFormatProperties->sampleCounts = max_sample_bits; } if (!(tiling_features2 & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT || tiling_features2 & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) { pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; } switch (info->type) { case VK_IMAGE_TYPE_1D: pImageFormatProperties->maxExtent.height = 1; pImageFormatProperties->maxExtent.depth = 1; pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; break; case VK_IMAGE_TYPE_2D: pImageFormatProperties->maxExtent.depth = 1; /* If a 2D image is created to be used in a cube map, then the sample * count must be restricted to 1 sample. */ if (info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; break; case VK_IMAGE_TYPE_3D: pImageFormatProperties->maxArrayLayers = 1; pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT; break; default: unreachable("Invalid image type."); } /* The spec says maxMipLevels may be 1 when tiling is VK_IMAGE_TILING_LINEAR * or VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, so for simplicity don't * support miplevels for these tilings. */ if (info->tiling == VK_IMAGE_TILING_LINEAR) { pImageFormatProperties->maxMipLevels = 1; } else { const uint32_t max_size = MAX3(pImageFormatProperties->maxExtent.width, pImageFormatProperties->maxExtent.height, pImageFormatProperties->maxExtent.depth); pImageFormatProperties->maxMipLevels = util_logbase2(max_size) + 1U; } /* Return 2GB (minimum required from spec). * * From the Vulkan spec: * * maxResourceSize is an upper bound on the total image size in bytes, * inclusive of all image subresources. Implementations may have an * address space limit on total size of a resource, which is advertised by * this property. maxResourceSize must be at least 2^31. */ pImageFormatProperties->maxResourceSize = 2ULL * 1024 * 1024 * 1024; return VK_SUCCESS; err_unsupported_format: /* From the Vulkan 1.0.42 spec: * * If the combination of parameters to * vkGetPhysicalDeviceImageFormatProperties2 is not supported by the * implementation for use in vkCreateImage, then all members of * imageFormatProperties will be filled with zero. */ *pImageFormatProperties = (VkImageFormatProperties){ 0 }; return result; } /* FIXME: Should this be returning VK_ERROR_FORMAT_NOT_SUPPORTED when tiling is * linear and the image type is 3D or flags contains * VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT? This should avoid well behaved apps * attempting to create invalid image views, as pvr_pack_tex_state() will return * VK_ERROR_FORMAT_NOT_SUPPORTED in these cases. */ VkResult pvr_GetPhysicalDeviceImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) { const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); VkExternalImageFormatProperties *external_props = NULL; VkResult result; result = pvr_get_image_format_properties( pdevice, pImageFormatInfo, &pImageFormatProperties->imageFormatProperties); if (result != VK_SUCCESS) return result; /* Extract input structs */ vk_foreach_struct_const (ext, pImageFormatInfo->pNext) { switch (ext->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: external_info = (const void *)ext; break; default: pvr_debug_ignored_stype(ext->sType); break; } } /* Extract output structs */ vk_foreach_struct (ext, pImageFormatProperties->pNext) { switch (ext->sType) { case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: external_props = (void *)ext; break; default: pvr_debug_ignored_stype(ext->sType); break; } } /* From the Vulkan 1.0.42 spec: * * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will * behave as if VkPhysicalDeviceExternalImageFormatInfo was not * present and VkExternalImageFormatProperties will be ignored. */ if (external_info && external_info->handleType != 0) { switch (external_info->handleType) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: if (!external_props) break; external_props->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; external_props->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; external_props->externalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; break; default: return vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED); } } return VK_SUCCESS; } void pvr_GetPhysicalDeviceSparseImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t *pNumProperties, VkSparseImageFormatProperties *pProperties) { /* Sparse images are not yet supported. */ *pNumProperties = 0; } void pvr_GetPhysicalDeviceSparseImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties) { /* Sparse images are not yet supported. */ *pPropertyCount = 0; } void pvr_GetPhysicalDeviceExternalBufferProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) { /* The Vulkan 1.0.42 spec says "handleType must be a valid * VkExternalMemoryHandleTypeFlagBits value" in * VkPhysicalDeviceExternalBufferInfo. This differs from * VkPhysicalDeviceExternalImageFormatInfo, which surprisingly permits * handleType == 0. */ assert(pExternalBufferInfo->handleType != 0); /* All of the current flags are for sparse which we don't support. */ if (pExternalBufferInfo->flags) goto unsupported; switch (pExternalBufferInfo->handleType) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: /* clang-format off */ pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; /* clang-format on */ return; default: break; } unsupported: /* From the Vulkan 1.1.113 spec: * * compatibleHandleTypes must include at least handleType. */ pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties){ .compatibleHandleTypes = pExternalBufferInfo->handleType, }; } bool pvr_format_is_pbe_downscalable(VkFormat vk_format) { if (vk_format_is_int(vk_format)) { /* PBE downscale behavior for integer formats does not match Vulkan * spec. Vulkan requires a single sample to be chosen instead of * taking the average sample color. */ return false; } switch (pvr_get_pbe_packmode(vk_format)) { default: return true; case ROGUE_PBESTATE_PACKMODE_U16U16U16U16: case ROGUE_PBESTATE_PACKMODE_S16S16S16S16: case ROGUE_PBESTATE_PACKMODE_U32U32U32U32: case ROGUE_PBESTATE_PACKMODE_S32S32S32S32: case ROGUE_PBESTATE_PACKMODE_F32F32F32F32: case ROGUE_PBESTATE_PACKMODE_U16U16U16: case ROGUE_PBESTATE_PACKMODE_S16S16S16: case ROGUE_PBESTATE_PACKMODE_U32U32U32: case ROGUE_PBESTATE_PACKMODE_S32S32S32: case ROGUE_PBESTATE_PACKMODE_F32F32F32: case ROGUE_PBESTATE_PACKMODE_U16U16: case ROGUE_PBESTATE_PACKMODE_S16S16: case ROGUE_PBESTATE_PACKMODE_U32U32: case ROGUE_PBESTATE_PACKMODE_S32S32: case ROGUE_PBESTATE_PACKMODE_F32F32: case ROGUE_PBESTATE_PACKMODE_U24ST8: case ROGUE_PBESTATE_PACKMODE_ST8U24: case ROGUE_PBESTATE_PACKMODE_U16: case ROGUE_PBESTATE_PACKMODE_S16: case ROGUE_PBESTATE_PACKMODE_U32: case ROGUE_PBESTATE_PACKMODE_S32: case ROGUE_PBESTATE_PACKMODE_F32: case ROGUE_PBESTATE_PACKMODE_X24U8F32: case ROGUE_PBESTATE_PACKMODE_X24X8F32: case ROGUE_PBESTATE_PACKMODE_X24G8X32: case ROGUE_PBESTATE_PACKMODE_X8U24: case ROGUE_PBESTATE_PACKMODE_U8X24: case ROGUE_PBESTATE_PACKMODE_PBYTE: case ROGUE_PBESTATE_PACKMODE_PWORD: case ROGUE_PBESTATE_PACKMODE_INVALID: return false; } } uint32_t pvr_pbe_pixel_num_loads(enum pvr_transfer_pbe_pixel_src pbe_format, uint32_t alpha_type) { switch (alpha_type) { default: case PVR_ALPHA_NONE: break; case PVR_ALPHA_SOURCE: case PVR_ALPHA_PREMUL_SOURCE: case PVR_ALPHA_PREMUL_SOURCE_WITH_GLOBAL: case PVR_ALPHA_GLOBAL: return 2U; } switch (pbe_format) { case PVR_TRANSFER_PBE_PIXEL_SRC_UU8888: case PVR_TRANSFER_PBE_PIXEL_SRC_US8888: case PVR_TRANSFER_PBE_PIXEL_SRC_UU16U16: case PVR_TRANSFER_PBE_PIXEL_SRC_US16S16: case PVR_TRANSFER_PBE_PIXEL_SRC_SU8888: case PVR_TRANSFER_PBE_PIXEL_SRC_SS8888: case PVR_TRANSFER_PBE_PIXEL_SRC_SU16U16: case PVR_TRANSFER_PBE_PIXEL_SRC_SS16S16: case PVR_TRANSFER_PBE_PIXEL_SRC_UU1010102: case PVR_TRANSFER_PBE_PIXEL_SRC_SU1010102: case PVR_TRANSFER_PBE_PIXEL_SRC_RBSWAP_UU1010102: case PVR_TRANSFER_PBE_PIXEL_SRC_RBSWAP_SU1010102: case PVR_TRANSFER_PBE_PIXEL_SRC_SU32U32: case PVR_TRANSFER_PBE_PIXEL_SRC_S4XU32: case PVR_TRANSFER_PBE_PIXEL_SRC_US32S32: case PVR_TRANSFER_PBE_PIXEL_SRC_U4XS32: case PVR_TRANSFER_PBE_PIXEL_SRC_F16F16: case PVR_TRANSFER_PBE_PIXEL_SRC_U16NORM: case PVR_TRANSFER_PBE_PIXEL_SRC_S16NORM: case PVR_TRANSFER_PBE_PIXEL_SRC_F32: case PVR_TRANSFER_PBE_PIXEL_SRC_F32X2: case PVR_TRANSFER_PBE_PIXEL_SRC_F32X4: case PVR_TRANSFER_PBE_PIXEL_SRC_RAW32: case PVR_TRANSFER_PBE_PIXEL_SRC_RAW64: case PVR_TRANSFER_PBE_PIXEL_SRC_RAW128: case PVR_TRANSFER_PBE_PIXEL_SRC_F16_U8: case PVR_TRANSFER_PBE_PIXEL_SRC_SWAP_LMSB: case PVR_TRANSFER_PBE_PIXEL_SRC_MOV_BY45: case PVR_TRANSFER_PBE_PIXEL_SRC_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_S8D24: case PVR_TRANSFER_PBE_PIXEL_SRC_D32S8: case PVR_TRANSFER_PBE_PIXEL_SRC_CONV_D24_D32: case PVR_TRANSFER_PBE_PIXEL_SRC_CONV_D32U_D32F: case PVR_TRANSFER_PBE_PIXEL_SRC_CONV_D32_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_CONV_S8D24_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_SMRG_S8_D32S8: case PVR_TRANSFER_PBE_PIXEL_SRC_SMRG_D24S8_D32S8: case PVR_TRANSFER_PBE_PIXEL_SRC_SMRG_D32S8_D32S8: case PVR_TRANSFER_PBE_PIXEL_SRC_DMRG_D32S8_D32S8: case PVR_TRANSFER_PBE_PIXEL_SRC_SMRG_S8_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_SMRG_D24S8_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_DMRG_D24S8_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_DMRG_D32_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_DMRG_D32U_D24S8: case PVR_TRANSFER_PBE_PIXEL_SRC_Y_UV_INTERLEAVED: case PVR_TRANSFER_PBE_PIXEL_SRC_Y_U_V: case PVR_TRANSFER_PBE_PIXEL_SRC_YUV_PACKED: case PVR_TRANSFER_PBE_PIXEL_SRC_YVU_PACKED: return 1U; case PVR_TRANSFER_PBE_PIXEL_SRC_NUM: default: return 0U; } }