mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 03:00:11 +01:00
panvk: Create MS shadow images and views
VK_EXT_multisampled_render_to_single_sampled needs those to be able to render to the MS attachment when the app only provides a single- sampled one. Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38825>
This commit is contained in:
parent
092d78ebf4
commit
cb3f648175
4 changed files with 276 additions and 2 deletions
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2025 Arm Ltd.
|
||||
* Copyright © 2021 Collabora Ltd.
|
||||
*
|
||||
* Derived from tu_image.c which is:
|
||||
|
|
@ -254,6 +255,18 @@ panvk_image_can_use_mod(struct panvk_image *image,
|
|||
if ((image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
|
||||
(image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT))
|
||||
return false;
|
||||
|
||||
/* No ms with AFBC, but we need to create multisampled images in the
|
||||
* background for which the view formats need to be compatible to avoid
|
||||
* headaches when copying --> disable afbc for the base image as well.
|
||||
* When copying the depth plane block sizes aren't matching between
|
||||
* utiled and afbc, thus the views created for the ms images are
|
||||
* invalid.
|
||||
*/
|
||||
if (image->vk.create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
|
||||
|
|
@ -604,6 +617,57 @@ panvk_image_plane_bind_addr(struct panvk_device *dev,
|
|||
plane->plane.base = addr;
|
||||
}
|
||||
|
||||
static void
|
||||
create_ms_images(struct panvk_device *dev, struct panvk_image *img,
|
||||
const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
struct panvk_physical_device *pdev =
|
||||
to_panvk_physical_device(dev->vk.physical);
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2 info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||
.format = pCreateInfo->format,
|
||||
.type = pCreateInfo->imageType,
|
||||
.tiling = pCreateInfo->tiling,
|
||||
.usage = pCreateInfo->usage,
|
||||
.flags = pCreateInfo->flags,
|
||||
};
|
||||
VkImageFormatProperties2 properties = {};
|
||||
panvk_GetPhysicalDeviceImageFormatProperties2(
|
||||
vk_physical_device_to_handle(&pdev->vk), &info, &properties);
|
||||
|
||||
VkImageCreateInfo ms_img_info = *pCreateInfo;
|
||||
|
||||
assert(ms_img_info.flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT);
|
||||
ms_img_info.flags &=
|
||||
~VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
|
||||
|
||||
for (uint32_t msaa_idx = 0; msaa_idx < ARRAY_SIZE(img->ms_imgs);
|
||||
++msaa_idx) {
|
||||
VkSampleCountFlagBits msaa = 1 << (msaa_idx + 1);
|
||||
|
||||
if ((properties.imageFormatProperties.sampleCounts & msaa) == 0) {
|
||||
img->ms_imgs[msaa_idx] = VK_NULL_HANDLE;
|
||||
continue;
|
||||
}
|
||||
|
||||
ms_img_info.samples = msaa;
|
||||
|
||||
panvk_CreateImage(panvk_device_to_handle(dev), &ms_img_info, pAllocator,
|
||||
&img->ms_imgs[msaa_idx]);
|
||||
|
||||
struct panvk_image *res = panvk_image_from_handle(img->ms_imgs[msaa_idx]);
|
||||
assert(res->vk.format = img->vk.format);
|
||||
assert(res->plane_count = img->plane_count);
|
||||
for (uint32_t i = 0; i < res->plane_count; ++i) {
|
||||
assert(res->planes[i].image.props.format ==
|
||||
img->planes[i].image.props.format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkImage *pImage)
|
||||
|
|
@ -677,6 +741,10 @@ panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
|
|||
}
|
||||
}
|
||||
|
||||
if (pCreateInfo->flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT)
|
||||
create_ms_images(dev, image, pCreateInfo, pAllocator);
|
||||
|
||||
*pImage = panvk_image_to_handle(image);
|
||||
return VK_SUCCESS;
|
||||
|
||||
|
|
@ -700,6 +768,13 @@ panvk_DestroyImage(VkDevice _device, VkImage _image,
|
|||
if (!image)
|
||||
return;
|
||||
|
||||
if (image->vk.create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(image->ms_imgs); ++i) {
|
||||
panvk_DestroyImage(_device, image->ms_imgs[i], pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
|
||||
uint64_t va_range = panvk_image_get_sparse_size(image);
|
||||
|
||||
|
|
@ -811,6 +886,24 @@ panvk_image_get_sparse_binding_granularity(struct panvk_image *image)
|
|||
return panvk_get_gpu_page_size(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
append_ms_to_ss_memory_reqs(VkMemoryRequirements2 *pMemoryRequirements,
|
||||
const VkMemoryRequirements2 *append)
|
||||
{
|
||||
pMemoryRequirements->memoryRequirements.alignment =
|
||||
MAX2(pMemoryRequirements->memoryRequirements.alignment,
|
||||
append->memoryRequirements.alignment);
|
||||
/* After the previous images, align this images start properly. */
|
||||
pMemoryRequirements->memoryRequirements.size =
|
||||
align(pMemoryRequirements->memoryRequirements.size,
|
||||
append->memoryRequirements.alignment);
|
||||
pMemoryRequirements->memoryRequirements.size +=
|
||||
append->memoryRequirements.size;
|
||||
pMemoryRequirements->memoryRequirements.memoryTypeBits &=
|
||||
append->memoryRequirements.memoryTypeBits;
|
||||
assert(pMemoryRequirements->memoryRequirements.memoryTypeBits != 0);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_GetImageMemoryRequirements2(VkDevice device,
|
||||
const VkImageMemoryRequirementsInfo2 *pInfo,
|
||||
|
|
@ -861,6 +954,24 @@ panvk_GetImageMemoryRequirements2(VkDevice device,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (image->vk.create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(image->ms_imgs); ++i) {
|
||||
if (image->ms_imgs[i] == VK_NULL_HANDLE)
|
||||
continue;
|
||||
|
||||
VkImageMemoryRequirementsInfo2 info = *pInfo;
|
||||
info.image = image->ms_imgs[i];
|
||||
|
||||
VkMemoryRequirements2 sub_reqs_2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
.memoryRequirements = {},
|
||||
};
|
||||
panvk_GetImageMemoryRequirements2(device, &info, &sub_reqs_2);
|
||||
append_ms_to_ss_memory_reqs(pMemoryRequirements, &sub_reqs_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
|
|
@ -870,9 +981,16 @@ panvk_GetDeviceImageMemoryRequirements(VkDevice device,
|
|||
{
|
||||
VK_FROM_HANDLE(panvk_device, dev, device);
|
||||
|
||||
/* Make a copy so we can turn off the ms2ss flag. */
|
||||
VkDeviceImageMemoryRequirements info = *pInfo;
|
||||
VkImageCreateInfo create_info = *(pInfo->pCreateInfo);
|
||||
create_info.flags &=
|
||||
~VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
|
||||
info.pCreateInfo = &create_info;
|
||||
|
||||
struct panvk_image image;
|
||||
vk_image_init(&dev->vk, &image.vk, pInfo->pCreateInfo);
|
||||
panvk_image_init(&image, pInfo->pCreateInfo);
|
||||
vk_image_init(&dev->vk, &image.vk, &create_info);
|
||||
panvk_image_init(&image, &create_info);
|
||||
|
||||
VkImageMemoryRequirementsInfo2 info2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
|
|
@ -880,6 +998,24 @@ panvk_GetDeviceImageMemoryRequirements(VkDevice device,
|
|||
};
|
||||
panvk_GetImageMemoryRequirements2(device, &info2, pMemoryRequirements);
|
||||
vk_image_finish(&image.vk);
|
||||
|
||||
if (pInfo->pCreateInfo->flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) {
|
||||
for (uint32_t msaa_idx = 0; msaa_idx < ARRAY_SIZE(image.ms_imgs);
|
||||
++msaa_idx) {
|
||||
/* idx 0 has sample count 2, 1 has sample count 4, ... */
|
||||
create_info.samples = 1 << (msaa_idx + 1);
|
||||
create_info.flags &=
|
||||
~VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
|
||||
|
||||
VkMemoryRequirements2 msaa_reqs = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
.memoryRequirements = {},
|
||||
};
|
||||
panvk_GetDeviceImageMemoryRequirements(device, &info, &msaa_reqs);
|
||||
append_ms_to_ss_memory_reqs(pMemoryRequirements, &msaa_reqs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See Vulkan spec, 35.4.3. Standard Sparse Image Block Shapes for details */
|
||||
|
|
@ -1016,6 +1152,93 @@ panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
|
|||
vk_image_finish(&image.vk);
|
||||
}
|
||||
|
||||
static VkResult panvk_image_bind(struct panvk_device *dev,
|
||||
const VkBindImageMemoryInfo *bind_info);
|
||||
|
||||
static void
|
||||
bind_ms_images(struct panvk_device *dev, const VkBindImageMemoryInfo *bind_info)
|
||||
{
|
||||
VK_FROM_HANDLE(panvk_image, image, bind_info->image);
|
||||
|
||||
uint64_t total_size = 0;
|
||||
{
|
||||
VkImageMemoryRequirementsInfo2 reqs_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.image = bind_info->image,
|
||||
};
|
||||
VkMemoryRequirements2 reqs2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
.memoryRequirements = {},
|
||||
};
|
||||
panvk_GetImageMemoryRequirements2(panvk_device_to_handle(dev), &reqs_info,
|
||||
&reqs2);
|
||||
|
||||
total_size = reqs2.memoryRequirements.size;
|
||||
}
|
||||
|
||||
uint64_t sub_sz[ARRAY_SIZE(image->ms_imgs)];
|
||||
uint64_t sub_al[ARRAY_SIZE(image->ms_imgs)];
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(image->ms_imgs); ++i) {
|
||||
if (image->ms_imgs[i] == VK_NULL_HANDLE) {
|
||||
sub_sz[i] = 0;
|
||||
sub_al[i] = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
VkImageMemoryRequirementsInfo2 reqs_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.image = image->ms_imgs[i],
|
||||
};
|
||||
VkMemoryRequirements2 reqs2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
.memoryRequirements = {},
|
||||
};
|
||||
panvk_GetImageMemoryRequirements2(panvk_device_to_handle(dev), &reqs_info,
|
||||
&reqs2);
|
||||
|
||||
sub_sz[i] = reqs2.memoryRequirements.size;
|
||||
sub_al[i] = reqs2.memoryRequirements.alignment;
|
||||
}
|
||||
|
||||
/*
|
||||
* sub_imgs_aligned_size
|
||||
* ----------------------------
|
||||
* [ base, sub_0, sub_1, sub_2, sub_3 ]
|
||||
* -->-> -->-> ... ------>
|
||||
* sz a sz a size only
|
||||
*/
|
||||
uint64_t sub_imgs_aligned_size = 0;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(image->ms_imgs); ++i) {
|
||||
sub_imgs_aligned_size += sub_sz[i];
|
||||
if (i < ARRAY_SIZE(image->ms_imgs) - 1) {
|
||||
sub_imgs_aligned_size = align(sub_imgs_aligned_size, sub_al[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t sub_image_offset =
|
||||
bind_info->memoryOffset + total_size - sub_imgs_aligned_size;
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(image->ms_imgs); ++i) {
|
||||
if (image->ms_imgs[i] == VK_NULL_HANDLE)
|
||||
continue;
|
||||
|
||||
sub_image_offset = align(sub_image_offset, sub_al[i]);
|
||||
|
||||
VkBindImageMemoryInfo sub_bind_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
||||
.image = image->ms_imgs[i],
|
||||
.memory = bind_info->memory,
|
||||
.memoryOffset = sub_image_offset,
|
||||
};
|
||||
|
||||
const VkResult res = panvk_image_bind(dev, &sub_bind_info);
|
||||
assert(res == VK_SUCCESS);
|
||||
|
||||
sub_image_offset += sub_sz[i];
|
||||
}
|
||||
}
|
||||
|
||||
static VkResult
|
||||
panvk_image_bind(struct panvk_device *dev,
|
||||
const VkBindImageMemoryInfo *bind_info)
|
||||
|
|
@ -1057,6 +1280,10 @@ panvk_image_bind(struct panvk_device *dev,
|
|||
panvk_image_plane_bind_mem(dev, &image->planes[plane], mem, offset);
|
||||
}
|
||||
|
||||
if (!!(image->vk.create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT))
|
||||
bind_ms_images(dev, bind_info);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ struct panvk_image {
|
|||
|
||||
uint8_t plane_count;
|
||||
struct panvk_image_plane planes[PANVK_MAX_PLANES];
|
||||
|
||||
/* One image each for 2x 4x 8x 16x. We don't support more than 16x. */
|
||||
VkImage ms_imgs[4];
|
||||
};
|
||||
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_image, vk.base, VkImage,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ struct panvk_image_view {
|
|||
struct mali_attribute_buffer_packed img_attrib_buf[2];
|
||||
#endif
|
||||
} descs;
|
||||
|
||||
/* One image each for 2x 4x 8x 16x. We don't support more than 16x. */
|
||||
VkImageView ms_views[4];
|
||||
};
|
||||
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_image_view, vk.base, VkImageView,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2025 Arm Ltd.
|
||||
* Copyright © 2021 Collabora Ltd.
|
||||
*
|
||||
* Derived from tu_image.c which is:
|
||||
|
|
@ -286,6 +287,34 @@ prepare_attr_buf_descs(struct panvk_image_view *view)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
create_ms_views(struct panvk_device *dev, struct panvk_image_view *view,
|
||||
const VkImageViewCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
struct panvk_image *source_img =
|
||||
panvk_image_from_handle(vk_image_to_handle(view->vk.image));
|
||||
const VkImage *target_images = source_img->ms_imgs;
|
||||
|
||||
VkImageViewCreateInfo create_info = *pCreateInfo;
|
||||
|
||||
for (uint32_t idx = 0; idx < ARRAY_SIZE(source_img->ms_imgs); ++idx) {
|
||||
if (target_images[idx] == VK_NULL_HANDLE)
|
||||
continue;
|
||||
|
||||
create_info.image = target_images[idx];
|
||||
|
||||
assert(vk_image_from_handle(create_info.image)->format ==
|
||||
source_img->vk.format);
|
||||
assert(view->vk.format == create_info.format);
|
||||
assert(!(vk_image_from_handle(create_info.image)->create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT));
|
||||
|
||||
panvk_per_arch(CreateImageView)(panvk_device_to_handle(dev), &create_info,
|
||||
pAllocator, &view->ms_views[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
panvk_per_arch(CreateImageView)(VkDevice _device,
|
||||
const VkImageViewCreateInfo *pCreateInfo,
|
||||
|
|
@ -386,6 +415,10 @@ panvk_per_arch(CreateImageView)(VkDevice _device,
|
|||
prepare_attr_buf_descs(view);
|
||||
#endif
|
||||
|
||||
if (view->vk.image->create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT)
|
||||
create_ms_views(device, view, pCreateInfo, pAllocator);
|
||||
|
||||
*pView = panvk_image_view_to_handle(view);
|
||||
return VK_SUCCESS;
|
||||
|
||||
|
|
@ -404,6 +437,14 @@ panvk_per_arch(DestroyImageView)(VkDevice _device, VkImageView _view,
|
|||
if (!view)
|
||||
return;
|
||||
|
||||
if (view->vk.image->create_flags &
|
||||
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(view->ms_views); ++i) {
|
||||
panvk_per_arch(DestroyImageView)(_device, view->ms_views[i],
|
||||
pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
panvk_pool_free_mem(&view->mem);
|
||||
vk_image_view_destroy(&device->vk, pAllocator, &view->vk);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue