If softpin is supported, create new BOs for the required size and add the respective BO maps. The other main change of this commit is that anv_block_pool_map() now returns the map for the BO that the given offset is part of. So there's no block_pool->map access anymore (when softpin is used. --- src/intel/vulkan/anv_allocator.c | 92 ++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 39 deletions(-)
diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 0d426edfb57..46f2278a56c 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -473,17 +473,19 @@ anv_block_pool_init(struct anv_block_pool *pool, pool->size = 0; pool->start_address = gen_canonical_address(start_address); - pool->fd = memfd_create("block pool", MFD_CLOEXEC); - if (pool->fd == -1) - return vk_error(VK_ERROR_INITIALIZATION_FAILED); - - /* Just make it 2GB up-front. The Linux kernel won't actually back it - * with pages until we either map and fault on one of them or we use - * userptr and send a chunk of it off to the GPU. - */ - if (ftruncate(pool->fd, BLOCK_POOL_MEMFD_SIZE) == -1) { - result = vk_error(VK_ERROR_INITIALIZATION_FAILED); - goto fail_fd; + if (!(pool->bo_flags & EXEC_OBJECT_PINNED)) { + pool->fd = memfd_create("block pool", MFD_CLOEXEC); + if (pool->fd == -1) + return vk_error(VK_ERROR_INITIALIZATION_FAILED); + + /* Just make it 2GB up-front. The Linux kernel won't actually back it + * with pages until we either map and fault on one of them or we use + * userptr and send a chunk of it off to the GPU. + */ + if (ftruncate(pool->fd, BLOCK_POOL_MEMFD_SIZE) == -1) { + result = vk_error(VK_ERROR_INITIALIZATION_FAILED); + goto fail_fd; + } } if (!u_vector_init(&pool->mmap_cleanups, @@ -507,7 +509,8 @@ anv_block_pool_init(struct anv_block_pool *pool, fail_mmap_cleanups: u_vector_finish(&pool->mmap_cleanups); fail_fd: - close(pool->fd); + if (!(pool->bo_flags & EXEC_OBJECT_PINNED)) + close(pool->fd); return result; } @@ -525,8 +528,9 @@ anv_block_pool_finish(struct anv_block_pool *pool) } u_vector_finish(&pool->mmap_cleanups); + if (!(pool->bo_flags & EXEC_OBJECT_PINNED)) + close(pool->fd); - close(pool->fd); anv_block_pool_bo_finish(pool); } @@ -537,6 +541,7 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, void *map; uint32_t gem_handle; struct anv_mmap_cleanup *cleanup; + const bool use_softpin = !!(pool->bo_flags & EXEC_OBJECT_PINNED); /* Assert that we only ever grow the pool */ assert(center_bo_offset >= pool->back_state.end); @@ -544,7 +549,8 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, /* Assert that we don't go outside the bounds of the memfd */ assert(center_bo_offset <= BLOCK_POOL_MEMFD_CENTER); - assert(size - center_bo_offset <= + assert(use_softpin || + size - center_bo_offset <= BLOCK_POOL_MEMFD_SIZE - BLOCK_POOL_MEMFD_CENTER); cleanup = u_vector_add(&pool->mmap_cleanups); @@ -553,28 +559,36 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, *cleanup = ANV_MMAP_CLEANUP_INIT; - /* Just leak the old map until we destroy the pool. We can't munmap it - * without races or imposing locking on the block allocate fast path. On - * the whole the leaked maps adds up to less than the size of the - * current map. MAP_POPULATE seems like the right thing to do, but we - * should try to get some numbers. - */ - map = mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, pool->fd, - BLOCK_POOL_MEMFD_CENTER - center_bo_offset); - if (map == MAP_FAILED) - return vk_errorf(pool->device->instance, pool->device, - VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m"); - - gem_handle = anv_gem_userptr(pool->device, map, size); - if (gem_handle == 0) { - munmap(map, size); - return vk_errorf(pool->device->instance, pool->device, - VK_ERROR_TOO_MANY_OBJECTS, "userptr failed: %m"); + uint32_t newbo_size = size - pool->size; + if (use_softpin) { + gem_handle = anv_gem_create(pool->device, newbo_size); + map = anv_gem_mmap(pool->device, gem_handle, 0, newbo_size, 0); + if (map == MAP_FAILED) + return vk_errorf(pool->device->instance, pool->device, + VK_ERROR_MEMORY_MAP_FAILED, "gem mmap failed: %m"); + } else { + /* Just leak the old map until we destroy the pool. We can't munmap it + * without races or imposing locking on the block allocate fast path. On + * the whole the leaked maps adds up to less than the size of the + * current map. MAP_POPULATE seems like the right thing to do, but we + * should try to get some numbers. + */ + map = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, pool->fd, + BLOCK_POOL_MEMFD_CENTER - center_bo_offset); + if (map == MAP_FAILED) + return vk_errorf(pool->device->instance, pool->device, + VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m"); + gem_handle = anv_gem_userptr(pool->device, map, size); + if (gem_handle == 0) { + munmap(map, size); + return vk_errorf(pool->device->instance, pool->device, + VK_ERROR_TOO_MANY_OBJECTS, "userptr failed: %m"); + } } cleanup->map = map; - cleanup->size = size; + cleanup->size = use_softpin ? newbo_size : size; cleanup->gem_handle = gem_handle; #if 0 @@ -593,7 +607,9 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, /* Now that we successfull allocated everything, we can write the new * values back into pool. */ - pool->map = map + center_bo_offset; + if (!use_softpin) { + pool->map = map + center_bo_offset; + } pool->center_bo_offset = center_bo_offset; /* For block pool BOs we have to be a bit careful about where we place them @@ -628,7 +644,7 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, * range. On the other hand, if not using softpin, we need to add a BO if we * don't have one yet. */ - if (!pool->bo) { + if (use_softpin || !pool->bo) { bo_elem = malloc(sizeof(*bo_elem)); bo = &bo_elem->bo; } else { @@ -639,10 +655,9 @@ anv_block_pool_expand_range(struct anv_block_pool *pool, if (!pool->bo) pool->bo = bo; - anv_bo_init(bo, gem_handle, size); + anv_bo_init(bo, gem_handle, use_softpin ? newbo_size : size); if (pool->bo_flags & EXEC_OBJECT_PINNED) { - bo->offset = pool->start_address + BLOCK_POOL_MEMFD_CENTER - - center_bo_offset; + bo->offset = pool->start_address + pool->size; } bo->flags = pool->bo_flags; bo->map = map; @@ -850,7 +865,6 @@ anv_block_pool_alloc_new(struct anv_block_pool *pool, while (1) { state.u64 = __sync_fetch_and_add(&pool_state->u64, block_size); if (state.next + block_size <= state.end) { - assert(pool->map); return state.next; } else if (state.next <= state.end) { if (pool->bo_flags & EXEC_OBJECT_PINNED && state.next < state.end) { -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev