From 8d054c390ea662526ebe44ad540706bf519336ba Mon Sep 17 00:00:00 2001 From: Mel Henning Date: Mon, 6 Apr 2026 17:38:51 -0400 Subject: [PATCH] nvk: Zero zcull data in layout transition We should have never been doing this as bind time. Instead, layout transitions out of UNDEFINED are in the spec specifically so the driver has a point where it can do initialization, so do our init there instead. Reviewed-by: Mary Guillemard Part-of: --- src/nouveau/vulkan/nvk_cmd_buffer.c | 20 ++++++++++++++++++++ src/nouveau/vulkan/nvk_host_copy.c | 7 ++++++- src/nouveau/vulkan/nvk_image.c | 14 -------------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index 9f2fa5b12f6..4f1d4b319a0 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -754,6 +754,25 @@ nvk_cmd_invalidate_deps(struct nvk_cmd_buffer *cmd, P_IMMD(p, NVB1C0, INVALIDATE_SKED_CACHES, 0); } +static void +nvk_cmd_image_layout_transition(struct nvk_cmd_buffer *cmd, + const VkDependencyInfo *dep) +{ + for (uint32_t i = 0; i < dep->imageMemoryBarrierCount; i++) { + const VkImageMemoryBarrier2 *bar = &dep->pImageMemoryBarriers[i]; + if (bar->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && + bar->newLayout != VK_IMAGE_LAYOUT_UNDEFINED) { + VK_FROM_HANDLE(nvk_image, image, bar->image); + /* + * zcull hardware kills the context if we try to LOAD_ZCULL on garbage + * data. Handle this by initializing the zcull data to zero. + */ + if (image->zcull.nil.size_B > 0) + nvk_cmd_fill_memory(cmd, image->zcull.addr, image->zcull.nil.size_B, 0); + } + } +} + VKAPI_ATTR void VKAPI_CALL nvk_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo *pDependencyInfo) @@ -761,6 +780,7 @@ nvk_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); nvk_cmd_flush_wait_dep(cmd, pDependencyInfo, true); + nvk_cmd_image_layout_transition(cmd, pDependencyInfo); nvk_cmd_invalidate_deps(cmd, 1, pDependencyInfo); } diff --git a/src/nouveau/vulkan/nvk_host_copy.c b/src/nouveau/vulkan/nvk_host_copy.c index 5d5d20046f6..e4d7ef0de74 100644 --- a/src/nouveau/vulkan/nvk_host_copy.c +++ b/src/nouveau/vulkan/nvk_host_copy.c @@ -572,6 +572,11 @@ nvk_TransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT *transitions) { - /* Nothing to do here */ + for (uint32_t t = 0; t < transitionCount; t++) { + VK_FROM_HANDLE(nvk_image, image, transitions[t].image); + + /* Zcull is disabled for VK_IMAGE_USAGE_HOST_TRANSFER_BIT */ + assert(image->zcull.nil.size_B == 0); + } return VK_SUCCESS; } diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index e5e4f4040b3..896d605b626 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -1698,20 +1698,6 @@ nvk_bind_image_memory(struct nvk_device *dev, result = nvk_image_zcull_bind(&image->zcull, mem, offset_B); if (result != VK_SUCCESS) return result; - - /* - * zcull hardware kills the context if we try to LOAD_ZCULL on garbage - * data. Work around this by always initializing the zcull data to zero. - */ - result = nvk_upload_queue_fill(dev, &dev->upload, - image->zcull.addr, - 0, image->zcull.nil.size_B); - if (result != VK_SUCCESS) - return result; - - result = nvk_upload_queue_sync(dev, &dev->upload); - if (result != VK_SUCCESS) - return result; } if (image->stencil_copy_temp.nil.size_B > 0) {