Home | History | Annotate | Download | only in vulkan
      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