mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 11:18:08 +02:00
panvk: implement VK_EXT_host_image_copy for tiled images
Since we don't have a CPU implementation of AFBC compression, host copy is only implemented for u-interleaved tiling. Signed-off-by: Olivia Lee <olivia.lee@collabora.com> Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35910>
This commit is contained in:
parent
0f6a06bbba
commit
476fb5c5cf
3 changed files with 122 additions and 48 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue