diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index a2ecd3bbcee..837f5bcf2a7 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -33,6 +33,7 @@ #include "common/intel_aux_map.h" #include "util/anon_file.h" #include "util/futex.h" +#include "util/os_mman.h" #ifdef HAVE_VALGRIND #define VG_NOACCESS_READ(__ptr) ({ \ @@ -1763,6 +1764,46 @@ anv_device_alloc_bo(struct anv_device *device, return VK_SUCCESS; } +static VkResult +map_placed_addr_slab(struct anv_device *device, + struct anv_bo *bo, + uint64_t offset, + size_t size, + void *placed_addr, + void **map_out) +{ + int prime_handle = anv_gem_handle_to_fd(device, bo->gem_handle); + VkResult result = VK_SUCCESS; + + if (prime_handle < 0) { + return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, + "anv_gem_handle_to_fd() before mmap failed: %m"); + } + + offset += (bo->offset - bo->slab_parent->offset); + void *map = os_mmap(placed_addr, + size, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, + prime_handle, + offset); + if (map == MAP_FAILED) { + result = vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m"); + goto end; + } + + assert(placed_addr == NULL || map == placed_addr); + assert(map != NULL); + VG(VALGRIND_MALLOCLIKE_BLOCK(map, size, 0, 1)); + + if (map_out) + *map_out = map; + +end: + close(prime_handle); + return result; +} + VkResult anv_device_map_bo(struct anv_device *device, struct anv_bo *bo, @@ -1777,6 +1818,9 @@ anv_device_map_bo(struct anv_device *device, struct anv_bo *real = anv_bo_get_real(bo); uint64_t offset_adjustment = 0; if (real != bo) { + if (placed_addr) + return map_placed_addr_slab(device, bo, offset, size, placed_addr, map_out); + offset += (bo->offset - real->offset); const uint64_t page_size = device->physical->page_size; @@ -1786,9 +1830,6 @@ anv_device_map_bo(struct anv_device *device, offset_adjustment = offset - munmap_offset; size += offset_adjustment; offset = munmap_offset; - - if (placed_addr) - placed_addr -= offset_adjustment; } assert((offset & (page_size - 1)) == 0); diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c index cdffa6b3637..a486ca5d9a2 100644 --- a/src/intel/vulkan/anv_gem.c +++ b/src/intel/vulkan/anv_gem.c @@ -91,7 +91,7 @@ anv_gem_handle_to_fd(struct anv_device *device, uint32_t gem_handle) int ret = intel_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); if (ret == -1) - return -1; + return -errno; return args.fd; } diff --git a/src/intel/vulkan/xe/anv_kmd_backend.c b/src/intel/vulkan/xe/anv_kmd_backend.c index f7e56013190..e56b9005551 100644 --- a/src/intel/vulkan/xe/anv_kmd_backend.c +++ b/src/intel/vulkan/xe/anv_kmd_backend.c @@ -32,6 +32,27 @@ #include "drm-uapi/gpu_scheduler.h" #include "drm-uapi/xe_drm.h" +static bool +is_slab_parent_memory_mapped_placeable(struct anv_device *device, + enum anv_bo_alloc_flags alloc_flags) +{ + if ((alloc_flags & ANV_BO_ALLOC_SLAB_PARENT) == false) + return false; + if (device->physical->instance->debug & ANV_DEBUG_NO_SLAB) + return false; + if (!device->vk.enabled_features.memoryMapPlaced) + return false; + + /* Not subject to vkMapMemory*() */ + enum anv_bo_alloc_flags no_vk_map_memory = ANV_BO_ALLOC_COMPRESSED | + ANV_BO_ALLOC_INTERNAL | + ANV_BO_ALLOC_DESCRIPTOR_POOL; + if (alloc_flags & no_vk_map_memory) + return false; + + return true; +} + static uint32_t xe_gem_create(struct anv_device *device, const struct intel_memory_class_instance **regions, @@ -70,12 +91,17 @@ xe_gem_create(struct anv_device *device, device->info->xe2_has_no_compression_hint) flags |= DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION; + /* From xe_drm.h: If a VM is specified, this BO must: + * 1. Only ever be bound to that VM. + * 2. Cannot be exported as a PRIME fd. + */ + uint32_t vm_id = device->vm_id; + if ((alloc_flags & ANV_BO_ALLOC_EXTERNAL) || + is_slab_parent_memory_mapped_placeable(device, alloc_flags)) + vm_id = 0; + struct drm_xe_gem_create gem_create = { - /* From xe_drm.h: If a VM is specified, this BO must: - * 1. Only ever be bound to that VM. - * 2. Cannot be exported as a PRIME fd. - */ - .vm_id = alloc_flags & ANV_BO_ALLOC_EXTERNAL ? 0 : device->vm_id, + .vm_id = vm_id, .size = align64(size, device->info->mem_alignment), .flags = flags, };