1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * \brief Vulkan external memory utilities 20 *//*--------------------------------------------------------------------*/ 21 22 #include "vktExternalMemoryUtil.hpp" 23 24 #include "vkQueryUtil.hpp" 25 26 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) 27 # include <unistd.h> 28 # include <fcntl.h> 29 # include <errno.h> 30 # include <sys/types.h> 31 # include <sys/socket.h> 32 #endif 33 34 #if (DE_OS == DE_OS_WIN32) 35 # define WIN32_LEAN_AND_MEAN 36 # include <windows.h> 37 #endif 38 39 namespace vkt 40 { 41 namespace ExternalMemoryUtil 42 { 43 namespace 44 { 45 deUint32 chooseMemoryType (deUint32 bits) 46 { 47 DE_ASSERT(bits != 0); 48 49 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++) 50 { 51 if ((bits & (1u << memoryTypeIndex)) != 0) 52 return memoryTypeIndex; 53 } 54 55 DE_FATAL("No supported memory types"); 56 return -1; 57 } 58 59 } // anonymous 60 61 NativeHandle::NativeHandle (void) 62 : m_fd (-1) 63 , m_win32HandleType (WIN32HANDLETYPE_LAST) 64 , m_win32Handle (DE_NULL) 65 { 66 } 67 68 NativeHandle::NativeHandle (const NativeHandle& other) 69 : m_fd (-1) 70 , m_win32HandleType (WIN32HANDLETYPE_LAST) 71 , m_win32Handle (DE_NULL) 72 { 73 if (other.m_fd >= 0) 74 { 75 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) 76 DE_ASSERT(!other.m_win32Handle.internal); 77 m_fd = dup(other.m_fd); 78 TCU_CHECK(m_fd >= 0); 79 #else 80 DE_FATAL("Platform doesn't support file descriptors"); 81 #endif 82 } 83 else if (other.m_win32Handle.internal) 84 { 85 #if (DE_OS == DE_OS_WIN32) 86 m_win32HandleType = other.m_win32HandleType; 87 88 switch (other.m_win32HandleType) 89 { 90 case WIN32HANDLETYPE_NT: 91 { 92 DE_ASSERT(other.m_fd == -1); 93 94 const HANDLE process = ::GetCurrentProcess(); 95 ::DuplicateHandle(process, other.m_win32Handle.internal, process, &m_win32Handle.internal, 0, TRUE, DUPLICATE_SAME_ACCESS); 96 97 break; 98 } 99 100 case WIN32HANDLETYPE_KMT: 101 { 102 m_win32Handle = other.m_win32Handle; 103 break; 104 } 105 106 default: 107 DE_FATAL("Unknown win32 handle type"); 108 } 109 #else 110 DE_FATAL("Platform doesn't support win32 handles"); 111 #endif 112 } 113 else 114 DE_FATAL("Native handle can't be duplicated"); 115 } 116 117 NativeHandle::NativeHandle (int fd) 118 : m_fd (fd) 119 , m_win32HandleType (WIN32HANDLETYPE_LAST) 120 , m_win32Handle (DE_NULL) 121 { 122 } 123 124 NativeHandle::NativeHandle (Win32HandleType handleType, vk::pt::Win32Handle handle) 125 : m_fd (-1) 126 , m_win32HandleType (handleType) 127 , m_win32Handle (handle) 128 { 129 } 130 131 NativeHandle::~NativeHandle (void) 132 { 133 reset(); 134 } 135 136 void NativeHandle::reset (void) 137 { 138 if (m_fd >= 0) 139 { 140 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) 141 DE_ASSERT(!m_win32Handle.internal); 142 ::close(m_fd); 143 #else 144 DE_FATAL("Platform doesn't support file descriptors"); 145 #endif 146 } 147 148 if (m_win32Handle.internal) 149 { 150 #if (DE_OS == DE_OS_WIN32) 151 switch (m_win32HandleType) 152 { 153 case WIN32HANDLETYPE_NT: 154 DE_ASSERT(m_fd == -1); 155 ::CloseHandle((HANDLE)m_win32Handle.internal); 156 break; 157 158 case WIN32HANDLETYPE_KMT: 159 break; 160 161 default: 162 DE_FATAL("Unknown win32 handle type"); 163 } 164 #else 165 DE_FATAL("Platform doesn't support win32 handles"); 166 #endif 167 } 168 169 m_fd = -1; 170 m_win32Handle = vk::pt::Win32Handle(DE_NULL); 171 m_win32HandleType = WIN32HANDLETYPE_LAST; 172 } 173 174 NativeHandle& NativeHandle::operator= (int fd) 175 { 176 reset(); 177 178 m_fd = fd; 179 180 return *this; 181 } 182 183 void NativeHandle::setWin32Handle (Win32HandleType type, vk::pt::Win32Handle handle) 184 { 185 reset(); 186 187 m_win32HandleType = type; 188 m_win32Handle = handle; 189 } 190 191 void NativeHandle::disown (void) 192 { 193 m_fd = -1; 194 m_win32Handle = vk::pt::Win32Handle(DE_NULL); 195 } 196 197 vk::pt::Win32Handle NativeHandle::getWin32Handle (void) const 198 { 199 DE_ASSERT(m_fd == -1); 200 return m_win32Handle; 201 } 202 203 int NativeHandle::getFd (void) const 204 { 205 DE_ASSERT(!m_win32Handle.internal); 206 207 return m_fd; 208 } 209 210 const char* externalSemaphoreTypeToName (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR type) 211 { 212 switch (type) 213 { 214 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 215 return "opaque_fd"; 216 217 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 218 return "opaque_win32"; 219 220 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 221 return "opaque_win32_kmt"; 222 223 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR: 224 return "d3d12_fenc"; 225 226 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 227 return "sync_fd"; 228 229 default: 230 DE_FATAL("Unknown external semaphore type"); 231 return DE_NULL; 232 } 233 } 234 235 const char* externalFenceTypeToName (vk::VkExternalFenceHandleTypeFlagBitsKHR type) 236 { 237 switch (type) 238 { 239 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 240 return "opaque_fd"; 241 242 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 243 return "opaque_win32"; 244 245 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 246 return "opaque_win32_kmt"; 247 248 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 249 return "sync_fd"; 250 251 default: 252 DE_FATAL("Unknown external fence type"); 253 return DE_NULL; 254 } 255 } 256 257 const char* externalMemoryTypeToName (vk::VkExternalMemoryHandleTypeFlagBitsKHR type) 258 { 259 switch (type) 260 { 261 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 262 return "opaque_fd"; 263 264 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 265 return "opaque_win32"; 266 267 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 268 return "opaque_win32_kmt"; 269 270 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR: 271 return "d3d11_texture"; 272 273 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR: 274 return "d3d11_texture_kmt"; 275 276 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR: 277 return "d3d12_heap"; 278 279 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR: 280 return "d3d12_resource"; 281 282 default: 283 DE_FATAL("Unknown external memory type"); 284 return DE_NULL; 285 } 286 } 287 288 bool isSupportedPermanence (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR type, 289 Permanence permanence) 290 { 291 switch (type) 292 { 293 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 294 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 295 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY; 296 297 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 298 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY; 299 300 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 301 return permanence == PERMANENCE_TEMPORARY; 302 303 default: 304 DE_FATAL("Unknown external semaphore type"); 305 return false; 306 } 307 } 308 309 Transference getHandelTypeTransferences (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR type) 310 { 311 switch (type) 312 { 313 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 314 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 315 return TRANSFERENCE_REFERENCE; 316 317 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 318 return TRANSFERENCE_REFERENCE; 319 320 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 321 return TRANSFERENCE_COPY; 322 323 default: 324 DE_FATAL("Unknown external semaphore type"); 325 return TRANSFERENCE_REFERENCE; 326 } 327 } 328 329 bool isSupportedPermanence (vk::VkExternalFenceHandleTypeFlagBitsKHR type, 330 Permanence permanence) 331 { 332 switch (type) 333 { 334 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 335 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 336 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY; 337 338 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 339 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY; 340 341 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 342 return permanence == PERMANENCE_TEMPORARY; 343 344 default: 345 DE_FATAL("Unknown external fence type"); 346 return false; 347 } 348 } 349 350 Transference getHandelTypeTransferences (vk::VkExternalFenceHandleTypeFlagBitsKHR type) 351 { 352 switch (type) 353 { 354 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 355 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 356 return TRANSFERENCE_REFERENCE; 357 358 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: 359 return TRANSFERENCE_REFERENCE; 360 361 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: 362 return TRANSFERENCE_COPY; 363 364 default: 365 DE_FATAL("Unknown external fence type"); 366 return TRANSFERENCE_REFERENCE; 367 } 368 } 369 370 int getMemoryFd (const vk::DeviceInterface& vkd, 371 vk::VkDevice device, 372 vk::VkDeviceMemory memory, 373 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType) 374 { 375 const vk::VkMemoryGetFdInfoKHR info = 376 { 377 vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 378 DE_NULL, 379 380 memory, 381 externalType 382 }; 383 int fd = -1; 384 385 VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd)); 386 TCU_CHECK(fd >= 0); 387 388 return fd; 389 } 390 391 void getMemoryNative (const vk::DeviceInterface& vkd, 392 vk::VkDevice device, 393 vk::VkDeviceMemory memory, 394 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 395 NativeHandle& nativeHandle) 396 { 397 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 398 { 399 const vk::VkMemoryGetFdInfoKHR info = 400 { 401 vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 402 DE_NULL, 403 404 memory, 405 externalType 406 }; 407 int fd = -1; 408 409 VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd)); 410 TCU_CHECK(fd >= 0); 411 nativeHandle = fd; 412 } 413 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 414 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 415 { 416 const vk::VkMemoryGetWin32HandleInfoKHR info = 417 { 418 vk::VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, 419 DE_NULL, 420 421 memory, 422 externalType 423 }; 424 vk::pt::Win32Handle handle (DE_NULL); 425 426 VK_CHECK(vkd.getMemoryWin32HandleKHR(device, &info, &handle)); 427 428 switch (externalType) 429 { 430 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 431 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle); 432 break; 433 434 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 435 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle); 436 break; 437 438 default: 439 DE_FATAL("Unknow external memory handle type"); 440 } 441 } 442 else 443 DE_FATAL("Unknow external memory handle type"); 444 } 445 446 vk::Move<vk::VkFence> createExportableFence (const vk::DeviceInterface& vkd, 447 vk::VkDevice device, 448 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType) 449 { 450 const vk::VkExportFenceCreateInfoKHR exportCreateInfo = 451 { 452 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR, 453 DE_NULL, 454 (vk::VkExternalFenceHandleTypeFlagsKHR)externalType 455 }; 456 const vk::VkFenceCreateInfo createInfo = 457 { 458 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 459 &exportCreateInfo, 460 0u 461 }; 462 463 return vk::createFence(vkd, device, &createInfo); 464 } 465 466 int getFenceFd (const vk::DeviceInterface& vkd, 467 vk::VkDevice device, 468 vk::VkFence fence, 469 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType) 470 { 471 const vk::VkFenceGetFdInfoKHR info = 472 { 473 vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, 474 DE_NULL, 475 476 fence, 477 externalType 478 }; 479 int fd = -1; 480 481 VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd)); 482 TCU_CHECK(fd >= 0); 483 484 return fd; 485 } 486 487 void getFenceNative (const vk::DeviceInterface& vkd, 488 vk::VkDevice device, 489 vk::VkFence fence, 490 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType, 491 NativeHandle& nativeHandle) 492 { 493 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR 494 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 495 { 496 const vk::VkFenceGetFdInfoKHR info = 497 { 498 vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, 499 DE_NULL, 500 501 fence, 502 externalType 503 }; 504 int fd = -1; 505 506 VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd)); 507 TCU_CHECK(fd >= 0); 508 nativeHandle = fd; 509 } 510 else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 511 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 512 { 513 const vk::VkFenceGetWin32HandleInfoKHR info = 514 { 515 vk::VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR, 516 DE_NULL, 517 518 fence, 519 externalType 520 }; 521 vk::pt::Win32Handle handle (DE_NULL); 522 523 VK_CHECK(vkd.getFenceWin32HandleKHR(device, &info, &handle)); 524 525 switch (externalType) 526 { 527 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 528 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle); 529 break; 530 531 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 532 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle); 533 break; 534 535 default: 536 DE_FATAL("Unknow external memory handle type"); 537 } 538 } 539 else 540 DE_FATAL("Unknow external fence handle type"); 541 } 542 543 void importFence (const vk::DeviceInterface& vkd, 544 const vk::VkDevice device, 545 const vk::VkFence fence, 546 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType, 547 NativeHandle& handle, 548 vk::VkFenceImportFlagsKHR flags) 549 { 550 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR 551 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 552 { 553 const vk::VkImportFenceFdInfoKHR importInfo = 554 { 555 vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, 556 DE_NULL, 557 fence, 558 flags, 559 externalType, 560 handle.getFd() 561 }; 562 563 VK_CHECK(vkd.importFenceFdKHR(device, &importInfo)); 564 handle.disown(); 565 } 566 else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 567 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 568 { 569 const vk::VkImportFenceWin32HandleInfoKHR importInfo = 570 { 571 vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, 572 DE_NULL, 573 fence, 574 flags, 575 externalType, 576 handle.getWin32Handle(), 577 DE_NULL 578 }; 579 580 VK_CHECK(vkd.importFenceWin32HandleKHR(device, &importInfo)); 581 // \note File descriptors and win32 handles behave differently, but this call wil make it seem like they would behave in same way 582 handle.reset(); 583 } 584 else 585 DE_FATAL("Unknown fence external handle type"); 586 } 587 588 vk::Move<vk::VkFence> createAndImportFence (const vk::DeviceInterface& vkd, 589 const vk::VkDevice device, 590 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType, 591 NativeHandle& handle, 592 vk::VkFenceImportFlagsKHR flags) 593 { 594 vk::Move<vk::VkFence> fence (createFence(vkd, device)); 595 596 importFence(vkd, device, *fence, externalType, handle, flags); 597 598 return fence; 599 } 600 601 vk::Move<vk::VkSemaphore> createExportableSemaphore (const vk::DeviceInterface& vkd, 602 vk::VkDevice device, 603 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType) 604 { 605 const vk::VkExportSemaphoreCreateInfoKHR exportCreateInfo = 606 { 607 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR, 608 DE_NULL, 609 (vk::VkExternalSemaphoreHandleTypeFlagsKHR)externalType 610 }; 611 const vk::VkSemaphoreCreateInfo createInfo = 612 { 613 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 614 &exportCreateInfo, 615 0u 616 }; 617 618 return vk::createSemaphore(vkd, device, &createInfo); 619 } 620 621 int getSemaphoreFd (const vk::DeviceInterface& vkd, 622 vk::VkDevice device, 623 vk::VkSemaphore semaphore, 624 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType) 625 { 626 const vk::VkSemaphoreGetFdInfoKHR info = 627 { 628 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, 629 DE_NULL, 630 631 semaphore, 632 externalType 633 }; 634 int fd = -1; 635 636 VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd)); 637 TCU_CHECK(fd >= 0); 638 639 return fd; 640 } 641 642 void getSemaphoreNative (const vk::DeviceInterface& vkd, 643 vk::VkDevice device, 644 vk::VkSemaphore semaphore, 645 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, 646 NativeHandle& nativeHandle) 647 { 648 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR 649 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 650 { 651 const vk::VkSemaphoreGetFdInfoKHR info = 652 { 653 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, 654 DE_NULL, 655 656 semaphore, 657 externalType 658 }; 659 int fd = -1; 660 661 VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd)); 662 TCU_CHECK(fd >= 0); 663 nativeHandle = fd; 664 } 665 else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 666 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 667 { 668 const vk::VkSemaphoreGetWin32HandleInfoKHR info = 669 { 670 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, 671 DE_NULL, 672 673 semaphore, 674 externalType 675 }; 676 vk::pt::Win32Handle handle (DE_NULL); 677 678 VK_CHECK(vkd.getSemaphoreWin32HandleKHR(device, &info, &handle)); 679 680 switch (externalType) 681 { 682 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: 683 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle); 684 break; 685 686 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: 687 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle); 688 break; 689 690 default: 691 DE_FATAL("Unknow external memory handle type"); 692 } 693 } 694 else 695 DE_FATAL("Unknow external semaphore handle type"); 696 } 697 698 void importSemaphore (const vk::DeviceInterface& vkd, 699 const vk::VkDevice device, 700 const vk::VkSemaphore semaphore, 701 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, 702 NativeHandle& handle, 703 vk::VkSemaphoreImportFlagsKHR flags) 704 { 705 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR 706 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 707 { 708 const vk::VkImportSemaphoreFdInfoKHR importInfo = 709 { 710 vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, 711 DE_NULL, 712 semaphore, 713 flags, 714 externalType, 715 handle.getFd() 716 }; 717 718 VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo)); 719 handle.disown(); 720 } 721 else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 722 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 723 { 724 const vk::VkImportSemaphoreWin32HandleInfoKHR importInfo = 725 { 726 vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, 727 DE_NULL, 728 semaphore, 729 flags, 730 externalType, 731 handle.getWin32Handle(), 732 DE_NULL 733 }; 734 735 VK_CHECK(vkd.importSemaphoreWin32HandleKHR(device, &importInfo)); 736 // \note File descriptors and win32 handles behave differently, but this call wil make it seem like they would behave in same way 737 handle.reset(); 738 } 739 else 740 DE_FATAL("Unknown semaphore external handle type"); 741 } 742 743 vk::Move<vk::VkSemaphore> createAndImportSemaphore (const vk::DeviceInterface& vkd, 744 const vk::VkDevice device, 745 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, 746 NativeHandle& handle, 747 vk::VkSemaphoreImportFlagsKHR flags) 748 { 749 vk::Move<vk::VkSemaphore> semaphore (createSemaphore(vkd, device)); 750 751 importSemaphore(vkd, device, *semaphore, externalType, handle, flags); 752 753 return semaphore; 754 } 755 756 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface& vkd, 757 vk::VkDevice device, 758 const vk::VkMemoryRequirements& requirements, 759 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 760 vk::VkBuffer buffer, 761 deUint32& exportedMemoryTypeIndex) 762 { 763 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits); 764 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = 765 { 766 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 767 DE_NULL, 768 769 (vk::VkImage)0, 770 buffer 771 }; 772 const vk::VkExportMemoryAllocateInfoKHR exportInfo = 773 { 774 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, 775 !!buffer ? &dedicatedInfo : DE_NULL, 776 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType 777 }; 778 const vk::VkMemoryAllocateInfo info = 779 { 780 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 781 &exportInfo, 782 requirements.size, 783 exportedMemoryTypeIndex 784 }; 785 return vk::allocateMemory(vkd, device, &info); 786 } 787 788 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface& vkd, 789 vk::VkDevice device, 790 const vk::VkMemoryRequirements& requirements, 791 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 792 vk::VkImage image, 793 deUint32& exportedMemoryTypeIndex) 794 { 795 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits); 796 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = 797 { 798 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 799 DE_NULL, 800 801 image, 802 (vk::VkBuffer)0 803 }; 804 const vk::VkExportMemoryAllocateInfoKHR exportInfo = 805 { 806 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, 807 !!image ? &dedicatedInfo : DE_NULL, 808 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType 809 }; 810 const vk::VkMemoryAllocateInfo info = 811 { 812 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 813 &exportInfo, 814 requirements.size, 815 exportedMemoryTypeIndex 816 }; 817 return vk::allocateMemory(vkd, device, &info); 818 } 819 820 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::InstanceInterface& vki, 821 vk::VkPhysicalDevice physicalDevice, 822 const vk::DeviceInterface& vkd, 823 vk::VkDevice device, 824 const vk::VkMemoryRequirements& requirements, 825 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 826 bool hostVisible, 827 vk::VkBuffer buffer, 828 deUint32& exportedMemoryTypeIndex) 829 { 830 const vk::VkPhysicalDeviceMemoryProperties properties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice); 831 832 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= requirements.memoryTypeBits; memoryTypeIndex++) 833 { 834 if (((requirements.memoryTypeBits & (1u << memoryTypeIndex)) != 0) 835 && (((properties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == hostVisible)) 836 { 837 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = 838 { 839 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 840 DE_NULL, 841 842 (vk::VkImage)0, 843 buffer 844 }; 845 const vk::VkExportMemoryAllocateInfoKHR exportInfo = 846 { 847 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, 848 !!buffer ? &dedicatedInfo : DE_NULL, 849 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType 850 }; 851 const vk::VkMemoryAllocateInfo info = 852 { 853 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 854 &exportInfo, 855 requirements.size, 856 memoryTypeIndex 857 }; 858 859 exportedMemoryTypeIndex = memoryTypeIndex; 860 return vk::allocateMemory(vkd, device, &info); 861 } 862 } 863 864 TCU_THROW(NotSupportedError, "No supported memory type found"); 865 } 866 867 static vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd, 868 vk::VkDevice device, 869 vk::VkBuffer buffer, 870 vk::VkImage image, 871 const vk::VkMemoryRequirements& requirements, 872 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 873 deUint32 memoryTypeIndex, 874 NativeHandle& handle) 875 { 876 const bool isDedicated = !!buffer || !!image; 877 878 DE_ASSERT(!buffer || !image); 879 880 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 881 { 882 const vk::VkImportMemoryFdInfoKHR importInfo = 883 { 884 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 885 DE_NULL, 886 externalType, 887 handle.getFd() 888 }; 889 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = 890 { 891 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 892 &importInfo, 893 image, 894 buffer, 895 }; 896 const vk::VkMemoryAllocateInfo info = 897 { 898 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 899 (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo), 900 requirements.size, 901 (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex 902 }; 903 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info)); 904 905 handle.disown(); 906 907 return memory; 908 } 909 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 910 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 911 { 912 const vk::VkImportMemoryWin32HandleInfoKHR importInfo = 913 { 914 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, 915 DE_NULL, 916 externalType, 917 handle.getWin32Handle(), 918 DE_NULL 919 }; 920 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = 921 { 922 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 923 &importInfo, 924 image, 925 buffer, 926 }; 927 const vk::VkMemoryAllocateInfo info = 928 { 929 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 930 (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo), 931 requirements.size, 932 (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex 933 }; 934 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info)); 935 936 handle.disown(); 937 938 return memory; 939 } 940 else 941 { 942 DE_FATAL("Unknown external memory type"); 943 return vk::Move<vk::VkDeviceMemory>(); 944 } 945 } 946 947 vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd, 948 vk::VkDevice device, 949 const vk::VkMemoryRequirements& requirements, 950 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 951 deUint32 memoryTypeIndex, 952 NativeHandle& handle) 953 { 954 return importMemory(vkd, device, (vk::VkBuffer)0, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle); 955 } 956 957 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface& vkd, 958 vk::VkDevice device, 959 vk::VkBuffer buffer, 960 const vk::VkMemoryRequirements& requirements, 961 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 962 deUint32 memoryTypeIndex, 963 NativeHandle& handle) 964 { 965 return importMemory(vkd, device, buffer, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle); 966 } 967 968 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface& vkd, 969 vk::VkDevice device, 970 vk::VkImage image, 971 const vk::VkMemoryRequirements& requirements, 972 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 973 deUint32 memoryTypeIndex, 974 NativeHandle& handle) 975 { 976 return importMemory(vkd, device, (vk::VkBuffer)0, image, requirements, externalType, memoryTypeIndex, handle); 977 } 978 979 vk::Move<vk::VkBuffer> createExternalBuffer (const vk::DeviceInterface& vkd, 980 vk::VkDevice device, 981 deUint32 queueFamilyIndex, 982 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 983 vk::VkDeviceSize size, 984 vk::VkBufferCreateFlags createFlags, 985 vk::VkBufferUsageFlags usageFlags) 986 { 987 const vk::VkExternalMemoryBufferCreateInfoKHR externalCreateInfo = 988 { 989 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, 990 DE_NULL, 991 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType 992 }; 993 const vk::VkBufferCreateInfo createInfo = 994 { 995 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 996 &externalCreateInfo, 997 createFlags, 998 size, 999 usageFlags, 1000 vk::VK_SHARING_MODE_EXCLUSIVE, 1001 1u, 1002 &queueFamilyIndex 1003 }; 1004 1005 return vk::createBuffer(vkd, device, &createInfo); 1006 } 1007 1008 vk::Move<vk::VkImage> createExternalImage (const vk::DeviceInterface& vkd, 1009 vk::VkDevice device, 1010 deUint32 queueFamilyIndex, 1011 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType, 1012 vk::VkFormat format, 1013 deUint32 width, 1014 deUint32 height, 1015 vk::VkImageTiling tiling, 1016 vk::VkImageCreateFlags createFlags, 1017 vk::VkImageUsageFlags usageFlags) 1018 { 1019 const vk::VkExternalMemoryImageCreateInfoKHR externalCreateInfo = 1020 { 1021 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR, 1022 DE_NULL, 1023 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType 1024 }; 1025 const vk::VkImageCreateInfo createInfo = 1026 { 1027 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 1028 &externalCreateInfo, 1029 createFlags, 1030 vk::VK_IMAGE_TYPE_2D, 1031 format, 1032 { width, height, 1u, }, 1033 1u, 1034 1u, 1035 vk::VK_SAMPLE_COUNT_1_BIT, 1036 tiling, 1037 usageFlags, 1038 vk::VK_SHARING_MODE_EXCLUSIVE, 1039 1, 1040 &queueFamilyIndex, 1041 vk::VK_IMAGE_LAYOUT_UNDEFINED 1042 }; 1043 1044 return vk::createImage(vkd, device, &createInfo); 1045 } 1046 1047 } // ExternalMemoryUtil 1048 } // vkt 1049