From 3ca679029b39ec84d16c7d5ea7ef9e0e54014925 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 6 May 2026 11:18:21 -0400 Subject: [PATCH 1/4] nvk/image: Style nits --- src/nouveau/vulkan/nvk_image.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 9af49253c99..06ed73dfe97 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -1156,7 +1156,7 @@ nvk_image_init(struct nvk_device *dev, image->image_align_B = MAX2(image->stencil_copy_temp.plane_align_B, image->image_align_B); } - + return VK_SUCCESS; } @@ -1165,6 +1165,7 @@ nvk_image_plane_alloc_va(struct nvk_device *dev, const struct nvk_image *image, struct nvk_image_plane *plane) { + assert(plane->va == NULL); VkResult result; const bool sparse_bound = @@ -1610,6 +1611,7 @@ nvk_image_plane_bind(struct nvk_device *dev, VkResult result = nvk_image_plane_alloc_va(dev, image, plane); if (result != VK_SUCCESS) return result; + result = nvkmd_va_bind_mem(plane->va, &image->vk.base, 0, mem->mem, offset_B, plane->va->size_B); From 62be7e0e4b8cfe5a1cbf1099b46c06e11184a266 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 6 May 2026 11:28:49 -0400 Subject: [PATCH 2/4] 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. --- src/nouveau/vulkan/nvk_image.c | 104 +++++++++++++++++---------------- 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 06ed73dfe97..8a65c65d942 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -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 From 782dfb09f08b974865f13249d19a09e5111c6e1a Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 6 May 2026 11:33:27 -0400 Subject: [PATCH 3/4] nvk/image: Take an nvk_physical_device in can_compress() This is more idiomatic with the rest of the NVK queries. --- src/nouveau/vulkan/nvk_image.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 8a65c65d942..809f50bd2f0 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -773,10 +773,10 @@ nvk_GetPhysicalDeviceSparseImageFormatProperties2( } static bool -nvk_image_can_compress(const struct nvkmd_pdev *nvkmd_pdev, +nvk_image_can_compress(const struct nvk_physical_device *pdev, const struct nvk_image *image) { - if (!nvkmd_pdev->kmd_info.has_compression) + if (!pdev->nvkmd->kmd_info.has_compression) return false; /* Our host copy code does not understand compression */ @@ -887,7 +887,7 @@ nvk_image_init(struct nvk_device *dev, * in GetImageMemoryRequirements() we are able to detect it and specify that * we prefer a dedicated allocation for it. */ - image->can_compress = nvk_image_can_compress(dev->nvkmd->pdev, image); + image->can_compress = nvk_image_can_compress(pdev, image); if (!image->can_compress) usage |= NIL_IMAGE_USAGE_UNCOMPRESSED_BIT; From 52afa936b2a087a911280feeec10f5f9552f914a Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 6 May 2026 11:35:28 -0400 Subject: [PATCH 4/4] nvk: Add an NVK_DEBUG=no_compression flag --- docs/drivers/nvk.rst | 2 ++ src/nouveau/vulkan/nvk_debug.h | 3 +++ src/nouveau/vulkan/nvk_image.c | 3 +++ src/nouveau/vulkan/nvk_instance.c | 1 + 4 files changed, 9 insertions(+) diff --git a/docs/drivers/nvk.rst b/docs/drivers/nvk.rst index bc787724d1f..c28a8fc03ab 100644 --- a/docs/drivers/nvk.rst +++ b/docs/drivers/nvk.rst @@ -76,6 +76,8 @@ specific to NVK: ``coherent`` Forces all memory maps to be coherent with the CPU caches. This only applies to Tegra devices. + ``no_compression`` + Disables image compression. .. envvar:: NVK_I_WANT_A_BROKEN_VULKAN_DRIVER diff --git a/src/nouveau/vulkan/nvk_debug.h b/src/nouveau/vulkan/nvk_debug.h index e68f3d25e81..06ce357b48d 100644 --- a/src/nouveau/vulkan/nvk_debug.h +++ b/src/nouveau/vulkan/nvk_debug.h @@ -42,6 +42,9 @@ enum nvk_debug { /* Force all memory allocations to go to GART */ NVK_DEBUG_FORCE_COHERENT = 1ull << 8, + + /* Disable image compression */ + NVK_DEBUG_NO_COMPRESSION = 1ull << 9, }; #endif /* NVK_DEBUG_H */ diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 809f50bd2f0..5f3c9ebe004 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -776,6 +776,9 @@ static bool nvk_image_can_compress(const struct nvk_physical_device *pdev, const struct nvk_image *image) { + if (pdev->debug_flags & NVK_DEBUG_NO_COMPRESSION) + return false; + if (!pdev->nvkmd->kmd_info.has_compression) return false; diff --git a/src/nouveau/vulkan/nvk_instance.c b/src/nouveau/vulkan/nvk_instance.c index 5a8464d0510..95550ab1985 100644 --- a/src/nouveau/vulkan/nvk_instance.c +++ b/src/nouveau/vulkan/nvk_instance.c @@ -91,6 +91,7 @@ nvk_init_debug_flags(struct nvk_instance *instance) { "edb_bview", NVK_DEBUG_FORCE_EDB_BVIEW }, { "gart", NVK_DEBUG_FORCE_GART }, { "coherent", NVK_DEBUG_FORCE_COHERENT }, + { "no_compression", NVK_DEBUG_NO_COMPRESSION }, { NULL, 0 }, };