mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 14:38:06 +02:00
panvk: sparse partially-resident image -related queries
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37483>
This commit is contained in:
parent
bd9aeeec0a
commit
7421b38521
3 changed files with 233 additions and 19 deletions
|
|
@ -796,12 +796,24 @@ panvk_GetDeviceImageSubresourceLayoutKHR(
|
|||
vk_image_finish(&image.vk);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
panvk_image_get_sparse_binding_granularity(struct panvk_image *image)
|
||||
{
|
||||
struct panvk_device *dev = to_panvk_device(image->vk.base.device);
|
||||
|
||||
assert(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT);
|
||||
|
||||
if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)
|
||||
return panvk_get_sparse_block_desc(image->vk.image_type, image->vk.format).size_B;
|
||||
|
||||
return panvk_get_gpu_page_size(dev);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_GetImageMemoryRequirements2(VkDevice device,
|
||||
const VkImageMemoryRequirementsInfo2 *pInfo,
|
||||
VkMemoryRequirements2 *pMemoryRequirements)
|
||||
{
|
||||
VK_FROM_HANDLE(panvk_device, dev, device);
|
||||
VK_FROM_HANDLE(panvk_image, image, pInfo->image);
|
||||
|
||||
/* For sparse resources alignment specifies binding granularity, rather than
|
||||
|
|
@ -810,7 +822,7 @@ panvk_GetImageMemoryRequirements2(VkDevice device,
|
|||
*/
|
||||
const uint64_t alignment =
|
||||
image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT
|
||||
? panvk_get_gpu_page_size(dev)
|
||||
? panvk_image_get_sparse_binding_granularity(image)
|
||||
: 4096;
|
||||
const VkImagePlaneMemoryRequirementsInfo *plane_info =
|
||||
vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
|
||||
|
|
@ -823,7 +835,7 @@ panvk_GetImageMemoryRequirements2(VkDevice device,
|
|||
panvk_image_get_total_size(image);
|
||||
const uint64_t size =
|
||||
image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT
|
||||
? align64(size_non_sparse, panvk_get_gpu_page_size(dev))
|
||||
? align64(size_non_sparse, alignment)
|
||||
: size_non_sparse;
|
||||
|
||||
pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
|
||||
|
|
@ -865,14 +877,117 @@ panvk_GetDeviceImageMemoryRequirements(VkDevice device,
|
|||
vk_image_finish(&image.vk);
|
||||
}
|
||||
|
||||
/* See Vulkan spec, 35.4.3. Standard Sparse Image Block Shapes for details */
|
||||
enum {
|
||||
STANDARD_SPARSE_BLOCK_SIZE_B = 65536,
|
||||
};
|
||||
|
||||
/* Sparse block extents, in texel blocks, single sample.
|
||||
* Indexed by log2(texel block size in bytes).
|
||||
* See Vulkan spec, 35.4.3. Standard Sparse Image Block Shapes for details. */
|
||||
static struct VkExtent3D standard_sparse_2d_blocks[] = {
|
||||
/* 1 */ {256, 256, 1},
|
||||
/* 2 */ {256, 128, 1},
|
||||
/* 4 */ {128, 128, 1},
|
||||
/* 8 */ {128, 64, 1},
|
||||
/* 16 */ {64, 64, 1},
|
||||
};
|
||||
|
||||
struct panvk_sparse_block_desc
|
||||
panvk_get_sparse_block_desc(VkImageType type, VkFormat format)
|
||||
{
|
||||
const struct util_format_description *fmt_desc = vk_format_description(format);
|
||||
|
||||
uint32_t texel_block_size_B = fmt_desc->block.bits / 8;
|
||||
|
||||
switch (type) {
|
||||
case VK_IMAGE_TYPE_2D: {
|
||||
if (!util_is_power_of_two_nonzero(texel_block_size_B))
|
||||
break;
|
||||
|
||||
uint32_t texel_block_size_B_log2 = util_logbase2(texel_block_size_B);
|
||||
if (texel_block_size_B_log2 >= ARRAY_SIZE(standard_sparse_2d_blocks))
|
||||
break;
|
||||
struct VkExtent3D extent = standard_sparse_2d_blocks[texel_block_size_B_log2];
|
||||
|
||||
assert(extent.width * extent.height * extent.depth * texel_block_size_B == STANDARD_SPARSE_BLOCK_SIZE_B);
|
||||
|
||||
extent.width *= fmt_desc->block.width;
|
||||
extent.height *= fmt_desc->block.height;
|
||||
extent.depth *= fmt_desc->block.depth;
|
||||
|
||||
return (struct panvk_sparse_block_desc){
|
||||
.extent = extent,
|
||||
.size_B = STANDARD_SPARSE_BLOCK_SIZE_B,
|
||||
.standard = true,
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (struct panvk_sparse_block_desc){};
|
||||
}
|
||||
|
||||
VkSparseImageFormatProperties
|
||||
panvk_get_sparse_image_fmt_props(VkImageType type, VkFormat format)
|
||||
{
|
||||
struct panvk_sparse_block_desc sblock_desc = panvk_get_sparse_block_desc(type, format);
|
||||
if (!panvk_sparse_block_is_valid(sblock_desc))
|
||||
return (VkSparseImageFormatProperties){};
|
||||
|
||||
VkSparseImageFormatProperties fmt_props = {};
|
||||
fmt_props.aspectMask = vk_format_aspects(format);
|
||||
fmt_props.imageGranularity = sblock_desc.extent;
|
||||
if (!sblock_desc.standard)
|
||||
fmt_props.flags |= VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT;
|
||||
return fmt_props;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_GetImageSparseMemoryRequirements2(
|
||||
VkDevice device, const VkImageSparseMemoryRequirementsInfo2 *pInfo,
|
||||
uint32_t *pSparseMemoryRequirementCount,
|
||||
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
|
||||
{
|
||||
/* Sparse images are not yet supported. */
|
||||
*pSparseMemoryRequirementCount = 0;
|
||||
VK_FROM_HANDLE(panvk_image, image, pInfo->image);
|
||||
VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
|
||||
pSparseMemoryRequirementCount);
|
||||
|
||||
if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
|
||||
return;
|
||||
|
||||
/* We only support single-plane images right now. See
|
||||
* https://gitlab.freedesktop.org/panfrost/mesa/-/issues/243 details. */
|
||||
unsigned plane_idx = 0;
|
||||
|
||||
struct panvk_sparse_block_desc sblock = panvk_get_sparse_block_desc(image->vk.image_type, image->vk.format);
|
||||
assert(panvk_sparse_block_is_valid(sblock));
|
||||
|
||||
struct panvk_image_plane *plane = &image->planes[plane_idx];
|
||||
|
||||
unsigned mip_tail_first_lod = 0;
|
||||
uint64_t mip_tail_begin = 0;
|
||||
for (unsigned level = 0; level < plane->image.props.nr_slices; level++) {
|
||||
uint64_t offset = plane->plane.layout.slices[level].offset_B;
|
||||
if (!util_is_aligned(offset, sblock.size_B))
|
||||
break;
|
||||
mip_tail_first_lod = level;
|
||||
mip_tail_begin = offset;
|
||||
}
|
||||
|
||||
uint64_t mip_tail_end = plane->plane.layout.array_stride_B;
|
||||
|
||||
vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, p) {
|
||||
p->memoryRequirements = (VkSparseImageMemoryRequirements){
|
||||
.formatProperties = panvk_get_sparse_image_fmt_props(image->vk.image_type, image->vk.format),
|
||||
.imageMipTailFirstLod = mip_tail_first_lod,
|
||||
.imageMipTailSize = mip_tail_end - mip_tail_begin,
|
||||
.imageMipTailOffset = mip_tail_begin,
|
||||
.imageMipTailStride = plane->plane.layout.array_stride_B,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
|
|
@ -881,8 +996,19 @@ panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
|
|||
uint32_t *pSparseMemoryRequirementCount,
|
||||
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
|
||||
{
|
||||
/* Sparse images are not yet supported. */
|
||||
*pSparseMemoryRequirementCount = 0;
|
||||
VK_FROM_HANDLE(panvk_device, dev, device);
|
||||
|
||||
struct panvk_image image;
|
||||
vk_image_init(&dev->vk, &image.vk, pInfo->pCreateInfo);
|
||||
panvk_image_init(&image, pInfo->pCreateInfo);
|
||||
|
||||
VkImageSparseMemoryRequirementsInfo2 info2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.image = panvk_image_to_handle(&image),
|
||||
};
|
||||
panvk_GetImageSparseMemoryRequirements2(device, &info2,
|
||||
pSparseMemoryRequirementCount, pSparseMemoryRequirements);
|
||||
vk_image_finish(&image.vk);
|
||||
}
|
||||
|
||||
static VkResult
|
||||
|
|
|
|||
|
|
@ -105,4 +105,20 @@ panvk_image_stencil_only_pfmt(const struct panvk_image *image)
|
|||
VkResult panvk_image_init(struct panvk_image *image,
|
||||
const VkImageCreateInfo *pCreateInfo);
|
||||
|
||||
struct panvk_sparse_block_desc {
|
||||
struct VkExtent3D extent;
|
||||
uint64_t size_B;
|
||||
|
||||
/* Whether this is a standard (as defined by Vulkan) sparse block size, for
|
||||
* the given arguments */
|
||||
bool standard;
|
||||
};
|
||||
|
||||
struct panvk_sparse_block_desc panvk_get_sparse_block_desc(VkImageType type, VkFormat format);
|
||||
|
||||
static inline bool
|
||||
panvk_sparse_block_is_valid(struct panvk_sparse_block_desc desc) { return desc.size_B > 0; }
|
||||
|
||||
VkSparseImageFormatProperties panvk_get_sparse_image_fmt_props(VkImageType type, VkFormat format);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -916,6 +916,59 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
|
|||
const struct vk_format_ycbcr_info *ycbcr_info =
|
||||
vk_format_get_ycbcr_info(info->format);
|
||||
|
||||
if (info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
|
||||
if (!physical_device->vk.supported_features.sparseBinding)
|
||||
goto unsupported;
|
||||
|
||||
/*
|
||||
* Sparse only manipulates device mappings and we implement host copies on
|
||||
* host. Purely hypotetically, we could implement host copies for sparse
|
||||
* images in one of, but not limited to, the following ways:
|
||||
*
|
||||
* * submitting a device copy and immediately waiting on it
|
||||
*
|
||||
* * mirror sparse binds' modifications to device mappings on host
|
||||
*
|
||||
* * share a single address space and thus mappings between host and device
|
||||
*
|
||||
* but realistically speaking, the set of people, apps and tests in the
|
||||
* CTS that expect a driver to implement host copies on sparse images is
|
||||
* exactly empty, so let's just not bother.
|
||||
*/
|
||||
if (info->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT)
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if (info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
|
||||
if (!((info->type == VK_IMAGE_TYPE_2D &&
|
||||
physical_device->vk.supported_features.sparseResidencyImage2D) ||
|
||||
(info->type == VK_IMAGE_TYPE_3D &&
|
||||
physical_device->vk.supported_features.sparseResidencyImage3D)))
|
||||
goto unsupported;
|
||||
|
||||
/* Only single aspect (thus single plane) stuff is supported for now */
|
||||
if (util_bitcount(vk_format_aspects(info->format)) != 1)
|
||||
goto unsupported;
|
||||
|
||||
if (info->tiling != VK_IMAGE_TILING_OPTIMAL)
|
||||
goto unsupported;
|
||||
|
||||
struct panvk_sparse_block_desc sblock_desc = panvk_get_sparse_block_desc(info->type, info->format);
|
||||
if (!panvk_sparse_block_is_valid(sblock_desc))
|
||||
goto unsupported;
|
||||
|
||||
VkImageUsageFlags allowed_usages =
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_STORAGE_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
|
||||
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
if (all_usage & ~allowed_usages)
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
switch (info->tiling) {
|
||||
case VK_IMAGE_TILING_LINEAR:
|
||||
case VK_IMAGE_TILING_OPTIMAL:
|
||||
|
|
@ -1325,24 +1378,43 @@ fail:
|
|||
return result;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_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;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_GetPhysicalDeviceSparseImageFormatProperties2(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
|
||||
uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties)
|
||||
{
|
||||
/* Sparse images are not yet supported. */
|
||||
*pPropertyCount = 0;
|
||||
VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out, pProperties, pPropertyCount);
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2 img_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||
.format = pFormatInfo->format,
|
||||
.type = pFormatInfo->type,
|
||||
.tiling = pFormatInfo->tiling,
|
||||
.usage = pFormatInfo->usage,
|
||||
.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
|
||||
VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
|
||||
};
|
||||
VkImageFormatProperties2 img_props = {};
|
||||
if (panvk_GetPhysicalDeviceImageFormatProperties2(physicalDevice, &img_info, &img_props) != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
if (!(img_props.imageFormatProperties.sampleCounts & pFormatInfo->samples))
|
||||
return;
|
||||
|
||||
/*
|
||||
* We don't support multisampled sparse partially-resident images for now.
|
||||
* Weirdly enough, banning it the obvious way by making
|
||||
* get_image_format_properties report sampleCounts of 1 when flags includes
|
||||
* SPARSE_RESIDENCY causes "required sample counts not supported" CTS fails,
|
||||
* so we ban them here.
|
||||
*/
|
||||
if (pFormatInfo->samples != 1)
|
||||
return;
|
||||
|
||||
vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, prop) {
|
||||
prop->properties = panvk_get_sparse_image_fmt_props(pFormatInfo->type, pFormatInfo->format);
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue