From b86ecec80bd4d0ae8e404bcd5cb0a391b24a5327 Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Thu, 12 Mar 2026 19:09:24 +0100 Subject: [PATCH] tu: Fix imported memory not being affected by DEVICE_ADDRESS_CAPTURE_REPLAY It's valid to import memory with DEVICE_ADDRESS_CAPTURE_REPLAY_BIT and we should allocate iova from the end of VMA heap, same as with ordinary memory allocations. This is important for replaying such memory, when it is being replayed without being imported. Fixes replay errors with RenderDoc. Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/vulkan/tu_device.cc | 27 +++++++++++++---------- src/freedreno/vulkan/tu_knl.cc | 4 +++- src/freedreno/vulkan/tu_knl.h | 3 ++- src/freedreno/vulkan/tu_knl_drm_msm.cc | 7 ++++-- src/freedreno/vulkan/tu_knl_drm_virtio.cc | 8 ++++--- src/freedreno/vulkan/tu_knl_kgsl.cc | 7 +++--- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc index d7256c3e9a0..f260e794d19 100644 --- a/src/freedreno/vulkan/tu_device.cc +++ b/src/freedreno/vulkan/tu_device.cc @@ -3571,6 +3571,16 @@ tu_AllocateMemory(VkDevice _device, mem->size = pAllocateInfo->allocationSize; mem->refcnt = 1; + BITMASK_ENUM(tu_bo_alloc_flags) alloc_flags = TU_BO_ALLOC_NO_FLAGS; + + const VkMemoryAllocateFlagsInfo *flags_info = vk_find_struct_const( + pAllocateInfo->pNext, MEMORY_ALLOCATE_FLAGS_INFO); + if (flags_info && + (flags_info->flags & + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT)) { + alloc_flags |= TU_BO_ALLOC_REPLAYABLE; + } + const VkImportMemoryFdInfoKHR *fd_info = vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR); @@ -3585,8 +3595,9 @@ tu_AllocateMemory(VkDevice _device, * reference counting. We need to maintain a per-instance handle-to-bo * table and add reference count to tu_bo. */ - result = tu_bo_init_dmabuf(device, &mem->bo, - pAllocateInfo->allocationSize, fd_info->fd); + result = + tu_bo_init_dmabuf(device, &mem->bo, pAllocateInfo->allocationSize, + alloc_flags, fd_info->fd); if (result == VK_SUCCESS) { /* take ownership and close the fd */ close(fd_info->fd); @@ -3596,13 +3607,13 @@ tu_AllocateMemory(VkDevice _device, const native_handle_t *handle = AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer); assert(handle->numFds > 0); size_t size = lseek(handle->data[0], 0, SEEK_END); - result = tu_bo_init_dmabuf(device, &mem->bo, size, handle->data[0]); + result = tu_bo_init_dmabuf(device, &mem->bo, size, alloc_flags, + handle->data[0]); #else result = VK_ERROR_FEATURE_NOT_PRESENT; #endif } else { uint64_t client_address = 0; - BITMASK_ENUM(tu_bo_alloc_flags) alloc_flags = TU_BO_ALLOC_NO_FLAGS; const VkMemoryOpaqueCaptureAddressAllocateInfo *replay_info = vk_find_struct_const(pAllocateInfo->pNext, @@ -3612,14 +3623,6 @@ tu_AllocateMemory(VkDevice _device, alloc_flags |= TU_BO_ALLOC_REPLAYABLE; } - const VkMemoryAllocateFlagsInfo *flags_info = vk_find_struct_const( - pAllocateInfo->pNext, MEMORY_ALLOCATE_FLAGS_INFO); - if (flags_info && - (flags_info->flags & - VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT)) { - alloc_flags |= TU_BO_ALLOC_REPLAYABLE; - } - const VkExportMemoryAllocateInfo *export_info = vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO); if (export_info && (export_info->handleTypes & diff --git a/src/freedreno/vulkan/tu_knl.cc b/src/freedreno/vulkan/tu_knl.cc index ba337d585cf..0b8e824145f 100644 --- a/src/freedreno/vulkan/tu_knl.cc +++ b/src/freedreno/vulkan/tu_knl.cc @@ -71,10 +71,12 @@ VkResult tu_bo_init_dmabuf(struct tu_device *dev, struct tu_bo **bo, uint64_t size, + enum tu_bo_alloc_flags flags, int fd) { + assert(!(flags & ~TU_BO_ALLOC_REPLAYABLE)); size = align64(size, os_page_size); - VkResult result = dev->instance->knl->bo_init_dmabuf(dev, bo, size, fd); + VkResult result = dev->instance->knl->bo_init_dmabuf(dev, bo, size, flags, fd); if (result != VK_SUCCESS) return result; diff --git a/src/freedreno/vulkan/tu_knl.h b/src/freedreno/vulkan/tu_knl.h index 93c1b6f6de8..195343e0e45 100644 --- a/src/freedreno/vulkan/tu_knl.h +++ b/src/freedreno/vulkan/tu_knl.h @@ -135,7 +135,7 @@ struct tu_knl { struct tu_sparse_vma *lazy_vma, const char *name); VkResult (*bo_init_dmabuf)(struct tu_device *dev, struct tu_bo **out_bo, - uint64_t size, int prime_fd); + uint64_t size, enum tu_bo_alloc_flags flags, int prime_fd); int (*bo_export_dmabuf)(struct tu_device *dev, struct tu_bo *bo); VkResult (*bo_alloc_lazy)(struct tu_device *dev, struct tu_bo *bo); VkResult (*bo_map)(struct tu_device *dev, struct tu_bo *bo, void *placed_addr); @@ -211,6 +211,7 @@ VkResult tu_bo_init_dmabuf(struct tu_device *dev, struct tu_bo **bo, uint64_t size, + enum tu_bo_alloc_flags flags, int fd); int diff --git a/src/freedreno/vulkan/tu_knl_drm_msm.cc b/src/freedreno/vulkan/tu_knl_drm_msm.cc index 1a47189d41d..8695981b6b1 100644 --- a/src/freedreno/vulkan/tu_knl_drm_msm.cc +++ b/src/freedreno/vulkan/tu_knl_drm_msm.cc @@ -976,8 +976,11 @@ static VkResult msm_bo_init_dmabuf(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size, + enum tu_bo_alloc_flags flags, int prime_fd) { + flags = (enum tu_bo_alloc_flags)(flags | TU_BO_ALLOC_DMABUF); + /* lseek() to get the real size */ off_t real_size = lseek(prime_fd, 0, SEEK_END); lseek(prime_fd, 0, SEEK_SET); @@ -1016,7 +1019,7 @@ msm_bo_init_dmabuf(struct tu_device *dev, } VkResult result = - tu_allocate_iova(dev, gem_handle, size, 0, TU_BO_ALLOC_DMABUF, &iova); + tu_allocate_iova(dev, gem_handle, size, 0, flags, &iova); if (result != VK_SUCCESS) { tu_gem_close(dev, gem_handle); @@ -1024,7 +1027,7 @@ msm_bo_init_dmabuf(struct tu_device *dev, } result = - tu_bo_init(dev, NULL, bo, gem_handle, size, iova, TU_BO_ALLOC_DMABUF, "dmabuf"); + tu_bo_init(dev, NULL, bo, gem_handle, size, iova, flags, "dmabuf"); if (result != VK_SUCCESS) { tu_free_iova(dev, iova, size); diff --git a/src/freedreno/vulkan/tu_knl_drm_virtio.cc b/src/freedreno/vulkan/tu_knl_drm_virtio.cc index e063030d70f..739bfc8a7cb 100644 --- a/src/freedreno/vulkan/tu_knl_drm_virtio.cc +++ b/src/freedreno/vulkan/tu_knl_drm_virtio.cc @@ -783,12 +783,14 @@ static VkResult virtio_bo_init_dmabuf(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size, + enum tu_bo_alloc_flags flags, int prime_fd) { MESA_TRACE_FUNC(); struct vdrm_device *vdrm = dev->vdev->vdrm; VkResult result; struct tu_bo* bo = NULL; + flags = (enum tu_bo_alloc_flags)(flags | TU_BO_ALLOC_DMABUF); /* lseek() to get the real size */ off_t real_size = lseek(prime_fd, 0, SEEK_END); @@ -836,8 +838,8 @@ virtio_bo_init_dmabuf(struct tu_device *dev, bo->res_id = res_id; mtx_lock(&dev->vma_mutex); - result = virtio_allocate_userspace_iova_locked(dev, handle, size, 0, - TU_BO_ALLOC_DMABUF, &iova); + result = virtio_allocate_userspace_iova_locked(dev, handle, size, 0, flags, + &iova); mtx_unlock(&dev->vma_mutex); if (result != VK_SUCCESS) { vdrm_bo_close(dev->vdev->vdrm, handle); @@ -845,7 +847,7 @@ virtio_bo_init_dmabuf(struct tu_device *dev, } result = - tu_bo_init(dev, NULL, bo, handle, size, iova, TU_BO_ALLOC_NO_FLAGS, "dmabuf"); + tu_bo_init(dev, NULL, bo, handle, size, iova, flags, "dmabuf"); if (result != VK_SUCCESS) { util_vma_heap_free(&dev->vma, iova, size); memset(bo, 0, sizeof(*bo)); diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc index 7ba858a974b..2e6da923da0 100644 --- a/src/freedreno/vulkan/tu_knl_kgsl.cc +++ b/src/freedreno/vulkan/tu_knl_kgsl.cc @@ -97,7 +97,7 @@ bo_init_new_dmaheap(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size, "DMA_HEAP_IOCTL_ALLOC failed (%s)", strerror(errno)); } - return tu_bo_init_dmabuf(dev, out_bo, -1, alloc.fd); + return tu_bo_init_dmabuf(dev, out_bo, -1, TU_BO_ALLOC_NO_FLAGS, alloc.fd); } static VkResult @@ -118,7 +118,7 @@ bo_init_new_ion(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size, "ION_IOC_NEW_ALLOC failed (%s)", strerror(errno)); } - return tu_bo_init_dmabuf(dev, out_bo, -1, alloc.fd); + return tu_bo_init_dmabuf(dev, out_bo, -1, TU_BO_ALLOC_NO_FLAGS, alloc.fd); } static VkResult @@ -160,7 +160,7 @@ bo_init_new_ion_legacy(struct tu_device *dev, struct tu_bo **out_bo, uint64_t si "ION_IOC_FREE failed (%s)", strerror(errno)); } - return tu_bo_init_dmabuf(dev, out_bo, -1, share.fd); + return tu_bo_init_dmabuf(dev, out_bo, -1, TU_BO_ALLOC_NO_FLAGS, share.fd); } static VkResult @@ -328,6 +328,7 @@ static VkResult kgsl_bo_init_dmabuf(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size, + enum tu_bo_alloc_flags flags, int fd) { struct kgsl_gpuobj_import_dma_buf import_dmabuf = {