diff --git a/src/panfrost/vulkan/panvk_host_copy.c b/src/panfrost/vulkan/panvk_host_copy.c index 5df6d068b64..e3e5b10a3d1 100644 --- a/src/panfrost/vulkan/panvk_host_copy.c +++ b/src/panfrost/vulkan/panvk_host_copy.c @@ -6,6 +6,7 @@ #include "panvk_device.h" #include "panvk_device_memory.h" #include "panvk_entrypoints.h" +#include "pan_tiling.h" #include "panvk_image.h" #include "vk_object.h" @@ -31,8 +32,10 @@ panvk_copy_image_to_from_memory(struct image_params img, VkExtent3D extent, VkHostImageCopyFlags flags, bool memory_to_img) { - /* We don't support copying tiled images yet */ - assert(img.img->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR); + /* AFBC should be disabled on images used for host image copy */ + assert(img.img->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR || + img.img->vk.drm_format_mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED); + bool linear = img.img->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR; /* We don't have to care about the multisample layout for image/memory * copies. From the Vulkan 1.4.317 spec: @@ -61,7 +64,8 @@ panvk_copy_image_to_from_memory(struct image_params img, VkFormat vkfmt = vk_format_get_aspect_format(img.img->vk.format, img.subres.aspectMask); - const struct util_format_description *fmt = vk_format_description(vkfmt); + enum pipe_format pfmt = vk_format_to_pipe_format(vkfmt); + const struct util_format_description *fmt = util_format_description(pfmt); unsigned block_width_px = fmt->block.width; unsigned block_height_px = fmt->block.height; @@ -98,20 +102,37 @@ panvk_copy_image_to_from_memory(struct image_params img, * layout, image_stride_B applies to both */ void *mem_depth_ptr = mem_layer_ptr + z * mem.layout.image_stride_B; - for (unsigned y = 0; y < extent.height; y += block_height_px) { - unsigned img_y_bl = (y + img.offset.y) / block_height_px; - unsigned mem_y_bl = y / block_height_px; - unsigned img_x_bl = img.offset.x / block_width_px; - void *img_row_ptr = img_depth_ptr + - img_y_bl * slice_layout->tiled_or_linear.row_stride_B + - img_x_bl * block_size_B; - void *mem_row_ptr = mem_depth_ptr + - mem_y_bl * mem.layout.row_stride_B; + if (linear) { + for (unsigned y = 0; y < extent.height; y += block_height_px) { + unsigned img_y_bl = (y + img.offset.y) / block_height_px; + unsigned mem_y_bl = y / block_height_px; + unsigned img_x_bl = img.offset.x / block_width_px; + void *img_row_ptr = img_depth_ptr + + img_y_bl * slice_layout->tiled_or_linear.row_stride_B + + img_x_bl * block_size_B; + void *mem_row_ptr = mem_depth_ptr + + mem_y_bl * mem.layout.row_stride_B; + if (memory_to_img) + memcpy(img_row_ptr, mem_row_ptr, row_size_B); + else + memcpy(mem_row_ptr, img_row_ptr, row_size_B); + } + } else { if (memory_to_img) - memcpy(img_row_ptr, mem_row_ptr, row_size_B); + pan_store_tiled_image( + img_depth_ptr, mem_depth_ptr, + img.offset.x, img.offset.y, extent.width, extent.height, + slice_layout->tiled_or_linear.row_stride_B, + mem.layout.row_stride_B, + pfmt); else - memcpy(mem_row_ptr, img_row_ptr, row_size_B); + pan_load_tiled_image( + mem_depth_ptr, img_depth_ptr, + img.offset.x, img.offset.y, extent.width, extent.height, + mem.layout.row_stride_B, + slice_layout->tiled_or_linear.row_stride_B, + pfmt); } } } @@ -212,9 +233,13 @@ panvk_copy_image_to_image(struct panvk_image *dst, void *dst_cpu, const VkImageCopy2 *region, VkHostImageCopyFlags flags) { - /* We don't support copying tiled images yet */ - assert(src->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR); - assert(dst->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR); + /* AFBC should be disabled on images used for host image copy */ + assert(src->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR || + src->vk.drm_format_mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED); + assert(dst->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR || + dst->vk.drm_format_mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED); + bool src_linear = src->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR; + bool dst_linear = dst->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR; VkImageSubresourceLayers src_subres = region->srcSubresource; VkImageSubresourceLayers dst_subres = region->dstSubresource; @@ -241,10 +266,12 @@ panvk_copy_image_to_image(struct panvk_image *dst, void *dst_cpu, vk_format_get_aspect_format(src->vk.format, src_subres.aspectMask); VkFormat dst_vkfmt = vk_format_get_aspect_format(dst->vk.format, dst_subres.aspectMask); + enum pipe_format src_pfmt = vk_format_to_pipe_format(src_vkfmt); + enum pipe_format dst_pfmt = vk_format_to_pipe_format(dst_vkfmt); const struct util_format_description *src_fmt = - vk_format_description(src_vkfmt); + util_format_description(src_pfmt); const struct util_format_description *dst_fmt = - vk_format_description(dst_vkfmt); + util_format_description(dst_pfmt); unsigned block_width_px = src_fmt->block.width; unsigned block_height_px = src_fmt->block.height; @@ -300,19 +327,55 @@ panvk_copy_image_to_image(struct panvk_image *dst, void *dst_cpu, void *dst_depth_ptr = dst_layer_ptr + dst_z * dst_slice_layout->tiled_or_linear.surface_stride_B; - for (unsigned y = 0; y < region->extent.height; y += block_height_px) { - unsigned src_y_bl = (y + region->srcOffset.y) / block_height_px; - unsigned dst_y_bl = (y + region->dstOffset.y) / block_height_px; + if (src_linear && dst_linear) { + for (unsigned y = 0; y < region->extent.height; + y += block_height_px) { + unsigned src_y_bl = (y + region->srcOffset.y) / block_height_px; + unsigned dst_y_bl = (y + region->dstOffset.y) / block_height_px; + unsigned src_x_bl = region->srcOffset.x / block_width_px; + unsigned dst_x_bl = region->dstOffset.x / block_width_px; + void *src_row_ptr = src_depth_ptr + + src_y_bl * src_slice_layout->tiled_or_linear.row_stride_B + + src_x_bl * block_size_B; + void *dst_row_ptr = dst_depth_ptr + + dst_y_bl * dst_slice_layout->tiled_or_linear.row_stride_B + + dst_x_bl * block_size_B; + + memcpy(dst_row_ptr, src_row_ptr, row_size_B); + } + } else if (src_linear && !dst_linear) { + unsigned src_y_bl = region->srcOffset.y / block_height_px; unsigned src_x_bl = region->srcOffset.x / block_width_px; - unsigned dst_x_bl = region->dstOffset.x / block_width_px; void *src_row_ptr = src_depth_ptr + src_y_bl * src_slice_layout->tiled_or_linear.row_stride_B + src_x_bl * block_size_B; + pan_store_tiled_image( + dst_depth_ptr, src_row_ptr, + region->dstOffset.x, region->dstOffset.y, + region->extent.width, region->extent.height, + dst_slice_layout->tiled_or_linear.row_stride_B, + src_slice_layout->tiled_or_linear.row_stride_B, + src_pfmt); + } else if (!src_linear && dst_linear) { + unsigned dst_y_bl = region->dstOffset.y / block_height_px; + unsigned dst_x_bl = region->dstOffset.x / block_width_px; void *dst_row_ptr = dst_depth_ptr + dst_y_bl * dst_slice_layout->tiled_or_linear.row_stride_B + dst_x_bl * block_size_B; - - memcpy(dst_row_ptr, src_row_ptr, row_size_B); + pan_load_tiled_image( + dst_row_ptr, src_depth_ptr, + region->srcOffset.x, region->srcOffset.y, + region->extent.width, region->extent.height, + dst_slice_layout->tiled_or_linear.row_stride_B, + src_slice_layout->tiled_or_linear.row_stride_B, + dst_pfmt); + } else { + pan_copy_tiled_image( + dst_depth_ptr, src_depth_ptr, region->dstOffset.x, + region->dstOffset.y, region->srcOffset.x, region->srcOffset.y, + region->extent.width, region->extent.height, + dst_slice_layout->tiled_or_linear.row_stride_B, + src_slice_layout->tiled_or_linear.row_stride_B, src_pfmt); } } } diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index 0c673c2e263..6a9f10e34d1 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -59,6 +59,7 @@ panvk_image_can_use_afbc( /* Disallow AFBC if either of these is true * - PANVK_DEBUG does not have the 'afbc' flag set * - storage image views are requested + * - host image copies are requested * - the GPU doesn't support AFBC * - the format is not AFBC-able * - tiling is set to linear @@ -68,7 +69,8 @@ panvk_image_can_use_afbc( */ return (instance->debug_flags & PANVK_DEBUG_AFBC) && - !(usage & (VK_IMAGE_USAGE_STORAGE_BIT)) && + !(usage & (VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_HOST_TRANSFER_BIT)) && pan_query_afbc(&phys_dev->kmod.props) && pan_afbc_supports_format(arch, pfmt) && tiling == VK_IMAGE_TILING_OPTIMAL && diff --git a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c index aa1f571d186..632711c011e 100644 --- a/src/panfrost/vulkan/panvk_physical_device.c +++ b/src/panfrost/vulkan/panvk_physical_device.c @@ -27,6 +27,7 @@ #include "panvk_physical_device.h" #include "panvk_wsi.h" +#include "pan_afbc.h" #include "pan_props.h" #include "genxml/gen_macros.h" @@ -530,7 +531,7 @@ format_is_supported(struct panvk_physical_device *physical_device, static VkFormatFeatureFlags2 get_image_plane_format_features(struct panvk_physical_device *physical_device, - VkFormat format, VkImageTiling tiling) + VkFormat format) { VkFormatFeatureFlags2 features = 0; enum pipe_format pfmt = vk_format_to_pipe_format(format); @@ -583,8 +584,7 @@ get_image_plane_format_features(struct panvk_physical_device *physical_device, if (fmt.bind & PAN_BIND_DEPTH_STENCIL) features |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT; - if (features != 0 && vk_format_is_color(format) && - tiling == VK_IMAGE_TILING_LINEAR) + if (features != 0 && vk_format_is_color(format)) features |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT; return features; @@ -592,7 +592,7 @@ get_image_plane_format_features(struct panvk_physical_device *physical_device, static VkFormatFeatureFlags2 get_image_format_features(struct panvk_physical_device *physical_device, - VkFormat format, VkImageTiling tiling) + VkFormat format) { const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(format); @@ -603,7 +603,7 @@ get_image_format_features(struct panvk_physical_device *physical_device, return 0; if (ycbcr_info == NULL) - return get_image_plane_format_features(physical_device, format, tiling); + return get_image_plane_format_features(physical_device, format); if (unsupported_yuv_format(vk_format_to_pipe_format(format))) return 0; @@ -617,8 +617,7 @@ get_image_format_features(struct panvk_physical_device *physical_device, const struct vk_format_ycbcr_plane *plane_info = &ycbcr_info->planes[plane]; features &= - get_image_plane_format_features(physical_device, plane_info->format, - tiling); + get_image_plane_format_features(physical_device, plane_info->format); if (plane_info->denominator_scales[0] > 1 || plane_info->denominator_scales[1] > 1) cosited_chroma = true; @@ -739,26 +738,22 @@ panvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, { VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice); - VkFormatFeatureFlags2 tex_linear = - get_image_format_features(physical_device, format, - VK_IMAGE_TILING_LINEAR); - VkFormatFeatureFlags2 tex_optimal = - get_image_format_features(physical_device, format, - VK_IMAGE_TILING_OPTIMAL); + VkFormatFeatureFlags2 tex = + get_image_format_features(physical_device, format); VkFormatFeatureFlags2 buffer = get_buffer_format_features(physical_device, format); pFormatProperties->formatProperties = (VkFormatProperties){ - .linearTilingFeatures = tex_linear, - .optimalTilingFeatures = tex_optimal, + .linearTilingFeatures = tex, + .optimalTilingFeatures = tex, .bufferFeatures = buffer, }; VkFormatProperties3 *formatProperties3 = vk_find_struct(pFormatProperties->pNext, FORMAT_PROPERTIES_3); if (formatProperties3) { - formatProperties3->linearTilingFeatures = tex_linear; - formatProperties3->optimalTilingFeatures = tex_optimal; + formatProperties3->linearTilingFeatures = tex; + formatProperties3->optimalTilingFeatures = tex; formatProperties3->bufferFeatures = buffer; } @@ -886,15 +881,14 @@ get_image_format_properties(struct panvk_physical_device *physical_device, */ if (ycbcr_info == NULL) { format_feature_flags = - get_image_format_features(physical_device, info->format, info->tiling); + get_image_format_features(physical_device, info->format); } else { format_feature_flags = ~0u; assert(ycbcr_info->n_planes > 0); for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) { const VkFormat plane_format = ycbcr_info->planes[plane].format; format_feature_flags &= - get_image_format_features(physical_device, plane_format, - info->tiling); + get_image_format_features(physical_device, plane_format); } } @@ -1080,6 +1074,7 @@ panvk_GetPhysicalDeviceImageFormatProperties2( VkImageFormatProperties2 *base_props) { VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice); + const VkImageStencilUsageCreateInfo *stencil_usage_info = NULL; const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL; VkExternalImageFormatProperties *external_props = NULL; @@ -1098,6 +1093,9 @@ panvk_GetPhysicalDeviceImageFormatProperties2( /* Extract input structs */ vk_foreach_struct_const(s, base_info->pNext) { switch (s->sType) { + case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: + stencil_usage_info = (const void*)s; + break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: external_info = (const void *)s; break; @@ -1172,8 +1170,19 @@ panvk_GetPhysicalDeviceImageFormatProperties2( } if (hic_props) { - hic_props->optimalDeviceAccess = true; - hic_props->identicalMemoryLayout = true; + VkImageUsageFlags stencil_usage = stencil_usage_info ? + stencil_usage_info->stencilUsage : base_info->usage; + + /* We don't support AFBC for images used for host transfer. So, if an + * image could have been tiled as AFBC if it weren't for host transfer, + * report suboptimal access. */ + VkImageUsageFlags usage = base_info->usage | stencil_usage; + usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT; + bool can_use_afbc = panvk_image_can_use_afbc( + physical_device, base_info->format, usage, base_info->type, + base_info->tiling, base_info->flags); + hic_props->optimalDeviceAccess = !can_use_afbc; + hic_props->identicalMemoryLayout = !can_use_afbc; } const struct vk_format_ycbcr_info *ycbcr_info =