1/* 2 * Copyright 2019 Google LLC 3 * SPDX-License-Identifier: MIT 4 * 5 * based in part on anv and radv which are: 6 * Copyright © 2015 Intel Corporation 7 * Copyright © 2016 Red Hat. 8 * Copyright © 2016 Bas Nieuwenhuizen 9 */ 10 11#include "vn_device_memory.h" 12 13#include "venus-protocol/vn_protocol_driver_device_memory.h" 14#include "venus-protocol/vn_protocol_driver_transport.h" 15 16#include "vn_android.h" 17#include "vn_buffer.h" 18#include "vn_device.h" 19#include "vn_image.h" 20#include "vn_physical_device.h" 21 22/* device memory commands */ 23 24static VkResult 25vn_device_memory_pool_grow_alloc(struct vn_device *dev, 26 uint32_t mem_type_index, 27 VkDeviceSize size, 28 struct vn_device_memory **out_mem) 29{ 30 VkDevice dev_handle = vn_device_to_handle(dev); 31 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 32 const VkPhysicalDeviceMemoryProperties *mem_props = 33 &dev->physical_device->memory_properties.memoryProperties; 34 const VkMemoryPropertyFlags mem_flags = 35 mem_props->memoryTypes[mem_type_index].propertyFlags; 36 struct vn_device_memory *mem = NULL; 37 VkDeviceMemory mem_handle = VK_NULL_HANDLE; 38 VkResult result; 39 40 mem = vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN, 41 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 42 if (!mem) 43 return VK_ERROR_OUT_OF_HOST_MEMORY; 44 45 vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base); 46 mem->size = size; 47 mem->flags = mem_flags; 48 49 mem_handle = vn_device_memory_to_handle(mem); 50 result = vn_call_vkAllocateMemory( 51 dev->instance, dev_handle, 52 &(const VkMemoryAllocateInfo){ 53 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 54 .allocationSize = size, 55 .memoryTypeIndex = mem_type_index, 56 }, 57 NULL, &mem_handle); 58 if (result != VK_SUCCESS) { 59 mem_handle = VK_NULL_HANDLE; 60 goto fail; 61 } 62 63 result = vn_renderer_bo_create_from_device_memory( 64 dev->renderer, mem->size, mem->base.id, mem->flags, 0, &mem->base_bo); 65 if (result != VK_SUCCESS) { 66 assert(!mem->base_bo); 67 goto fail; 68 } 69 70 result = 71 vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno); 72 if (result != VK_SUCCESS) 73 goto fail; 74 75 mem->bo_roundtrip_seqno_valid = true; 76 *out_mem = mem; 77 78 return VK_SUCCESS; 79 80fail: 81 if (mem->base_bo) 82 vn_renderer_bo_unref(dev->renderer, mem->base_bo); 83 if (mem_handle != VK_NULL_HANDLE) 84 vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL); 85 vn_object_base_fini(&mem->base); 86 vk_free(alloc, mem); 87 return result; 88} 89 90static struct vn_device_memory * 91vn_device_memory_pool_ref(struct vn_device *dev, 92 struct vn_device_memory *pool_mem) 93{ 94 assert(pool_mem->base_bo); 95 96 vn_renderer_bo_ref(dev->renderer, pool_mem->base_bo); 97 98 return pool_mem; 99} 100 101static void 102vn_device_memory_pool_unref(struct vn_device *dev, 103 struct vn_device_memory *pool_mem) 104{ 105 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 106 107 assert(pool_mem->base_bo); 108 109 if (!vn_renderer_bo_unref(dev->renderer, pool_mem->base_bo)) 110 return; 111 112 /* wait on valid bo_roundtrip_seqno before vkFreeMemory */ 113 if (pool_mem->bo_roundtrip_seqno_valid) 114 vn_instance_wait_roundtrip(dev->instance, pool_mem->bo_roundtrip_seqno); 115 116 vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev), 117 vn_device_memory_to_handle(pool_mem), NULL); 118 vn_object_base_fini(&pool_mem->base); 119 vk_free(alloc, pool_mem); 120} 121 122void 123vn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index) 124{ 125 struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index]; 126 if (pool->memory) 127 vn_device_memory_pool_unref(dev, pool->memory); 128 mtx_destroy(&pool->mutex); 129} 130 131static VkResult 132vn_device_memory_pool_grow_locked(struct vn_device *dev, 133 uint32_t mem_type_index, 134 VkDeviceSize size) 135{ 136 struct vn_device_memory *mem; 137 VkResult result = 138 vn_device_memory_pool_grow_alloc(dev, mem_type_index, size, &mem); 139 if (result != VK_SUCCESS) 140 return result; 141 142 struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index]; 143 if (pool->memory) 144 vn_device_memory_pool_unref(dev, pool->memory); 145 146 pool->memory = mem; 147 pool->used = 0; 148 149 return VK_SUCCESS; 150} 151 152static VkResult 153vn_device_memory_pool_suballocate(struct vn_device *dev, 154 struct vn_device_memory *mem, 155 uint32_t mem_type_index) 156{ 157 const VkDeviceSize pool_size = 16 * 1024 * 1024; 158 /* XXX We don't know the alignment requirement. Use 64K because some GPUs 159 * have 64K pages. It is also required by newer Intel GPUs. But really we 160 * should require kernel 5.12+, where there is no KVM memslot limit, and 161 * remove this whole thing. 162 */ 163 const VkDeviceSize pool_align = 64 * 1024; 164 struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index]; 165 166 assert(mem->size <= pool_size); 167 168 mtx_lock(&pool->mutex); 169 170 if (!pool->memory || pool->used + mem->size > pool_size) { 171 VkResult result = 172 vn_device_memory_pool_grow_locked(dev, mem_type_index, pool_size); 173 if (result != VK_SUCCESS) { 174 mtx_unlock(&pool->mutex); 175 return result; 176 } 177 } 178 179 mem->base_memory = vn_device_memory_pool_ref(dev, pool->memory); 180 181 /* point mem->base_bo at pool base_bo and assign base_offset accordingly */ 182 mem->base_bo = pool->memory->base_bo; 183 mem->base_offset = pool->used; 184 pool->used += align64(mem->size, pool_align); 185 186 mtx_unlock(&pool->mutex); 187 188 return VK_SUCCESS; 189} 190 191static bool 192vn_device_memory_should_suballocate(const struct vn_device *dev, 193 const VkMemoryAllocateInfo *alloc_info, 194 const VkMemoryPropertyFlags flags) 195{ 196 const struct vn_instance *instance = dev->physical_device->instance; 197 const struct vn_renderer_info *renderer = &instance->renderer->info; 198 199 if (renderer->has_guest_vram) 200 return false; 201 202 /* We should not support suballocations because apps can do better. But 203 * each BO takes up a KVM memslot currently and some CTS tests exhausts 204 * them. This might not be needed on newer (host) kernels where there are 205 * many more KVM memslots. 206 */ 207 208 /* consider host-visible memory only */ 209 if (!(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) 210 return false; 211 212 /* reject larger allocations */ 213 if (alloc_info->allocationSize > 64 * 1024) 214 return false; 215 216 /* reject if there is any pnext struct other than 217 * VkMemoryDedicatedAllocateInfo, or if dedicated allocation is required 218 */ 219 if (alloc_info->pNext) { 220 const VkMemoryDedicatedAllocateInfo *dedicated = alloc_info->pNext; 221 if (dedicated->sType != 222 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO || 223 dedicated->pNext) 224 return false; 225 226 const struct vn_image *img = vn_image_from_handle(dedicated->image); 227 if (img) { 228 for (uint32_t i = 0; i < ARRAY_SIZE(img->requirements); i++) { 229 if (img->requirements[i].dedicated.requiresDedicatedAllocation) 230 return false; 231 } 232 } 233 234 const struct vn_buffer *buf = vn_buffer_from_handle(dedicated->buffer); 235 if (buf && buf->requirements.dedicated.requiresDedicatedAllocation) 236 return false; 237 } 238 239 return true; 240} 241 242VkResult 243vn_device_memory_import_dma_buf(struct vn_device *dev, 244 struct vn_device_memory *mem, 245 const VkMemoryAllocateInfo *alloc_info, 246 bool force_unmappable, 247 int fd) 248{ 249 VkDevice device = vn_device_to_handle(dev); 250 VkDeviceMemory memory = vn_device_memory_to_handle(mem); 251 const VkPhysicalDeviceMemoryProperties *mem_props = 252 &dev->physical_device->memory_properties.memoryProperties; 253 VkMemoryPropertyFlags mem_flags = 254 mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags; 255 struct vn_renderer_bo *bo; 256 VkResult result = VK_SUCCESS; 257 258 if (force_unmappable) 259 mem_flags &= ~VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 260 261 result = vn_renderer_bo_create_from_dma_buf( 262 dev->renderer, alloc_info->allocationSize, fd, mem_flags, &bo); 263 if (result != VK_SUCCESS) 264 return result; 265 266 vn_instance_roundtrip(dev->instance); 267 268 /* XXX fix VkImportMemoryResourceInfoMESA to support memory planes */ 269 const VkImportMemoryResourceInfoMESA import_memory_resource_info = { 270 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA, 271 .pNext = alloc_info->pNext, 272 .resourceId = bo->res_id, 273 }; 274 const VkMemoryAllocateInfo memory_allocate_info = { 275 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 276 .pNext = &import_memory_resource_info, 277 .allocationSize = alloc_info->allocationSize, 278 .memoryTypeIndex = alloc_info->memoryTypeIndex, 279 }; 280 result = vn_call_vkAllocateMemory(dev->instance, device, 281 &memory_allocate_info, NULL, &memory); 282 if (result != VK_SUCCESS) { 283 vn_renderer_bo_unref(dev->renderer, bo); 284 return result; 285 } 286 287 /* need to close import fd on success to avoid fd leak */ 288 close(fd); 289 mem->base_bo = bo; 290 291 return VK_SUCCESS; 292} 293 294static VkResult 295vn_device_memory_alloc_guest_vram( 296 struct vn_device *dev, 297 struct vn_device_memory *mem, 298 const VkMemoryAllocateInfo *alloc_info, 299 VkExternalMemoryHandleTypeFlags external_handles) 300{ 301 VkDevice dev_handle = vn_device_to_handle(dev); 302 VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem); 303 VkResult result = VK_SUCCESS; 304 305 result = vn_renderer_bo_create_from_device_memory( 306 dev->renderer, mem->size, 0, mem->flags, external_handles, 307 &mem->base_bo); 308 if (result != VK_SUCCESS) { 309 return result; 310 } 311 312 const VkImportMemoryResourceInfoMESA import_memory_resource_info = { 313 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA, 314 .pNext = alloc_info->pNext, 315 .resourceId = mem->base_bo->res_id, 316 }; 317 318 const VkMemoryAllocateInfo memory_allocate_info = { 319 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 320 .pNext = &import_memory_resource_info, 321 .allocationSize = alloc_info->allocationSize, 322 .memoryTypeIndex = alloc_info->memoryTypeIndex, 323 }; 324 325 vn_instance_roundtrip(dev->instance); 326 327 result = vn_call_vkAllocateMemory( 328 dev->instance, dev_handle, &memory_allocate_info, NULL, &mem_handle); 329 if (result != VK_SUCCESS) { 330 vn_renderer_bo_unref(dev->renderer, mem->base_bo); 331 return result; 332 } 333 334 result = 335 vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno); 336 if (result != VK_SUCCESS) { 337 vn_renderer_bo_unref(dev->renderer, mem->base_bo); 338 vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL); 339 return result; 340 } 341 342 mem->bo_roundtrip_seqno_valid = true; 343 344 return VK_SUCCESS; 345} 346 347static VkResult 348vn_device_memory_alloc_generic( 349 struct vn_device *dev, 350 struct vn_device_memory *mem, 351 const VkMemoryAllocateInfo *alloc_info, 352 VkExternalMemoryHandleTypeFlags external_handles) 353{ 354 VkDevice dev_handle = vn_device_to_handle(dev); 355 VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem); 356 VkResult result = VK_SUCCESS; 357 358 result = vn_call_vkAllocateMemory(dev->instance, dev_handle, alloc_info, 359 NULL, &mem_handle); 360 if (result != VK_SUCCESS || !external_handles) 361 return result; 362 363 result = vn_renderer_bo_create_from_device_memory( 364 dev->renderer, mem->size, mem->base.id, mem->flags, external_handles, 365 &mem->base_bo); 366 if (result != VK_SUCCESS) { 367 vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL); 368 return result; 369 } 370 371 result = 372 vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno); 373 if (result != VK_SUCCESS) { 374 vn_renderer_bo_unref(dev->renderer, mem->base_bo); 375 vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL); 376 return result; 377 } 378 379 mem->bo_roundtrip_seqno_valid = true; 380 381 return VK_SUCCESS; 382} 383 384static VkResult 385vn_device_memory_alloc(struct vn_device *dev, 386 struct vn_device_memory *mem, 387 const VkMemoryAllocateInfo *alloc_info, 388 VkExternalMemoryHandleTypeFlags external_handles) 389{ 390 const struct vn_instance *instance = dev->physical_device->instance; 391 const struct vn_renderer_info *renderer_info = &instance->renderer->info; 392 393 if (renderer_info->has_guest_vram) { 394 return vn_device_memory_alloc_guest_vram(dev, mem, alloc_info, 395 external_handles); 396 } 397 398 return vn_device_memory_alloc_generic(dev, mem, alloc_info, 399 external_handles); 400} 401 402VkResult 403vn_AllocateMemory(VkDevice device, 404 const VkMemoryAllocateInfo *pAllocateInfo, 405 const VkAllocationCallbacks *pAllocator, 406 VkDeviceMemory *pMemory) 407{ 408 VN_TRACE_FUNC(); 409 struct vn_device *dev = vn_device_from_handle(device); 410 const VkAllocationCallbacks *alloc = 411 pAllocator ? pAllocator : &dev->base.base.alloc; 412 413 const VkPhysicalDeviceMemoryProperties *mem_props = 414 &dev->physical_device->memory_properties.memoryProperties; 415 const VkMemoryPropertyFlags mem_flags = 416 mem_props->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags; 417 418 const VkExportMemoryAllocateInfo *export_info = NULL; 419 const VkImportAndroidHardwareBufferInfoANDROID *import_ahb_info = NULL; 420 const VkImportMemoryFdInfoKHR *import_fd_info = NULL; 421 bool export_ahb = false; 422 423 vk_foreach_struct_const(pnext, pAllocateInfo->pNext) { 424 switch (pnext->sType) { 425 case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: 426 export_info = (void *)pnext; 427 if (export_info->handleTypes & 428 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) 429 export_ahb = true; 430 else if (!export_info->handleTypes) 431 export_info = NULL; 432 break; 433 case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: 434 import_ahb_info = (void *)pnext; 435 break; 436 case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: 437 import_fd_info = (void *)pnext; 438 break; 439 default: 440 break; 441 } 442 } 443 444 struct vn_device_memory *mem = 445 vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN, 446 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 447 if (!mem) 448 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 449 450 vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base); 451 mem->size = pAllocateInfo->allocationSize; 452 mem->flags = mem_flags; 453 454 VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem); 455 VkResult result; 456 if (import_ahb_info) { 457 result = vn_android_device_import_ahb(dev, mem, pAllocateInfo, alloc, 458 import_ahb_info->buffer, false); 459 } else if (export_ahb) { 460 result = vn_android_device_allocate_ahb(dev, mem, pAllocateInfo, alloc); 461 } else if (import_fd_info) { 462 result = vn_device_memory_import_dma_buf(dev, mem, pAllocateInfo, false, 463 import_fd_info->fd); 464 } else if (export_info) { 465 result = vn_device_memory_alloc(dev, mem, pAllocateInfo, 466 export_info->handleTypes); 467 } else if (vn_device_memory_should_suballocate(dev, pAllocateInfo, 468 mem_flags)) { 469 result = vn_device_memory_pool_suballocate( 470 dev, mem, pAllocateInfo->memoryTypeIndex); 471 } else { 472 result = vn_device_memory_alloc(dev, mem, pAllocateInfo, 0); 473 } 474 if (result != VK_SUCCESS) { 475 vn_object_base_fini(&mem->base); 476 vk_free(alloc, mem); 477 return vn_error(dev->instance, result); 478 } 479 480 *pMemory = mem_handle; 481 482 return VK_SUCCESS; 483} 484 485void 486vn_FreeMemory(VkDevice device, 487 VkDeviceMemory memory, 488 const VkAllocationCallbacks *pAllocator) 489{ 490 VN_TRACE_FUNC(); 491 struct vn_device *dev = vn_device_from_handle(device); 492 struct vn_device_memory *mem = vn_device_memory_from_handle(memory); 493 const VkAllocationCallbacks *alloc = 494 pAllocator ? pAllocator : &dev->base.base.alloc; 495 496 if (!mem) 497 return; 498 499 if (mem->base_memory) { 500 vn_device_memory_pool_unref(dev, mem->base_memory); 501 } else { 502 if (mem->base_bo) 503 vn_renderer_bo_unref(dev->renderer, mem->base_bo); 504 505 if (mem->bo_roundtrip_seqno_valid) 506 vn_instance_wait_roundtrip(dev->instance, mem->bo_roundtrip_seqno); 507 508 vn_async_vkFreeMemory(dev->instance, device, memory, NULL); 509 } 510 511 if (mem->ahb) 512 vn_android_release_ahb(mem->ahb); 513 514 vn_object_base_fini(&mem->base); 515 vk_free(alloc, mem); 516} 517 518uint64_t 519vn_GetDeviceMemoryOpaqueCaptureAddress( 520 VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo) 521{ 522 struct vn_device *dev = vn_device_from_handle(device); 523 ASSERTED struct vn_device_memory *mem = 524 vn_device_memory_from_handle(pInfo->memory); 525 526 assert(!mem->base_memory); 527 return vn_call_vkGetDeviceMemoryOpaqueCaptureAddress(dev->instance, device, 528 pInfo); 529} 530 531VkResult 532vn_MapMemory(VkDevice device, 533 VkDeviceMemory memory, 534 VkDeviceSize offset, 535 VkDeviceSize size, 536 VkMemoryMapFlags flags, 537 void **ppData) 538{ 539 VN_TRACE_FUNC(); 540 struct vn_device *dev = vn_device_from_handle(device); 541 struct vn_device_memory *mem = vn_device_memory_from_handle(memory); 542 const bool need_bo = !mem->base_bo; 543 void *ptr = NULL; 544 VkResult result; 545 546 assert(mem->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); 547 548 /* We don't want to blindly create a bo for each HOST_VISIBLE memory as 549 * that has a cost. By deferring bo creation until now, we can avoid the 550 * cost unless a bo is really needed. However, that means 551 * vn_renderer_bo_map will block until the renderer creates the resource 552 * and injects the pages into the guest. 553 */ 554 if (need_bo) { 555 result = vn_renderer_bo_create_from_device_memory( 556 dev->renderer, mem->size, mem->base.id, mem->flags, 0, 557 &mem->base_bo); 558 if (result != VK_SUCCESS) 559 return vn_error(dev->instance, result); 560 } 561 562 ptr = vn_renderer_bo_map(dev->renderer, mem->base_bo); 563 if (!ptr) { 564 /* vn_renderer_bo_map implies a roundtrip on success, but not here. */ 565 if (need_bo) { 566 result = vn_instance_submit_roundtrip(dev->instance, 567 &mem->bo_roundtrip_seqno); 568 if (result != VK_SUCCESS) 569 return vn_error(dev->instance, result); 570 571 mem->bo_roundtrip_seqno_valid = true; 572 } 573 574 return vn_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED); 575 } 576 577 mem->map_end = size == VK_WHOLE_SIZE ? mem->size : offset + size; 578 579 *ppData = ptr + mem->base_offset + offset; 580 581 return VK_SUCCESS; 582} 583 584void 585vn_UnmapMemory(VkDevice device, VkDeviceMemory memory) 586{ 587 VN_TRACE_FUNC(); 588} 589 590VkResult 591vn_FlushMappedMemoryRanges(VkDevice device, 592 uint32_t memoryRangeCount, 593 const VkMappedMemoryRange *pMemoryRanges) 594{ 595 VN_TRACE_FUNC(); 596 struct vn_device *dev = vn_device_from_handle(device); 597 598 for (uint32_t i = 0; i < memoryRangeCount; i++) { 599 const VkMappedMemoryRange *range = &pMemoryRanges[i]; 600 struct vn_device_memory *mem = 601 vn_device_memory_from_handle(range->memory); 602 603 const VkDeviceSize size = range->size == VK_WHOLE_SIZE 604 ? mem->map_end - range->offset 605 : range->size; 606 vn_renderer_bo_flush(dev->renderer, mem->base_bo, 607 mem->base_offset + range->offset, size); 608 } 609 610 return VK_SUCCESS; 611} 612 613VkResult 614vn_InvalidateMappedMemoryRanges(VkDevice device, 615 uint32_t memoryRangeCount, 616 const VkMappedMemoryRange *pMemoryRanges) 617{ 618 VN_TRACE_FUNC(); 619 struct vn_device *dev = vn_device_from_handle(device); 620 621 for (uint32_t i = 0; i < memoryRangeCount; i++) { 622 const VkMappedMemoryRange *range = &pMemoryRanges[i]; 623 struct vn_device_memory *mem = 624 vn_device_memory_from_handle(range->memory); 625 626 const VkDeviceSize size = range->size == VK_WHOLE_SIZE 627 ? mem->map_end - range->offset 628 : range->size; 629 vn_renderer_bo_invalidate(dev->renderer, mem->base_bo, 630 mem->base_offset + range->offset, size); 631 } 632 633 return VK_SUCCESS; 634} 635 636void 637vn_GetDeviceMemoryCommitment(VkDevice device, 638 VkDeviceMemory memory, 639 VkDeviceSize *pCommittedMemoryInBytes) 640{ 641 struct vn_device *dev = vn_device_from_handle(device); 642 ASSERTED struct vn_device_memory *mem = 643 vn_device_memory_from_handle(memory); 644 645 assert(!mem->base_memory); 646 vn_call_vkGetDeviceMemoryCommitment(dev->instance, device, memory, 647 pCommittedMemoryInBytes); 648} 649 650VkResult 651vn_GetMemoryFdKHR(VkDevice device, 652 const VkMemoryGetFdInfoKHR *pGetFdInfo, 653 int *pFd) 654{ 655 VN_TRACE_FUNC(); 656 struct vn_device *dev = vn_device_from_handle(device); 657 struct vn_device_memory *mem = 658 vn_device_memory_from_handle(pGetFdInfo->memory); 659 660 /* At the moment, we support only the below handle types. */ 661 assert(pGetFdInfo->handleType & 662 (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 663 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)); 664 assert(!mem->base_memory && mem->base_bo); 665 *pFd = vn_renderer_bo_export_dma_buf(dev->renderer, mem->base_bo); 666 if (*pFd < 0) 667 return vn_error(dev->instance, VK_ERROR_TOO_MANY_OBJECTS); 668 669 return VK_SUCCESS; 670} 671 672VkResult 673vn_get_memory_dma_buf_properties(struct vn_device *dev, 674 int fd, 675 uint64_t *out_alloc_size, 676 uint32_t *out_mem_type_bits) 677{ 678 VkDevice device = vn_device_to_handle(dev); 679 struct vn_renderer_bo *bo = NULL; 680 VkResult result = VK_SUCCESS; 681 682 result = vn_renderer_bo_create_from_dma_buf(dev->renderer, 0 /* size */, 683 fd, 0 /* flags */, &bo); 684 if (result != VK_SUCCESS) 685 return result; 686 687 vn_instance_roundtrip(dev->instance); 688 689 VkMemoryResourceAllocationSizeProperties100000MESA alloc_size_props = { 690 .sType = 691 VK_STRUCTURE_TYPE_MEMORY_RESOURCE_ALLOCATION_SIZE_PROPERTIES_100000_MESA, 692 .pNext = NULL, 693 .allocationSize = 0, 694 }; 695 VkMemoryResourcePropertiesMESA props = { 696 .sType = VK_STRUCTURE_TYPE_MEMORY_RESOURCE_PROPERTIES_MESA, 697 .pNext = 698 dev->instance->experimental.memoryResourceAllocationSize == VK_TRUE 699 ? &alloc_size_props 700 : NULL, 701 .memoryTypeBits = 0, 702 }; 703 result = vn_call_vkGetMemoryResourcePropertiesMESA(dev->instance, device, 704 bo->res_id, &props); 705 vn_renderer_bo_unref(dev->renderer, bo); 706 if (result != VK_SUCCESS) 707 return result; 708 709 *out_alloc_size = alloc_size_props.allocationSize; 710 *out_mem_type_bits = props.memoryTypeBits; 711 712 return VK_SUCCESS; 713} 714 715VkResult 716vn_GetMemoryFdPropertiesKHR(VkDevice device, 717 VkExternalMemoryHandleTypeFlagBits handleType, 718 int fd, 719 VkMemoryFdPropertiesKHR *pMemoryFdProperties) 720{ 721 VN_TRACE_FUNC(); 722 struct vn_device *dev = vn_device_from_handle(device); 723 uint64_t alloc_size = 0; 724 uint32_t mem_type_bits = 0; 725 VkResult result = VK_SUCCESS; 726 727 if (handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) 728 return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 729 730 result = 731 vn_get_memory_dma_buf_properties(dev, fd, &alloc_size, &mem_type_bits); 732 if (result != VK_SUCCESS) 733 return vn_error(dev->instance, result); 734 735 pMemoryFdProperties->memoryTypeBits = mem_type_bits; 736 737 return VK_SUCCESS; 738} 739