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"
30 #include "vkApiVersion.hpp"
32 #include "tcuTestLog.hpp"
34 #include "deUniquePtr.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
40 #include "vktExternalMemoryUtil.hpp"
42 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
46 # include <sys/types.h>
47 # include <sys/socket.h>
50 #if (DE_OS == DE_OS_WIN32)
51 # define WIN32_LEAN_AND_MEAN
57 using namespace vkt::ExternalMemoryUtil;
66 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
70 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo =
72 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
76 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
78 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
83 vk::VkMemoryRequirements2 requirements =
85 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
86 &dedicatedRequirements,
90 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
92 return dedicatedRequirements;
95 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
99 const vk::VkImageMemoryRequirementsInfo2 requirementInfo =
101 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
105 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
107 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
112 vk::VkMemoryRequirements2 requirements =
114 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
115 &dedicatedRequirements,
119 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
121 return dedicatedRequirements;
124 void writeHostMemory (const vk::DeviceInterface& vkd,
126 vk::VkDeviceMemory memory,
130 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
132 deMemcpy(ptr, data, size);
134 vkd.unmapMemory(device, memory);
137 void checkHostMemory (const vk::DeviceInterface& vkd,
139 vk::VkDeviceMemory memory,
143 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
145 if (deMemCmp(ptr, data, size) != 0)
146 TCU_FAIL("Memory contents don't match");
148 vkd.unmapMemory(device, memory);
151 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
153 de::Random rng (seed);
154 std::vector<deUint8> data (size);
156 for (size_t ndx = 0; ndx < size; ndx++)
158 data[ndx] = rng.getUint8();
164 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki,
165 vk::VkPhysicalDevice device,
166 vk::VkQueueFlags requireFlags)
168 const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
170 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
172 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
173 return queueFamilyIndex;
176 TCU_THROW(NotSupportedError, "Queue type not supported");
179 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
180 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
181 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
182 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
184 std::vector<std::string> instanceExtensions;
186 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
187 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
189 if (externalSemaphoreTypes != 0)
190 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
191 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
193 if (externalMemoryTypes != 0)
194 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
195 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
197 if (externalFenceTypes != 0)
198 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
199 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
201 return instanceExtensions;
204 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp,
205 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
206 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
207 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
211 deUint32 version = 0u;
212 vkp.enumerateInstanceVersion(&version);
213 return vk::createDefaultInstance(vkp, version, std::vector<std::string>(), getInstanceExtensions(version, externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
215 catch (const vk::Error& error)
217 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
218 TCU_THROW(NotSupportedError, "Required extensions not supported");
224 vk::Move<vk::VkDevice> createDevice (const deUint32 apiVersion,
225 const vk::InstanceInterface& vki,
226 vk::VkPhysicalDevice physicalDevice,
227 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
228 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
229 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,
230 deUint32 queueFamilyIndex,
231 bool useDedicatedAllocs = false)
233 std::vector<const char*> deviceExtensions;
235 if ((externalSemaphoreTypes
236 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
237 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
239 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
242 if ((externalFenceTypes
243 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
244 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
246 deviceExtensions.push_back("VK_KHR_external_fence_fd");
249 if (useDedicatedAllocs)
251 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
252 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
253 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
254 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
257 if ((externalMemoryTypes
258 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) != 0)
260 deviceExtensions.push_back("VK_KHR_external_memory_fd");
263 if ((externalSemaphoreTypes
264 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
265 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
267 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
270 if ((externalFenceTypes
271 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
272 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
274 deviceExtensions.push_back("VK_KHR_external_fence_win32");
277 if ((externalMemoryTypes
278 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
279 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
280 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
281 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
282 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
283 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
285 deviceExtensions.push_back("VK_KHR_external_memory_win32");
288 const float priority = 0.5f;
289 const vk::VkDeviceQueueCreateInfo queues[] =
292 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
301 const vk::VkDeviceCreateInfo deviceCreateInfo =
303 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
307 DE_LENGTH_OF_ARRAY(queues),
313 (deUint32)deviceExtensions.size(),
314 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
320 return vk::createDevice(vki, physicalDevice, &deviceCreateInfo);
322 catch (const vk::Error& error)
324 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
325 TCU_THROW(NotSupportedError, "Required extensions not supported");
331 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
333 deUint32 queueFamilyIndex)
337 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
342 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
343 vk::VkPhysicalDevice device,
344 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
346 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
348 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
352 vk::VkExternalSemaphoreProperties properties =
354 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
361 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
363 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
364 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
366 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
367 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
370 void checkFenceSupport (const vk::InstanceInterface& vki,
371 vk::VkPhysicalDevice device,
372 vk::VkExternalFenceHandleTypeFlagBits externalType)
374 const vk::VkPhysicalDeviceExternalFenceInfo info =
376 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
380 vk::VkExternalFenceProperties properties =
382 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
389 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
391 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
392 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
394 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
395 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
398 void checkBufferSupport (const vk::InstanceInterface& vki,
399 vk::VkPhysicalDevice device,
400 vk::VkExternalMemoryHandleTypeFlagBits externalType,
401 vk::VkBufferViewCreateFlags createFlag,
402 vk::VkBufferUsageFlags usageFlag,
405 const vk::VkPhysicalDeviceExternalBufferInfo info =
407 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
414 vk::VkExternalBufferProperties properties =
416 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
422 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
424 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
425 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
427 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
428 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
430 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
431 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
434 void checkImageSupport (const vk::InstanceInterface& vki,
435 vk::VkPhysicalDevice device,
436 vk::VkExternalMemoryHandleTypeFlagBits externalType,
437 vk::VkImageViewCreateFlags createFlag,
438 vk::VkImageUsageFlags usageFlag,
440 vk::VkImageTiling tiling,
443 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
445 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
449 const vk::VkPhysicalDeviceImageFormatInfo2 info =
451 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
455 vk::VK_IMAGE_TYPE_2D,
460 vk::VkExternalImageFormatProperties externalProperties =
462 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
466 vk::VkImageFormatProperties2 properties =
468 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
479 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
481 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
482 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
484 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
485 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
487 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
488 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
491 void submitDummySignal (const vk::DeviceInterface& vkd,
493 vk::VkSemaphore semaphore)
495 const vk::VkSubmitInfo submit =
497 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
511 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
514 void submitDummySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk,
517 deUint32 queueFamilyIndex,
518 vk::VkSemaphore semaphore,
519 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
520 NativeHandle& nativeHandle)
522 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
523 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
525 const vk::VkEventCreateInfo eventCreateInfo =
527 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
532 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
534 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
536 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
538 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
542 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
544 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
545 VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
546 may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
547 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
548 is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
549 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
551 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);
552 vk.endCommandBuffer(*cmdBuffer);
554 const vk::VkSubmitInfo submit =
556 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
570 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
572 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
574 VK_CHECK(vk.setEvent(device, *event));
576 VK_CHECK(vk.queueWaitIdle(queue));
579 void submitDummyWait (const vk::DeviceInterface& vkd,
581 vk::VkSemaphore semaphore)
583 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
584 const vk::VkSubmitInfo submit =
586 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
600 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
603 void submitDummySignal (const vk::DeviceInterface& vkd,
607 const vk::VkSubmitInfo submit =
609 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
623 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
626 void submitDummySignalAndGetFenceNative ( const vk::DeviceInterface& vk,
629 deUint32 queueFamilyIndex,
631 vk::VkExternalFenceHandleTypeFlagBits externalType,
632 NativeHandle& nativeHandle)
634 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
635 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
637 const vk::VkEventCreateInfo eventCreateInfo =
639 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
644 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
646 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
648 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
650 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
654 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
656 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
657 VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
658 could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
659 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
660 file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
661 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
663 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);
664 vk.endCommandBuffer(*cmdBuffer);
666 const vk::VkSubmitInfo submit =
668 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
682 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
684 getFenceNative(vk, device, fence, externalType, nativeHandle);
686 VK_CHECK(vk.setEvent(device, *event));
688 VK_CHECK(vk.queueWaitIdle(queue));
691 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
693 const vk::PlatformInterface& vkp (context.getPlatformInterface());
694 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, externalType, 0u, 0u));
695 const vk::InstanceDriver vki (vkp, *instance);
696 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
698 TestLog& log = context.getTestContext().getLog();
700 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
702 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
706 vk::VkExternalSemaphoreProperties properties =
708 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
715 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
716 log << TestLog::Message << properties << TestLog::EndMessage;
718 TCU_CHECK(properties.pNext == DE_NULL);
719 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
721 return tcu::TestStatus::pass("Pass");
724 struct SemaphoreTestConfig
726 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
727 Permanence permanence_)
728 : externalType (externalType_)
729 , permanence (permanence_)
733 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
734 Permanence permanence;
737 tcu::TestStatus testSemaphoreWin32Create (Context& context,
738 const SemaphoreTestConfig config)
740 #if (DE_OS == DE_OS_WIN32)
741 const Transference transference (getHandelTypeTransferences(config.externalType));
742 const vk::PlatformInterface& vkp (context.getPlatformInterface());
743 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
744 const vk::InstanceDriver vki (vkp, *instance);
745 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
746 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
748 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
751 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
752 const vk::DeviceDriver vkd (vki, *device);
753 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
754 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
756 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
759 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
760 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
763 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
765 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
767 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
769 const vk::VkSemaphoreCreateInfo createInfo =
771 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
775 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
777 if (transference == TRANSFERENCE_COPY)
778 submitDummySignal(vkd, queue, *semaphore);
780 NativeHandle handleA;
781 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
784 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
785 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
787 if (transference == TRANSFERENCE_COPY)
788 submitDummyWait(vkd, queue, *semaphoreA);
789 else if (transference == TRANSFERENCE_REFERENCE)
791 submitDummySignal(vkd, queue, *semaphore);
792 submitDummyWait(vkd, queue, *semaphoreA);
795 DE_FATAL("Unknown transference.");
797 VK_CHECK(vkd.queueWaitIdle(queue));
800 return tcu::TestStatus::pass("Pass");
805 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
809 tcu::TestStatus testSemaphoreImportTwice (Context& context,
810 const SemaphoreTestConfig config)
812 const Transference transference (getHandelTypeTransferences(config.externalType));
813 const vk::PlatformInterface& vkp (context.getPlatformInterface());
814 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
815 const vk::InstanceDriver vki (vkp, *instance);
816 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
817 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
819 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
822 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
823 const vk::DeviceDriver vkd (vki, *device);
824 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
825 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
826 NativeHandle handleA;
828 if (transference == TRANSFERENCE_COPY)
829 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
831 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
834 NativeHandle handleB (handleA);
835 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
836 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
837 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
839 if (transference == TRANSFERENCE_COPY)
840 submitDummyWait(vkd, queue, *semaphoreA);
841 else if (transference == TRANSFERENCE_REFERENCE)
843 submitDummySignal(vkd, queue, *semaphoreA);
844 submitDummyWait(vkd, queue, *semaphoreB);
847 DE_FATAL("Unknown transference.");
849 VK_CHECK(vkd.queueWaitIdle(queue));
852 return tcu::TestStatus::pass("Pass");
856 tcu::TestStatus testSemaphoreImportReimport (Context& context,
857 const SemaphoreTestConfig config)
859 const Transference transference (getHandelTypeTransferences(config.externalType));
860 const vk::PlatformInterface& vkp (context.getPlatformInterface());
861 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
862 const vk::InstanceDriver vki (vkp, *instance);
863 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
864 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
866 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
869 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
870 const vk::DeviceDriver vkd (vki, *device);
871 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
873 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
874 NativeHandle handleA;
876 if (transference == TRANSFERENCE_COPY)
877 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
879 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
881 NativeHandle handleB (handleA);
882 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
883 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
885 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
887 if (transference == TRANSFERENCE_COPY)
888 submitDummyWait(vkd, queue, *semaphoreB);
889 else if (transference == TRANSFERENCE_REFERENCE)
891 submitDummySignal(vkd, queue, *semaphoreA);
892 submitDummyWait(vkd, queue, *semaphoreB);
895 DE_FATAL("Unknown transference.");
897 VK_CHECK(vkd.queueWaitIdle(queue));
899 return tcu::TestStatus::pass("Pass");
903 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
904 const SemaphoreTestConfig config)
906 const vk::PlatformInterface& vkp (context.getPlatformInterface());
907 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
908 const vk::InstanceDriver vki (vkp, *instance);
909 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
910 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
912 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
915 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
916 const vk::DeviceDriver vkd (vki, *device);
917 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
918 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
922 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
925 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
926 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
927 submitDummyWait(vkd, queue, *semaphoreB);
929 VK_CHECK(vkd.queueWaitIdle(queue));
933 return tcu::TestStatus::pass("Pass");
937 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
938 const SemaphoreTestConfig config)
940 const vk::PlatformInterface& vkp (context.getPlatformInterface());
941 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
942 const vk::InstanceDriver vki (vkp, *instance);
943 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
944 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
945 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
947 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
948 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
951 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
952 const vk::DeviceDriver vkd (vki, *device);
953 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
955 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
958 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
960 submitDummySignal(vkd, queue, *semaphoreA);
963 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
965 submitDummyWait(vkd, queue, *semaphoreB);
966 VK_CHECK(vkd.queueWaitIdle(queue));
970 return tcu::TestStatus::pass("Pass");
974 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
975 const SemaphoreTestConfig config)
977 const vk::PlatformInterface& vkp (context.getPlatformInterface());
978 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
979 const vk::InstanceDriver vki (vkp, *instance);
980 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
981 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
983 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
984 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
987 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
988 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
989 const vk::DeviceDriver vkd (vki, *device);
990 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
992 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
995 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
997 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
999 submitDummySignal(vkd, queue, *semaphoreA);
1000 submitDummyWait(vkd, queue, *semaphoreB);
1002 VK_CHECK(vkd.queueWaitIdle(queue));
1004 return tcu::TestStatus::pass("Pass");
1008 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1009 const SemaphoreTestConfig config)
1011 const Transference transference (getHandelTypeTransferences(config.externalType));
1012 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1013 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1014 const vk::InstanceDriver vki (vkp, *instance);
1015 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1016 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1018 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1021 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1022 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1023 const vk::DeviceDriver vkd (vki, *device);
1024 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1026 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1027 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1028 NativeHandle handle;
1030 submitDummySignal(vkd, queue, *semaphoreB);
1031 VK_CHECK(vkd.queueWaitIdle(queue));
1033 if (transference == TRANSFERENCE_COPY)
1034 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1036 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1038 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1040 if (transference == TRANSFERENCE_COPY)
1041 submitDummyWait(vkd, queue, *semaphoreB);
1042 else if (transference == TRANSFERENCE_REFERENCE)
1044 submitDummySignal(vkd, queue, *semaphoreA);
1045 submitDummyWait(vkd, queue, *semaphoreB);
1048 DE_FATAL("Unknown transference.");
1050 VK_CHECK(vkd.queueWaitIdle(queue));
1052 return tcu::TestStatus::pass("Pass");
1056 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1057 const SemaphoreTestConfig config)
1059 const Transference transference (getHandelTypeTransferences(config.externalType));
1060 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1061 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1062 const vk::InstanceDriver vki (vkp, *instance);
1063 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1064 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1066 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1069 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1070 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1071 const vk::DeviceDriver vkd (vki, *device);
1072 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1074 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1075 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1076 NativeHandle handle;
1078 if (transference == TRANSFERENCE_COPY)
1079 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1081 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1083 submitDummySignal(vkd, queue, *semaphoreB);
1084 submitDummyWait(vkd, queue, *semaphoreB);
1086 VK_CHECK(vkd.queueWaitIdle(queue));
1088 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1090 if (transference == TRANSFERENCE_COPY)
1091 submitDummyWait(vkd, queue, *semaphoreB);
1092 else if (transference == TRANSFERENCE_REFERENCE)
1094 submitDummySignal(vkd, queue, *semaphoreA);
1095 submitDummyWait(vkd, queue, *semaphoreB);
1098 DE_FATAL("Unknown transference.");
1100 VK_CHECK(vkd.queueWaitIdle(queue));
1102 return tcu::TestStatus::pass("Pass");
1106 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1107 const SemaphoreTestConfig config)
1109 const size_t exportCount = 4 * 1024;
1110 const Transference transference (getHandelTypeTransferences(config.externalType));
1111 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1112 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1113 const vk::InstanceDriver vki (vkp, *instance);
1114 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1115 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1117 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1120 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1121 const vk::DeviceDriver vkd (vki, *device);
1122 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1123 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1125 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1127 NativeHandle handle;
1129 if (transference == TRANSFERENCE_COPY)
1130 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1132 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1135 submitDummySignal(vkd, queue, *semaphore);
1136 submitDummyWait(vkd, queue, *semaphore);
1138 VK_CHECK(vkd.queueWaitIdle(queue));
1141 return tcu::TestStatus::pass("Pass");
1144 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1145 const SemaphoreTestConfig config)
1147 const size_t importCount = 4 * 1024;
1148 const Transference transference (getHandelTypeTransferences(config.externalType));
1149 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1150 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1151 const vk::InstanceDriver vki (vkp, *instance);
1152 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1153 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1155 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1158 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1159 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1160 const vk::DeviceDriver vkd (vki, *device);
1161 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1162 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1163 NativeHandle handleA;
1165 if (transference == TRANSFERENCE_COPY)
1166 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1168 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1170 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1172 NativeHandle handleB (handleA);
1173 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1176 if (transference == TRANSFERENCE_COPY)
1178 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1179 submitDummyWait(vkd, queue, *semaphoreA);
1181 else if (transference == TRANSFERENCE_REFERENCE)
1183 submitDummySignal(vkd, queue, *semaphoreA);
1184 submitDummyWait(vkd, queue, *semaphoreA);
1187 DE_FATAL("Unknown transference.");
1189 VK_CHECK(vkd.queueWaitIdle(queue));
1192 return tcu::TestStatus::pass("Pass");
1195 tcu::TestStatus testSemaphoreTransference (Context& context,
1196 const SemaphoreTestConfig config)
1198 const Transference transference (getHandelTypeTransferences(config.externalType));
1199 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1200 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1201 const vk::InstanceDriver vki (vkp, *instance);
1202 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1203 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1205 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1208 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1209 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1210 const vk::DeviceDriver vkd (vki, *device);
1211 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1213 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1214 NativeHandle handle;
1216 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1219 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1221 if (config.permanence == PERMANENCE_PERMANENT)
1223 if (transference == TRANSFERENCE_COPY)
1225 submitDummySignal(vkd, queue, *semaphoreA);
1226 submitDummyWait(vkd, queue, *semaphoreB);
1227 VK_CHECK(vkd.queueWaitIdle(queue));
1229 submitDummySignal(vkd, queue, *semaphoreB);
1231 submitDummyWait(vkd, queue, *semaphoreA);
1232 submitDummyWait(vkd, queue, *semaphoreB);
1233 VK_CHECK(vkd.queueWaitIdle(queue));
1235 else if (transference== TRANSFERENCE_REFERENCE)
1237 submitDummyWait(vkd, queue, *semaphoreB);
1238 VK_CHECK(vkd.queueWaitIdle(queue));
1240 submitDummySignal(vkd, queue, *semaphoreA);
1241 submitDummyWait(vkd, queue, *semaphoreB);
1243 submitDummySignal(vkd, queue, *semaphoreB);
1244 submitDummyWait(vkd, queue, *semaphoreA);
1245 VK_CHECK(vkd.queueWaitIdle(queue));
1248 DE_FATAL("Unknown transference.");
1250 else if (config.permanence == PERMANENCE_TEMPORARY)
1252 if (transference == TRANSFERENCE_COPY)
1254 submitDummySignal(vkd, queue, *semaphoreA);
1255 submitDummyWait(vkd, queue, *semaphoreB);
1256 VK_CHECK(vkd.queueWaitIdle(queue));
1258 submitDummySignal(vkd, queue, *semaphoreB);
1260 submitDummyWait(vkd, queue, *semaphoreA);
1261 submitDummyWait(vkd, queue, *semaphoreB);
1262 VK_CHECK(vkd.queueWaitIdle(queue));
1264 else if (transference== TRANSFERENCE_REFERENCE)
1266 submitDummyWait(vkd, queue, *semaphoreB);
1267 VK_CHECK(vkd.queueWaitIdle(queue));
1269 submitDummySignal(vkd, queue, *semaphoreA);
1270 submitDummySignal(vkd, queue, *semaphoreB);
1272 submitDummyWait(vkd, queue, *semaphoreB);
1273 submitDummyWait(vkd, queue, *semaphoreA);
1274 VK_CHECK(vkd.queueWaitIdle(queue));
1277 DE_FATAL("Unknown transference.");
1280 DE_FATAL("Unknown permanence.");
1283 return tcu::TestStatus::pass("Pass");
1287 tcu::TestStatus testSemaphoreFdDup (Context& context,
1288 const SemaphoreTestConfig config)
1290 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1291 const Transference transference (getHandelTypeTransferences(config.externalType));
1292 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1293 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1294 const vk::InstanceDriver vki (vkp, *instance);
1295 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1296 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1298 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1301 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1302 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1303 const vk::DeviceDriver vkd (vki, *device);
1304 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1306 TestLog& log = context.getTestContext().getLog();
1307 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1312 if (transference == TRANSFERENCE_COPY)
1313 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1315 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1317 NativeHandle newFd (dup(fd.getFd()));
1319 if (newFd.getFd() < 0)
1320 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1322 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1325 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1327 if (transference == TRANSFERENCE_COPY)
1328 submitDummyWait(vkd, queue, *semaphoreB);
1329 else if (transference == TRANSFERENCE_REFERENCE)
1331 submitDummySignal(vkd, queue, *semaphoreA);
1332 submitDummyWait(vkd, queue, *semaphoreB);
1335 DE_FATAL("Unknown permanence.");
1339 VK_CHECK(vkd.queueWaitIdle(queue));
1341 return tcu::TestStatus::pass("Pass");
1346 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1350 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1351 const SemaphoreTestConfig config)
1353 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1354 const Transference transference (getHandelTypeTransferences(config.externalType));
1355 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1356 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1357 const vk::InstanceDriver vki (vkp, *instance);
1358 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1359 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1361 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1364 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1365 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1366 const vk::DeviceDriver vkd (vki, *device);
1367 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1369 TestLog& log = context.getTestContext().getLog();
1370 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1371 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1374 NativeHandle fd, secondFd;
1376 if (transference == TRANSFERENCE_COPY)
1378 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1379 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1383 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1384 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1387 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1390 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1392 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1395 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1397 if (transference == TRANSFERENCE_COPY)
1398 submitDummyWait(vkd, queue, *semaphoreC);
1399 else if (transference == TRANSFERENCE_REFERENCE)
1401 submitDummySignal(vkd, queue, *semaphoreA);
1402 submitDummyWait(vkd, queue, *semaphoreC);
1405 DE_FATAL("Unknown permanence.");
1409 VK_CHECK(vkd.queueWaitIdle(queue));
1411 return tcu::TestStatus::pass("Pass");
1416 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1420 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1421 const SemaphoreTestConfig config)
1423 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1424 const Transference transference (getHandelTypeTransferences(config.externalType));
1425 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1426 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1427 const vk::InstanceDriver vki (vkp, *instance);
1428 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1429 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1431 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1434 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1435 const vk::DeviceDriver vkd (vki, *device);
1436 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1438 TestLog& log = context.getTestContext().getLog();
1439 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1440 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1443 NativeHandle fd, secondFd;
1445 if (transference == TRANSFERENCE_COPY)
1447 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1448 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1452 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1453 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1456 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1457 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1460 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1462 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1465 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1467 if (transference == TRANSFERENCE_COPY)
1468 submitDummyWait(vkd, queue, *semaphoreC);
1469 else if (transference == TRANSFERENCE_REFERENCE)
1471 submitDummySignal(vkd, queue, *semaphoreA);
1472 submitDummyWait(vkd, queue, *semaphoreC);
1475 DE_FATAL("Unknown permanence.");
1479 VK_CHECK(vkd.queueWaitIdle(queue));
1481 return tcu::TestStatus::pass("Pass");
1486 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1490 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1491 const SemaphoreTestConfig config)
1493 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1494 const Transference transference (getHandelTypeTransferences(config.externalType));
1495 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1496 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, config.externalType, 0u, 0u));
1497 const vk::InstanceDriver vki (vkp, *instance);
1498 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1499 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1501 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1504 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1505 const vk::DeviceDriver vkd (vki, *device);
1506 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1508 TestLog& log = context.getTestContext().getLog();
1509 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1512 if (transference == TRANSFERENCE_COPY)
1513 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1515 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1520 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1522 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1523 TCU_FAIL("Failed to create socket pair");
1527 const NativeHandle srcSocket (sv[0]);
1528 const NativeHandle dstSocket (sv[1]);
1529 std::string sendData ("deqp");
1533 const int fdRaw (fd.getFd());
1536 char buffer[CMSG_SPACE(sizeof(int))];
1537 iovec iov = { &sendData[0], sendData.length()};
1539 deMemset(&msg, 0, sizeof(msg));
1541 msg.msg_control = buffer;
1542 msg.msg_controllen = sizeof(buffer);
1546 cmsg = CMSG_FIRSTHDR(&msg);
1547 cmsg->cmsg_level = SOL_SOCKET;
1548 cmsg->cmsg_type = SCM_RIGHTS;
1549 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1551 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1552 msg.msg_controllen = cmsg->cmsg_len;
1554 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1556 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1557 TCU_FAIL("Failed to send fd over socket");
1564 char buffer[CMSG_SPACE(sizeof(int))];
1565 std::string recvData (4, '\0');
1566 iovec iov = { &recvData[0], recvData.length() };
1568 deMemset(&msg, 0, sizeof(msg));
1570 msg.msg_control = buffer;
1571 msg.msg_controllen = sizeof(buffer);
1575 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1579 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1580 TCU_FAIL("Failed to recv fd over socket");
1583 else if (bytes != (ssize_t)sendData.length())
1585 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1589 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1590 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1592 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1593 NativeHandle newFd (newFd_);
1595 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1596 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1597 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1598 TCU_CHECK(recvData == sendData);
1599 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1602 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1604 if (transference == TRANSFERENCE_COPY)
1605 submitDummyWait(vkd, queue, *newSemaphore);
1606 else if (transference == TRANSFERENCE_REFERENCE)
1608 submitDummySignal(vkd, queue, *newSemaphore);
1609 submitDummyWait(vkd, queue, *newSemaphore);
1612 DE_FATAL("Unknown permanence.");
1614 VK_CHECK(vkd.queueWaitIdle(queue));
1622 return tcu::TestStatus::pass("Pass");
1626 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1630 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1632 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1633 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, externalType));
1634 const vk::InstanceDriver vki (vkp, *instance);
1635 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1637 TestLog& log = context.getTestContext().getLog();
1639 const vk::VkPhysicalDeviceExternalFenceInfo info =
1641 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1645 vk::VkExternalFenceProperties properties =
1647 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1654 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1655 log << TestLog::Message << properties << TestLog::EndMessage;
1657 TCU_CHECK(properties.pNext == DE_NULL);
1658 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1660 return tcu::TestStatus::pass("Pass");
1663 struct FenceTestConfig
1665 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
1666 Permanence permanence_)
1667 : externalType (externalType_)
1668 , permanence (permanence_)
1672 vk::VkExternalFenceHandleTypeFlagBits externalType;
1673 Permanence permanence;
1677 tcu::TestStatus testFenceWin32Create (Context& context,
1678 const FenceTestConfig config)
1680 #if (DE_OS == DE_OS_WIN32)
1681 const Transference transference (getHandelTypeTransferences(config.externalType));
1682 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1683 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1684 const vk::InstanceDriver vki (vkp, *instance);
1685 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1686 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1688 checkFenceSupport(vki, physicalDevice, config.externalType);
1691 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1692 const vk::DeviceDriver vkd (vki, *device);
1693 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1694 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1696 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1699 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1700 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1703 const vk::VkExportFenceCreateInfo exportCreateInfo=
1705 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1707 (vk::VkExternalFenceHandleTypeFlags)config.externalType
1709 const vk::VkFenceCreateInfo createInfo =
1711 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1715 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1717 if (transference == TRANSFERENCE_COPY)
1718 submitDummySignal(vkd, queue, *fence);
1720 NativeHandle handleA;
1721 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1724 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1725 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1727 if (transference == TRANSFERENCE_COPY)
1728 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1729 else if (transference == TRANSFERENCE_REFERENCE)
1731 submitDummySignal(vkd, queue, *fence);
1732 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1735 DE_FATAL("Unknown transference.");
1737 VK_CHECK(vkd.queueWaitIdle(queue));
1740 return tcu::TestStatus::pass("Pass");
1745 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1749 tcu::TestStatus testFenceImportTwice (Context& context,
1750 const FenceTestConfig config)
1752 const Transference transference (getHandelTypeTransferences(config.externalType));
1753 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1754 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1755 const vk::InstanceDriver vki (vkp, *instance);
1756 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1757 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1759 checkFenceSupport(vki, physicalDevice, config.externalType);
1762 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1763 const vk::DeviceDriver vkd (vki, *device);
1764 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1765 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1766 NativeHandle handleA;
1768 if (transference == TRANSFERENCE_COPY)
1769 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1771 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1774 NativeHandle handleB (handleA);
1775 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1776 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1777 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1779 if (transference == TRANSFERENCE_COPY)
1780 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1781 else if (transference == TRANSFERENCE_REFERENCE)
1783 submitDummySignal(vkd, queue, *fenceA);
1784 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1787 DE_FATAL("Unknown transference.");
1789 VK_CHECK(vkd.queueWaitIdle(queue));
1792 return tcu::TestStatus::pass("Pass");
1796 tcu::TestStatus testFenceImportReimport (Context& context,
1797 const FenceTestConfig config)
1799 const Transference transference (getHandelTypeTransferences(config.externalType));
1800 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1801 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1802 const vk::InstanceDriver vki (vkp, *instance);
1803 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1804 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1806 checkFenceSupport(vki, physicalDevice, config.externalType);
1809 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1810 const vk::DeviceDriver vkd (vki, *device);
1811 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1813 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1814 NativeHandle handleA;
1816 if (transference == TRANSFERENCE_COPY)
1817 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1819 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1821 NativeHandle handleB (handleA);
1822 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1823 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1825 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1827 if (transference == TRANSFERENCE_COPY)
1828 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1829 else if (transference == TRANSFERENCE_REFERENCE)
1831 submitDummySignal(vkd, queue, *fenceA);
1832 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1835 DE_FATAL("Unknown transference.");
1837 VK_CHECK(vkd.queueWaitIdle(queue));
1839 return tcu::TestStatus::pass("Pass");
1843 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1844 const FenceTestConfig config)
1846 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1847 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1848 const vk::InstanceDriver vki (vkp, *instance);
1849 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1850 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1852 checkFenceSupport(vki, physicalDevice, config.externalType);
1855 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1856 const vk::DeviceDriver vkd (vki, *device);
1857 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1858 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1861 NativeHandle handle;
1863 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1866 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1867 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1868 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1870 VK_CHECK(vkd.queueWaitIdle(queue));
1874 return tcu::TestStatus::pass("Pass");
1878 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
1879 const FenceTestConfig config)
1881 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1882 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1883 const vk::InstanceDriver vki (vkp, *instance);
1884 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1885 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1886 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1888 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1889 checkFenceSupport(vki, physicalDevice, config.externalType);
1892 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1893 const vk::DeviceDriver vkd (vki, *device);
1894 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1896 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1897 NativeHandle handle;
1899 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1901 submitDummySignal(vkd, queue, *fenceA);
1904 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1906 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1907 VK_CHECK(vkd.queueWaitIdle(queue));
1911 return tcu::TestStatus::pass("Pass");
1915 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
1916 const FenceTestConfig config)
1918 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1919 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1920 const vk::InstanceDriver vki (vkp, *instance);
1921 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1922 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1924 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1925 checkFenceSupport(vki, physicalDevice, config.externalType);
1928 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1929 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1930 const vk::DeviceDriver vkd (vki, *device);
1931 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1933 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1934 NativeHandle handle;
1936 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1938 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1940 submitDummySignal(vkd, queue, *fenceA);
1941 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1943 VK_CHECK(vkd.queueWaitIdle(queue));
1945 return tcu::TestStatus::pass("Pass");
1949 tcu::TestStatus testFenceSignalImport (Context& context,
1950 const FenceTestConfig config)
1952 const Transference transference (getHandelTypeTransferences(config.externalType));
1953 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1954 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
1955 const vk::InstanceDriver vki (vkp, *instance);
1956 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1957 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1959 checkFenceSupport(vki, physicalDevice, config.externalType);
1962 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1963 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1964 const vk::DeviceDriver vkd (vki, *device);
1965 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1967 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1968 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
1969 NativeHandle handle;
1971 submitDummySignal(vkd, queue, *fenceB);
1972 VK_CHECK(vkd.queueWaitIdle(queue));
1974 if (transference == TRANSFERENCE_COPY)
1975 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1977 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1979 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
1981 if (transference == TRANSFERENCE_COPY)
1982 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1983 else if (transference == TRANSFERENCE_REFERENCE)
1985 submitDummySignal(vkd, queue, *fenceA);
1986 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1989 DE_FATAL("Unknown transference.");
1991 VK_CHECK(vkd.queueWaitIdle(queue));
1993 return tcu::TestStatus::pass("Pass");
1997 tcu::TestStatus testFenceReset (Context& context,
1998 const FenceTestConfig config)
2000 const Transference transference (getHandelTypeTransferences(config.externalType));
2001 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2002 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2003 const vk::InstanceDriver vki (vkp, *instance);
2004 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2005 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2007 checkFenceSupport(vki, physicalDevice, config.externalType);
2010 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2011 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2012 const vk::DeviceDriver vkd (vki, *device);
2013 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2015 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2016 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2017 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2018 NativeHandle handle;
2020 submitDummySignal(vkd, queue, *fenceB);
2021 VK_CHECK(vkd.queueWaitIdle(queue));
2023 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2025 NativeHandle handleB (handle);
2026 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2028 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2030 VK_CHECK(vkd.queueWaitIdle(queue));
2031 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2033 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2035 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2036 // or fenceB should be separate copy of the payload and not affect fenceC
2037 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2039 // vkResetFences() should have restored fenceBs prior state and should be now reset
2040 // or fenceB should have it's separate payload
2041 submitDummySignal(vkd, queue, *fenceB);
2042 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2044 else if (config.permanence == PERMANENCE_PERMANENT)
2046 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2048 // Reset fences should have reset all of the fences
2049 submitDummySignal(vkd, queue, *fenceC);
2051 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2052 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2053 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2056 DE_FATAL("Unknown permanence");
2058 VK_CHECK(vkd.queueWaitIdle(queue));
2060 return tcu::TestStatus::pass("Pass");
2064 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2065 const FenceTestConfig config)
2067 const Transference transference (getHandelTypeTransferences(config.externalType));
2068 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2069 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2070 const vk::InstanceDriver vki (vkp, *instance);
2071 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2072 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2074 checkFenceSupport(vki, physicalDevice, config.externalType);
2077 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2078 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2079 const vk::DeviceDriver vkd (vki, *device);
2080 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2082 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2083 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2084 NativeHandle handle;
2086 if (transference == TRANSFERENCE_COPY)
2087 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2089 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2091 submitDummySignal(vkd, queue, *fenceB);
2092 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2094 VK_CHECK(vkd.queueWaitIdle(queue));
2096 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2098 if (transference == TRANSFERENCE_COPY)
2099 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2100 else if (transference == TRANSFERENCE_REFERENCE)
2102 submitDummySignal(vkd, queue, *fenceA);
2103 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2106 DE_FATAL("Unknown transference.");
2108 VK_CHECK(vkd.queueWaitIdle(queue));
2110 return tcu::TestStatus::pass("Pass");
2114 tcu::TestStatus testFenceMultipleExports (Context& context,
2115 const FenceTestConfig config)
2117 const size_t exportCount = 4 * 1024;
2118 const Transference transference (getHandelTypeTransferences(config.externalType));
2119 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2120 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2121 const vk::InstanceDriver vki (vkp, *instance);
2122 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2123 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2125 checkFenceSupport(vki, physicalDevice, config.externalType);
2128 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2129 const vk::DeviceDriver vkd (vki, *device);
2130 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2131 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2133 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2135 NativeHandle handle;
2137 if (transference == TRANSFERENCE_COPY)
2138 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle);
2140 getFenceNative(vkd, *device, *fence, config.externalType, handle);
2143 submitDummySignal(vkd, queue, *fence);
2144 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2146 VK_CHECK(vkd.queueWaitIdle(queue));
2149 return tcu::TestStatus::pass("Pass");
2152 tcu::TestStatus testFenceMultipleImports (Context& context,
2153 const FenceTestConfig config)
2155 const size_t importCount = 4 * 1024;
2156 const Transference transference (getHandelTypeTransferences(config.externalType));
2157 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2158 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2159 const vk::InstanceDriver vki (vkp, *instance);
2160 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2161 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2163 checkFenceSupport(vki, physicalDevice, config.externalType);
2166 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2167 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2168 const vk::DeviceDriver vkd (vki, *device);
2169 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2170 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2171 NativeHandle handleA;
2173 if (transference == TRANSFERENCE_COPY)
2174 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2176 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2178 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2180 NativeHandle handleB (handleA);
2181 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2184 if (transference == TRANSFERENCE_COPY)
2186 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2187 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2189 else if (transference == TRANSFERENCE_REFERENCE)
2191 submitDummySignal(vkd, queue, *fenceA);
2192 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2195 DE_FATAL("Unknown transference.");
2197 VK_CHECK(vkd.queueWaitIdle(queue));
2200 return tcu::TestStatus::pass("Pass");
2203 tcu::TestStatus testFenceTransference (Context& context,
2204 const FenceTestConfig config)
2206 const Transference transference (getHandelTypeTransferences(config.externalType));
2207 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2208 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2209 const vk::InstanceDriver vki (vkp, *instance);
2210 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2211 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2213 checkFenceSupport(vki, physicalDevice, config.externalType);
2216 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2217 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2218 const vk::DeviceDriver vkd (vki, *device);
2219 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2221 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2222 NativeHandle handle;
2224 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2227 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2229 if (config.permanence == PERMANENCE_PERMANENT)
2231 if (transference == TRANSFERENCE_COPY)
2233 submitDummySignal(vkd, queue, *fenceA);
2234 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2235 VK_CHECK(vkd.queueWaitIdle(queue));
2237 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2238 submitDummySignal(vkd, queue, *fenceB);
2240 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2241 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2242 VK_CHECK(vkd.queueWaitIdle(queue));
2244 else if (transference== TRANSFERENCE_REFERENCE)
2246 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2247 VK_CHECK(vkd.queueWaitIdle(queue));
2249 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2250 submitDummySignal(vkd, queue, *fenceA);
2251 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2253 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2254 submitDummySignal(vkd, queue, *fenceB);
2255 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2256 VK_CHECK(vkd.queueWaitIdle(queue));
2259 DE_FATAL("Unknown transference.");
2261 else if (config.permanence == PERMANENCE_TEMPORARY)
2263 if (transference == TRANSFERENCE_COPY)
2265 submitDummySignal(vkd, queue, *fenceA);
2266 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2267 VK_CHECK(vkd.queueWaitIdle(queue));
2269 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2270 submitDummySignal(vkd, queue, *fenceB);
2272 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2273 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2274 VK_CHECK(vkd.queueWaitIdle(queue));
2276 else if (transference == TRANSFERENCE_REFERENCE)
2278 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2279 VK_CHECK(vkd.queueWaitIdle(queue));
2281 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2282 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2283 submitDummySignal(vkd, queue, *fenceA);
2284 submitDummySignal(vkd, queue, *fenceB);
2286 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2287 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2288 VK_CHECK(vkd.queueWaitIdle(queue));
2291 DE_FATAL("Unknown transference.");
2294 DE_FATAL("Unknown permanence.");
2297 return tcu::TestStatus::pass("Pass");
2301 tcu::TestStatus testFenceFdDup (Context& context,
2302 const FenceTestConfig config)
2304 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2305 const Transference transference (getHandelTypeTransferences(config.externalType));
2306 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2307 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2308 const vk::InstanceDriver vki (vkp, *instance);
2309 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2310 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2312 checkFenceSupport(vki, physicalDevice, config.externalType);
2315 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2316 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2317 const vk::DeviceDriver vkd (vki, *device);
2318 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2320 TestLog& log = context.getTestContext().getLog();
2321 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2326 if (transference == TRANSFERENCE_COPY)
2327 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2329 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2331 NativeHandle newFd (dup(fd.getFd()));
2333 if (newFd.getFd() < 0)
2334 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2336 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2339 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2341 if (transference == TRANSFERENCE_COPY)
2342 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2343 else if (transference == TRANSFERENCE_REFERENCE)
2345 submitDummySignal(vkd, queue, *fenceA);
2346 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2349 DE_FATAL("Unknown permanence.");
2353 VK_CHECK(vkd.queueWaitIdle(queue));
2355 return tcu::TestStatus::pass("Pass");
2360 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2364 tcu::TestStatus testFenceFdDup2 (Context& context,
2365 const FenceTestConfig config)
2367 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2368 const Transference transference (getHandelTypeTransferences(config.externalType));
2369 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2370 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2371 const vk::InstanceDriver vki (vkp, *instance);
2372 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2373 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2375 checkFenceSupport(vki, physicalDevice, config.externalType);
2378 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2379 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2380 const vk::DeviceDriver vkd (vki, *device);
2381 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2383 TestLog& log = context.getTestContext().getLog();
2384 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2385 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2388 NativeHandle fd, secondFd;
2390 if (transference == TRANSFERENCE_COPY)
2392 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2393 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2397 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2398 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2401 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2404 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2406 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2409 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2411 if (transference == TRANSFERENCE_COPY)
2412 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2413 else if (transference == TRANSFERENCE_REFERENCE)
2415 submitDummySignal(vkd, queue, *fenceA);
2416 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2419 DE_FATAL("Unknown permanence.");
2423 VK_CHECK(vkd.queueWaitIdle(queue));
2425 return tcu::TestStatus::pass("Pass");
2430 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2434 tcu::TestStatus testFenceFdDup3 (Context& context,
2435 const FenceTestConfig config)
2437 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2438 const Transference transference (getHandelTypeTransferences(config.externalType));
2439 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2440 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2441 const vk::InstanceDriver vki (vkp, *instance);
2442 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2443 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2445 checkFenceSupport(vki, physicalDevice, config.externalType);
2448 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2449 const vk::DeviceDriver vkd (vki, *device);
2450 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2452 TestLog& log = context.getTestContext().getLog();
2453 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2454 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2457 NativeHandle fd, secondFd;
2459 if (transference == TRANSFERENCE_COPY)
2461 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2462 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2466 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2467 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2470 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2471 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2474 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2476 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2479 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2481 if (transference == TRANSFERENCE_COPY)
2482 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2483 else if (transference == TRANSFERENCE_REFERENCE)
2485 submitDummySignal(vkd, queue, *fenceA);
2486 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2489 DE_FATAL("Unknown permanence.");
2493 VK_CHECK(vkd.queueWaitIdle(queue));
2495 return tcu::TestStatus::pass("Pass");
2500 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2504 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2505 const FenceTestConfig config)
2507 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2508 const Transference transference (getHandelTypeTransferences(config.externalType));
2509 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2510 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, 0u, config.externalType));
2511 const vk::InstanceDriver vki (vkp, *instance);
2512 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2513 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2515 checkFenceSupport(vki, physicalDevice, config.externalType);
2518 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2519 const vk::DeviceDriver vkd (vki, *device);
2520 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2522 TestLog& log = context.getTestContext().getLog();
2523 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2526 if (transference == TRANSFERENCE_COPY)
2527 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2529 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2534 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2536 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2537 TCU_FAIL("Failed to create socket pair");
2541 const NativeHandle srcSocket (sv[0]);
2542 const NativeHandle dstSocket (sv[1]);
2543 std::string sendData ("deqp");
2547 const int fdRaw (fd.getFd());
2550 char buffer[CMSG_SPACE(sizeof(int))];
2551 iovec iov = { &sendData[0], sendData.length()};
2553 deMemset(&msg, 0, sizeof(msg));
2555 msg.msg_control = buffer;
2556 msg.msg_controllen = sizeof(buffer);
2560 cmsg = CMSG_FIRSTHDR(&msg);
2561 cmsg->cmsg_level = SOL_SOCKET;
2562 cmsg->cmsg_type = SCM_RIGHTS;
2563 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2565 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2566 msg.msg_controllen = cmsg->cmsg_len;
2568 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2570 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2571 TCU_FAIL("Failed to send fd over socket");
2578 char buffer[CMSG_SPACE(sizeof(int))];
2579 std::string recvData (4, '\0');
2580 iovec iov = { &recvData[0], recvData.length() };
2582 deMemset(&msg, 0, sizeof(msg));
2584 msg.msg_control = buffer;
2585 msg.msg_controllen = sizeof(buffer);
2589 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2593 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2594 TCU_FAIL("Failed to recv fd over socket");
2597 else if (bytes != (ssize_t)sendData.length())
2599 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2603 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2604 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2606 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2607 NativeHandle newFd (newFd_);
2609 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2610 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2611 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2612 TCU_CHECK(recvData == sendData);
2613 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2616 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2618 if (transference == TRANSFERENCE_COPY)
2619 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2620 else if (transference == TRANSFERENCE_REFERENCE)
2622 submitDummySignal(vkd, queue, *newFence);
2623 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2626 DE_FATAL("Unknown permanence.");
2628 VK_CHECK(vkd.queueWaitIdle(queue));
2636 return tcu::TestStatus::pass("Pass");
2640 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2644 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2646 const vk::VkBufferCreateFlags createFlags[] =
2649 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2650 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2651 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2653 const vk::VkBufferUsageFlags usageFlags[] =
2655 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2656 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2657 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2658 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2659 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2660 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2661 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2662 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2663 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2665 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2666 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, externalType, 0u));
2667 const vk::InstanceDriver vki (vkp, *instance);
2668 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2669 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2670 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2672 // VkDevice is only created if physical device claims to support any of these types.
2673 vk::Move<vk::VkDevice> device;
2674 de::MovePtr<vk::DeviceDriver> vkd;
2675 bool deviceHasDedicated = false;
2677 TestLog& log = context.getTestContext().getLog();
2679 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2680 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2682 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2683 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2684 const vk::VkPhysicalDeviceExternalBufferInfo info =
2686 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2692 vk::VkExternalBufferProperties properties =
2694 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2699 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2700 (deviceFeatures.sparseBinding == VK_FALSE))
2703 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2704 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2707 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2708 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2711 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2713 log << TestLog::Message << properties << TestLog::EndMessage;
2715 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2716 TCU_CHECK(properties.pNext == DE_NULL);
2717 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2719 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2721 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2723 if (!device || (requiresDedicated && !deviceHasDedicated))
2725 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2728 device = createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2729 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
2730 deviceHasDedicated = requiresDedicated;
2732 catch (const tcu::NotSupportedError& e)
2735 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2740 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2742 DE_ASSERT(!!device);
2745 if (deviceHasDedicated)
2747 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2748 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2749 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2750 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2752 if (propertiesRequiresDedicated != objectRequiresDedicated)
2753 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2757 // We can't query whether dedicated memory is required or not on per-object basis.
2758 // This check should be redundant as the code above tries to create device with
2759 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2760 // is required. However, checking again doesn't hurt.
2761 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2766 return tcu::TestStatus::pass("Pass");
2769 struct MemoryTestConfig
2771 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
2774 : externalType (externalType_)
2775 , hostVisible (hostVisible_)
2776 , dedicated (dedicated_)
2780 vk::VkExternalMemoryHandleTypeFlagBits externalType;
2785 #if (DE_OS == DE_OS_WIN32)
2786 deUint32 chooseMemoryType (deUint32 bits)
2789 TCU_THROW(NotSupportedError, "No compatible memory type found");
2791 return deCtz32(bits);
2795 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2797 #if (DE_OS == DE_OS_WIN32)
2798 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2799 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2800 const vk::InstanceDriver vki (vkp, *instance);
2801 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2802 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2803 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2804 const vk::DeviceDriver vkd (vki, *device);
2805 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2806 const deUint32 seed = 1261033864u;
2807 const vk::VkDeviceSize bufferSize = 1024;
2808 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2810 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2811 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2813 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2815 // \note Buffer is only allocated to get memory requirements
2816 deUint32 exportedMemoryTypeIndex = ~0U;
2817 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2818 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2819 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2821 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2824 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2825 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2828 const vk::VkExportMemoryAllocateInfo exportInfo =
2830 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2832 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
2835 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2836 const vk::VkMemoryAllocateInfo info =
2838 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2841 exportedMemoryTypeIndex
2843 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2844 NativeHandle handleA;
2846 if (config.hostVisible)
2847 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2849 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2852 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2854 if (config.hostVisible)
2856 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2857 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2859 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2860 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2862 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2863 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
2865 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2866 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2870 return tcu::TestStatus::pass("Pass");
2874 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2878 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2880 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2881 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2882 const vk::InstanceDriver vki (vkp, *instance);
2883 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2884 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2885 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2886 const vk::DeviceDriver vkd (vki, *device);
2887 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2888 const deUint32 seed = 1261033864u;
2889 const vk::VkDeviceSize bufferSize = 1024;
2890 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2892 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2894 deUint32 exportedMemoryTypeIndex = ~0U;
2895 // \note Buffer is only allocated to get memory requirements
2896 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2897 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2898 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2899 NativeHandle handleA;
2901 if (config.hostVisible)
2902 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2904 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2907 NativeHandle handleB (handleA);
2908 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2909 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2911 if (config.hostVisible)
2913 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2914 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2916 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2917 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
2919 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
2920 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
2922 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2923 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2927 return tcu::TestStatus::pass("Pass");
2930 tcu::TestStatus testMemoryMultimpleImports (Context& context, MemoryTestConfig config)
2932 const size_t count = 4 * 1024;
2933 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2934 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2935 const vk::InstanceDriver vki (vkp, *instance);
2936 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2937 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2938 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2939 const vk::DeviceDriver vkd (vki, *device);
2940 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2941 const vk::VkDeviceSize bufferSize = 1024;
2943 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2945 deUint32 exportedMemoryTypeIndex = ~0U;
2946 // \note Buffer is only allocated to get memory requirements
2947 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2948 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2949 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2950 NativeHandle handleA;
2952 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2954 for (size_t ndx = 0; ndx < count; ndx++)
2956 NativeHandle handleB (handleA);
2957 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2960 return tcu::TestStatus::pass("Pass");
2963 tcu::TestStatus testMemoryMultimpleExports (Context& context, MemoryTestConfig config)
2965 const size_t count = 4 * 1024;
2966 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2967 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2968 const vk::InstanceDriver vki (vkp, *instance);
2969 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2970 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2971 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2972 const vk::DeviceDriver vkd (vki, *device);
2973 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2974 const vk::VkDeviceSize bufferSize = 1024;
2976 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2978 deUint32 exportedMemoryTypeIndex = ~0U;
2979 // \note Buffer is only allocated to get memory requirements
2980 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2981 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2982 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2984 for (size_t ndx = 0; ndx < count; ndx++)
2986 NativeHandle handle;
2987 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
2990 return tcu::TestStatus::pass("Pass");
2993 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
2995 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2996 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2997 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
2998 const vk::InstanceDriver vki (vkp, *instance);
2999 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3000 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3003 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3004 const vk::DeviceDriver vkd (vki, *device);
3006 TestLog& log = context.getTestContext().getLog();
3007 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3008 const vk::VkDeviceSize bufferSize = 1024;
3009 const deUint32 seed = 851493858u;
3010 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3012 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3014 deUint32 exportedMemoryTypeIndex = ~0U;
3015 // \note Buffer is only allocated to get memory requirements
3016 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3017 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3018 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3020 if (config.hostVisible)
3021 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3023 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3024 NativeHandle newFd (dup(fd.getFd()));
3026 if (newFd.getFd() < 0)
3027 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3029 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3032 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3034 if (config.hostVisible)
3036 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3038 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3040 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3041 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3045 return tcu::TestStatus::pass("Pass");
3050 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3054 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3056 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3057 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3058 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3059 const vk::InstanceDriver vki (vkp, *instance);
3060 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3061 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3064 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3065 const vk::DeviceDriver vkd (vki, *device);
3067 TestLog& log = context.getTestContext().getLog();
3068 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3069 const vk::VkDeviceSize bufferSize = 1024;
3070 const deUint32 seed = 224466865u;
3071 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3073 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3075 deUint32 exportedMemoryTypeIndex = ~0U;
3076 // \note Buffer is only allocated to get memory requirements
3077 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3078 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3079 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3081 if (config.hostVisible)
3082 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3084 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3085 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3086 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3089 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3091 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3094 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3096 if (config.hostVisible)
3098 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3100 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3102 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3103 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3107 return tcu::TestStatus::pass("Pass");
3112 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3116 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3118 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3119 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3120 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3121 const vk::InstanceDriver vki (vkp, *instance);
3122 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3123 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3126 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3127 const vk::DeviceDriver vkd (vki, *device);
3129 TestLog& log = context.getTestContext().getLog();
3130 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3131 const vk::VkDeviceSize bufferSize = 1024;
3132 const deUint32 seed = 2554088961u;
3133 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3135 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3137 deUint32 exportedMemoryTypeIndex = ~0U;
3138 // \note Buffer is only allocated to get memory requirements
3139 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3140 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3141 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3143 if (config.hostVisible)
3144 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3146 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3147 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3148 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3151 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3153 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3156 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3158 if (config.hostVisible)
3160 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3162 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3164 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3165 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3169 return tcu::TestStatus::pass("Pass");
3174 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3178 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3180 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3181 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3182 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3183 const vk::InstanceDriver vki (vkp, *instance);
3184 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3185 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3188 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3189 const vk::DeviceDriver vkd (vki, *device);
3191 TestLog& log = context.getTestContext().getLog();
3192 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3193 const vk::VkDeviceSize bufferSize = 1024;
3194 const deUint32 seed = 3403586456u;
3195 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3197 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3199 deUint32 exportedMemoryTypeIndex = ~0U;
3200 // \note Buffer is only allocated to get memory requirements
3201 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3202 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3203 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3205 if (config.hostVisible)
3206 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3208 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3213 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3215 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3216 TCU_FAIL("Failed to create socket pair");
3220 const NativeHandle srcSocket (sv[0]);
3221 const NativeHandle dstSocket (sv[1]);
3222 std::string sendData ("deqp");
3226 const int fdRaw (fd.getFd());
3229 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3230 iovec iov = { &sendData[0], sendData.length()};
3232 deMemset(&msg, 0, sizeof(msg));
3234 msg.msg_control = tmpBuffer;
3235 msg.msg_controllen = sizeof(tmpBuffer);
3239 cmsg = CMSG_FIRSTHDR(&msg);
3240 cmsg->cmsg_level = SOL_SOCKET;
3241 cmsg->cmsg_type = SCM_RIGHTS;
3242 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3244 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3245 msg.msg_controllen = cmsg->cmsg_len;
3247 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3249 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3250 TCU_FAIL("Failed to send fd over socket");
3257 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3258 std::string recvData (4, '\0');
3259 iovec iov = { &recvData[0], recvData.length() };
3261 deMemset(&msg, 0, sizeof(msg));
3263 msg.msg_control = tmpBuffer;
3264 msg.msg_controllen = sizeof(tmpBuffer);
3268 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3272 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3273 TCU_FAIL("Failed to recv fd over socket");
3276 else if (bytes != (ssize_t)sendData.length())
3278 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3282 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3284 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3285 NativeHandle newFd (newFd_);
3287 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3288 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3289 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3290 TCU_CHECK(recvData == sendData);
3291 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3294 const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3296 if (config.hostVisible)
3298 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3300 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3302 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3303 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3312 return tcu::TestStatus::pass("Pass");
3316 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3320 struct BufferTestConfig
3322 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3324 : externalType (externalType_)
3325 , dedicated (dedicated_)
3329 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3333 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3334 const BufferTestConfig config)
3336 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3337 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3338 const vk::InstanceDriver vki (vkp, *instance);
3339 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3340 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3341 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3342 const vk::DeviceDriver vkd (vki, *device);
3343 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3344 const vk::VkDeviceSize bufferSize = 1024;
3346 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3348 deUint32 exportedMemoryTypeIndex = ~0U;
3349 // \note Buffer is only allocated to get memory requirements
3350 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3351 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3352 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3353 NativeHandle handle;
3355 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3357 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3360 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3361 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3363 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3366 return tcu::TestStatus::pass("Pass");
3369 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3370 const BufferTestConfig config)
3372 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3373 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3374 const vk::InstanceDriver vki (vkp, *instance);
3375 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3376 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3377 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3378 const vk::DeviceDriver vkd (vki, *device);
3379 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3380 const vk::VkDeviceSize bufferSize = 1024;
3382 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3384 deUint32 exportedMemoryTypeIndex = ~0U;
3385 // \note Buffer is only allocated to get memory requirements
3386 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3387 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3388 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3389 NativeHandle handle;
3391 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3392 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3395 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3396 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3398 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3401 return tcu::TestStatus::pass("Pass");
3404 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3405 const BufferTestConfig config)
3407 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3408 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3409 const vk::InstanceDriver vki (vkp, *instance);
3410 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3411 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3412 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3413 const vk::DeviceDriver vkd (vki, *device);
3414 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3415 const vk::VkDeviceSize bufferSize = 1024;
3417 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3419 deUint32 exportedMemoryTypeIndex = ~0U;
3420 // \note Buffer is only allocated to get memory requirements
3421 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3422 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3423 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3424 NativeHandle handle;
3426 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3429 const vk::Unique<vk::VkDeviceMemory> memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3430 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3432 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3433 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3436 return tcu::TestStatus::pass("Pass");
3439 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3441 const vk::VkImageCreateFlags createFlags[] =
3444 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3445 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3446 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3447 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3448 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
3449 vk::VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
3451 const vk::VkImageUsageFlags usageFlags[] =
3453 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3454 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3455 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3456 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3457 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3458 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3459 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
3460 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3462 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3463 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, externalType, 0u));
3464 const vk::InstanceDriver vki (vkp, *instance);
3465 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3466 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3467 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3469 // VkDevice is only created if physical device claims to support any of these types.
3470 vk::Move<vk::VkDevice> device;
3471 de::MovePtr<vk::DeviceDriver> vkd;
3472 bool deviceHasDedicated = false;
3474 TestLog& log = context.getTestContext().getLog();
3476 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3477 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3479 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3480 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3481 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3482 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3483 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3484 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3486 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3490 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3492 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3501 vk::VkExternalImageFormatProperties externalProperties =
3503 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3507 vk::VkImageFormatProperties2 properties =
3509 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3510 &externalProperties,
3520 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3521 (deviceFeatures.sparseBinding == VK_FALSE))
3524 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3525 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3528 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3529 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3532 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
3534 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3535 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3536 TCU_CHECK(externalProperties.pNext == DE_NULL);
3537 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3539 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3541 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3543 if (!device || (requiresDedicated && !deviceHasDedicated))
3545 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3548 device = createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3549 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
3550 deviceHasDedicated = requiresDedicated;
3552 catch (const tcu::NotSupportedError& e)
3555 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3560 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3562 DE_ASSERT(!!device);
3565 if (deviceHasDedicated)
3567 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3568 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3569 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3570 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3572 if (propertiesRequiresDedicated != objectRequiresDedicated)
3573 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3577 // We can't query whether dedicated memory is required or not on per-object basis.
3578 // This check should be redundant as the code above tries to create device with
3579 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3580 // is required. However, checking again doesn't hurt.
3581 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3586 return tcu::TestStatus::pass("Pass");
3589 struct ImageTestConfig
3591 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3593 : externalType (externalType_)
3594 , dedicated (dedicated_)
3598 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3602 tcu::TestStatus testImageBindExportImportBind (Context& context,
3603 const ImageTestConfig config)
3605 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3606 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3607 const vk::InstanceDriver vki (vkp, *instance);
3608 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3609 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3610 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3611 const vk::DeviceDriver vkd (vki, *device);
3612 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3613 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3614 const deUint32 width = 64u;
3615 const deUint32 height = 64u;
3616 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3618 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3620 deUint32 exportedMemoryTypeIndex = ~0U;
3621 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3622 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3623 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3624 NativeHandle handle;
3626 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3628 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3631 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3632 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3633 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3634 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3636 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3639 return tcu::TestStatus::pass("Pass");
3642 tcu::TestStatus testImageExportBindImportBind (Context& context,
3643 const ImageTestConfig config)
3645 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3646 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3647 const vk::InstanceDriver vki (vkp, *instance);
3648 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3649 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3650 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3651 const vk::DeviceDriver vkd (vki, *device);
3652 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3653 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3654 const deUint32 width = 64u;
3655 const deUint32 height = 64u;
3656 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3658 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3660 deUint32 exportedMemoryTypeIndex = ~0U;
3661 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3662 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3663 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3664 NativeHandle handle;
3666 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3667 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3670 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3671 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3672 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3673 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3675 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3678 return tcu::TestStatus::pass("Pass");
3681 tcu::TestStatus testImageExportImportBindBind (Context& context,
3682 const ImageTestConfig config)
3684 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3685 const vk::Unique<vk::VkInstance> instance (createInstance(vkp, 0u, config.externalType, 0u));
3686 const vk::InstanceDriver vki (vkp, *instance);
3687 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3688 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3689 const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3690 const vk::DeviceDriver vkd (vki, *device);
3691 const vk::VkImageUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3692 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3693 const deUint32 width = 64u;
3694 const deUint32 height = 64u;
3695 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3697 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3699 deUint32 exportedMemoryTypeIndex = ~0U;
3700 // \note Image is only allocated to get memory requirements
3701 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3702 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA));
3703 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3704 NativeHandle handle;
3706 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3709 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3710 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3711 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3712 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3714 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3715 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3718 return tcu::TestStatus::pass("Pass");
3720 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3724 const char* const name;
3725 const Permanence permanence;
3728 { "temporary", PERMANENCE_TEMPORARY },
3729 { "permanent", PERMANENCE_PERMANENT }
3732 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3734 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3736 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3738 const Permanence permanence (permanences[permanenceNdx].permanence);
3739 const char* const permanenceName (permanences[permanenceNdx].name);
3740 const FenceTestConfig config (externalType, permanence);
3742 if (!isSupportedPermanence(externalType, permanence))
3745 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3746 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3748 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
3751 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", testFenceImportTwice, config);
3752 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", testFenceImportReimport, config);
3753 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", testFenceMultipleImports, config);
3754 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testFenceSignalExportImportWait, config);
3755 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", testFenceSignalImport, config);
3756 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", testFenceReset, config);
3757 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", testFenceTransference, config);
3759 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
3760 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
3762 // \note Not supported on WIN32 handles
3763 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", testFenceMultipleExports, config);
3765 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", testFenceFdDup, config);
3766 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", testFenceFdDup2, config);
3767 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", testFenceFdDup3, config);
3768 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", testFenceFdSendOverSocket, config);
3771 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3773 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
3774 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
3775 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
3782 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
3784 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
3786 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
3787 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
3788 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
3789 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
3794 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
3798 const char* const name;
3799 const Permanence permanence;
3802 { "temporary", PERMANENCE_TEMPORARY },
3803 { "permanent", PERMANENCE_PERMANENT }
3806 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
3808 addFunctionCase(semaphoreGroup.get(), "info", "Test external semaphore queries.", testSemaphoreQueries, externalType);
3810 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3812 const Permanence permanence (permanences[permanenceNdx].permanence);
3813 const char* const permanenceName (permanences[permanenceNdx].name);
3814 const SemaphoreTestConfig config (externalType, permanence);
3816 if (!isSupportedPermanence(externalType, permanence))
3819 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3820 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3822 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
3825 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", testSemaphoreImportTwice, config);
3826 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", testSemaphoreImportReimport, config);
3827 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", testSemaphoreMultipleImports, config);
3828 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testSemaphoreSignalExportImportWait, config);
3829 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", testSemaphoreSignalImport, config);
3830 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", testSemaphoreTransference, config);
3832 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
3833 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
3835 // \note Not supported on WIN32 handles
3836 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", testSemaphoreMultipleExports, config);
3838 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", testSemaphoreFdDup, config);
3839 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", testSemaphoreFdDup2, config);
3840 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", testSemaphoreFdDup3, config);
3841 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", testSemaphoreFdSendOverSocket, config);
3844 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3846 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
3847 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
3848 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", testSemaphoreExportImportSignalWait, config);
3852 return semaphoreGroup;
3855 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
3857 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
3859 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
3860 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
3861 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
3862 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
3864 return semaphoreGroup;
3867 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3869 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
3871 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
3873 const bool dedicated (dedicatedNdx == 1);
3874 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
3876 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
3878 const bool hostVisible (hostVisibleNdx == 1);
3879 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
3880 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
3882 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
3883 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3885 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
3888 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
3889 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultimpleImports, memoryConfig);
3891 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
3893 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
3894 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
3895 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
3896 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
3897 // \note Not supported on WIN32 handles
3898 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultimpleExports, memoryConfig);
3901 dedicatedGroup->addChild(hostVisibleGroup.release());
3905 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
3906 const BufferTestConfig bufferConfig (externalType, dedicated);
3908 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
3909 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
3910 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
3911 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importind and binding buffer.", testBufferExportImportBindBind, bufferConfig);
3913 dedicatedGroup->addChild(bufferGroup.release());
3917 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
3918 const ImageTestConfig imageConfig (externalType, dedicated);
3920 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
3921 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
3922 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
3923 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importind and binding image.", testImageExportImportBindBind, imageConfig);
3925 dedicatedGroup->addChild(imageGroup.release());
3928 group->addChild(dedicatedGroup.release());
3934 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
3936 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
3938 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
3939 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
3940 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
3947 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
3949 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
3951 group->addChild(createSemaphoreTests(testCtx).release());
3952 group->addChild(createMemoryTests(testCtx).release());
3953 group->addChild(createFenceTests(testCtx).release());
3955 return group.release();