diff --git a/src/broadcom/vulkan/v3dv_formats.c b/src/broadcom/vulkan/v3dv_formats.c index 373306117c3..a7bf14746bb 100644 --- a/src/broadcom/vulkan/v3dv_formats.c +++ b/src/broadcom/vulkan/v3dv_formats.c @@ -372,6 +372,35 @@ v3dv_tfu_supports_tex_format(const struct v3d_device_info *devinfo, } } +/* Some cases of transfer operations are raw data copies that don't depend + * on the semantics of the pixel format (no pixel format conversions are + * involved). In these cases, it is safe to choose any format supported by + * the TFU so long as it has the same texel size, which allows us to use the + * TFU paths with formats that are not TFU supported otherwise. + */ +const struct v3dv_format * +v3dv_get_compatible_tfu_format(const struct v3d_device_info *devinfo, + uint32_t bpp, + VkFormat *out_vk_format) +{ + VkFormat vk_format; + switch (bpp) { + case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break; + case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break; + case 4: vk_format = VK_FORMAT_R32_SFLOAT; break; + case 2: vk_format = VK_FORMAT_R16_SFLOAT; break; + case 1: vk_format = VK_FORMAT_R8_UNORM; break; + default: unreachable("unsupported format bit-size"); break; + }; + + if (out_vk_format) + *out_vk_format = vk_format; + + const struct v3dv_format *format = v3dv_get_format(vk_format); + assert(v3dv_tfu_supports_tex_format(devinfo, format->tex_type)); + + return format; +} static bool format_supports_blending(const struct v3dv_format *format) diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c index 09a106dc273..9aba1a9ed25 100644 --- a/src/broadcom/vulkan/v3dv_meta_copy.c +++ b/src/broadcom/vulkan/v3dv_meta_copy.c @@ -1605,18 +1605,9 @@ copy_image_tfu(struct v3dv_cmd_buffer *cmd_buffer, * to use compatible formats that are supported with the TFU unit. */ assert(dst->cpp == src->cpp); - VkFormat vk_format; - switch (dst->cpp) { - case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break; - case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break; - case 4: vk_format = VK_FORMAT_R32_SFLOAT; break; - case 2: vk_format = VK_FORMAT_R16_SFLOAT; break; - case 1: vk_format = VK_FORMAT_R8_UNORM; break; - default: unreachable("unsupported format bit-size"); break; - }; - const struct v3dv_format *format = v3dv_get_format(vk_format); - assert(v3dv_tfu_supports_tex_format(&cmd_buffer->device->devinfo, - format->tex_type)); + const struct v3dv_format *format = + v3dv_get_compatible_tfu_format(&cmd_buffer->device->devinfo, + dst->cpp, NULL); /* Emit a TFU job for each layer to blit */ const uint32_t layer_count = dst->type != VK_IMAGE_TYPE_3D ? @@ -2620,18 +2611,9 @@ copy_buffer_to_image_tfu(struct v3dv_cmd_buffer *cmd_buffer, * the image's format and choose a compatible TFU format for the image * texel size instead, which expands the list of formats we can handle here. */ - VkFormat vk_format; - switch (image->cpp) { - case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break; - case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break; - case 4: vk_format = VK_FORMAT_R32_SFLOAT; break; - case 2: vk_format = VK_FORMAT_R16_SFLOAT; break; - case 1: vk_format = VK_FORMAT_R8_UNORM; break; - default: unreachable("unsupported format bit-size"); break; - }; - const struct v3dv_format *format = v3dv_get_format(vk_format); - assert(v3dv_tfu_supports_tex_format(&cmd_buffer->device->devinfo, - format->tex_type)); + const struct v3dv_format *format = + v3dv_get_compatible_tfu_format(&cmd_buffer->device->devinfo, + image->cpp, NULL); const uint32_t mip_level = region->imageSubresource.mipLevel; const struct v3d_resource_slice *slice = &image->slices[mip_level]; @@ -4079,18 +4061,9 @@ blit_tfu(struct v3dv_cmd_buffer *cmd_buffer, * conversions and we can rewrite the format to use one that is TFU * compatible based on its texel size. */ - VkFormat vk_format; - switch (dst->cpp) { - case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break; - case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break; - case 4: vk_format = VK_FORMAT_R32_SFLOAT; break; - case 2: vk_format = VK_FORMAT_R16_SFLOAT; break; - case 1: vk_format = VK_FORMAT_R8_UNORM; break; - default: unreachable("unsupported format bit-size"); break; - }; - const struct v3dv_format *format = v3dv_get_format(vk_format); - assert(v3dv_tfu_supports_tex_format(&cmd_buffer->device->devinfo, - format->tex_type)); + const struct v3dv_format *format = + v3dv_get_compatible_tfu_format(&cmd_buffer->device->devinfo, + dst->cpp, NULL); /* Emit a TFU job for each layer to blit */ assert(region->dstSubresource.layerCount == diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index a5cb135b42a..a88a8872095 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -1845,6 +1845,9 @@ void v3dv_get_internal_type_bpp_for_output_format(uint32_t format, uint32_t *typ uint8_t v3dv_get_tex_return_size(const struct v3dv_format *vf, bool compare_enable); bool v3dv_tfu_supports_tex_format(const struct v3d_device_info *devinfo, uint32_t tex_format); +const struct v3dv_format * +v3dv_get_compatible_tfu_format(const struct v3d_device_info *devinfo, + uint32_t bpp, VkFormat *out_vk_format); bool v3dv_buffer_format_supports_features(VkFormat vk_format, VkFormatFeatureFlags features); bool v3dv_format_supports_tlb_resolve(const struct v3dv_format *format);