diff --git a/src/nouveau/vulkan/nvk_device_memory.c b/src/nouveau/vulkan/nvk_device_memory.c index 9c6a0b9132c..a645b073c67 100644 --- a/src/nouveau/vulkan/nvk_device_memory.c +++ b/src/nouveau/vulkan/nvk_device_memory.c @@ -282,6 +282,13 @@ nvk_MapMemory2KHR(VkDevice device, vk_device_memory_range(&mem->vk, pMemoryMapInfo->offset, pMemoryMapInfo->size); + void *fixed_addr = NULL; + if (pMemoryMapInfo->flags & VK_MEMORY_MAP_PLACED_BIT_EXT) { + const VkMemoryMapPlacedInfoEXT *placed_info = + vk_find_struct_const(pMemoryMapInfo->pNext, MEMORY_MAP_PLACED_INFO_EXT); + fixed_addr = placed_info->pPlacedAddress; + } + /* From the Vulkan spec version 1.0.32 docs for MapMemory: * * * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0 @@ -307,7 +314,7 @@ nvk_MapMemory2KHR(VkDevice device, "Memory object already mapped."); } - mem->map = nouveau_ws_bo_map(mem->bo, NOUVEAU_WS_BO_RDWR, NULL); + mem->map = nouveau_ws_bo_map(mem->bo, NOUVEAU_WS_BO_RDWR, fixed_addr); if (mem->map == NULL) { return vk_errorf(dev, VK_ERROR_MEMORY_MAP_FAILED, "Memory object couldn't be mapped."); @@ -322,12 +329,22 @@ VKAPI_ATTR VkResult VKAPI_CALL nvk_UnmapMemory2KHR(VkDevice device, const VkMemoryUnmapInfoKHR *pMemoryUnmapInfo) { + VK_FROM_HANDLE(nvk_device, dev, device); VK_FROM_HANDLE(nvk_device_memory, mem, pMemoryUnmapInfo->memory); if (mem == NULL) return VK_SUCCESS; - nouveau_ws_bo_unmap(mem->bo, mem->map); + if (pMemoryUnmapInfo->flags & VK_MEMORY_UNMAP_RESERVE_BIT_EXT) { + int err = nouveau_ws_bo_overmap(mem->bo, mem->map); + if (err) { + return vk_errorf(dev, VK_ERROR_MEMORY_MAP_FAILED, + "Failed to map over original mapping"); + } + } else { + nouveau_ws_bo_unmap(mem->bo, mem->map); + } + mem->map = NULL; return VK_SUCCESS; diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index acdacf67e16..086a72fd33b 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -176,6 +176,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance, .EXT_inline_uniform_block = true, .EXT_line_rasterization = true, .EXT_load_store_op_none = true, + .EXT_map_memory_placed = true, .EXT_multi_draw = true, .EXT_mutable_descriptor_type = true, .EXT_non_seamless_cube_map = true, @@ -470,6 +471,11 @@ nvk_get_device_features(const struct nv_device_info *info, .stippledBresenhamLines = true, .stippledSmoothLines = true, + /* VK_EXT_map_memory_placed */ + .memoryMapPlaced = true, + .memoryMapRangePlaced = false, + .memoryUnmapReserve = true, + /* VK_EXT_multi_draw */ .multiDraw = true, @@ -550,6 +556,9 @@ nvk_get_device_properties(const struct nvk_instance *instance, VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT; + uint64_t os_page_size = 4096; + os_get_page_size(&os_page_size); + *properties = (struct vk_properties) { .apiVersion = nvk_get_vk_version(info), .driverVersion = vk_get_driver_version(), @@ -785,6 +794,9 @@ nvk_get_device_properties(const struct nvk_instance *instance, /* VK_KHR_line_rasterization */ .lineSubPixelPrecisionBits = 8, + /* VK_EXT_map_memory_placed */ + .minPlacedMemoryMapAlignment = os_page_size, + /* VK_EXT_multi_draw */ .maxMultiDrawCount = UINT32_MAX, diff --git a/src/nouveau/winsys/nouveau_bo.h b/src/nouveau/winsys/nouveau_bo.h index 8947aec4f07..27a2c5ebf57 100644 --- a/src/nouveau/winsys/nouveau_bo.h +++ b/src/nouveau/winsys/nouveau_bo.h @@ -89,6 +89,14 @@ nouveau_ws_bo_unmap(struct nouveau_ws_bo *bo, void *ptr) munmap(ptr, bo->size); } +static inline int +nouveau_ws_bo_overmap(struct nouveau_ws_bo *bo, void *ptr) +{ + void *map = mmap(ptr, bo->size, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + return map == MAP_FAILED ? -1 : 0; +} + #ifdef __cplusplus } #endif