From 4ad79bfef427b0b40acca403587b2e249389f533 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Tue, 13 Feb 2024 22:56:52 -0600 Subject: [PATCH] nvk: Set tile mode and PTE kind on dedicated dma-buf BOs This is our compromise to make NVK and nouveau GL play nice when it comes to modifiers. The old GL driver depends heavily on the PTE kind and tile mode, even for images with modifiers. While it correctly encodes the PTE kind and tile mode in the modifiers it advertises, it may ignore the modifier and just trust what's set on the BO when it imports a dma-buf image. This is partly because it doesn't support VM_BIND and partly because of preexisting bugs in the modifiers implementation. In either case, we can't fix it retroactively. To work around this, NVK also sets the PTE kind and tile mode on the BO when it's a dedicated allocation created for a DRM format modifiers image. If DRM format modifiers are used without dedicated allocations, things may still break but that's getting into vanishingly unlikely scenarios. Reviewed-by: Dave Airlie Part-of: --- src/nouveau/vulkan/nvk_device_memory.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/nouveau/vulkan/nvk_device_memory.c b/src/nouveau/vulkan/nvk_device_memory.c index 474637df36b..d39a73436b6 100644 --- a/src/nouveau/vulkan/nvk_device_memory.c +++ b/src/nouveau/vulkan/nvk_device_memory.c @@ -127,6 +127,8 @@ nvk_AllocateMemory(VkDevice device, vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR); const VkExportMemoryAllocateInfo *export_info = vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO); + const VkMemoryDedicatedAllocateInfo *dedicated_info = + vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); const VkMemoryType *type = &pdev->mem_types[pAllocateInfo->memoryTypeIndex]; @@ -143,6 +145,21 @@ nvk_AllocateMemory(VkDevice device, if (flags & NOUVEAU_WS_BO_LOCAL) alignment = (1ULL << 16); + uint8_t pte_kind = 0, tile_mode = 0; + if (dedicated_info != NULL) { + VK_FROM_HANDLE(nvk_image, image, dedicated_info->image); + if (image != NULL && + image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { + /* This image might be shared with GL so we need to set the BO flags + * such that GL can bind and use it. + */ + assert(image->plane_count == 1); + alignment = MAX2(alignment, image->planes[0].nil.align_B); + pte_kind = image->planes[0].nil.pte_kind; + tile_mode = image->planes[0].nil.tile_mode; + } + } + const uint64_t aligned_size = align64(pAllocateInfo->allocationSize, alignment); @@ -170,6 +187,13 @@ nvk_AllocateMemory(VkDevice device, */ if (fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) assert(!(flags & ~mem->bo->flags)); + } else if (pte_kind != 0 || tile_mode != 0) { + mem->bo = nouveau_ws_bo_new_tiled(dev->ws_dev, aligned_size, alignment, + pte_kind, tile_mode, flags); + if (!mem->bo) { + result = vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY, "%m"); + goto fail_alloc; + } } else { mem->bo = nouveau_ws_bo_new(dev->ws_dev, aligned_size, alignment, flags); if (!mem->bo) {