1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \brief Vulkan external memory API tests
20 *//*--------------------------------------------------------------------*/
22 #include "vktApiExternalMemoryTests.hpp"
24 #include "vktTestCaseUtil.hpp"
25 #include "vkRefUtil.hpp"
26 #include "vkDeviceUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkPlatform.hpp"
29 #include "vkMemUtil.hpp"
31 #include "tcuTestLog.hpp"
33 #include "deUniquePtr.hpp"
34 #include "deStringUtil.hpp"
35 #include "deRandom.hpp"
39 #include "vktExternalMemoryUtil.hpp"
41 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
45 # include <sys/types.h>
46 # include <sys/socket.h>
49 #if (DE_OS == DE_OS_WIN32)
50 # define WIN32_LEAN_AND_MEAN
56 using namespace vkt::ExternalMemoryUtil;
65 vk::VkMemoryDedicatedRequirementsKHR getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
69 const vk::VkBufferMemoryRequirementsInfo2KHR requirementInfo =
71 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
75 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
77 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
82 vk::VkMemoryRequirements2KHR requirements =
84 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
85 &dedicatedRequirements,
89 vkd.getBufferMemoryRequirements2KHR(device, &requirementInfo, &requirements);
91 return dedicatedRequirements;
94 vk::VkMemoryDedicatedRequirementsKHR getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
98 const vk::VkImageMemoryRequirementsInfo2KHR requirementInfo =
100 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
104 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
106 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
111 vk::VkMemoryRequirements2KHR requirements =
113 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
114 &dedicatedRequirements,
118 vkd.getImageMemoryRequirements2KHR(device, &requirementInfo, &requirements);
120 return dedicatedRequirements;
123 void writeHostMemory (const vk::DeviceInterface& vkd,
125 vk::VkDeviceMemory memory,
129 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
131 deMemcpy(ptr, data, size);
133 vkd.unmapMemory(device, memory);
136 void checkHostMemory (const vk::DeviceInterface& vkd,
138 vk::VkDeviceMemory memory,
142 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
144 if (deMemCmp(ptr, data, size) != 0)
145 TCU_FAIL("Memory contents don't match");
147 vkd.unmapMemory(device, memory);
150 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
152 de::Random rng (seed);
153 std::vector<deUint8> data (size);
155 for (size_t ndx = 0; ndx < size; ndx++)
157 data[ndx] = rng.getUint8();
163 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki,
164 vk::VkPhysicalDevice device,
165 vk::VkQueueFlags requireFlags)
167 const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
169 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
171 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
172 return queueFamilyIndex;
175 TCU_THROW(NotSupportedError, "Queue type not supported");
178 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp,
179 const vk::VkExternalSemaphoreHandleTypeFlagsKHR externalSemaphoreTypes,
180 const vk::VkExternalMemoryHandleTypeFlagsKHR externalMemoryTypes,
181 const vk::VkExternalFenceHandleTypeFlagsKHR externalFenceTypes)
183 std::vector<std::string> instanceExtensions;
185 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
187 if (externalSemaphoreTypes != 0)
188 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
190 if (externalMemoryTypes != 0)
191 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
193 if (externalFenceTypes != 0)
194 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
198 return vk::createDefaultInstance(vkp, std::vector<std::string>(), instanceExtensions);
200 catch (const vk::Error& error)
202 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
203 TCU_THROW(NotSupportedError, "Required extensions not supported");
209 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface& vki,
210 vk::VkPhysicalDevice physicalDevice,
211 const vk::VkExternalSemaphoreHandleTypeFlagsKHR externalSemaphoreTypes,
212 const vk::VkExternalMemoryHandleTypeFlagsKHR externalMemoryTypes,
213 const vk::VkExternalFenceHandleTypeFlagsKHR externalFenceTypes,
214 deUint32 queueFamilyIndex,
215 bool useDedicatedAllocs = false)
217 std::vector<const char*> deviceExtensions;
219 if ((externalSemaphoreTypes
220 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
221 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)) != 0)
223 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
226 if ((externalFenceTypes
227 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
228 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)) != 0)
230 deviceExtensions.push_back("VK_KHR_external_fence_fd");
233 if (useDedicatedAllocs)
235 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
236 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
239 if ((externalMemoryTypes
240 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) != 0)
242 deviceExtensions.push_back("VK_KHR_external_memory_fd");
245 if ((externalSemaphoreTypes
246 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
247 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)) != 0)
249 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
252 if ((externalFenceTypes
253 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
254 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)) != 0)
256 deviceExtensions.push_back("VK_KHR_external_fence_win32");
259 if ((externalMemoryTypes
260 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
261 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
262 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR
263 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR
264 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR
265 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR)) != 0)
267 deviceExtensions.push_back("VK_KHR_external_memory_win32");
270 const float priority = 0.5f;
271 const vk::VkDeviceQueueCreateInfo queues[] =
274 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
283 const vk::VkDeviceCreateInfo deviceCreateInfo =
285 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
289 DE_LENGTH_OF_ARRAY(queues),
295 (deUint32)deviceExtensions.size(),
296 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
302 return vk::createDevice(vki, physicalDevice, &deviceCreateInfo);
304 catch (const vk::Error& error)
306 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
307 TCU_THROW(NotSupportedError, "Required extensions not supported");
313 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
315 deUint32 queueFamilyIndex)
319 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
324 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
325 vk::VkPhysicalDevice device,
326 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType)
328 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR info =
330 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
334 vk::VkExternalSemaphorePropertiesKHR properties =
336 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR,
343 vki.getPhysicalDeviceExternalSemaphorePropertiesKHR(device, &info, &properties);
345 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0)
346 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
348 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
349 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
352 void checkFenceSupport (const vk::InstanceInterface& vki,
353 vk::VkPhysicalDevice device,
354 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType)
356 const vk::VkPhysicalDeviceExternalFenceInfoKHR info =
358 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR,
362 vk::VkExternalFencePropertiesKHR properties =
364 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR,
371 vki.getPhysicalDeviceExternalFencePropertiesKHR(device, &info, &properties);
373 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR) == 0)
374 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
376 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
377 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
380 void checkBufferSupport (const vk::InstanceInterface& vki,
381 vk::VkPhysicalDevice device,
382 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
383 vk::VkBufferViewCreateFlags createFlag,
384 vk::VkBufferUsageFlags usageFlag,
387 const vk::VkPhysicalDeviceExternalBufferInfoKHR info =
389 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
396 vk::VkExternalBufferPropertiesKHR properties =
398 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
404 vki.getPhysicalDeviceExternalBufferPropertiesKHR(device, &info, &properties);
406 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
407 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
409 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
410 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
412 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
413 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
416 void checkImageSupport (const vk::InstanceInterface& vki,
417 vk::VkPhysicalDevice device,
418 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
419 vk::VkImageViewCreateFlags createFlag,
420 vk::VkImageUsageFlags usageFlag,
422 vk::VkImageTiling tiling,
425 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR externalInfo =
427 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
431 const vk::VkPhysicalDeviceImageFormatInfo2KHR info =
433 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
437 vk::VK_IMAGE_TYPE_2D,
442 vk::VkExternalImageFormatPropertiesKHR externalProperties =
444 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
448 vk::VkImageFormatProperties2KHR properties =
450 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
461 vki.getPhysicalDeviceImageFormatProperties2KHR(device, &info, &properties);
463 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
464 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
466 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
467 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
469 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
470 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
473 void submitDummySignal (const vk::DeviceInterface& vkd,
475 vk::VkSemaphore semaphore)
477 const vk::VkSubmitInfo submit =
479 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
493 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
496 void submitDummySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk,
499 deUint32 queueFamilyIndex,
500 vk::VkSemaphore semaphore,
501 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType,
502 NativeHandle& nativeHandle)
504 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
505 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
507 const vk::VkEventCreateInfo eventCreateInfo =
509 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
514 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
516 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
518 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
520 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
524 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
526 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
527 VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
528 may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
529 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
530 is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
531 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
533 vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
534 vk.endCommandBuffer(*cmdBuffer);
536 const vk::VkSubmitInfo submit =
538 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
552 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
554 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
556 VK_CHECK(vk.setEvent(device, *event));
558 VK_CHECK(vk.queueWaitIdle(queue));
561 void submitDummyWait (const vk::DeviceInterface& vkd,
563 vk::VkSemaphore semaphore)
565 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
566 const vk::VkSubmitInfo submit =
568 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
582 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
585 void submitDummySignal (const vk::DeviceInterface& vkd,
589 const vk::VkSubmitInfo submit =
591 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
605 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
608 void submitDummySignalAndGetFenceNative ( const vk::DeviceInterface& vk,
611 deUint32 queueFamilyIndex,
613 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType,
614 NativeHandle& nativeHandle)
616 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
617 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
619 const vk::VkEventCreateInfo eventCreateInfo =
621 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
626 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
628 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
630 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
632 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
636 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
638 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
639 VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
640 could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
641 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
642 file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
643 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
645 vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
646 vk.endCommandBuffer(*cmdBuffer);
648 const vk::VkSubmitInfo submit =
650 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
664 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
666 getFenceNative(vk, device, fence, externalType, nativeHandle);
668 VK_CHECK(vk.setEvent(device, *event));
670 VK_CHECK(vk.queueWaitIdle(queue));
673 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType)
675 const vk::PlatformInterface& vkp (context.getPlatformInterface());
676 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, externalType, 0u, 0u));
677 const vk::InstanceDriver vki (vkp, *instance);
678 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
680 TestLog& log = context.getTestContext().getLog();
682 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR info =
684 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
688 vk::VkExternalSemaphorePropertiesKHR properties =
690 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR,
697 vki.getPhysicalDeviceExternalSemaphorePropertiesKHR(device, &info, &properties);
698 log << TestLog::Message << properties << TestLog::EndMessage;
700 TCU_CHECK(properties.pNext == DE_NULL);
701 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR);
703 return tcu::TestStatus::pass("Pass");
706 struct SemaphoreTestConfig
708 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType_,
709 Permanence permanence_)
710 : externalType (externalType_)
711 , permanence (permanence_)
715 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType;
716 Permanence permanence;
719 tcu::TestStatus testSemaphoreWin32Create (Context& context,
720 const SemaphoreTestConfig config)
722 #if (DE_OS == DE_OS_WIN32)
723 const Transference transference (getHandelTypeTransferences(config.externalType));
724 const vk::PlatformInterface& vkp (context.getPlatformInterface());
725 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
726 const vk::InstanceDriver vki (vkp, *instance);
727 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
728 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
730 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
733 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
734 const vk::DeviceDriver vkd (vki, *device);
735 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
736 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
738 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
741 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
742 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
745 const vk::VkExportSemaphoreCreateInfoKHR exportCreateInfo=
747 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR,
749 (vk::VkExternalMemoryHandleTypeFlagsKHR)config.externalType
751 const vk::VkSemaphoreCreateInfo createInfo =
753 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
757 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
759 if (transference == TRANSFERENCE_COPY)
760 submitDummySignal(vkd, queue, *semaphore);
762 NativeHandle handleA;
763 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
766 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
767 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
769 if (transference == TRANSFERENCE_COPY)
770 submitDummyWait(vkd, queue, *semaphoreA);
771 else if (transference == TRANSFERENCE_REFERENCE)
773 submitDummySignal(vkd, queue, *semaphore);
774 submitDummyWait(vkd, queue, *semaphoreA);
777 DE_FATAL("Unknown transference.");
779 VK_CHECK(vkd.queueWaitIdle(queue));
782 return tcu::TestStatus::pass("Pass");
787 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
791 tcu::TestStatus testSemaphoreImportTwice (Context& context,
792 const SemaphoreTestConfig config)
794 const Transference transference (getHandelTypeTransferences(config.externalType));
795 const vk::PlatformInterface& vkp (context.getPlatformInterface());
796 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
797 const vk::InstanceDriver vki (vkp, *instance);
798 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
799 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
801 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
804 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
805 const vk::DeviceDriver vkd (vki, *device);
806 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
807 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
808 NativeHandle handleA;
810 if (transference == TRANSFERENCE_COPY)
811 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
813 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
816 NativeHandle handleB (handleA);
817 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
818 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
819 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
821 if (transference == TRANSFERENCE_COPY)
822 submitDummyWait(vkd, queue, *semaphoreA);
823 else if (transference == TRANSFERENCE_REFERENCE)
825 submitDummySignal(vkd, queue, *semaphoreA);
826 submitDummyWait(vkd, queue, *semaphoreB);
829 DE_FATAL("Unknown transference.");
831 VK_CHECK(vkd.queueWaitIdle(queue));
834 return tcu::TestStatus::pass("Pass");
838 tcu::TestStatus testSemaphoreImportReimport (Context& context,
839 const SemaphoreTestConfig config)
841 const Transference transference (getHandelTypeTransferences(config.externalType));
842 const vk::PlatformInterface& vkp (context.getPlatformInterface());
843 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
844 const vk::InstanceDriver vki (vkp, *instance);
845 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
846 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
848 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
851 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
852 const vk::DeviceDriver vkd (vki, *device);
853 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
855 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
856 NativeHandle handleA;
858 if (transference == TRANSFERENCE_COPY)
859 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
861 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
863 NativeHandle handleB (handleA);
864 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
865 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
867 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
869 if (transference == TRANSFERENCE_COPY)
870 submitDummyWait(vkd, queue, *semaphoreB);
871 else if (transference == TRANSFERENCE_REFERENCE)
873 submitDummySignal(vkd, queue, *semaphoreA);
874 submitDummyWait(vkd, queue, *semaphoreB);
877 DE_FATAL("Unknown transference.");
879 VK_CHECK(vkd.queueWaitIdle(queue));
881 return tcu::TestStatus::pass("Pass");
885 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
886 const SemaphoreTestConfig config)
888 const vk::PlatformInterface& vkp (context.getPlatformInterface());
889 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
890 const vk::InstanceDriver vki (vkp, *instance);
891 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
892 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
894 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
897 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
898 const vk::DeviceDriver vkd (vki, *device);
899 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
900 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
904 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
907 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
908 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
909 submitDummyWait(vkd, queue, *semaphoreB);
911 VK_CHECK(vkd.queueWaitIdle(queue));
915 return tcu::TestStatus::pass("Pass");
919 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
920 const SemaphoreTestConfig config)
922 const vk::PlatformInterface& vkp (context.getPlatformInterface());
923 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
924 const vk::InstanceDriver vki (vkp, *instance);
925 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
926 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
927 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
929 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
930 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
933 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
934 const vk::DeviceDriver vkd (vki, *device);
935 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
937 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
940 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
942 submitDummySignal(vkd, queue, *semaphoreA);
945 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
947 submitDummyWait(vkd, queue, *semaphoreB);
948 VK_CHECK(vkd.queueWaitIdle(queue));
952 return tcu::TestStatus::pass("Pass");
956 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
957 const SemaphoreTestConfig config)
959 const vk::PlatformInterface& vkp (context.getPlatformInterface());
960 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
961 const vk::InstanceDriver vki (vkp, *instance);
962 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
963 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
965 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
966 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
969 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
970 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
971 const vk::DeviceDriver vkd (vki, *device);
972 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
974 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
977 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
979 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
981 submitDummySignal(vkd, queue, *semaphoreA);
982 submitDummyWait(vkd, queue, *semaphoreB);
984 VK_CHECK(vkd.queueWaitIdle(queue));
986 return tcu::TestStatus::pass("Pass");
990 tcu::TestStatus testSemaphoreSignalImport (Context& context,
991 const SemaphoreTestConfig config)
993 const Transference transference (getHandelTypeTransferences(config.externalType));
994 const vk::PlatformInterface& vkp (context.getPlatformInterface());
995 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
996 const vk::InstanceDriver vki (vkp, *instance);
997 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
998 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1000 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1003 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1004 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1005 const vk::DeviceDriver vkd (vki, *device);
1006 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1008 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1009 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1010 NativeHandle handle;
1012 submitDummySignal(vkd, queue, *semaphoreB);
1013 VK_CHECK(vkd.queueWaitIdle(queue));
1015 if (transference == TRANSFERENCE_COPY)
1016 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1018 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1020 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1022 if (transference == TRANSFERENCE_COPY)
1023 submitDummyWait(vkd, queue, *semaphoreB);
1024 else if (transference == TRANSFERENCE_REFERENCE)
1026 submitDummySignal(vkd, queue, *semaphoreA);
1027 submitDummyWait(vkd, queue, *semaphoreB);
1030 DE_FATAL("Unknown transference.");
1032 VK_CHECK(vkd.queueWaitIdle(queue));
1034 return tcu::TestStatus::pass("Pass");
1038 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1039 const SemaphoreTestConfig config)
1041 const Transference transference (getHandelTypeTransferences(config.externalType));
1042 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1043 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1044 const vk::InstanceDriver vki (vkp, *instance);
1045 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1046 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1048 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1051 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1052 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1053 const vk::DeviceDriver vkd (vki, *device);
1054 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1056 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1057 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1058 NativeHandle handle;
1060 if (transference == TRANSFERENCE_COPY)
1061 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1063 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1065 submitDummySignal(vkd, queue, *semaphoreB);
1066 submitDummyWait(vkd, queue, *semaphoreB);
1068 VK_CHECK(vkd.queueWaitIdle(queue));
1070 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1072 if (transference == TRANSFERENCE_COPY)
1073 submitDummyWait(vkd, queue, *semaphoreB);
1074 else if (transference == TRANSFERENCE_REFERENCE)
1076 submitDummySignal(vkd, queue, *semaphoreA);
1077 submitDummyWait(vkd, queue, *semaphoreB);
1080 DE_FATAL("Unknown transference.");
1082 VK_CHECK(vkd.queueWaitIdle(queue));
1084 return tcu::TestStatus::pass("Pass");
1088 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1089 const SemaphoreTestConfig config)
1091 const size_t exportCount = 4 * 1024;
1092 const Transference transference (getHandelTypeTransferences(config.externalType));
1093 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1094 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1095 const vk::InstanceDriver vki (vkp, *instance);
1096 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1097 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1099 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1102 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1103 const vk::DeviceDriver vkd (vki, *device);
1104 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1105 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1107 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1109 NativeHandle handle;
1111 if (transference == TRANSFERENCE_COPY)
1112 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1114 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1117 submitDummySignal(vkd, queue, *semaphore);
1118 submitDummyWait(vkd, queue, *semaphore);
1120 VK_CHECK(vkd.queueWaitIdle(queue));
1123 return tcu::TestStatus::pass("Pass");
1126 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1127 const SemaphoreTestConfig config)
1129 const size_t importCount = 4 * 1024;
1130 const Transference transference (getHandelTypeTransferences(config.externalType));
1131 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1132 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1133 const vk::InstanceDriver vki (vkp, *instance);
1134 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1135 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1137 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1140 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1141 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1142 const vk::DeviceDriver vkd (vki, *device);
1143 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1144 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1145 NativeHandle handleA;
1147 if (transference == TRANSFERENCE_COPY)
1148 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1150 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1152 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1154 NativeHandle handleB (handleA);
1155 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1158 if (transference == TRANSFERENCE_COPY)
1160 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1161 submitDummyWait(vkd, queue, *semaphoreA);
1163 else if (transference == TRANSFERENCE_REFERENCE)
1165 submitDummySignal(vkd, queue, *semaphoreA);
1166 submitDummyWait(vkd, queue, *semaphoreA);
1169 DE_FATAL("Unknown transference.");
1171 VK_CHECK(vkd.queueWaitIdle(queue));
1174 return tcu::TestStatus::pass("Pass");
1177 tcu::TestStatus testSemaphoreTransference (Context& context,
1178 const SemaphoreTestConfig config)
1180 const Transference transference (getHandelTypeTransferences(config.externalType));
1181 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1182 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1183 const vk::InstanceDriver vki (vkp, *instance);
1184 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1185 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1187 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1190 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1191 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1192 const vk::DeviceDriver vkd (vki, *device);
1193 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1195 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1196 NativeHandle handle;
1198 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1201 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1203 if (config.permanence == PERMANENCE_PERMANENT)
1205 if (transference == TRANSFERENCE_COPY)
1207 submitDummySignal(vkd, queue, *semaphoreA);
1208 submitDummyWait(vkd, queue, *semaphoreB);
1209 VK_CHECK(vkd.queueWaitIdle(queue));
1211 submitDummySignal(vkd, queue, *semaphoreB);
1213 submitDummyWait(vkd, queue, *semaphoreA);
1214 submitDummyWait(vkd, queue, *semaphoreB);
1215 VK_CHECK(vkd.queueWaitIdle(queue));
1217 else if (transference== TRANSFERENCE_REFERENCE)
1219 submitDummyWait(vkd, queue, *semaphoreB);
1220 VK_CHECK(vkd.queueWaitIdle(queue));
1222 submitDummySignal(vkd, queue, *semaphoreA);
1223 submitDummyWait(vkd, queue, *semaphoreB);
1225 submitDummySignal(vkd, queue, *semaphoreB);
1226 submitDummyWait(vkd, queue, *semaphoreA);
1227 VK_CHECK(vkd.queueWaitIdle(queue));
1230 DE_FATAL("Unknown transference.");
1232 else if (config.permanence == PERMANENCE_TEMPORARY)
1234 if (transference == TRANSFERENCE_COPY)
1236 submitDummySignal(vkd, queue, *semaphoreA);
1237 submitDummyWait(vkd, queue, *semaphoreB);
1238 VK_CHECK(vkd.queueWaitIdle(queue));
1240 submitDummySignal(vkd, queue, *semaphoreB);
1242 submitDummyWait(vkd, queue, *semaphoreA);
1243 submitDummyWait(vkd, queue, *semaphoreB);
1244 VK_CHECK(vkd.queueWaitIdle(queue));
1246 else if (transference== TRANSFERENCE_REFERENCE)
1248 submitDummyWait(vkd, queue, *semaphoreB);
1249 VK_CHECK(vkd.queueWaitIdle(queue));
1251 submitDummySignal(vkd, queue, *semaphoreA);
1252 submitDummySignal(vkd, queue, *semaphoreB);
1254 submitDummyWait(vkd, queue, *semaphoreB);
1255 submitDummyWait(vkd, queue, *semaphoreA);
1256 VK_CHECK(vkd.queueWaitIdle(queue));
1259 DE_FATAL("Unknown transference.");
1262 DE_FATAL("Unknown permanence.");
1265 return tcu::TestStatus::pass("Pass");
1269 tcu::TestStatus testSemaphoreFdDup (Context& context,
1270 const SemaphoreTestConfig config)
1272 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1273 const Transference transference (getHandelTypeTransferences(config.externalType));
1274 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1275 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1276 const vk::InstanceDriver vki (vkp, *instance);
1277 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1278 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1280 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1283 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1284 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1285 const vk::DeviceDriver vkd (vki, *device);
1286 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1288 TestLog& log = context.getTestContext().getLog();
1289 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1294 if (transference == TRANSFERENCE_COPY)
1295 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1297 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1299 NativeHandle newFd (dup(fd.getFd()));
1301 if (newFd.getFd() < 0)
1302 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1304 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1307 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1309 if (transference == TRANSFERENCE_COPY)
1310 submitDummyWait(vkd, queue, *semaphoreB);
1311 else if (transference == TRANSFERENCE_REFERENCE)
1313 submitDummySignal(vkd, queue, *semaphoreA);
1314 submitDummyWait(vkd, queue, *semaphoreB);
1317 DE_FATAL("Unknown permanence.");
1321 VK_CHECK(vkd.queueWaitIdle(queue));
1323 return tcu::TestStatus::pass("Pass");
1328 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1332 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1333 const SemaphoreTestConfig config)
1335 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1336 const Transference transference (getHandelTypeTransferences(config.externalType));
1337 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1338 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1339 const vk::InstanceDriver vki (vkp, *instance);
1340 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1341 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1343 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1346 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1347 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1348 const vk::DeviceDriver vkd (vki, *device);
1349 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1351 TestLog& log = context.getTestContext().getLog();
1352 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1353 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1356 NativeHandle fd, secondFd;
1358 if (transference == TRANSFERENCE_COPY)
1360 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1361 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1365 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1366 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1369 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1372 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1374 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1377 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1379 if (transference == TRANSFERENCE_COPY)
1380 submitDummyWait(vkd, queue, *semaphoreC);
1381 else if (transference == TRANSFERENCE_REFERENCE)
1383 submitDummySignal(vkd, queue, *semaphoreA);
1384 submitDummyWait(vkd, queue, *semaphoreC);
1387 DE_FATAL("Unknown permanence.");
1391 VK_CHECK(vkd.queueWaitIdle(queue));
1393 return tcu::TestStatus::pass("Pass");
1398 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1402 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1403 const SemaphoreTestConfig config)
1405 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1406 const Transference transference (getHandelTypeTransferences(config.externalType));
1407 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1408 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1409 const vk::InstanceDriver vki (vkp, *instance);
1410 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1411 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1413 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1416 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1417 const vk::DeviceDriver vkd (vki, *device);
1418 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1420 TestLog& log = context.getTestContext().getLog();
1421 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1422 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1425 NativeHandle fd, secondFd;
1427 if (transference == TRANSFERENCE_COPY)
1429 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1430 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1434 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1435 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1438 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1439 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1442 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1444 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1447 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1449 if (transference == TRANSFERENCE_COPY)
1450 submitDummyWait(vkd, queue, *semaphoreC);
1451 else if (transference == TRANSFERENCE_REFERENCE)
1453 submitDummySignal(vkd, queue, *semaphoreA);
1454 submitDummyWait(vkd, queue, *semaphoreC);
1457 DE_FATAL("Unknown permanence.");
1461 VK_CHECK(vkd.queueWaitIdle(queue));
1463 return tcu::TestStatus::pass("Pass");
1468 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1472 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1473 const SemaphoreTestConfig config)
1475 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1476 const Transference transference (getHandelTypeTransferences(config.externalType));
1477 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1478 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1479 const vk::InstanceDriver vki (vkp, *instance);
1480 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1481 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1483 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1486 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1487 const vk::DeviceDriver vkd (vki, *device);
1488 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1490 TestLog& log = context.getTestContext().getLog();
1491 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1494 if (transference == TRANSFERENCE_COPY)
1495 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1497 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1502 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1504 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1505 TCU_FAIL("Failed to create socket pair");
1509 const NativeHandle srcSocket (sv[0]);
1510 const NativeHandle dstSocket (sv[1]);
1511 std::string sendData ("deqp");
1515 const int fdRaw (fd.getFd());
1518 char buffer[CMSG_SPACE(sizeof(int))];
1519 iovec iov = { &sendData[0], sendData.length()};
1521 deMemset(&msg, 0, sizeof(msg));
1523 msg.msg_control = buffer;
1524 msg.msg_controllen = sizeof(buffer);
1528 cmsg = CMSG_FIRSTHDR(&msg);
1529 cmsg->cmsg_level = SOL_SOCKET;
1530 cmsg->cmsg_type = SCM_RIGHTS;
1531 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1533 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1534 msg.msg_controllen = cmsg->cmsg_len;
1536 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1538 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1539 TCU_FAIL("Failed to send fd over socket");
1546 char buffer[CMSG_SPACE(sizeof(int))];
1547 std::string recvData (4, '\0');
1548 iovec iov = { &recvData[0], recvData.length() };
1550 deMemset(&msg, 0, sizeof(msg));
1552 msg.msg_control = buffer;
1553 msg.msg_controllen = sizeof(buffer);
1557 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1561 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1562 TCU_FAIL("Failed to recv fd over socket");
1565 else if (bytes != (ssize_t)sendData.length())
1567 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1571 const vk::VkSemaphoreImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1572 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1574 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1575 NativeHandle newFd (newFd_);
1577 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1578 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1579 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1580 TCU_CHECK(recvData == sendData);
1581 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1584 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1586 if (transference == TRANSFERENCE_COPY)
1587 submitDummyWait(vkd, queue, *newSemaphore);
1588 else if (transference == TRANSFERENCE_REFERENCE)
1590 submitDummySignal(vkd, queue, *newSemaphore);
1591 submitDummyWait(vkd, queue, *newSemaphore);
1594 DE_FATAL("Unknown permanence.");
1596 VK_CHECK(vkd.queueWaitIdle(queue));
1604 return tcu::TestStatus::pass("Pass");
1608 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1612 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBitsKHR externalType)
1614 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1615 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, externalType));
1616 const vk::InstanceDriver vki (vkp, *instance);
1617 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1619 TestLog& log = context.getTestContext().getLog();
1621 const vk::VkPhysicalDeviceExternalFenceInfoKHR info =
1623 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR,
1627 vk::VkExternalFencePropertiesKHR properties =
1629 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR,
1636 vki.getPhysicalDeviceExternalFencePropertiesKHR(device, &info, &properties);
1637 log << TestLog::Message << properties << TestLog::EndMessage;
1639 TCU_CHECK(properties.pNext == DE_NULL);
1640 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR);
1642 return tcu::TestStatus::pass("Pass");
1645 struct FenceTestConfig
1647 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBitsKHR externalType_,
1648 Permanence permanence_)
1649 : externalType (externalType_)
1650 , permanence (permanence_)
1654 vk::VkExternalFenceHandleTypeFlagBitsKHR externalType;
1655 Permanence permanence;
1659 tcu::TestStatus testFenceWin32Create (Context& context,
1660 const FenceTestConfig config)
1662 #if (DE_OS == DE_OS_WIN32)
1663 const Transference transference (getHandelTypeTransferences(config.externalType));
1664 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1665 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1666 const vk::InstanceDriver vki (vkp, *instance);
1667 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1668 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1670 checkFenceSupport(vki, physicalDevice, config.externalType);
1673 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1674 const vk::DeviceDriver vkd (vki, *device);
1675 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1676 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1678 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1681 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1682 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1685 const vk::VkExportFenceCreateInfoKHR exportCreateInfo=
1687 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR,
1689 (vk::VkExternalFenceHandleTypeFlagsKHR)config.externalType
1691 const vk::VkFenceCreateInfo createInfo =
1693 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1697 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1699 if (transference == TRANSFERENCE_COPY)
1700 submitDummySignal(vkd, queue, *fence);
1702 NativeHandle handleA;
1703 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1706 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1707 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1709 if (transference == TRANSFERENCE_COPY)
1710 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1711 else if (transference == TRANSFERENCE_REFERENCE)
1713 submitDummySignal(vkd, queue, *fence);
1714 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1717 DE_FATAL("Unknown transference.");
1719 VK_CHECK(vkd.queueWaitIdle(queue));
1722 return tcu::TestStatus::pass("Pass");
1727 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1731 tcu::TestStatus testFenceImportTwice (Context& context,
1732 const FenceTestConfig config)
1734 const Transference transference (getHandelTypeTransferences(config.externalType));
1735 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1736 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1737 const vk::InstanceDriver vki (vkp, *instance);
1738 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1739 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1741 checkFenceSupport(vki, physicalDevice, config.externalType);
1744 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1745 const vk::DeviceDriver vkd (vki, *device);
1746 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1747 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1748 NativeHandle handleA;
1750 if (transference == TRANSFERENCE_COPY)
1751 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1753 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1756 NativeHandle handleB (handleA);
1757 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1758 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1759 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1761 if (transference == TRANSFERENCE_COPY)
1762 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1763 else if (transference == TRANSFERENCE_REFERENCE)
1765 submitDummySignal(vkd, queue, *fenceA);
1766 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1769 DE_FATAL("Unknown transference.");
1771 VK_CHECK(vkd.queueWaitIdle(queue));
1774 return tcu::TestStatus::pass("Pass");
1778 tcu::TestStatus testFenceImportReimport (Context& context,
1779 const FenceTestConfig config)
1781 const Transference transference (getHandelTypeTransferences(config.externalType));
1782 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1783 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1784 const vk::InstanceDriver vki (vkp, *instance);
1785 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1786 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1788 checkFenceSupport(vki, physicalDevice, config.externalType);
1791 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1792 const vk::DeviceDriver vkd (vki, *device);
1793 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1795 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1796 NativeHandle handleA;
1798 if (transference == TRANSFERENCE_COPY)
1799 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1801 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1803 NativeHandle handleB (handleA);
1804 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1805 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1807 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1809 if (transference == TRANSFERENCE_COPY)
1810 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1811 else if (transference == TRANSFERENCE_REFERENCE)
1813 submitDummySignal(vkd, queue, *fenceA);
1814 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1817 DE_FATAL("Unknown transference.");
1819 VK_CHECK(vkd.queueWaitIdle(queue));
1821 return tcu::TestStatus::pass("Pass");
1825 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1826 const FenceTestConfig config)
1828 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1829 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1830 const vk::InstanceDriver vki (vkp, *instance);
1831 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1832 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1834 checkFenceSupport(vki, physicalDevice, config.externalType);
1837 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1838 const vk::DeviceDriver vkd (vki, *device);
1839 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1840 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1843 NativeHandle handle;
1845 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1848 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1849 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1850 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1852 VK_CHECK(vkd.queueWaitIdle(queue));
1856 return tcu::TestStatus::pass("Pass");
1860 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
1861 const FenceTestConfig config)
1863 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1864 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1865 const vk::InstanceDriver vki (vkp, *instance);
1866 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1867 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1868 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1870 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1871 checkFenceSupport(vki, physicalDevice, config.externalType);
1874 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1875 const vk::DeviceDriver vkd (vki, *device);
1876 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1878 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1879 NativeHandle handle;
1881 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1883 submitDummySignal(vkd, queue, *fenceA);
1886 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1888 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1889 VK_CHECK(vkd.queueWaitIdle(queue));
1893 return tcu::TestStatus::pass("Pass");
1897 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
1898 const FenceTestConfig config)
1900 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1901 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1902 const vk::InstanceDriver vki (vkp, *instance);
1903 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1904 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1906 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1907 checkFenceSupport(vki, physicalDevice, config.externalType);
1910 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1911 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1912 const vk::DeviceDriver vkd (vki, *device);
1913 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1915 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1916 NativeHandle handle;
1918 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1920 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1922 submitDummySignal(vkd, queue, *fenceA);
1923 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1925 VK_CHECK(vkd.queueWaitIdle(queue));
1927 return tcu::TestStatus::pass("Pass");
1931 tcu::TestStatus testFenceSignalImport (Context& context,
1932 const FenceTestConfig config)
1934 const Transference transference (getHandelTypeTransferences(config.externalType));
1935 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1936 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1937 const vk::InstanceDriver vki (vkp, *instance);
1938 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1939 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1941 checkFenceSupport(vki, physicalDevice, config.externalType);
1944 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1945 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1946 const vk::DeviceDriver vkd (vki, *device);
1947 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1949 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1950 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
1951 NativeHandle handle;
1953 submitDummySignal(vkd, queue, *fenceB);
1954 VK_CHECK(vkd.queueWaitIdle(queue));
1956 if (transference == TRANSFERENCE_COPY)
1957 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1959 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1961 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
1963 if (transference == TRANSFERENCE_COPY)
1964 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1965 else if (transference == TRANSFERENCE_REFERENCE)
1967 submitDummySignal(vkd, queue, *fenceA);
1968 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1971 DE_FATAL("Unknown transference.");
1973 VK_CHECK(vkd.queueWaitIdle(queue));
1975 return tcu::TestStatus::pass("Pass");
1979 tcu::TestStatus testFenceReset (Context& context,
1980 const FenceTestConfig config)
1982 const Transference transference (getHandelTypeTransferences(config.externalType));
1983 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1984 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1985 const vk::InstanceDriver vki (vkp, *instance);
1986 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1987 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1989 checkFenceSupport(vki, physicalDevice, config.externalType);
1992 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1993 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1994 const vk::DeviceDriver vkd (vki, *device);
1995 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1997 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1998 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
1999 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2000 NativeHandle handle;
2002 submitDummySignal(vkd, queue, *fenceB);
2003 VK_CHECK(vkd.queueWaitIdle(queue));
2005 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2007 NativeHandle handleB (handle);
2008 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2010 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2012 VK_CHECK(vkd.queueWaitIdle(queue));
2013 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2015 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2017 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2018 // or fenceB should be separate copy of the payload and not affect fenceC
2019 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2021 // vkResetFences() should have restored fenceBs prior state and should be now reset
2022 // or fenceB should have it's separate payload
2023 submitDummySignal(vkd, queue, *fenceB);
2024 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2026 else if (config.permanence == PERMANENCE_PERMANENT)
2028 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2030 // Reset fences should have reset all of the fences
2031 submitDummySignal(vkd, queue, *fenceC);
2033 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2034 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2035 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2038 DE_FATAL("Unknown permanence");
2040 VK_CHECK(vkd.queueWaitIdle(queue));
2042 return tcu::TestStatus::pass("Pass");
2046 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2047 const FenceTestConfig config)
2049 const Transference transference (getHandelTypeTransferences(config.externalType));
2050 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2051 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2052 const vk::InstanceDriver vki (vkp, *instance);
2053 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2054 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2056 checkFenceSupport(vki, physicalDevice, config.externalType);
2059 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2060 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2061 const vk::DeviceDriver vkd (vki, *device);
2062 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2064 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2065 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2066 NativeHandle handle;
2068 if (transference == TRANSFERENCE_COPY)
2069 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2071 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2073 submitDummySignal(vkd, queue, *fenceB);
2074 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2076 VK_CHECK(vkd.queueWaitIdle(queue));
2078 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2080 if (transference == TRANSFERENCE_COPY)
2081 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2082 else if (transference == TRANSFERENCE_REFERENCE)
2084 submitDummySignal(vkd, queue, *fenceA);
2085 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2088 DE_FATAL("Unknown transference.");
2090 VK_CHECK(vkd.queueWaitIdle(queue));
2092 return tcu::TestStatus::pass("Pass");
2096 tcu::TestStatus testFenceMultipleExports (Context& context,
2097 const FenceTestConfig config)
2099 const size_t exportCount = 4 * 1024;
2100 const Transference transference (getHandelTypeTransferences(config.externalType));
2101 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2102 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2103 const vk::InstanceDriver vki (vkp, *instance);
2104 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2105 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2107 checkFenceSupport(vki, physicalDevice, config.externalType);
2110 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2111 const vk::DeviceDriver vkd (vki, *device);
2112 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2113 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2115 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2117 NativeHandle handle;
2119 if (transference == TRANSFERENCE_COPY)
2120 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle);
2122 getFenceNative(vkd, *device, *fence, config.externalType, handle);
2125 submitDummySignal(vkd, queue, *fence);
2126 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2128 VK_CHECK(vkd.queueWaitIdle(queue));
2131 return tcu::TestStatus::pass("Pass");
2134 tcu::TestStatus testFenceMultipleImports (Context& context,
2135 const FenceTestConfig config)
2137 const size_t importCount = 4 * 1024;
2138 const Transference transference (getHandelTypeTransferences(config.externalType));
2139 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2140 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2141 const vk::InstanceDriver vki (vkp, *instance);
2142 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2143 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2145 checkFenceSupport(vki, physicalDevice, config.externalType);
2148 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2149 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2150 const vk::DeviceDriver vkd (vki, *device);
2151 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2152 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2153 NativeHandle handleA;
2155 if (transference == TRANSFERENCE_COPY)
2156 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2158 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2160 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2162 NativeHandle handleB (handleA);
2163 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2166 if (transference == TRANSFERENCE_COPY)
2168 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2169 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2171 else if (transference == TRANSFERENCE_REFERENCE)
2173 submitDummySignal(vkd, queue, *fenceA);
2174 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2177 DE_FATAL("Unknown transference.");
2179 VK_CHECK(vkd.queueWaitIdle(queue));
2182 return tcu::TestStatus::pass("Pass");
2185 tcu::TestStatus testFenceTransference (Context& context,
2186 const FenceTestConfig config)
2188 const Transference transference (getHandelTypeTransferences(config.externalType));
2189 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2190 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2191 const vk::InstanceDriver vki (vkp, *instance);
2192 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2193 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2195 checkFenceSupport(vki, physicalDevice, config.externalType);
2198 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2199 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2200 const vk::DeviceDriver vkd (vki, *device);
2201 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2203 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2204 NativeHandle handle;
2206 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2209 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2211 if (config.permanence == PERMANENCE_PERMANENT)
2213 if (transference == TRANSFERENCE_COPY)
2215 submitDummySignal(vkd, queue, *fenceA);
2216 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2217 VK_CHECK(vkd.queueWaitIdle(queue));
2219 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2220 submitDummySignal(vkd, queue, *fenceB);
2222 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2223 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2224 VK_CHECK(vkd.queueWaitIdle(queue));
2226 else if (transference== TRANSFERENCE_REFERENCE)
2228 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2229 VK_CHECK(vkd.queueWaitIdle(queue));
2231 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2232 submitDummySignal(vkd, queue, *fenceA);
2233 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2235 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2236 submitDummySignal(vkd, queue, *fenceB);
2237 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2238 VK_CHECK(vkd.queueWaitIdle(queue));
2241 DE_FATAL("Unknown transference.");
2243 else if (config.permanence == PERMANENCE_TEMPORARY)
2245 if (transference == TRANSFERENCE_COPY)
2247 submitDummySignal(vkd, queue, *fenceA);
2248 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2249 VK_CHECK(vkd.queueWaitIdle(queue));
2251 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2252 submitDummySignal(vkd, queue, *fenceB);
2254 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2255 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2256 VK_CHECK(vkd.queueWaitIdle(queue));
2258 else if (transference == TRANSFERENCE_REFERENCE)
2260 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2261 VK_CHECK(vkd.queueWaitIdle(queue));
2263 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2264 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2265 submitDummySignal(vkd, queue, *fenceA);
2266 submitDummySignal(vkd, queue, *fenceB);
2268 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2269 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2270 VK_CHECK(vkd.queueWaitIdle(queue));
2273 DE_FATAL("Unknown transference.");
2276 DE_FATAL("Unknown permanence.");
2279 return tcu::TestStatus::pass("Pass");
2283 tcu::TestStatus testFenceFdDup (Context& context,
2284 const FenceTestConfig config)
2286 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2287 const Transference transference (getHandelTypeTransferences(config.externalType));
2288 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2289 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2290 const vk::InstanceDriver vki (vkp, *instance);
2291 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2292 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2294 checkFenceSupport(vki, physicalDevice, config.externalType);
2297 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2298 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2299 const vk::DeviceDriver vkd (vki, *device);
2300 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2302 TestLog& log = context.getTestContext().getLog();
2303 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2308 if (transference == TRANSFERENCE_COPY)
2309 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2311 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2313 NativeHandle newFd (dup(fd.getFd()));
2315 if (newFd.getFd() < 0)
2316 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2318 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2321 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2323 if (transference == TRANSFERENCE_COPY)
2324 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2325 else if (transference == TRANSFERENCE_REFERENCE)
2327 submitDummySignal(vkd, queue, *fenceA);
2328 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2331 DE_FATAL("Unknown permanence.");
2335 VK_CHECK(vkd.queueWaitIdle(queue));
2337 return tcu::TestStatus::pass("Pass");
2342 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2346 tcu::TestStatus testFenceFdDup2 (Context& context,
2347 const FenceTestConfig config)
2349 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2350 const Transference transference (getHandelTypeTransferences(config.externalType));
2351 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2352 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2353 const vk::InstanceDriver vki (vkp, *instance);
2354 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2355 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2357 checkFenceSupport(vki, physicalDevice, config.externalType);
2360 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2361 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2362 const vk::DeviceDriver vkd (vki, *device);
2363 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2365 TestLog& log = context.getTestContext().getLog();
2366 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2367 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2370 NativeHandle fd, secondFd;
2372 if (transference == TRANSFERENCE_COPY)
2374 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2375 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2379 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2380 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2383 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2386 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2388 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2391 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2393 if (transference == TRANSFERENCE_COPY)
2394 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2395 else if (transference == TRANSFERENCE_REFERENCE)
2397 submitDummySignal(vkd, queue, *fenceA);
2398 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2401 DE_FATAL("Unknown permanence.");
2405 VK_CHECK(vkd.queueWaitIdle(queue));
2407 return tcu::TestStatus::pass("Pass");
2412 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2416 tcu::TestStatus testFenceFdDup3 (Context& context,
2417 const FenceTestConfig config)
2419 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2420 const Transference transference (getHandelTypeTransferences(config.externalType));
2421 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2422 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2423 const vk::InstanceDriver vki (vkp, *instance);
2424 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2425 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2427 checkFenceSupport(vki, physicalDevice, config.externalType);
2430 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2431 const vk::DeviceDriver vkd (vki, *device);
2432 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2434 TestLog& log = context.getTestContext().getLog();
2435 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2436 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2439 NativeHandle fd, secondFd;
2441 if (transference == TRANSFERENCE_COPY)
2443 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2444 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2448 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2449 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2452 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2453 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2456 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2458 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2461 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2463 if (transference == TRANSFERENCE_COPY)
2464 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2465 else if (transference == TRANSFERENCE_REFERENCE)
2467 submitDummySignal(vkd, queue, *fenceA);
2468 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2471 DE_FATAL("Unknown permanence.");
2475 VK_CHECK(vkd.queueWaitIdle(queue));
2477 return tcu::TestStatus::pass("Pass");
2482 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2486 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2487 const FenceTestConfig config)
2489 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2490 const Transference transference (getHandelTypeTransferences(config.externalType));
2491 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2492 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2493 const vk::InstanceDriver vki (vkp, *instance);
2494 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2495 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2497 checkFenceSupport(vki, physicalDevice, config.externalType);
2500 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2501 const vk::DeviceDriver vkd (vki, *device);
2502 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2504 TestLog& log = context.getTestContext().getLog();
2505 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2508 if (transference == TRANSFERENCE_COPY)
2509 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2511 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2516 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2518 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2519 TCU_FAIL("Failed to create socket pair");
2523 const NativeHandle srcSocket (sv[0]);
2524 const NativeHandle dstSocket (sv[1]);
2525 std::string sendData ("deqp");
2529 const int fdRaw (fd.getFd());
2532 char buffer[CMSG_SPACE(sizeof(int))];
2533 iovec iov = { &sendData[0], sendData.length()};
2535 deMemset(&msg, 0, sizeof(msg));
2537 msg.msg_control = buffer;
2538 msg.msg_controllen = sizeof(buffer);
2542 cmsg = CMSG_FIRSTHDR(&msg);
2543 cmsg->cmsg_level = SOL_SOCKET;
2544 cmsg->cmsg_type = SCM_RIGHTS;
2545 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2547 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2548 msg.msg_controllen = cmsg->cmsg_len;
2550 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2552 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2553 TCU_FAIL("Failed to send fd over socket");
2560 char buffer[CMSG_SPACE(sizeof(int))];
2561 std::string recvData (4, '\0');
2562 iovec iov = { &recvData[0], recvData.length() };
2564 deMemset(&msg, 0, sizeof(msg));
2566 msg.msg_control = buffer;
2567 msg.msg_controllen = sizeof(buffer);
2571 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2575 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2576 TCU_FAIL("Failed to recv fd over socket");
2579 else if (bytes != (ssize_t)sendData.length())
2581 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2585 const vk::VkFenceImportFlagsKHR flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2586 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2588 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2589 NativeHandle newFd (newFd_);
2591 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2592 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2593 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2594 TCU_CHECK(recvData == sendData);
2595 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2598 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2600 if (transference == TRANSFERENCE_COPY)
2601 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2602 else if (transference == TRANSFERENCE_REFERENCE)
2604 submitDummySignal(vkd, queue, *newFence);
2605 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2608 DE_FATAL("Unknown permanence.");
2610 VK_CHECK(vkd.queueWaitIdle(queue));
2618 return tcu::TestStatus::pass("Pass");
2622 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2626 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
2628 const vk::VkBufferCreateFlags createFlags[] =
2631 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2632 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2633 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2635 const vk::VkBufferUsageFlags usageFlags[] =
2637 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2638 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2639 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2640 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2641 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2642 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2643 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2644 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2645 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2647 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2648 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, externalType, 0u));
2649 const vk::InstanceDriver vki (vkp, *instance);
2650 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2651 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2652 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2654 // VkDevice is only created if physical device claims to support any of these types.
2655 vk::Move<vk::VkDevice> device;
2656 de::MovePtr<vk::DeviceDriver> vkd;
2657 bool deviceHasDedicated = false;
2659 TestLog& log = context.getTestContext().getLog();
2661 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2662 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2664 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2665 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2666 const vk::VkPhysicalDeviceExternalBufferInfoKHR info =
2668 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
2674 vk::VkExternalBufferPropertiesKHR properties =
2676 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
2681 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2682 (deviceFeatures.sparseBinding == VK_FALSE))
2685 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2686 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2689 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2690 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2693 vki.getPhysicalDeviceExternalBufferPropertiesKHR(physicalDevice, &info, &properties);
2695 log << TestLog::Message << properties << TestLog::EndMessage;
2697 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR);
2698 TCU_CHECK(properties.pNext == DE_NULL);
2699 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2701 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)) != 0)
2703 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
2705 if (!device || (requiresDedicated && !deviceHasDedicated))
2707 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2710 device = createDevice(vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2711 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
2712 deviceHasDedicated = requiresDedicated;
2714 catch (const tcu::NotSupportedError& e)
2717 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2722 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) != 0)
2724 DE_ASSERT(!!device);
2727 if (deviceHasDedicated)
2729 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2730 const vk::VkMemoryDedicatedRequirementsKHR reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2731 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
2732 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2734 if (propertiesRequiresDedicated != objectRequiresDedicated)
2735 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2739 // We can't query whether dedicated memory is required or not on per-object basis.
2740 // This check should be redundant as the code above tries to create device with
2741 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2742 // is required. However, checking again doesn't hurt.
2743 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) == 0);
2748 return tcu::TestStatus::pass("Pass");
2751 struct MemoryTestConfig
2753 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType_,
2756 : externalType (externalType_)
2757 , hostVisible (hostVisible_)
2758 , dedicated (dedicated_)
2762 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType;
2767 #if (DE_OS == DE_OS_WIN32)
2768 deUint32 chooseMemoryType (deUint32 bits)
2771 TCU_THROW(NotSupportedError, "No compatible memory type found");
2773 return deCtz32(bits);
2777 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2779 #if (DE_OS == DE_OS_WIN32)
2780 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2781 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2782 const vk::InstanceDriver vki (vkp, *instance);
2783 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2784 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2785 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2786 const vk::DeviceDriver vkd (vki, *device);
2787 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2788 const deUint32 seed = 1261033864u;
2789 const vk::VkDeviceSize bufferSize = 1024;
2790 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2792 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2793 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2795 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2797 // \note Buffer is only allocated to get memory requirements
2798 deUint32 exportedMemoryTypeIndex = ~0U;
2799 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2800 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2801 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2803 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2806 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2807 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2810 const vk::VkExportMemoryAllocateInfoKHR exportInfo =
2812 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
2814 (vk::VkExternalMemoryHandleTypeFlagsKHR)config.externalType
2817 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2818 const vk::VkMemoryAllocateInfo info =
2820 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2823 exportedMemoryTypeIndex
2825 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2826 NativeHandle handleA;
2828 if (config.hostVisible)
2829 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2831 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2834 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2836 if (config.hostVisible)
2838 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2839 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2841 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2842 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2844 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2845 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
2847 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2848 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2852 return tcu::TestStatus::pass("Pass");
2856 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2860 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2862 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2863 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2864 const vk::InstanceDriver vki (vkp, *instance);
2865 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2866 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2867 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2868 const vk::DeviceDriver vkd (vki, *device);
2869 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2870 const deUint32 seed = 1261033864u;
2871 const vk::VkDeviceSize bufferSize = 1024;
2872 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2874 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2876 deUint32 exportedMemoryTypeIndex = ~0U;
2877 // \note Buffer is only allocated to get memory requirements
2878 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2879 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2880 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2881 NativeHandle handleA;
2883 if (config.hostVisible)
2884 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2886 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2889 NativeHandle handleB (handleA);
2890 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2891 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2893 if (config.hostVisible)
2895 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2896 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2898 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2899 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
2901 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
2902 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
2904 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2905 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2909 return tcu::TestStatus::pass("Pass");
2912 tcu::TestStatus testMemoryMultimpleImports (Context& context, MemoryTestConfig config)
2914 const size_t count = 4 * 1024;
2915 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2916 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2917 const vk::InstanceDriver vki (vkp, *instance);
2918 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2919 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2920 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2921 const vk::DeviceDriver vkd (vki, *device);
2922 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2923 const vk::VkDeviceSize bufferSize = 1024;
2925 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2927 deUint32 exportedMemoryTypeIndex = ~0U;
2928 // \note Buffer is only allocated to get memory requirements
2929 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2930 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2931 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2932 NativeHandle handleA;
2934 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2936 for (size_t ndx = 0; ndx < count; ndx++)
2938 NativeHandle handleB (handleA);
2939 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2942 return tcu::TestStatus::pass("Pass");
2945 tcu::TestStatus testMemoryMultimpleExports (Context& context, MemoryTestConfig config)
2947 const size_t count = 4 * 1024;
2948 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2949 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2950 const vk::InstanceDriver vki (vkp, *instance);
2951 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2952 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2953 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2954 const vk::DeviceDriver vkd (vki, *device);
2955 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2956 const vk::VkDeviceSize bufferSize = 1024;
2958 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2960 deUint32 exportedMemoryTypeIndex = ~0U;
2961 // \note Buffer is only allocated to get memory requirements
2962 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2963 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2964 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2966 for (size_t ndx = 0; ndx < count; ndx++)
2968 NativeHandle handle;
2969 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
2972 return tcu::TestStatus::pass("Pass");
2975 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
2977 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2978 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2979 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2980 const vk::InstanceDriver vki (vkp, *instance);
2981 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2982 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2985 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2986 const vk::DeviceDriver vkd (vki, *device);
2988 TestLog& log = context.getTestContext().getLog();
2989 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2990 const vk::VkDeviceSize bufferSize = 1024;
2991 const deUint32 seed = 851493858u;
2992 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2994 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2996 deUint32 exportedMemoryTypeIndex = ~0U;
2997 // \note Buffer is only allocated to get memory requirements
2998 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2999 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3000 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3002 if (config.hostVisible)
3003 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3005 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3006 NativeHandle newFd (dup(fd.getFd()));
3008 if (newFd.getFd() < 0)
3009 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3011 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3014 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3016 if (config.hostVisible)
3018 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3020 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3022 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3023 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3027 return tcu::TestStatus::pass("Pass");
3032 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3036 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3038 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3039 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3040 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3041 const vk::InstanceDriver vki (vkp, *instance);
3042 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3043 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3046 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3047 const vk::DeviceDriver vkd (vki, *device);
3049 TestLog& log = context.getTestContext().getLog();
3050 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3051 const vk::VkDeviceSize bufferSize = 1024;
3052 const deUint32 seed = 224466865u;
3053 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3055 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3057 deUint32 exportedMemoryTypeIndex = ~0U;
3058 // \note Buffer is only allocated to get memory requirements
3059 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3060 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3061 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3063 if (config.hostVisible)
3064 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3066 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3067 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3068 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3071 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3073 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3076 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3078 if (config.hostVisible)
3080 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3082 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3084 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3085 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3089 return tcu::TestStatus::pass("Pass");
3094 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3098 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3100 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3101 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3102 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3103 const vk::InstanceDriver vki (vkp, *instance);
3104 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3105 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3108 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3109 const vk::DeviceDriver vkd (vki, *device);
3111 TestLog& log = context.getTestContext().getLog();
3112 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3113 const vk::VkDeviceSize bufferSize = 1024;
3114 const deUint32 seed = 2554088961u;
3115 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3117 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3119 deUint32 exportedMemoryTypeIndex = ~0U;
3120 // \note Buffer is only allocated to get memory requirements
3121 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3122 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3123 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3125 if (config.hostVisible)
3126 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3128 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3129 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3130 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3133 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3135 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3138 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3140 if (config.hostVisible)
3142 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3144 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3146 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3147 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3151 return tcu::TestStatus::pass("Pass");
3156 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3160 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3162 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3163 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3164 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3165 const vk::InstanceDriver vki (vkp, *instance);
3166 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3167 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3170 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3171 const vk::DeviceDriver vkd (vki, *device);
3173 TestLog& log = context.getTestContext().getLog();
3174 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3175 const vk::VkDeviceSize bufferSize = 1024;
3176 const deUint32 seed = 3403586456u;
3177 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3179 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3181 deUint32 exportedMemoryTypeIndex = ~0U;
3182 // \note Buffer is only allocated to get memory requirements
3183 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3184 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3185 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3187 if (config.hostVisible)
3188 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3190 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3195 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3197 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3198 TCU_FAIL("Failed to create socket pair");
3202 const NativeHandle srcSocket (sv[0]);
3203 const NativeHandle dstSocket (sv[1]);
3204 std::string sendData ("deqp");
3208 const int fdRaw (fd.getFd());
3211 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3212 iovec iov = { &sendData[0], sendData.length()};
3214 deMemset(&msg, 0, sizeof(msg));
3216 msg.msg_control = tmpBuffer;
3217 msg.msg_controllen = sizeof(tmpBuffer);
3221 cmsg = CMSG_FIRSTHDR(&msg);
3222 cmsg->cmsg_level = SOL_SOCKET;
3223 cmsg->cmsg_type = SCM_RIGHTS;
3224 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3226 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3227 msg.msg_controllen = cmsg->cmsg_len;
3229 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3231 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3232 TCU_FAIL("Failed to send fd over socket");
3239 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3240 std::string recvData (4, '\0');
3241 iovec iov = { &recvData[0], recvData.length() };
3243 deMemset(&msg, 0, sizeof(msg));
3245 msg.msg_control = tmpBuffer;
3246 msg.msg_controllen = sizeof(tmpBuffer);
3250 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3254 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3255 TCU_FAIL("Failed to recv fd over socket");
3258 else if (bytes != (ssize_t)sendData.length())
3260 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3264 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3266 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3267 NativeHandle newFd (newFd_);
3269 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3270 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3271 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3272 TCU_CHECK(recvData == sendData);
3273 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3276 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3278 if (config.hostVisible)
3280 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3282 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3284 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3285 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3294 return tcu::TestStatus::pass("Pass");
3298 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3302 struct BufferTestConfig
3304 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType_,
3306 : externalType (externalType_)
3307 , dedicated (dedicated_)
3311 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType;
3315 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3316 const BufferTestConfig config)
3318 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3319 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3320 const vk::InstanceDriver vki (vkp, *instance);
3321 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3322 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3323 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3324 const vk::DeviceDriver vkd (vki, *device);
3325 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3326 const vk::VkDeviceSize bufferSize = 1024;
3328 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3330 deUint32 exportedMemoryTypeIndex = ~0U;
3331 // \note Buffer is only allocated to get memory requirements
3332 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3333 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3334 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3335 NativeHandle handle;
3337 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3339 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3342 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3343 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3345 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3348 return tcu::TestStatus::pass("Pass");
3351 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3352 const BufferTestConfig config)
3354 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3355 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3356 const vk::InstanceDriver vki (vkp, *instance);
3357 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3358 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3359 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3360 const vk::DeviceDriver vkd (vki, *device);
3361 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3362 const vk::VkDeviceSize bufferSize = 1024;
3364 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3366 deUint32 exportedMemoryTypeIndex = ~0U;
3367 // \note Buffer is only allocated to get memory requirements
3368 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3369 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3370 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3371 NativeHandle handle;
3373 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3374 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3377 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3378 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3380 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3383 return tcu::TestStatus::pass("Pass");
3386 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3387 const BufferTestConfig config)
3389 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3390 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3391 const vk::InstanceDriver vki (vkp, *instance);
3392 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3393 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3394 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3395 const vk::DeviceDriver vkd (vki, *device);
3396 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3397 const vk::VkDeviceSize bufferSize = 1024;
3399 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3401 deUint32 exportedMemoryTypeIndex = ~0U;
3402 // \note Buffer is only allocated to get memory requirements
3403 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3404 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3405 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3406 NativeHandle handle;
3408 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3411 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3412 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3414 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3415 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3418 return tcu::TestStatus::pass("Pass");
3421 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
3423 const vk::VkImageCreateFlags createFlags[] =
3426 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3427 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3428 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3429 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3430 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
3431 vk::VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR
3433 const vk::VkImageUsageFlags usageFlags[] =
3435 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3436 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3437 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3438 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3439 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3440 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3441 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
3442 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3444 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3445 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, externalType, 0u));
3446 const vk::InstanceDriver vki (vkp, *instance);
3447 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3448 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3449 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3451 // VkDevice is only created if physical device claims to support any of these types.
3452 vk::Move<vk::VkDevice> device;
3453 de::MovePtr<vk::DeviceDriver> vkd;
3454 bool deviceHasDedicated = false;
3456 TestLog& log = context.getTestContext().getLog();
3458 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3459 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3461 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3462 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3463 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3464 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3465 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3466 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR externalInfo =
3468 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
3472 const vk::VkPhysicalDeviceImageFormatInfo2KHR info =
3474 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
3483 vk::VkExternalImageFormatPropertiesKHR externalProperties =
3485 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
3489 vk::VkImageFormatProperties2KHR properties =
3491 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
3492 &externalProperties,
3502 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3503 (deviceFeatures.sparseBinding == VK_FALSE))
3506 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3507 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3510 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3511 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3514 vki.getPhysicalDeviceImageFormatProperties2KHR(physicalDevice, &info, &properties);
3516 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3517 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR);
3518 TCU_CHECK(externalProperties.pNext == DE_NULL);
3519 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3521 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)) != 0)
3523 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
3525 if (!device || (requiresDedicated && !deviceHasDedicated))
3527 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3530 device = createDevice(vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3531 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
3532 deviceHasDedicated = requiresDedicated;
3534 catch (const tcu::NotSupportedError& e)
3537 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3542 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) != 0)
3544 DE_ASSERT(!!device);
3547 if (deviceHasDedicated)
3549 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3550 const vk::VkMemoryDedicatedRequirementsKHR reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3551 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
3552 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3554 if (propertiesRequiresDedicated != objectRequiresDedicated)
3555 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3559 // We can't query whether dedicated memory is required or not on per-object basis.
3560 // This check should be redundant as the code above tries to create device with
3561 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3562 // is required. However, checking again doesn't hurt.
3563 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) == 0);
3568 return tcu::TestStatus::pass("Pass");
3571 struct ImageTestConfig
3573 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType_,
3575 : externalType (externalType_)
3576 , dedicated (dedicated_)
3580 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType;
3584 tcu::TestStatus testImageBindExportImportBind (Context& context,
3585 const ImageTestConfig config)
3587 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3588 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3589 const vk::InstanceDriver vki (vkp, *instance);
3590 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3591 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3592 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3593 const vk::DeviceDriver vkd (vki, *device);
3594 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3595 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3596 const deUint32 width = 64u;
3597 const deUint32 height = 64u;
3598 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3600 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3602 deUint32 exportedMemoryTypeIndex = ~0U;
3603 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3604 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3605 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3606 NativeHandle handle;
3608 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3610 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3613 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3614 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3616 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3619 return tcu::TestStatus::pass("Pass");
3622 tcu::TestStatus testImageExportBindImportBind (Context& context,
3623 const ImageTestConfig config)
3625 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3626 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3627 const vk::InstanceDriver vki (vkp, *instance);
3628 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3629 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3630 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3631 const vk::DeviceDriver vkd (vki, *device);
3632 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3633 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3634 const deUint32 width = 64u;
3635 const deUint32 height = 64u;
3636 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3638 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3640 deUint32 exportedMemoryTypeIndex = ~0U;
3641 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3642 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3643 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3644 NativeHandle handle;
3646 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3647 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3650 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3651 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3653 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3656 return tcu::TestStatus::pass("Pass");
3659 tcu::TestStatus testImageExportImportBindBind (Context& context,
3660 const ImageTestConfig config)
3662 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3663 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3664 const vk::InstanceDriver vki (vkp, *instance);
3665 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3666 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3667 const vk::Unique<vk::VkDevice> device (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3668 const vk::DeviceDriver vkd (vki, *device);
3669 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3670 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3671 const deUint32 width = 64u;
3672 const deUint32 height = 64u;
3673 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3675 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3677 deUint32 exportedMemoryTypeIndex = ~0U;
3678 // \note Image is only allocated to get memory requirements
3679 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3680 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3681 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3682 NativeHandle handle;
3684 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3687 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3688 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3690 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3691 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3694 return tcu::TestStatus::pass("Pass");
3696 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBitsKHR externalType)
3700 const char* const name;
3701 const Permanence permanence;
3704 { "temporary", PERMANENCE_TEMPORARY },
3705 { "permanent", PERMANENCE_PERMANENT }
3708 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3710 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3712 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3714 const Permanence permanence (permanences[permanenceNdx].permanence);
3715 const char* const permanenceName (permanences[permanenceNdx].name);
3716 const FenceTestConfig config (externalType, permanence);
3718 if (!isSupportedPermanence(externalType, permanence))
3721 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3722 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3724 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
3727 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", testFenceImportTwice, config);
3728 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", testFenceImportReimport, config);
3729 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", testFenceMultipleImports, config);
3730 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testFenceSignalExportImportWait, config);
3731 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", testFenceSignalImport, config);
3732 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", testFenceReset, config);
3733 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", testFenceTransference, config);
3735 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
3736 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3738 // \note Not supported on WIN32 handles
3739 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", testFenceMultipleExports, config);
3741 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", testFenceFdDup, config);
3742 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", testFenceFdDup2, config);
3743 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", testFenceFdDup3, config);
3744 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", testFenceFdSendOverSocket, config);
3747 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3749 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
3750 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
3751 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
3758 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
3760 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
3762 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR).release());
3763 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3764 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3765 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3770 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType)
3774 const char* const name;
3775 const Permanence permanence;
3778 { "temporary", PERMANENCE_TEMPORARY },
3779 { "permanent", PERMANENCE_PERMANENT }
3782 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
3784 addFunctionCase(semaphoreGroup.get(), "info", "Test external semaphore queries.", testSemaphoreQueries, externalType);
3786 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3788 const Permanence permanence (permanences[permanenceNdx].permanence);
3789 const char* const permanenceName (permanences[permanenceNdx].name);
3790 const SemaphoreTestConfig config (externalType, permanence);
3792 if (!isSupportedPermanence(externalType, permanence))
3795 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3796 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3798 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
3801 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", testSemaphoreImportTwice, config);
3802 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", testSemaphoreImportReimport, config);
3803 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", testSemaphoreMultipleImports, config);
3804 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testSemaphoreSignalExportImportWait, config);
3805 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", testSemaphoreSignalImport, config);
3806 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", testSemaphoreTransference, config);
3808 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
3809 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3811 // \note Not supported on WIN32 handles
3812 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", testSemaphoreMultipleExports, config);
3814 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", testSemaphoreFdDup, config);
3815 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", testSemaphoreFdDup2, config);
3816 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", testSemaphoreFdDup3, config);
3817 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", testSemaphoreFdSendOverSocket, config);
3820 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3822 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
3823 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
3824 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", testSemaphoreExportImportSignalWait, config);
3828 return semaphoreGroup;
3831 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
3833 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
3835 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR).release());
3836 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3837 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3838 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3840 return semaphoreGroup;
3843 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
3845 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
3847 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
3849 const bool dedicated (dedicatedNdx == 1);
3850 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
3852 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
3854 const bool hostVisible (hostVisibleNdx == 1);
3855 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
3856 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
3858 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3859 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3861 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
3864 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
3865 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultimpleImports, memoryConfig);
3867 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3869 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
3870 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
3871 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
3872 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
3873 // \note Not supported on WIN32 handles
3874 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultimpleExports, memoryConfig);
3877 dedicatedGroup->addChild(hostVisibleGroup.release());
3881 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
3882 const BufferTestConfig bufferConfig (externalType, dedicated);
3884 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
3885 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
3886 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
3887 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importind and binding buffer.", testBufferExportImportBindBind, bufferConfig);
3889 dedicatedGroup->addChild(bufferGroup.release());
3893 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
3894 const ImageTestConfig imageConfig (externalType, dedicated);
3896 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
3897 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
3898 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
3899 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importind and binding image.", testImageExportImportBindBind, imageConfig);
3901 dedicatedGroup->addChild(imageGroup.release());
3904 group->addChild(dedicatedGroup.release());
3910 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
3912 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
3914 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3915 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3916 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3923 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
3925 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
3927 group->addChild(createSemaphoreTests(testCtx).release());
3928 group->addChild(createMemoryTests(testCtx).release());
3929 group->addChild(createFenceTests(testCtx).release());
3931 return group.release();