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"
23 #include "vktCustomInstancesDevices.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vkRefUtil.hpp"
27 #include "vkDeviceUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkApiVersion.hpp"
32 #include "vkImageUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuCommandLine.hpp"
37 #include "deUniquePtr.hpp"
38 #include "deStringUtil.hpp"
39 #include "deRandom.hpp"
43 #include "vktExternalMemoryUtil.hpp"
45 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
49 # include <sys/types.h>
50 # include <sys/socket.h>
53 #if (DE_OS == DE_OS_WIN32)
54 # define WIN32_LEAN_AND_MEAN
60 using namespace vkt::ExternalMemoryUtil;
70 std::string getFormatCaseName (vk::VkFormat format)
72 return de::toLower(de::toString(getFormatStr(format)).substr(10));
75 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
79 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo =
81 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
85 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
87 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
92 vk::VkMemoryRequirements2 requirements =
94 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
95 &dedicatedRequirements,
99 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
101 return dedicatedRequirements;
104 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
108 const vk::VkImageMemoryRequirementsInfo2 requirementInfo =
110 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
114 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
116 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
121 vk::VkMemoryRequirements2 requirements =
123 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
124 &dedicatedRequirements,
128 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
130 return dedicatedRequirements;
133 void writeHostMemory (const vk::DeviceInterface& vkd,
135 vk::VkDeviceMemory memory,
139 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
141 deMemcpy(ptr, data, size);
143 flushMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
145 vkd.unmapMemory(device, memory);
148 void checkHostMemory (const vk::DeviceInterface& vkd,
150 vk::VkDeviceMemory memory,
154 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
156 invalidateMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
158 if (deMemCmp(ptr, data, size) != 0)
159 TCU_FAIL("Memory contents don't match");
161 vkd.unmapMemory(device, memory);
164 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
166 de::Random rng (seed);
167 std::vector<deUint8> data (size);
169 for (size_t ndx = 0; ndx < size; ndx++)
171 data[ndx] = rng.getUint8();
177 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki,
178 vk::VkPhysicalDevice device,
179 vk::VkQueueFlags requireFlags)
181 const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
183 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
185 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
186 return queueFamilyIndex;
189 TCU_THROW(NotSupportedError, "Queue type not supported");
192 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
193 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
194 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
195 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
197 std::vector<std::string> instanceExtensions;
199 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
200 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
202 if (externalSemaphoreTypes != 0)
203 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
204 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
206 if (externalMemoryTypes != 0)
207 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
208 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
210 if (externalFenceTypes != 0)
211 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
212 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
214 return instanceExtensions;
217 CustomInstance createTestInstance (Context& context,
218 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
219 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
220 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
224 return vkt::createCustomInstanceWithExtensions(context, getInstanceExtensions(context.getUsedApiVersion(), externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
226 catch (const vk::Error& error)
228 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
229 TCU_THROW(NotSupportedError, "Required extensions not supported");
235 vk::Move<vk::VkDevice> createTestDevice (const Context& context,
236 const vk::PlatformInterface& vkp,
237 vk::VkInstance instance,
238 const vk::InstanceInterface& vki,
239 vk::VkPhysicalDevice physicalDevice,
240 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
241 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
242 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,
243 deUint32 queueFamilyIndex,
244 bool useDedicatedAllocs = false,
245 void * protectedFeatures = DE_NULL)
247 const deUint32 apiVersion = context.getUsedApiVersion();
248 bool useExternalSemaphore = false;
249 bool useExternalFence = false;
250 bool useExternalMemory = false;
251 std::vector<const char*> deviceExtensions;
253 if ((externalSemaphoreTypes
254 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
255 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
257 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
258 useExternalSemaphore = true;
261 if ((externalFenceTypes
262 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
263 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
265 deviceExtensions.push_back("VK_KHR_external_fence_fd");
266 useExternalFence = true;
269 if (useDedicatedAllocs)
271 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
272 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
273 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
274 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
277 if ((externalMemoryTypes
278 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
279 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
281 deviceExtensions.push_back("VK_KHR_external_memory_fd");
282 useExternalMemory = true;
285 if ((externalMemoryTypes
286 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
288 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
289 useExternalMemory = true;
292 if ((externalSemaphoreTypes
293 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
294 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
296 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
297 useExternalSemaphore = true;
300 if ((externalFenceTypes
301 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
302 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
304 deviceExtensions.push_back("VK_KHR_external_fence_win32");
305 useExternalFence = true;
308 if ((externalMemoryTypes
309 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
310 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
311 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
312 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
313 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
314 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
316 deviceExtensions.push_back("VK_KHR_external_memory_win32");
317 useExternalMemory = true;
320 if ((externalMemoryTypes
321 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
323 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
324 useExternalMemory = true;
325 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
326 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
327 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
328 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
331 if (useExternalSemaphore)
333 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
334 deviceExtensions.push_back("VK_KHR_external_semaphore");
337 if (useExternalFence)
339 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
340 deviceExtensions.push_back("VK_KHR_external_fence");
343 if (useExternalMemory)
345 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
346 deviceExtensions.push_back("VK_KHR_external_memory");
349 const float priority = 0.5f;
350 const vk::VkDeviceQueueCreateInfo queues[] =
353 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
362 const vk::VkDeviceCreateInfo deviceCreateInfo =
364 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
368 DE_LENGTH_OF_ARRAY(queues),
374 (deUint32)deviceExtensions.size(),
375 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
381 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
383 catch (const vk::Error& error)
385 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
386 TCU_THROW(NotSupportedError, "Required extensions not supported");
392 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
394 deUint32 queueFamilyIndex)
398 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
403 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
404 vk::VkPhysicalDevice device,
405 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
407 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
409 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
413 vk::VkExternalSemaphoreProperties properties =
415 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
422 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
424 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
425 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
427 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
428 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
431 void checkFenceSupport (const vk::InstanceInterface& vki,
432 vk::VkPhysicalDevice device,
433 vk::VkExternalFenceHandleTypeFlagBits externalType)
435 const vk::VkPhysicalDeviceExternalFenceInfo info =
437 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
441 vk::VkExternalFenceProperties properties =
443 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
450 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
452 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
453 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
455 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
456 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
459 void checkBufferSupport (const vk::InstanceInterface& vki,
460 vk::VkPhysicalDevice device,
461 vk::VkExternalMemoryHandleTypeFlagBits externalType,
462 vk::VkBufferViewCreateFlags createFlag,
463 vk::VkBufferUsageFlags usageFlag,
466 const vk::VkPhysicalDeviceExternalBufferInfo info =
468 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
475 vk::VkExternalBufferProperties properties =
477 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
483 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
485 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
486 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
488 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
489 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
491 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
492 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
495 void checkImageSupport (const vk::InstanceInterface& vki,
496 vk::VkPhysicalDevice device,
497 vk::VkExternalMemoryHandleTypeFlagBits externalType,
498 vk::VkImageViewCreateFlags createFlag,
499 vk::VkImageUsageFlags usageFlag,
501 vk::VkImageTiling tiling,
504 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
506 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
510 const vk::VkPhysicalDeviceImageFormatInfo2 info =
512 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
516 vk::VK_IMAGE_TYPE_2D,
521 vk::VkExternalImageFormatProperties externalProperties =
523 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
527 vk::VkImageFormatProperties2 properties =
529 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
540 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
542 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
543 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
545 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
546 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
548 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
549 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
552 void submitEmptySignal (const vk::DeviceInterface& vkd,
554 vk::VkSemaphore semaphore)
556 const vk::VkSubmitInfo submit =
558 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
572 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
575 void submitEmptySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk,
578 deUint32 queueFamilyIndex,
579 vk::VkSemaphore semaphore,
580 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
581 NativeHandle& nativeHandle)
583 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
584 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
586 const vk::VkEventCreateInfo eventCreateInfo =
588 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
593 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
595 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
597 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
599 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
603 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
605 The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
606 VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
607 may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
608 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
609 is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
610 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
612 vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
613 vk.endCommandBuffer(*cmdBuffer);
615 const vk::VkSubmitInfo submit =
617 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
631 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
633 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
635 VK_CHECK(vk.setEvent(device, *event));
637 VK_CHECK(vk.queueWaitIdle(queue));
640 void submitEmptyWait (const vk::DeviceInterface& vkd,
642 vk::VkSemaphore semaphore)
644 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
645 const vk::VkSubmitInfo submit =
647 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
661 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
664 void submitEmptySignal (const vk::DeviceInterface& vkd,
668 const vk::VkSubmitInfo submit =
670 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
684 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
687 void submitEmptySignalAndGetFenceNative ( const vk::DeviceInterface& vk,
690 deUint32 queueFamilyIndex,
692 vk::VkExternalFenceHandleTypeFlagBits externalType,
693 NativeHandle& nativeHandle,
694 bool expectFenceUnsignaled = true)
696 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
697 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
699 const vk::VkEventCreateInfo eventCreateInfo =
701 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
706 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
708 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
710 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
712 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
716 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
718 The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
719 VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
720 could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
721 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
722 file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
723 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
725 vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
726 vk.endCommandBuffer(*cmdBuffer);
728 const vk::VkSubmitInfo submit =
730 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
744 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
746 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
748 VK_CHECK(vk.setEvent(device, *event));
750 VK_CHECK(vk.queueWaitIdle(queue));
753 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
755 const CustomInstance instance (createTestInstance(context, externalType, 0u, 0u));
756 const vk::InstanceDriver& vki (instance.getDriver());
757 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
759 TestLog& log = context.getTestContext().getLog();
761 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
763 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
767 vk::VkExternalSemaphoreProperties properties =
769 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
776 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
777 log << TestLog::Message << properties << TestLog::EndMessage;
779 TCU_CHECK(properties.pNext == DE_NULL);
780 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
782 return tcu::TestStatus::pass("Pass");
785 struct SemaphoreTestConfig
787 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
788 Permanence permanence_)
789 : externalType (externalType_)
790 , permanence (permanence_)
794 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
795 Permanence permanence;
798 tcu::TestStatus testSemaphoreWin32Create (Context& context,
799 const SemaphoreTestConfig config)
801 #if (DE_OS == DE_OS_WIN32)
802 const Transference transference (getHandelTypeTransferences(config.externalType));
803 const vk::PlatformInterface& vkp (context.getPlatformInterface());
804 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
805 const vk::InstanceDriver& vki (instance.getDriver());
806 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
807 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
809 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
812 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
813 const vk::DeviceDriver vkd (vkp, instance, *device);
814 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
815 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
817 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
820 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
821 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
822 (vk::pt::Win32LPCWSTR)DE_NULL
824 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
826 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
828 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
830 const vk::VkSemaphoreCreateInfo createInfo =
832 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
836 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
838 if (transference == TRANSFERENCE_COPY)
839 submitEmptySignal(vkd, queue, *semaphore);
841 NativeHandle handleA;
842 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
845 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
846 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
848 if (transference == TRANSFERENCE_COPY)
849 submitEmptyWait(vkd, queue, *semaphoreA);
850 else if (transference == TRANSFERENCE_REFERENCE)
852 submitEmptySignal(vkd, queue, *semaphore);
853 submitEmptyWait(vkd, queue, *semaphoreA);
856 DE_FATAL("Unknown transference.");
858 VK_CHECK(vkd.queueWaitIdle(queue));
861 return tcu::TestStatus::pass("Pass");
866 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
870 tcu::TestStatus testSemaphoreImportTwice (Context& context,
871 const SemaphoreTestConfig config)
873 const Transference transference (getHandelTypeTransferences(config.externalType));
874 const vk::PlatformInterface& vkp (context.getPlatformInterface());
875 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
876 const vk::InstanceDriver& vki (instance.getDriver());
877 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
878 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
880 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
883 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
884 const vk::DeviceDriver vkd (vkp, instance, *device);
885 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
886 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
887 NativeHandle handleA;
889 if (transference == TRANSFERENCE_COPY)
890 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
892 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
895 NativeHandle handleB (handleA);
896 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
897 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
898 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
900 if (transference == TRANSFERENCE_COPY)
901 submitEmptyWait(vkd, queue, *semaphoreA);
902 else if (transference == TRANSFERENCE_REFERENCE)
904 submitEmptySignal(vkd, queue, *semaphoreA);
905 submitEmptyWait(vkd, queue, *semaphoreB);
908 DE_FATAL("Unknown transference.");
910 VK_CHECK(vkd.queueWaitIdle(queue));
913 return tcu::TestStatus::pass("Pass");
917 tcu::TestStatus testSemaphoreImportReimport (Context& context,
918 const SemaphoreTestConfig config)
920 const Transference transference (getHandelTypeTransferences(config.externalType));
921 const vk::PlatformInterface& vkp (context.getPlatformInterface());
922 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
923 const vk::InstanceDriver& vki (instance.getDriver());
924 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
925 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
927 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
930 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
931 const vk::DeviceDriver vkd (vkp, instance, *device);
932 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
934 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
935 NativeHandle handleA;
937 if (transference == TRANSFERENCE_COPY)
938 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
940 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
942 NativeHandle handleB (handleA);
943 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
944 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
946 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
948 if (transference == TRANSFERENCE_COPY)
949 submitEmptyWait(vkd, queue, *semaphoreB);
950 else if (transference == TRANSFERENCE_REFERENCE)
952 submitEmptySignal(vkd, queue, *semaphoreA);
953 submitEmptyWait(vkd, queue, *semaphoreB);
956 DE_FATAL("Unknown transference.");
958 VK_CHECK(vkd.queueWaitIdle(queue));
960 return tcu::TestStatus::pass("Pass");
964 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
965 const SemaphoreTestConfig config)
967 const vk::PlatformInterface& vkp (context.getPlatformInterface());
968 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
969 const vk::InstanceDriver& vki (instance.getDriver());
970 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
971 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
973 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
976 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
977 const vk::DeviceDriver vkd (vkp, instance, *device);
978 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
979 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
983 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
986 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
987 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
988 submitEmptyWait(vkd, queue, *semaphoreB);
990 VK_CHECK(vkd.queueWaitIdle(queue));
994 return tcu::TestStatus::pass("Pass");
998 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
999 const SemaphoreTestConfig config)
1001 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1002 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1003 const vk::InstanceDriver& vki (instance.getDriver());
1004 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1005 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1006 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1008 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1009 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1012 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1013 const vk::DeviceDriver vkd (vkp, instance, *device);
1014 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1016 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1017 NativeHandle handle;
1019 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1021 submitEmptySignal(vkd, queue, *semaphoreA);
1024 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1026 submitEmptyWait(vkd, queue, *semaphoreB);
1027 VK_CHECK(vkd.queueWaitIdle(queue));
1031 return tcu::TestStatus::pass("Pass");
1035 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1036 const SemaphoreTestConfig config)
1038 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1039 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1040 const vk::InstanceDriver& vki (instance.getDriver());
1041 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1042 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1044 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1045 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1048 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1049 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1050 const vk::DeviceDriver vkd (vkp, instance, *device);
1051 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1053 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1054 NativeHandle handle;
1056 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1058 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1060 submitEmptySignal(vkd, queue, *semaphoreA);
1061 submitEmptyWait(vkd, queue, *semaphoreB);
1063 VK_CHECK(vkd.queueWaitIdle(queue));
1065 return tcu::TestStatus::pass("Pass");
1069 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1070 const SemaphoreTestConfig config)
1072 const Transference transference (getHandelTypeTransferences(config.externalType));
1073 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1074 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1075 const vk::InstanceDriver& vki (instance.getDriver());
1076 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1077 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1079 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1082 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1083 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1084 const vk::DeviceDriver vkd (vkp, instance, *device);
1085 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1087 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1088 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1089 NativeHandle handle;
1091 submitEmptySignal(vkd, queue, *semaphoreB);
1092 VK_CHECK(vkd.queueWaitIdle(queue));
1094 if (transference == TRANSFERENCE_COPY)
1095 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1097 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1099 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1101 if (transference == TRANSFERENCE_COPY)
1102 submitEmptyWait(vkd, queue, *semaphoreB);
1103 else if (transference == TRANSFERENCE_REFERENCE)
1105 submitEmptySignal(vkd, queue, *semaphoreA);
1106 submitEmptyWait(vkd, queue, *semaphoreB);
1109 DE_FATAL("Unknown transference.");
1111 VK_CHECK(vkd.queueWaitIdle(queue));
1113 return tcu::TestStatus::pass("Pass");
1117 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1118 const SemaphoreTestConfig config)
1120 const Transference transference (getHandelTypeTransferences(config.externalType));
1121 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1122 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1123 const vk::InstanceDriver& vki (instance.getDriver());
1124 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1125 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1127 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1130 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1131 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1132 const vk::DeviceDriver vkd (vkp, instance, *device);
1133 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1135 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1136 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1137 NativeHandle handle;
1139 if (transference == TRANSFERENCE_COPY)
1140 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1142 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1144 submitEmptySignal(vkd, queue, *semaphoreB);
1145 submitEmptyWait(vkd, queue, *semaphoreB);
1147 VK_CHECK(vkd.queueWaitIdle(queue));
1149 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1151 if (transference == TRANSFERENCE_COPY)
1152 submitEmptyWait(vkd, queue, *semaphoreB);
1153 else if (transference == TRANSFERENCE_REFERENCE)
1155 submitEmptySignal(vkd, queue, *semaphoreA);
1156 submitEmptyWait(vkd, queue, *semaphoreB);
1159 DE_FATAL("Unknown transference.");
1161 VK_CHECK(vkd.queueWaitIdle(queue));
1163 return tcu::TestStatus::pass("Pass");
1167 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context,
1168 const SemaphoreTestConfig config)
1170 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1171 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1172 const vk::InstanceDriver& vki (instance.getDriver());
1173 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1174 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1175 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1177 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1180 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1181 const vk::DeviceDriver vkd (vkp, instance, *device);
1182 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1183 NativeHandle handle = -1;
1184 const vk::Unique<vk::VkSemaphore> semaphore (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1186 submitEmptyWait(vkd, queue, *semaphore);
1187 VK_CHECK(vkd.queueWaitIdle(queue));
1189 return tcu::TestStatus::pass("Pass");
1193 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1194 const SemaphoreTestConfig config)
1196 const size_t exportCount = 4 * 1024;
1197 const Transference transference (getHandelTypeTransferences(config.externalType));
1198 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1199 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1200 const vk::InstanceDriver& vki (instance.getDriver());
1201 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1202 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1204 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1207 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1208 const vk::DeviceDriver vkd (vkp, instance, *device);
1209 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1210 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1212 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1214 NativeHandle handle;
1216 if (transference == TRANSFERENCE_COPY)
1217 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1219 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1222 submitEmptySignal(vkd, queue, *semaphore);
1223 submitEmptyWait(vkd, queue, *semaphore);
1225 VK_CHECK(vkd.queueWaitIdle(queue));
1228 return tcu::TestStatus::pass("Pass");
1231 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1232 const SemaphoreTestConfig config)
1234 const size_t importCount = 4 * 1024;
1235 const Transference transference (getHandelTypeTransferences(config.externalType));
1236 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1237 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1238 const vk::InstanceDriver& vki (instance.getDriver());
1239 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1240 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1242 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1245 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1246 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1247 const vk::DeviceDriver vkd (vkp, instance, *device);
1248 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1249 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1250 NativeHandle handleA;
1252 if (transference == TRANSFERENCE_COPY)
1253 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1255 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1257 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1259 NativeHandle handleB (handleA);
1260 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1263 if (transference == TRANSFERENCE_COPY)
1265 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1266 submitEmptyWait(vkd, queue, *semaphoreA);
1268 else if (transference == TRANSFERENCE_REFERENCE)
1270 submitEmptySignal(vkd, queue, *semaphoreA);
1271 submitEmptyWait(vkd, queue, *semaphoreA);
1274 DE_FATAL("Unknown transference.");
1276 VK_CHECK(vkd.queueWaitIdle(queue));
1279 return tcu::TestStatus::pass("Pass");
1282 tcu::TestStatus testSemaphoreTransference (Context& context,
1283 const SemaphoreTestConfig config)
1285 const Transference transference (getHandelTypeTransferences(config.externalType));
1286 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1287 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1288 const vk::InstanceDriver& vki (instance.getDriver());
1289 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1290 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1292 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1295 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1296 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1297 const vk::DeviceDriver vkd (vkp, instance, *device);
1298 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1300 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1301 NativeHandle handle;
1303 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1306 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1308 if (config.permanence == PERMANENCE_PERMANENT)
1310 if (transference == TRANSFERENCE_COPY)
1312 submitEmptySignal(vkd, queue, *semaphoreA);
1313 submitEmptyWait(vkd, queue, *semaphoreB);
1314 VK_CHECK(vkd.queueWaitIdle(queue));
1316 submitEmptySignal(vkd, queue, *semaphoreB);
1318 submitEmptyWait(vkd, queue, *semaphoreA);
1319 submitEmptyWait(vkd, queue, *semaphoreB);
1320 VK_CHECK(vkd.queueWaitIdle(queue));
1322 else if (transference== TRANSFERENCE_REFERENCE)
1324 submitEmptyWait(vkd, queue, *semaphoreB);
1325 VK_CHECK(vkd.queueWaitIdle(queue));
1327 submitEmptySignal(vkd, queue, *semaphoreA);
1328 submitEmptyWait(vkd, queue, *semaphoreB);
1330 submitEmptySignal(vkd, queue, *semaphoreB);
1331 submitEmptyWait(vkd, queue, *semaphoreA);
1332 VK_CHECK(vkd.queueWaitIdle(queue));
1335 DE_FATAL("Unknown transference.");
1337 else if (config.permanence == PERMANENCE_TEMPORARY)
1339 if (transference == TRANSFERENCE_COPY)
1341 submitEmptySignal(vkd, queue, *semaphoreA);
1342 submitEmptyWait(vkd, queue, *semaphoreB);
1343 VK_CHECK(vkd.queueWaitIdle(queue));
1345 submitEmptySignal(vkd, queue, *semaphoreB);
1347 submitEmptyWait(vkd, queue, *semaphoreA);
1348 submitEmptyWait(vkd, queue, *semaphoreB);
1349 VK_CHECK(vkd.queueWaitIdle(queue));
1351 else if (transference== TRANSFERENCE_REFERENCE)
1353 submitEmptyWait(vkd, queue, *semaphoreB);
1354 VK_CHECK(vkd.queueWaitIdle(queue));
1356 submitEmptySignal(vkd, queue, *semaphoreA);
1357 submitEmptySignal(vkd, queue, *semaphoreB);
1359 submitEmptyWait(vkd, queue, *semaphoreB);
1360 submitEmptyWait(vkd, queue, *semaphoreA);
1361 VK_CHECK(vkd.queueWaitIdle(queue));
1364 DE_FATAL("Unknown transference.");
1367 DE_FATAL("Unknown permanence.");
1370 return tcu::TestStatus::pass("Pass");
1374 tcu::TestStatus testSemaphoreFdDup (Context& context,
1375 const SemaphoreTestConfig config)
1377 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1378 const Transference transference (getHandelTypeTransferences(config.externalType));
1379 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1380 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1381 const vk::InstanceDriver& vki (instance.getDriver());
1382 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1383 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1385 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1388 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1389 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1390 const vk::DeviceDriver vkd (vkp, instance, *device);
1391 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1393 TestLog& log = context.getTestContext().getLog();
1394 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1399 if (transference == TRANSFERENCE_COPY)
1400 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1402 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1404 NativeHandle newFd (dup(fd.getFd()));
1406 if (newFd.getFd() < 0)
1407 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1409 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1412 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1414 if (transference == TRANSFERENCE_COPY)
1415 submitEmptyWait(vkd, queue, *semaphoreB);
1416 else if (transference == TRANSFERENCE_REFERENCE)
1418 submitEmptySignal(vkd, queue, *semaphoreA);
1419 submitEmptyWait(vkd, queue, *semaphoreB);
1422 DE_FATAL("Unknown permanence.");
1424 VK_CHECK(vkd.queueWaitIdle(queue));
1428 return tcu::TestStatus::pass("Pass");
1433 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1437 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1438 const SemaphoreTestConfig config)
1440 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1441 const Transference transference (getHandelTypeTransferences(config.externalType));
1442 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1443 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1444 const vk::InstanceDriver& vki (instance.getDriver());
1445 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1446 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1448 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1451 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1452 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1453 const vk::DeviceDriver vkd (vkp, instance, *device);
1454 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1456 TestLog& log = context.getTestContext().getLog();
1457 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1458 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1461 NativeHandle fd, secondFd;
1463 if (transference == TRANSFERENCE_COPY)
1465 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1466 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1470 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1471 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1474 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1477 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1479 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1482 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1484 if (transference == TRANSFERENCE_COPY)
1485 submitEmptyWait(vkd, queue, *semaphoreC);
1486 else if (transference == TRANSFERENCE_REFERENCE)
1488 submitEmptySignal(vkd, queue, *semaphoreA);
1489 submitEmptyWait(vkd, queue, *semaphoreC);
1492 DE_FATAL("Unknown permanence.");
1494 VK_CHECK(vkd.queueWaitIdle(queue));
1498 return tcu::TestStatus::pass("Pass");
1503 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1507 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1508 const SemaphoreTestConfig config)
1510 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1511 const Transference transference (getHandelTypeTransferences(config.externalType));
1512 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1513 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1514 const vk::InstanceDriver& vki (instance.getDriver());
1515 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1516 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1518 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1521 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1522 const vk::DeviceDriver vkd (vkp, instance, *device);
1523 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1525 TestLog& log = context.getTestContext().getLog();
1526 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1527 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1530 NativeHandle fd, secondFd;
1532 if (transference == TRANSFERENCE_COPY)
1534 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1535 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1539 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1540 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1543 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1544 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1547 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1549 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1552 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1554 if (transference == TRANSFERENCE_COPY)
1555 submitEmptyWait(vkd, queue, *semaphoreC);
1556 else if (transference == TRANSFERENCE_REFERENCE)
1558 submitEmptySignal(vkd, queue, *semaphoreA);
1559 submitEmptyWait(vkd, queue, *semaphoreC);
1562 DE_FATAL("Unknown permanence.");
1564 VK_CHECK(vkd.queueWaitIdle(queue));
1568 return tcu::TestStatus::pass("Pass");
1573 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1577 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1578 const SemaphoreTestConfig config)
1580 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1581 const Transference transference (getHandelTypeTransferences(config.externalType));
1582 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1583 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1584 const vk::InstanceDriver& vki (instance.getDriver());
1585 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1586 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1588 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1591 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1592 const vk::DeviceDriver vkd (vkp, instance, *device);
1593 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1595 TestLog& log = context.getTestContext().getLog();
1596 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1599 if (transference == TRANSFERENCE_COPY)
1600 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1602 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1607 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1609 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1610 TCU_FAIL("Failed to create socket pair");
1614 const NativeHandle srcSocket (sv[0]);
1615 const NativeHandle dstSocket (sv[1]);
1616 std::string sendData ("deqp");
1620 const int fdRaw (fd.getFd());
1623 char buffer[CMSG_SPACE(sizeof(int))];
1624 iovec iov = { &sendData[0], sendData.length()};
1626 deMemset(&msg, 0, sizeof(msg));
1628 msg.msg_control = buffer;
1629 msg.msg_controllen = sizeof(buffer);
1633 cmsg = CMSG_FIRSTHDR(&msg);
1634 cmsg->cmsg_level = SOL_SOCKET;
1635 cmsg->cmsg_type = SCM_RIGHTS;
1636 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1638 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1639 msg.msg_controllen = cmsg->cmsg_len;
1641 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1643 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1644 TCU_FAIL("Failed to send fd over socket");
1651 char buffer[CMSG_SPACE(sizeof(int))];
1652 std::string recvData (4, '\0');
1653 iovec iov = { &recvData[0], recvData.length() };
1655 deMemset(&msg, 0, sizeof(msg));
1657 msg.msg_control = buffer;
1658 msg.msg_controllen = sizeof(buffer);
1662 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1666 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1667 TCU_FAIL("Failed to recv fd over socket");
1670 else if (bytes != (ssize_t)sendData.length())
1672 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1676 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1677 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1679 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1680 NativeHandle newFd (newFd_);
1682 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1683 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1684 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1685 TCU_CHECK(recvData == sendData);
1686 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1689 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1691 if (transference == TRANSFERENCE_COPY)
1692 submitEmptyWait(vkd, queue, *newSemaphore);
1693 else if (transference == TRANSFERENCE_REFERENCE)
1695 submitEmptySignal(vkd, queue, *newSemaphore);
1696 submitEmptyWait(vkd, queue, *newSemaphore);
1699 DE_FATAL("Unknown permanence.");
1701 VK_CHECK(vkd.queueWaitIdle(queue));
1709 return tcu::TestStatus::pass("Pass");
1713 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1717 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1719 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1720 const vk::InstanceDriver& vki (instance.getDriver());
1721 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1723 TestLog& log = context.getTestContext().getLog();
1725 const vk::VkPhysicalDeviceExternalFenceInfo info =
1727 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1731 vk::VkExternalFenceProperties properties =
1733 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1740 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1741 log << TestLog::Message << properties << TestLog::EndMessage;
1743 TCU_CHECK(properties.pNext == DE_NULL);
1744 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1746 return tcu::TestStatus::pass("Pass");
1749 struct FenceTestConfig
1751 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
1752 Permanence permanence_)
1753 : externalType (externalType_)
1754 , permanence (permanence_)
1758 vk::VkExternalFenceHandleTypeFlagBits externalType;
1759 Permanence permanence;
1763 tcu::TestStatus testFenceWin32Create (Context& context,
1764 const FenceTestConfig config)
1766 #if (DE_OS == DE_OS_WIN32)
1767 const Transference transference (getHandelTypeTransferences(config.externalType));
1768 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1769 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1770 const vk::InstanceDriver& vki (instance.getDriver());
1771 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1772 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1774 checkFenceSupport(vki, physicalDevice, config.externalType);
1777 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1778 const vk::DeviceDriver vkd (vkp, instance, *device);
1779 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1780 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1782 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1785 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1786 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1787 (vk::pt::Win32LPCWSTR)DE_NULL
1789 const vk::VkExportFenceCreateInfo exportCreateInfo=
1791 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1793 (vk::VkExternalFenceHandleTypeFlags)config.externalType
1795 const vk::VkFenceCreateInfo createInfo =
1797 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1801 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1803 if (transference == TRANSFERENCE_COPY)
1804 submitEmptySignal(vkd, queue, *fence);
1806 NativeHandle handleA;
1807 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1810 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1811 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1813 if (transference == TRANSFERENCE_COPY)
1814 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1815 else if (transference == TRANSFERENCE_REFERENCE)
1817 submitEmptySignal(vkd, queue, *fence);
1818 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1821 DE_FATAL("Unknown transference.");
1823 VK_CHECK(vkd.queueWaitIdle(queue));
1826 return tcu::TestStatus::pass("Pass");
1831 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1835 tcu::TestStatus testFenceImportTwice (Context& context,
1836 const FenceTestConfig config)
1838 const Transference transference (getHandelTypeTransferences(config.externalType));
1839 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1840 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1841 const vk::InstanceDriver& vki (instance.getDriver());
1842 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1843 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1845 checkFenceSupport(vki, physicalDevice, config.externalType);
1848 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1849 const vk::DeviceDriver vkd (vkp, instance, *device);
1850 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1851 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1852 NativeHandle handleA;
1854 if (transference == TRANSFERENCE_COPY)
1855 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1857 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1860 NativeHandle handleB (handleA);
1861 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1862 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1863 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1865 if (transference == TRANSFERENCE_COPY)
1866 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1867 else if (transference == TRANSFERENCE_REFERENCE)
1869 submitEmptySignal(vkd, queue, *fenceA);
1870 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1873 DE_FATAL("Unknown transference.");
1875 VK_CHECK(vkd.queueWaitIdle(queue));
1878 return tcu::TestStatus::pass("Pass");
1882 tcu::TestStatus testFenceImportReimport (Context& context,
1883 const FenceTestConfig config)
1885 const Transference transference (getHandelTypeTransferences(config.externalType));
1886 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1887 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1888 const vk::InstanceDriver& vki (instance.getDriver());
1889 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1890 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1892 checkFenceSupport(vki, physicalDevice, config.externalType);
1895 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1896 const vk::DeviceDriver vkd (vkp, instance, *device);
1897 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1899 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1900 NativeHandle handleA;
1902 if (transference == TRANSFERENCE_COPY)
1903 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1905 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1907 NativeHandle handleB (handleA);
1908 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1909 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1911 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1913 if (transference == TRANSFERENCE_COPY)
1914 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1915 else if (transference == TRANSFERENCE_REFERENCE)
1917 submitEmptySignal(vkd, queue, *fenceA);
1918 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1921 DE_FATAL("Unknown transference.");
1923 VK_CHECK(vkd.queueWaitIdle(queue));
1925 return tcu::TestStatus::pass("Pass");
1929 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1930 const FenceTestConfig config)
1932 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1933 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1934 const vk::InstanceDriver& vki (instance.getDriver());
1935 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1936 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1938 checkFenceSupport(vki, physicalDevice, config.externalType);
1941 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1942 const vk::DeviceDriver vkd (vkp, instance, *device);
1943 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1944 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1947 NativeHandle handle;
1949 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1952 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1953 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1954 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1956 VK_CHECK(vkd.queueWaitIdle(queue));
1960 return tcu::TestStatus::pass("Pass");
1964 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
1965 const FenceTestConfig config)
1967 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1968 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1969 const vk::InstanceDriver& vki (instance.getDriver());
1970 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1971 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1972 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1974 checkFenceSupport(vki, physicalDevice, config.externalType);
1977 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1978 const vk::DeviceDriver vkd (vkp, instance, *device);
1979 NativeHandle handle = -1;
1980 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1982 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
1983 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
1985 return tcu::TestStatus::pass("Pass");
1989 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
1990 const FenceTestConfig config)
1992 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1993 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1994 const vk::InstanceDriver& vki (instance.getDriver());
1995 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1996 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1997 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1999 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2000 checkFenceSupport(vki, physicalDevice, config.externalType);
2003 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2004 const vk::DeviceDriver vkd (vkp, instance, *device);
2005 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2007 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2008 NativeHandle handle;
2010 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2012 submitEmptySignal(vkd, queue, *fenceA);
2015 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2017 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2018 VK_CHECK(vkd.queueWaitIdle(queue));
2022 return tcu::TestStatus::pass("Pass");
2026 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2027 const FenceTestConfig config)
2029 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2030 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2031 const vk::InstanceDriver& vki (instance.getDriver());
2032 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2033 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2035 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2036 checkFenceSupport(vki, physicalDevice, config.externalType);
2039 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2040 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2041 const vk::DeviceDriver vkd (vkp, instance, *device);
2042 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2044 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2045 NativeHandle handle;
2047 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2049 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2051 submitEmptySignal(vkd, queue, *fenceA);
2052 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2054 VK_CHECK(vkd.queueWaitIdle(queue));
2056 return tcu::TestStatus::pass("Pass");
2060 tcu::TestStatus testFenceSignalImport (Context& context,
2061 const FenceTestConfig config)
2063 const Transference transference (getHandelTypeTransferences(config.externalType));
2064 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2065 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2066 const vk::InstanceDriver& vki (instance.getDriver());
2067 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2068 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2070 checkFenceSupport(vki, physicalDevice, config.externalType);
2073 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2074 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2075 const vk::DeviceDriver vkd (vkp, instance, *device);
2076 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2078 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2079 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2080 NativeHandle handle;
2082 submitEmptySignal(vkd, queue, *fenceB);
2083 VK_CHECK(vkd.queueWaitIdle(queue));
2085 if (transference == TRANSFERENCE_COPY)
2086 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2088 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2090 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2092 if (transference == TRANSFERENCE_COPY)
2093 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2094 else if (transference == TRANSFERENCE_REFERENCE)
2096 submitEmptySignal(vkd, queue, *fenceA);
2097 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2100 DE_FATAL("Unknown transference.");
2102 VK_CHECK(vkd.queueWaitIdle(queue));
2104 return tcu::TestStatus::pass("Pass");
2108 tcu::TestStatus testFenceReset (Context& context,
2109 const FenceTestConfig config)
2111 const Transference transference (getHandelTypeTransferences(config.externalType));
2112 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2113 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2114 const vk::InstanceDriver& vki (instance.getDriver());
2115 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2116 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2118 checkFenceSupport(vki, physicalDevice, config.externalType);
2121 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2122 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2123 const vk::DeviceDriver vkd (vkp, instance, *device);
2124 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2126 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2127 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2128 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2129 NativeHandle handle;
2131 submitEmptySignal(vkd, queue, *fenceB);
2132 VK_CHECK(vkd.queueWaitIdle(queue));
2134 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2135 NativeHandle handleB (handle);
2136 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2137 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2139 VK_CHECK(vkd.queueWaitIdle(queue));
2140 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2142 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2144 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2145 // or fenceB should be separate copy of the payload and not affect fenceC
2146 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2148 // vkResetFences() should have restored fenceBs prior state and should be now reset
2149 // or fenceB should have it's separate payload
2150 submitEmptySignal(vkd, queue, *fenceB);
2151 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2153 else if (config.permanence == PERMANENCE_PERMANENT)
2155 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2157 // Reset fences should have reset all of the fences
2158 submitEmptySignal(vkd, queue, *fenceC);
2160 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2161 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2162 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2165 DE_FATAL("Unknown permanence");
2167 VK_CHECK(vkd.queueWaitIdle(queue));
2169 return tcu::TestStatus::pass("Pass");
2173 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2174 const FenceTestConfig config)
2176 const Transference transference (getHandelTypeTransferences(config.externalType));
2177 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2178 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2179 const vk::InstanceDriver& vki (instance.getDriver());
2180 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2181 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2183 checkFenceSupport(vki, physicalDevice, config.externalType);
2186 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2187 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2188 const vk::DeviceDriver vkd (vkp, instance, *device);
2189 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2191 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2192 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2193 NativeHandle handle;
2195 if (transference == TRANSFERENCE_COPY)
2196 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2198 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2200 submitEmptySignal(vkd, queue, *fenceB);
2201 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2203 VK_CHECK(vkd.queueWaitIdle(queue));
2205 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2207 if (transference == TRANSFERENCE_COPY)
2208 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2209 else if (transference == TRANSFERENCE_REFERENCE)
2211 submitEmptySignal(vkd, queue, *fenceA);
2212 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2215 DE_FATAL("Unknown transference.");
2217 VK_CHECK(vkd.queueWaitIdle(queue));
2219 return tcu::TestStatus::pass("Pass");
2223 tcu::TestStatus testFenceMultipleExports (Context& context,
2224 const FenceTestConfig config)
2226 const size_t exportCount = 4 * 1024;
2227 const Transference transference (getHandelTypeTransferences(config.externalType));
2228 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2229 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2230 const vk::InstanceDriver& vki (instance.getDriver());
2231 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2232 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2234 checkFenceSupport(vki, physicalDevice, config.externalType);
2237 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2238 const vk::DeviceDriver vkd (vkp, instance, *device);
2239 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2240 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2242 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2244 NativeHandle handle;
2246 if (transference == TRANSFERENCE_COPY)
2247 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2249 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2252 submitEmptySignal(vkd, queue, *fence);
2253 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2255 VK_CHECK(vkd.queueWaitIdle(queue));
2258 return tcu::TestStatus::pass("Pass");
2261 tcu::TestStatus testFenceMultipleImports (Context& context,
2262 const FenceTestConfig config)
2264 const size_t importCount = 4 * 1024;
2265 const Transference transference (getHandelTypeTransferences(config.externalType));
2266 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2267 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2268 const vk::InstanceDriver& vki (instance.getDriver());
2269 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2270 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2272 checkFenceSupport(vki, physicalDevice, config.externalType);
2275 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2276 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2277 const vk::DeviceDriver vkd (vkp, instance, *device);
2278 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2279 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2280 NativeHandle handleA;
2282 if (transference == TRANSFERENCE_COPY)
2283 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2285 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2287 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2289 NativeHandle handleB (handleA);
2290 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2293 if (transference == TRANSFERENCE_COPY)
2295 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2296 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2298 else if (transference == TRANSFERENCE_REFERENCE)
2300 submitEmptySignal(vkd, queue, *fenceA);
2301 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2304 DE_FATAL("Unknown transference.");
2306 VK_CHECK(vkd.queueWaitIdle(queue));
2309 return tcu::TestStatus::pass("Pass");
2312 tcu::TestStatus testFenceTransference (Context& context,
2313 const FenceTestConfig config)
2315 const Transference transference (getHandelTypeTransferences(config.externalType));
2316 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2317 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2318 const vk::InstanceDriver& vki (instance.getDriver());
2319 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2320 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2322 checkFenceSupport(vki, physicalDevice, config.externalType);
2325 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2326 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2327 const vk::DeviceDriver vkd (vkp, instance, *device);
2328 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2330 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2331 NativeHandle handle;
2333 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2336 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2338 if (config.permanence == PERMANENCE_PERMANENT)
2340 if (transference == TRANSFERENCE_COPY)
2342 submitEmptySignal(vkd, queue, *fenceA);
2343 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2344 VK_CHECK(vkd.queueWaitIdle(queue));
2346 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2347 submitEmptySignal(vkd, queue, *fenceB);
2349 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2350 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2351 VK_CHECK(vkd.queueWaitIdle(queue));
2353 else if (transference== TRANSFERENCE_REFERENCE)
2355 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2356 VK_CHECK(vkd.queueWaitIdle(queue));
2358 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2359 submitEmptySignal(vkd, queue, *fenceA);
2360 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2362 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2363 submitEmptySignal(vkd, queue, *fenceB);
2364 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2365 VK_CHECK(vkd.queueWaitIdle(queue));
2368 DE_FATAL("Unknown transference.");
2370 else if (config.permanence == PERMANENCE_TEMPORARY)
2372 if (transference == TRANSFERENCE_COPY)
2374 submitEmptySignal(vkd, queue, *fenceA);
2375 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2376 VK_CHECK(vkd.queueWaitIdle(queue));
2378 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2379 submitEmptySignal(vkd, queue, *fenceB);
2381 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2382 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2383 VK_CHECK(vkd.queueWaitIdle(queue));
2385 else if (transference == TRANSFERENCE_REFERENCE)
2387 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2388 VK_CHECK(vkd.queueWaitIdle(queue));
2390 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2391 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2392 submitEmptySignal(vkd, queue, *fenceA);
2393 submitEmptySignal(vkd, queue, *fenceB);
2395 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2396 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2397 VK_CHECK(vkd.queueWaitIdle(queue));
2400 DE_FATAL("Unknown transference.");
2403 DE_FATAL("Unknown permanence.");
2406 return tcu::TestStatus::pass("Pass");
2410 tcu::TestStatus testFenceFdDup (Context& context,
2411 const FenceTestConfig config)
2413 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2414 const Transference transference (getHandelTypeTransferences(config.externalType));
2415 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2416 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2417 const vk::InstanceDriver& vki (instance.getDriver());
2418 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2419 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2421 checkFenceSupport(vki, physicalDevice, config.externalType);
2424 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2425 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2426 const vk::DeviceDriver vkd (vkp, instance, *device);
2427 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2429 TestLog& log = context.getTestContext().getLog();
2430 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2435 if (transference == TRANSFERENCE_COPY)
2436 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2438 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2440 NativeHandle newFd (dup(fd.getFd()));
2442 if (newFd.getFd() < 0)
2443 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2445 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2448 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2450 if (transference == TRANSFERENCE_COPY)
2451 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2452 else if (transference == TRANSFERENCE_REFERENCE)
2454 submitEmptySignal(vkd, queue, *fenceA);
2455 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2458 DE_FATAL("Unknown permanence.");
2460 VK_CHECK(vkd.queueWaitIdle(queue));
2464 return tcu::TestStatus::pass("Pass");
2469 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2473 tcu::TestStatus testFenceFdDup2 (Context& context,
2474 const FenceTestConfig config)
2476 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2477 const Transference transference (getHandelTypeTransferences(config.externalType));
2478 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2479 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2480 const vk::InstanceDriver& vki (instance.getDriver());
2481 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2482 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2484 checkFenceSupport(vki, physicalDevice, config.externalType);
2487 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2488 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2489 const vk::DeviceDriver vkd (vkp, instance, *device);
2490 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2492 TestLog& log = context.getTestContext().getLog();
2493 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2494 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2497 NativeHandle fd, secondFd;
2499 if (transference == TRANSFERENCE_COPY)
2501 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2502 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2506 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2507 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2510 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2513 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2515 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2518 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2520 if (transference == TRANSFERENCE_COPY)
2521 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2522 else if (transference == TRANSFERENCE_REFERENCE)
2524 submitEmptySignal(vkd, queue, *fenceA);
2525 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2528 DE_FATAL("Unknown permanence.");
2530 VK_CHECK(vkd.queueWaitIdle(queue));
2534 return tcu::TestStatus::pass("Pass");
2539 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2543 tcu::TestStatus testFenceFdDup3 (Context& context,
2544 const FenceTestConfig config)
2546 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2547 const Transference transference (getHandelTypeTransferences(config.externalType));
2548 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2549 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2550 const vk::InstanceDriver& vki (instance.getDriver());
2551 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2552 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2554 checkFenceSupport(vki, physicalDevice, config.externalType);
2557 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2558 const vk::DeviceDriver vkd (vkp, instance, *device);
2559 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2561 TestLog& log = context.getTestContext().getLog();
2562 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2563 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2566 NativeHandle fd, secondFd;
2568 if (transference == TRANSFERENCE_COPY)
2570 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2571 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2575 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2576 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2579 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2580 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2583 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2585 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2588 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2590 if (transference == TRANSFERENCE_COPY)
2591 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2592 else if (transference == TRANSFERENCE_REFERENCE)
2594 submitEmptySignal(vkd, queue, *fenceA);
2595 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2598 DE_FATAL("Unknown permanence.");
2600 VK_CHECK(vkd.queueWaitIdle(queue));
2604 return tcu::TestStatus::pass("Pass");
2609 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2613 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2614 const FenceTestConfig config)
2616 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2617 const Transference transference (getHandelTypeTransferences(config.externalType));
2618 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2619 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2620 const vk::InstanceDriver& vki (instance.getDriver());
2621 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2622 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2624 checkFenceSupport(vki, physicalDevice, config.externalType);
2627 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2628 const vk::DeviceDriver vkd (vkp, instance, *device);
2629 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2631 TestLog& log = context.getTestContext().getLog();
2632 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2635 if (transference == TRANSFERENCE_COPY)
2636 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2638 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2643 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2645 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2646 TCU_FAIL("Failed to create socket pair");
2650 const NativeHandle srcSocket (sv[0]);
2651 const NativeHandle dstSocket (sv[1]);
2652 std::string sendData ("deqp");
2656 const int fdRaw (fd.getFd());
2659 char buffer[CMSG_SPACE(sizeof(int))];
2660 iovec iov = { &sendData[0], sendData.length()};
2662 deMemset(&msg, 0, sizeof(msg));
2664 msg.msg_control = buffer;
2665 msg.msg_controllen = sizeof(buffer);
2669 cmsg = CMSG_FIRSTHDR(&msg);
2670 cmsg->cmsg_level = SOL_SOCKET;
2671 cmsg->cmsg_type = SCM_RIGHTS;
2672 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2674 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2675 msg.msg_controllen = cmsg->cmsg_len;
2677 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2679 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2680 TCU_FAIL("Failed to send fd over socket");
2687 char buffer[CMSG_SPACE(sizeof(int))];
2688 std::string recvData (4, '\0');
2689 iovec iov = { &recvData[0], recvData.length() };
2691 deMemset(&msg, 0, sizeof(msg));
2693 msg.msg_control = buffer;
2694 msg.msg_controllen = sizeof(buffer);
2698 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2702 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2703 TCU_FAIL("Failed to recv fd over socket");
2706 else if (bytes != (ssize_t)sendData.length())
2708 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2712 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2713 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2715 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2716 NativeHandle newFd (newFd_);
2718 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2719 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2720 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2721 TCU_CHECK(recvData == sendData);
2722 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2725 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2727 if (transference == TRANSFERENCE_COPY)
2728 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2729 else if (transference == TRANSFERENCE_REFERENCE)
2731 submitEmptySignal(vkd, queue, *newFence);
2732 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2735 DE_FATAL("Unknown permanence.");
2737 VK_CHECK(vkd.queueWaitIdle(queue));
2745 return tcu::TestStatus::pass("Pass");
2749 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2753 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2755 const vk::VkBufferCreateFlags createFlags[] =
2758 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2759 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2760 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2762 const vk::VkBufferUsageFlags usageFlags[] =
2764 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2765 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2766 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2767 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2768 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2769 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2770 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2771 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2772 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2774 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2775 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
2776 const vk::InstanceDriver& vki (instance.getDriver());
2777 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2778 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2779 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2781 // VkDevice is only created if physical device claims to support any of these types.
2782 vk::Move<vk::VkDevice> device;
2783 de::MovePtr<vk::DeviceDriver> vkd;
2784 bool deviceHasDedicated = false;
2786 TestLog& log = context.getTestContext().getLog();
2788 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2789 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2791 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2792 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2793 const vk::VkPhysicalDeviceExternalBufferInfo info =
2795 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2801 vk::VkExternalBufferProperties properties =
2803 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2808 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2809 (deviceFeatures.sparseBinding == VK_FALSE))
2812 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2813 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2816 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2817 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2820 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2822 log << TestLog::Message << properties << TestLog::EndMessage;
2824 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2825 TCU_CHECK(properties.pNext == DE_NULL);
2826 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2828 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2830 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2832 if (!device || (requiresDedicated && !deviceHasDedicated))
2834 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2837 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2838 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
2839 deviceHasDedicated = requiresDedicated;
2841 catch (const tcu::NotSupportedError& e)
2844 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2849 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2851 DE_ASSERT(!!device);
2854 if (deviceHasDedicated)
2856 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2857 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2858 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2859 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2861 if (propertiesRequiresDedicated != objectRequiresDedicated)
2862 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2866 // We can't query whether dedicated memory is required or not on per-object basis.
2867 // This check should be redundant as the code above tries to create device with
2868 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2869 // is required. However, checking again doesn't hurt.
2870 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2875 return tcu::TestStatus::pass("Pass");
2878 struct MemoryTestConfig
2880 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
2883 : externalType (externalType_)
2884 , hostVisible (hostVisible_)
2885 , dedicated (dedicated_)
2889 vk::VkExternalMemoryHandleTypeFlagBits externalType;
2894 #if (DE_OS == DE_OS_WIN32)
2895 deUint32 chooseWin32MemoryType(deUint32 bits)
2898 TCU_THROW(NotSupportedError, "No compatible memory type found");
2900 return deCtz32(bits);
2904 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2906 #if (DE_OS == DE_OS_WIN32)
2907 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2908 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
2909 const vk::InstanceDriver& vki (instance.getDriver());
2910 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2911 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2912 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2913 const vk::DeviceDriver vkd (vkp, instance, *device);
2914 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2915 const deUint32 seed = 1261033864u;
2916 const vk::VkDeviceSize bufferSize = 1024;
2917 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2919 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2920 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2922 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2924 // \note Buffer is only allocated to get memory requirements
2925 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2926 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2927 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2929 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2932 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2933 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2934 (vk::pt::Win32LPCWSTR)DE_NULL
2936 const vk::VkExportMemoryAllocateInfo exportInfo =
2938 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2940 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
2943 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2944 const vk::VkMemoryAllocateInfo info =
2946 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2949 exportedMemoryTypeIndex
2951 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2952 NativeHandle handleA;
2954 if (config.hostVisible)
2955 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2957 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2960 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2962 if (config.hostVisible)
2964 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2965 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2967 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2968 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2970 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2971 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
2973 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2974 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2978 return tcu::TestStatus::pass("Pass");
2982 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2986 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
2990 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2991 return chooseHostVisibleMemoryType(memoryBits, properties);
2994 return chooseMemoryType(memoryBits);
2997 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2999 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3000 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3001 const vk::InstanceDriver& vki (instance.getDriver());
3002 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3003 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3004 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3005 const vk::DeviceDriver vkd (vkp, instance, *device);
3006 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3007 const deUint32 seed = 1261033864u;
3008 const vk::VkDeviceSize bufferSize = 1024;
3009 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3011 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3013 // \note Buffer is only allocated to get memory requirements
3014 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3015 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3016 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3017 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3018 NativeHandle handleA;
3020 if (config.hostVisible)
3021 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3023 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3026 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3027 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3028 NativeHandle handleB (handleA);
3029 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3030 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3031 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3032 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3033 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3034 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3036 if (config.hostVisible)
3038 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3039 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3041 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3042 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3044 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3045 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3047 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3048 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3052 return tcu::TestStatus::pass("Pass");
3055 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3057 const size_t count = 4 * 1024;
3058 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3059 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3060 const vk::InstanceDriver& vki (instance.getDriver());
3061 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3062 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3063 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3064 const vk::DeviceDriver vkd (vkp, instance, *device);
3065 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3066 const vk::VkDeviceSize bufferSize = 1024;
3068 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3070 // \note Buffer is only allocated to get memory requirements
3071 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3072 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3073 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3074 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3075 NativeHandle handleA;
3077 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3079 for (size_t ndx = 0; ndx < count; ndx++)
3081 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3082 NativeHandle handleB (handleA);
3083 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3084 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3085 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3088 return tcu::TestStatus::pass("Pass");
3091 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3093 const size_t count = 4 * 1024;
3094 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3095 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3096 const vk::InstanceDriver& vki (instance.getDriver());
3097 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3098 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3099 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3100 const vk::DeviceDriver vkd (vkp, instance, *device);
3101 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3102 const vk::VkDeviceSize bufferSize = 1024;
3104 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3106 // \note Buffer is only allocated to get memory requirements
3107 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3108 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3109 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3110 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3112 for (size_t ndx = 0; ndx < count; ndx++)
3114 NativeHandle handle;
3115 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3118 return tcu::TestStatus::pass("Pass");
3121 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3123 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3124 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3125 const vk::InstanceDriver& vki (instance.getDriver());
3126 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3127 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3128 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3129 const vk::DeviceDriver vkd (vkp, instance, *device);
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;
3133 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3135 // \note Buffer is only allocated to get memory requirements
3136 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3137 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3138 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3139 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3141 vk::VkMemoryFdPropertiesKHR properties;
3142 NativeHandle handle;
3144 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3145 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3146 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3148 switch (config.externalType)
3150 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3151 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3154 // Invalid external memory type for this test.
3159 return tcu::TestStatus::pass("Pass");
3162 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3164 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3165 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3166 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3167 const vk::InstanceDriver& vki (instance.getDriver());
3168 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3169 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3172 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3173 const vk::DeviceDriver vkd (vkp, instance, *device);
3175 TestLog& log = context.getTestContext().getLog();
3176 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3177 const vk::VkDeviceSize bufferSize = 1024;
3178 const deUint32 seed = 851493858u;
3179 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3181 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3183 // \note Buffer is only allocated to get memory requirements
3184 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3185 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3186 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3187 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3189 if (config.hostVisible)
3190 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3192 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3193 NativeHandle newFd (dup(fd.getFd()));
3195 if (newFd.getFd() < 0)
3196 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3198 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3201 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3202 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3203 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3204 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3206 if (config.hostVisible)
3208 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3210 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3212 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3213 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3217 return tcu::TestStatus::pass("Pass");
3222 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3226 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3228 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3229 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3230 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3231 const vk::InstanceDriver& vki (instance.getDriver());
3232 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3233 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3236 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3237 const vk::DeviceDriver vkd (vkp, instance, *device);
3239 TestLog& log = context.getTestContext().getLog();
3240 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3241 const vk::VkDeviceSize bufferSize = 1024;
3242 const deUint32 seed = 224466865u;
3243 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3245 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3247 // \note Buffer is only allocated to get memory requirements
3248 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3249 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3250 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3251 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3253 if (config.hostVisible)
3254 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3256 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3257 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3258 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3261 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3263 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3266 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3267 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3268 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3269 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3271 if (config.hostVisible)
3273 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3275 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3277 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3278 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3282 return tcu::TestStatus::pass("Pass");
3287 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3291 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3293 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3294 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3295 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3296 const vk::InstanceDriver& vki (instance.getDriver());
3297 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3298 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3301 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3302 const vk::DeviceDriver vkd (vkp, instance, *device);
3304 TestLog& log = context.getTestContext().getLog();
3305 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3306 const vk::VkDeviceSize bufferSize = 1024;
3307 const deUint32 seed = 2554088961u;
3308 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3310 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3312 // \note Buffer is only allocated to get memory requirements
3313 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3314 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3315 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3316 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3318 if (config.hostVisible)
3319 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3321 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3322 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3323 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3326 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3328 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3331 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3332 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3333 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3334 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3336 if (config.hostVisible)
3338 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3340 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3342 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3343 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3347 return tcu::TestStatus::pass("Pass");
3352 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3356 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3358 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3359 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3360 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3361 const vk::InstanceDriver& vki (instance.getDriver());
3362 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3363 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3366 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3367 const vk::DeviceDriver vkd (vkp, instance, *device);
3369 TestLog& log = context.getTestContext().getLog();
3370 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3371 const vk::VkDeviceSize bufferSize = 1024;
3372 const deUint32 seed = 3403586456u;
3373 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3375 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3377 // \note Buffer is only allocated to get memory requirements
3378 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3379 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3380 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3381 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3383 if (config.hostVisible)
3384 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3386 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3391 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3393 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3394 TCU_FAIL("Failed to create socket pair");
3398 const NativeHandle srcSocket (sv[0]);
3399 const NativeHandle dstSocket (sv[1]);
3400 std::string sendData ("deqp");
3404 const int fdRaw (fd.getFd());
3407 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3408 iovec iov = { &sendData[0], sendData.length()};
3410 deMemset(&msg, 0, sizeof(msg));
3412 msg.msg_control = tmpBuffer;
3413 msg.msg_controllen = sizeof(tmpBuffer);
3417 cmsg = CMSG_FIRSTHDR(&msg);
3418 cmsg->cmsg_level = SOL_SOCKET;
3419 cmsg->cmsg_type = SCM_RIGHTS;
3420 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3422 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3423 msg.msg_controllen = cmsg->cmsg_len;
3425 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3427 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3428 TCU_FAIL("Failed to send fd over socket");
3435 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3436 std::string recvData (4, '\0');
3437 iovec iov = { &recvData[0], recvData.length() };
3439 deMemset(&msg, 0, sizeof(msg));
3441 msg.msg_control = tmpBuffer;
3442 msg.msg_controllen = sizeof(tmpBuffer);
3446 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3450 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3451 TCU_FAIL("Failed to recv fd over socket");
3454 else if (bytes != (ssize_t)sendData.length())
3456 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3460 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3462 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3463 NativeHandle newFd (newFd_);
3465 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3466 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3467 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3468 TCU_CHECK(recvData == sendData);
3469 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3472 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3473 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3474 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3475 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3477 if (config.hostVisible)
3479 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3481 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3483 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3484 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3493 return tcu::TestStatus::pass("Pass");
3497 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3501 struct BufferTestConfig
3503 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3505 : externalType (externalType_)
3506 , dedicated (dedicated_)
3510 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3514 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3515 const BufferTestConfig config)
3517 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3518 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3519 const vk::InstanceDriver& vki (instance.getDriver());
3520 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3521 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3522 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3523 const vk::DeviceDriver vkd (vkp, instance, *device);
3524 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3525 const vk::VkDeviceSize bufferSize = 1024;
3527 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3529 // \note Buffer is only allocated to get memory requirements
3530 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3531 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3532 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3533 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3534 NativeHandle handle;
3536 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3538 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3541 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3542 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3543 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3544 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3546 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3549 return tcu::TestStatus::pass("Pass");
3552 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3553 const BufferTestConfig config)
3555 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3556 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3557 const vk::InstanceDriver& vki (instance.getDriver());
3558 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3559 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3560 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3561 const vk::DeviceDriver vkd (vkp, instance, *device);
3562 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3563 const vk::VkDeviceSize bufferSize = 1024;
3565 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3567 // \note Buffer is only allocated to get memory requirements
3568 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3569 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3570 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3571 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3572 NativeHandle handle;
3574 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3575 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3578 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3579 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3580 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3581 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3583 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3586 return tcu::TestStatus::pass("Pass");
3589 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3590 const BufferTestConfig config)
3592 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3593 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3594 const vk::InstanceDriver& vki (instance.getDriver());
3595 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3596 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3597 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3598 const vk::DeviceDriver vkd (vkp, instance, *device);
3599 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3600 const vk::VkDeviceSize bufferSize = 1024;
3602 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3604 // \note Buffer is only allocated to get memory requirements
3605 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3606 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3607 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3608 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3609 NativeHandle handle;
3611 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3614 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3615 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3616 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3617 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3619 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3620 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3623 return tcu::TestStatus::pass("Pass");
3626 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3628 const vk::VkImageCreateFlags createFlags[] =
3631 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3632 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3633 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3634 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3635 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3637 const vk::VkImageUsageFlags usageFlags[] =
3639 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3640 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3641 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3642 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3643 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3644 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3645 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3646 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3647 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3648 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3650 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3651 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3652 const vk::InstanceDriver& vki (instance.getDriver());
3653 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3654 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3655 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3657 // VkDevice is only created if physical device claims to support any of these types.
3658 vk::Move<vk::VkDevice> device;
3659 de::MovePtr<vk::DeviceDriver> vkd;
3660 bool deviceHasDedicated = false;
3662 TestLog& log = context.getTestContext().getLog();
3664 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3665 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3667 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3668 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3669 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3670 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3671 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3672 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3674 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3678 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3680 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3689 vk::VkExternalImageFormatProperties externalProperties =
3691 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3695 vk::VkImageFormatProperties2 properties =
3697 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3698 &externalProperties,
3708 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3709 (deviceFeatures.sparseBinding == VK_FALSE))
3712 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3713 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3716 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3717 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3720 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
3722 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3723 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3724 TCU_CHECK(externalProperties.pNext == DE_NULL);
3725 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3727 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3729 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3731 if (!device || (requiresDedicated && !deviceHasDedicated))
3733 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3736 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3737 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3738 deviceHasDedicated = requiresDedicated;
3740 catch (const tcu::NotSupportedError& e)
3743 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3748 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3750 DE_ASSERT(!!device);
3753 if (deviceHasDedicated)
3755 // Memory requirements cannot be queried without binding the image.
3756 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3759 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3760 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3761 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3762 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3764 if (propertiesRequiresDedicated != objectRequiresDedicated)
3765 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3769 // We can't query whether dedicated memory is required or not on per-object basis.
3770 // This check should be redundant as the code above tries to create device with
3771 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3772 // is required. However, checking again doesn't hurt.
3773 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3778 return tcu::TestStatus::pass("Pass");
3781 struct ImageTestConfig
3783 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3785 : externalType (externalType_)
3786 , dedicated (dedicated_)
3790 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3794 tcu::TestStatus testImageBindExportImportBind (Context& context,
3795 const ImageTestConfig config)
3797 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3798 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3799 const vk::InstanceDriver& vki (instance.getDriver());
3800 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3801 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3802 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3803 const vk::DeviceDriver vkd (vkp, instance, *device);
3804 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3805 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3806 const deUint32 width = 64u;
3807 const deUint32 height = 64u;
3808 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3810 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3812 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3813 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3814 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3815 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3816 NativeHandle handle;
3818 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3820 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3823 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3824 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3825 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3826 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3827 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3829 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3832 return tcu::TestStatus::pass("Pass");
3835 tcu::TestStatus testImageExportBindImportBind (Context& context,
3836 const ImageTestConfig config)
3838 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3839 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3840 const vk::InstanceDriver& vki (instance.getDriver());
3841 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3842 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3843 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3844 const vk::DeviceDriver vkd (vkp, instance, *device);
3845 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3846 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3847 const deUint32 width = 64u;
3848 const deUint32 height = 64u;
3849 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3851 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3853 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3854 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3855 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3856 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3857 NativeHandle handle;
3859 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3861 // AHB required the image memory to be bound first.
3862 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3863 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3867 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3868 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3872 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3873 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3874 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3875 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3876 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3878 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3881 return tcu::TestStatus::pass("Pass");
3884 tcu::TestStatus testImageExportImportBindBind (Context& context,
3885 const ImageTestConfig config)
3887 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3888 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3889 const vk::InstanceDriver& vki (instance.getDriver());
3890 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3891 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3892 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3893 const vk::DeviceDriver vkd (vkp, instance, *device);
3894 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3895 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3896 const deUint32 width = 64u;
3897 const deUint32 height = 64u;
3898 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3900 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3902 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3904 // AHB required the image memory to be bound first, which is not possible in this test.
3905 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
3908 // \note Image is only allocated to get memory requirements
3909 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3910 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3911 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3912 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3913 NativeHandle handle;
3915 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3918 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3919 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3920 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3921 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3922 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3924 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3925 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3928 return tcu::TestStatus::pass("Pass");
3931 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
3933 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
3934 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
3937 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
3939 const Transference transference (getHandelTypeTransferences(config.externalType));
3940 if (transference == TRANSFERENCE_COPY)
3941 checkEvent(context, config);
3944 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3948 const char* const name;
3949 const Permanence permanence;
3952 { "temporary", PERMANENCE_TEMPORARY },
3953 { "permanent", PERMANENCE_PERMANENT }
3956 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3958 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3960 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3962 const Permanence permanence (permanences[permanenceNdx].permanence);
3963 const char* const permanenceName (permanences[permanenceNdx].name);
3964 const FenceTestConfig config (externalType, permanence);
3966 if (!isSupportedPermanence(externalType, permanence))
3969 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3970 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3972 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
3975 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, testFenceImportTwice, config);
3976 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, testFenceImportReimport, config);
3977 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, testFenceMultipleImports, config);
3978 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testFenceSignalExportImportWait, config);
3979 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, testFenceSignalImport, config);
3980 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, testFenceReset, config);
3981 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, testFenceTransference, config);
3983 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
3985 addFunctionCase(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", testFenceImportSyncFdSignaled, config);
3988 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
3989 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
3991 // \note Not supported on WIN32 handles
3992 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, testFenceMultipleExports, config);
3994 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, testFenceFdDup, config);
3995 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, testFenceFdDup2, config);
3996 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, testFenceFdDup3, config);
3997 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, testFenceFdSendOverSocket, config);
4000 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4002 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4003 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4004 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4011 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4013 DE_UNREF(createFlag);
4015 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4018 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4021 #if (DE_OS == DE_OS_ANDROID)
4022 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4023 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4027 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4028 if (ahb.internal == DE_NULL)
4030 enableMaxLayerTest = false;
4031 // try again with layerCount '1'
4032 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4033 if (ahb.internal == DE_NULL)
4038 NativeHandle nativeHandle(ahb);
4040 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4041 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4043 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4045 // Both mappings should be equivalent and work.
4046 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4048 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4050 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4052 vk::VK_FORMAT_UNDEFINED,
4056 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4057 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4058 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4059 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4062 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4064 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4070 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4071 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4072 TCU_CHECK(formatProperties.format == format);
4073 TCU_CHECK(formatProperties.externalFormat != 0u);
4074 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4075 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4081 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4083 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4086 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4089 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4090 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4091 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4092 const vk::InstanceDriver& vki (instance.getDriver());
4093 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4094 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4095 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex));
4096 const vk::DeviceDriver vkd (vkp, instance, *device);
4097 TestLog& log = context.getTestContext().getLog();
4098 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4100 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4101 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4103 const vk::VkImageUsageFlagBits usageFlags[] =
4105 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4106 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4107 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4108 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4109 framebufferUsageFlag,
4111 const vk::VkImageCreateFlagBits createFlags[] =
4113 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4114 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4115 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4117 const vk::VkImageTiling tilings[] =
4119 vk::VK_IMAGE_TILING_OPTIMAL,
4120 vk::VK_IMAGE_TILING_LINEAR,
4122 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4123 const size_t one = 1u;
4124 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4125 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4126 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4127 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4129 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4131 vk::VkImageUsageFlags usage = 0;
4132 vk::VkImageCreateFlags createFlag = 0;
4133 deUint64 requiredAhbUsage = 0;
4134 bool enableMaxLayerTest = true;
4135 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4137 if ((combo & (one << usageNdx)) == 0)
4139 usage |= usageFlags[usageNdx];
4140 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4142 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4144 const size_t bit = numOfUsageFlags + createFlagNdx;
4145 if ((combo & (one << bit)) == 0)
4147 createFlag |= createFlags[createFlagNdx];
4148 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4151 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4152 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4155 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4156 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4159 bool foundAnyUsableTiling = false;
4160 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4162 const vk::VkImageTiling tiling = tilings[tilingIndex];
4164 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4166 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4168 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4170 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4172 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4175 vk::VK_IMAGE_TYPE_2D,
4181 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4183 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4187 vk::VkExternalImageFormatProperties externalProperties =
4189 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4190 &ahbUsageProperties,
4193 vk::VkImageFormatProperties2 properties =
4195 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4196 &externalProperties,
4206 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4208 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4212 foundAnyUsableTiling = true;
4214 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4215 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4216 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4217 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4218 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4219 TCU_CHECK(maxWidth >= 4096);
4220 TCU_CHECK(maxHeight >= 4096);
4221 // Even if not requested, at least one of GPU_* usage flags must be present.
4222 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4223 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4224 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4226 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4227 << TestLog::EndMessage;
4239 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4241 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4242 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4243 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4244 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4245 NativeHandle handle;
4247 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4248 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4250 deUint32 ahbFormat = 0;
4251 deUint64 anhUsage = 0;
4252 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4253 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4254 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4256 // Let watchdog know we're alive
4257 context.getTestContext().touchWatchdog();
4260 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4262 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4263 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4264 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4265 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4266 NativeHandle handle;
4268 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4269 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4271 deUint32 ahbFormat = 0;
4272 deUint64 anhUsage = 0;
4273 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4274 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4275 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4278 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4280 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4281 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4282 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4283 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4284 NativeHandle handle;
4286 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4287 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4289 deUint32 ahbFormat = 0;
4290 deUint64 anhUsage = 0;
4291 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4292 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4293 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4297 TCU_CHECK(foundAnyUsableTiling);
4299 return tcu::TestStatus::pass("Pass");
4302 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4304 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4306 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4307 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4308 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4309 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4314 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4318 const char* const name;
4319 const Permanence permanence;
4322 { "temporary", PERMANENCE_TEMPORARY },
4323 { "permanent", PERMANENCE_PERMANENT }
4326 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4328 addFunctionCase(semaphoreGroup.get(), "info", "Test external semaphore queries.", testSemaphoreQueries, externalType);
4330 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4332 const Permanence permanence (permanences[permanenceNdx].permanence);
4333 const char* const permanenceName (permanences[permanenceNdx].name);
4334 const SemaphoreTestConfig config (externalType, permanence);
4336 if (!isSupportedPermanence(externalType, permanence))
4339 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4340 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4342 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4345 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, testSemaphoreImportTwice, config);
4346 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, testSemaphoreImportReimport, config);
4347 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, testSemaphoreMultipleImports, config);
4348 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testSemaphoreSignalExportImportWait, config);
4349 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, testSemaphoreSignalImport, config);
4350 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, testSemaphoreTransference, config);
4352 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4354 addFunctionCase(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", testSemaphoreImportSyncFdSignaled, config);
4358 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4359 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4361 // \note Not supported on WIN32 handles
4362 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, testSemaphoreMultipleExports, config);
4364 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, testSemaphoreFdDup, config);
4365 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, testSemaphoreFdDup2, config);
4366 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, testSemaphoreFdDup3, config);
4367 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, testSemaphoreFdSendOverSocket, config);
4370 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4372 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4373 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4374 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4378 return semaphoreGroup;
4381 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4383 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4385 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4386 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4387 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4388 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4390 return semaphoreGroup;
4393 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4395 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4397 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4399 const bool dedicated (dedicatedNdx == 1);
4400 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4402 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4404 const bool hostVisible (hostVisibleNdx == 1);
4405 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4406 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4408 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4409 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4411 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4414 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4415 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4417 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4418 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4420 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4421 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4422 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4423 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4424 // \note Not supported on WIN32 handles
4425 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4428 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4430 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4433 dedicatedGroup->addChild(hostVisibleGroup.release());
4437 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4438 const BufferTestConfig bufferConfig (externalType, dedicated);
4440 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4441 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4442 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4443 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4445 dedicatedGroup->addChild(bufferGroup.release());
4449 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4450 const ImageTestConfig imageConfig (externalType, dedicated);
4452 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4453 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4454 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4455 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4457 dedicatedGroup->addChild(imageGroup.release());
4460 group->addChild(dedicatedGroup.release());
4463 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4465 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4467 const vk::VkFormat ahbFormats[] =
4469 vk::VK_FORMAT_R8G8B8_UNORM,
4470 vk::VK_FORMAT_R8G8B8A8_UNORM,
4471 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4472 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4473 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4474 vk::VK_FORMAT_D16_UNORM,
4475 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4476 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4477 vk::VK_FORMAT_D32_SFLOAT,
4478 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4479 vk::VK_FORMAT_S8_UINT,
4481 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4483 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4485 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4486 const std::string testCaseName = getFormatCaseName(format);
4488 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4491 group->addChild(formatGroup.release());
4497 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4499 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4501 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4502 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4503 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4504 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4505 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4512 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4514 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4516 group->addChild(createSemaphoreTests(testCtx).release());
4517 group->addChild(createMemoryTests(testCtx).release());
4518 group->addChild(createFenceTests(testCtx).release());
4520 return group.release();