nvk/image: Rewrite nvk_image_can_compress() to use early returns

This basically turns the giant comment at the top into a series of
easy-to-follow early returns, each with its own comment explaining why
that case is disallowed.  This should be much easier to follow.
This commit is contained in:
Faith Ekstrand 2026-05-06 11:28:49 -04:00
parent 3ca679029b
commit 62be7e0e4b

View file

@ -772,61 +772,65 @@ nvk_GetPhysicalDeviceSparseImageFormatProperties2(
}
}
/* To use compression and larger page sizes, we need to signal to the kernel
* that the memory requested is going to be VRAM resident. However, this
* comes with an issue where said memory can't be evicted to host RAM under
* pressure, so we work around this by going with a dedicated allocation for
* color, Z/S, and storage image targets which are the main types that would
* benefit from compression as they're heavy on writes. Additionally, they
* also aren't the majority of memory used, so they can be safely pinned in
* VRAM without worrying about eviction under high pressure.
*
* There are some additional restrictions we need to keep in mind, however:
* 1. We can only enable this for Turing onwards because prior architectures
* relied on firmware to manage the compression tags, and it's impossible to
* do this on nouveau. Additionally, since compression needs kernel changes,
* we can only enable it if the detected kernel supports it.
*
* 2. Given our approach depends on dedicated allocations, we can't enable
* compression for sparse images as dedicated allocations are not compatible
* with sparse.
*
* 3. In similar vein, we currently don't do multiplanar dedicated allocations
* so we can't do compression for multi-plane YCbCr images.
*
* 4. Host copies are a complete no-go for compression as the host doesn't know
* about the modified data layout nor the compression tags.
*
* 5. The API for VK_EXT_image_drm_format_modifier requires that we report the
* supported modifiers in GetPhysicalDeviceFormatProperties2(). However,
* since we can only know whether an image is compressed or not at bind time
* we can't actually expose any of the compressed modifiers in case the app
* chooses a compressed modifier for a non-compressed image. So for now, we
* have to disable compression for TILING_DRM_FORMAT_MODIFIER_EXT images.
*
* This helper enforces these restrictions and also makes sure to enable
* compression for storage, color, and Z/S targets only so as to avoid pinning
* too many things to VRAM.
*/
static bool
nvk_image_can_compress(const struct nvkmd_pdev *nvkmd_pdev,
const struct nvk_image *image)
{
if (nvkmd_pdev->kmd_info.has_compression) {
if (image->plane_count > 1 ||
image->vk.usage & (VK_IMAGE_USAGE_HOST_TRANSFER_BIT) ||
image->vk.create_flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
return false;
else if (image->vk.usage & (VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) &&
image->vk.tiling == VK_IMAGE_TILING_OPTIMAL)
return true;
else
return false;
} else
if (!nvkmd_pdev->kmd_info.has_compression)
return false;
/* Our host copy code does not understand compression */
if (image->vk.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT)
return false;
/* Our compression strategy depends on dedicated allocations, so we can't
* enable compression for sparse images as dedicated allocations are not
* compatible with sparse.
*/
if (image->vk.create_flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
return false;
/* In similar vein, we currently don't do multiplanar dedicated allocations
* so we can't do compression for multi-plane YCbCr images.
*/
if (image->plane_count > 1)
return false;
/* Linear images cannot be compressed. */
if (image->vk.tiling == VK_IMAGE_TILING_LINEAR)
return false;
/* The API for VK_EXT_image_drm_format_modifier requires that we report the
* supported modifiers in GetPhysicalDeviceFormatProperties2(). However,
* since we can only know whether an image is compressed or not at bind
* time we can't actually expose any of the compressed modifiers in case
* the app chooses a compressed modifier for a non-compressed image. So for
* now, we have to disable compression for TILING_DRM_FORMAT_MODIFIER_EXT
* images.
*/
if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
return false;
assert(image->vk.tiling == VK_IMAGE_TILING_OPTIMAL);
/* To use compression and larger page sizes, we need to signal to the
* kernel that the memory requested is going to be VRAM resident. However,
* this comes with an issue where said memory can't be evicted to host RAM
* under pressure.
*
* So we work around this by only allowing compression for color, Z/S, and
* storage image targets which are the main types that would benefit from
* compression as they're heavy on writes. Additionally, they also aren't
* the majority of memory used, so they can be safely pinned in VRAM
* without worrying about eviction under high pressure.
*/
if (!(image->vk.usage & (VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
return false;
return true;
}
static VkResult